mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-10 04:05:00 +01:00
Multi-improvements
- Make lib instance shaders multiply color value instead of overriding it - Improve MultiBlockModelBuilder - Accept an Iterable<BlockPos> instead of a Collection<StructureBlockInfo> and assume all block state data is already contained within the render world - Accept a Function instead of a Map as the model data lookup - Allow enabling fluid rendering (all rendered fluids are currently unshaded) - Refactor VirtualEmptyBlockGetter - Move elementary implementations into abstract VirtualBlockGetter class - Extract virtual LevelLightEngine into separate VirtualLightEngine class with ability to lookup light values per pos - Turn VirtualEmptyBlockGetter into a class and make all methods final to ensure instances of this class are actually empty even if subclassed - Make BakedModelBufferer class package private - Remove unused VertexTransformations class - Remove Experimental annotation from VisualizationContext.createEmbedding
This commit is contained in:
parent
c3307630b2
commit
115aad3d40
14 changed files with 361 additions and 245 deletions
|
@ -1,7 +1,5 @@
|
||||||
package com.jozufozu.flywheel.api.visualization;
|
package com.jozufozu.flywheel.api.visualization;
|
||||||
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.BackendImplemented;
|
import com.jozufozu.flywheel.api.BackendImplemented;
|
||||||
import com.jozufozu.flywheel.api.instance.InstancerProvider;
|
import com.jozufozu.flywheel.api.instance.InstancerProvider;
|
||||||
|
|
||||||
|
@ -24,6 +22,5 @@ public interface VisualizationContext {
|
||||||
*/
|
*/
|
||||||
Vec3i renderOrigin();
|
Vec3i renderOrigin();
|
||||||
|
|
||||||
@ApiStatus.Experimental
|
|
||||||
VisualEmbedding createEmbedding();
|
VisualEmbedding createEmbedding();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,16 @@ import com.jozufozu.flywheel.api.model.Model;
|
||||||
|
|
||||||
public class SingleMeshModel implements Model {
|
public class SingleMeshModel implements Model {
|
||||||
private final Mesh mesh;
|
private final Mesh mesh;
|
||||||
private final Material material;
|
private final ImmutableList<ConfiguredMesh> meshList;
|
||||||
|
|
||||||
public SingleMeshModel(Mesh mesh, Material material) {
|
public SingleMeshModel(Mesh mesh, Material material) {
|
||||||
this.mesh = mesh;
|
this.mesh = mesh;
|
||||||
this.material = material;
|
meshList = ImmutableList.of(new ConfiguredMesh(material, mesh));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ConfiguredMesh> meshes() {
|
public List<ConfiguredMesh> meshes() {
|
||||||
return ImmutableList.of(new ConfiguredMesh(material, mesh));
|
return meshList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.jozufozu.flywheel.lib.model.baked;
|
package com.jozufozu.flywheel.lib.model.baked;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||||
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
||||||
|
@ -21,11 +22,11 @@ import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.RenderShape;
|
import net.minecraft.world.level.block.RenderShape;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import net.minecraftforge.client.ChunkRenderTypeSet;
|
import net.minecraftforge.client.ChunkRenderTypeSet;
|
||||||
import net.minecraftforge.client.model.data.ModelData;
|
import net.minecraftforge.client.model.data.ModelData;
|
||||||
|
|
||||||
public final class BakedModelBufferer {
|
final class BakedModelBufferer {
|
||||||
private static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new);
|
private static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new);
|
||||||
private static final int CHUNK_LAYER_AMOUNT = CHUNK_LAYERS.length;
|
private static final int CHUNK_LAYER_AMOUNT = CHUNK_LAYERS.length;
|
||||||
|
|
||||||
|
@ -122,12 +123,13 @@ public final class BakedModelBufferer {
|
||||||
bufferSingleShadeSeparated(renderDispatcher.getModelRenderer(), renderWorld, renderDispatcher.getBlockModel(state), state, poseStack, modelData, resultConsumer);
|
bufferSingleShadeSeparated(renderDispatcher.getModelRenderer(), renderWorld, renderDispatcher.getBlockModel(state), state, poseStack, modelData, resultConsumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bufferMultiBlock(Collection<StructureTemplate.StructureBlockInfo> blocks, BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, @Nullable PoseStack poseStack, Map<BlockPos, ModelData> modelDataMap, ResultConsumer resultConsumer) {
|
public static void bufferMultiBlock(BlockRenderDispatcher renderDispatcher, Iterator<BlockPos> posIterator, BlockAndTintGetter renderWorld, @Nullable PoseStack poseStack, Function<BlockPos, ModelData> modelDataLookup, boolean renderFluids, ResultConsumer resultConsumer) {
|
||||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||||
if (poseStack == null) {
|
if (poseStack == null) {
|
||||||
poseStack = objects.identityPoseStack;
|
poseStack = objects.identityPoseStack;
|
||||||
}
|
}
|
||||||
RandomSource random = objects.random;
|
RandomSource random = objects.random;
|
||||||
|
TransformingVertexConsumer transformingWrapper = objects.transformingWrapper;
|
||||||
|
|
||||||
BufferBuilder[] buffers = objects.shadedBuffers;
|
BufferBuilder[] buffers = objects.shadedBuffers;
|
||||||
for (BufferBuilder buffer : buffers) {
|
for (BufferBuilder buffer : buffers) {
|
||||||
|
@ -137,35 +139,51 @@ public final class BakedModelBufferer {
|
||||||
ModelBlockRenderer blockRenderer = renderDispatcher.getModelRenderer();
|
ModelBlockRenderer blockRenderer = renderDispatcher.getModelRenderer();
|
||||||
ModelBlockRenderer.enableCaching();
|
ModelBlockRenderer.enableCaching();
|
||||||
|
|
||||||
for (StructureTemplate.StructureBlockInfo blockInfo : blocks) {
|
while (posIterator.hasNext()) {
|
||||||
BlockState state = blockInfo.state();
|
BlockPos pos = posIterator.next();
|
||||||
|
BlockState state = renderWorld.getBlockState(pos);
|
||||||
|
|
||||||
if (state.getRenderShape() != RenderShape.MODEL) {
|
if (renderFluids) {
|
||||||
continue;
|
FluidState fluidState = state.getFluidState();
|
||||||
|
|
||||||
|
if (!fluidState.isEmpty()) {
|
||||||
|
RenderType layer = ItemBlockRenderTypes.getRenderLayer(fluidState);
|
||||||
|
int layerIndex = layer.getChunkLayerId();
|
||||||
|
|
||||||
|
transformingWrapper.prepare(buffers[layerIndex], poseStack);
|
||||||
|
|
||||||
|
poseStack.pushPose();
|
||||||
|
poseStack.translate(pos.getX() - (pos.getX() & 0xF), pos.getY() - (pos.getY() & 0xF), pos.getZ() - (pos.getZ() & 0xF));
|
||||||
|
renderDispatcher.renderLiquid(pos, renderWorld, transformingWrapper, state, fluidState);
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockPos pos = blockInfo.pos();
|
if (state.getRenderShape() == RenderShape.MODEL) {
|
||||||
long seed = state.getSeed(pos);
|
long seed = state.getSeed(pos);
|
||||||
BakedModel model = renderDispatcher.getBlockModel(state);
|
BakedModel model = renderDispatcher.getBlockModel(state);
|
||||||
ModelData modelData = modelDataMap.getOrDefault(pos, ModelData.EMPTY);
|
ModelData modelData = modelDataLookup.apply(pos);
|
||||||
modelData = model.getModelData(renderWorld, pos, state, modelData);
|
modelData = model.getModelData(renderWorld, pos, state, modelData);
|
||||||
random.setSeed(seed);
|
random.setSeed(seed);
|
||||||
ChunkRenderTypeSet renderTypes = model.getRenderTypes(state, random, modelData);
|
ChunkRenderTypeSet renderTypes = model.getRenderTypes(state, random, modelData);
|
||||||
|
|
||||||
for (RenderType renderType : renderTypes) {
|
for (RenderType renderType : renderTypes) {
|
||||||
int layerIndex = renderType.getChunkLayerId();
|
int layerIndex = renderType.getChunkLayerId();
|
||||||
|
|
||||||
BufferBuilder buffer = buffers[layerIndex];
|
BufferBuilder buffer = buffers[layerIndex];
|
||||||
|
|
||||||
poseStack.pushPose();
|
poseStack.pushPose();
|
||||||
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
|
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
|
||||||
blockRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, buffer, true, random, seed, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
blockRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, buffer, true, random, seed, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
||||||
poseStack.popPose();
|
poseStack.popPose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelBlockRenderer.clearCache();
|
ModelBlockRenderer.clearCache();
|
||||||
|
|
||||||
|
transformingWrapper.clear();
|
||||||
|
|
||||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||||
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
||||||
BufferBuilder buffer = buffers[layerIndex];
|
BufferBuilder buffer = buffers[layerIndex];
|
||||||
|
@ -177,13 +195,14 @@ public final class BakedModelBufferer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bufferMultiBlockShadeSeparated(Collection<StructureTemplate.StructureBlockInfo> blocks, BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, @Nullable PoseStack poseStack, Map<BlockPos, ModelData> modelDataMap, ShadeSeparatedResultConsumer resultConsumer) {
|
public static void bufferMultiBlockShadeSeparated(BlockRenderDispatcher renderDispatcher, Iterator<BlockPos> posIterator, BlockAndTintGetter renderWorld, @Nullable PoseStack poseStack, Function<BlockPos, ModelData> modelDataLookup, boolean renderFluids, ShadeSeparatedResultConsumer resultConsumer) {
|
||||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||||
if (poseStack == null) {
|
if (poseStack == null) {
|
||||||
poseStack = objects.identityPoseStack;
|
poseStack = objects.identityPoseStack;
|
||||||
}
|
}
|
||||||
RandomSource random = objects.random;
|
RandomSource random = objects.random;
|
||||||
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
|
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
|
||||||
|
TransformingVertexConsumer transformingWrapper = objects.transformingWrapper;
|
||||||
|
|
||||||
BufferBuilder[] shadedBuffers = objects.shadedBuffers;
|
BufferBuilder[] shadedBuffers = objects.shadedBuffers;
|
||||||
BufferBuilder[] unshadedBuffers = objects.unshadedBuffers;
|
BufferBuilder[] unshadedBuffers = objects.unshadedBuffers;
|
||||||
|
@ -197,36 +216,51 @@ public final class BakedModelBufferer {
|
||||||
ModelBlockRenderer blockRenderer = renderDispatcher.getModelRenderer();
|
ModelBlockRenderer blockRenderer = renderDispatcher.getModelRenderer();
|
||||||
ModelBlockRenderer.enableCaching();
|
ModelBlockRenderer.enableCaching();
|
||||||
|
|
||||||
for (StructureTemplate.StructureBlockInfo blockInfo : blocks) {
|
while (posIterator.hasNext()) {
|
||||||
BlockState state = blockInfo.state();
|
BlockPos pos = posIterator.next();
|
||||||
|
BlockState state = renderWorld.getBlockState(pos);
|
||||||
|
|
||||||
if (state.getRenderShape() != RenderShape.MODEL) {
|
if (renderFluids) {
|
||||||
continue;
|
FluidState fluidState = state.getFluidState();
|
||||||
|
|
||||||
|
if (!fluidState.isEmpty()) {
|
||||||
|
RenderType layer = ItemBlockRenderTypes.getRenderLayer(fluidState);
|
||||||
|
int layerIndex = layer.getChunkLayerId();
|
||||||
|
|
||||||
|
transformingWrapper.prepare(shadedBuffers[layerIndex], poseStack);
|
||||||
|
|
||||||
|
poseStack.pushPose();
|
||||||
|
poseStack.translate(pos.getX() - (pos.getX() & 0xF), pos.getY() - (pos.getY() & 0xF), pos.getZ() - (pos.getZ() & 0xF));
|
||||||
|
renderDispatcher.renderLiquid(pos, renderWorld, transformingWrapper, state, fluidState);
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockPos pos = blockInfo.pos();
|
if (state.getRenderShape() == RenderShape.MODEL) {
|
||||||
long seed = state.getSeed(pos);
|
long seed = state.getSeed(pos);
|
||||||
BakedModel model = renderDispatcher.getBlockModel(state);
|
BakedModel model = renderDispatcher.getBlockModel(state);
|
||||||
ModelData modelData = modelDataMap.getOrDefault(pos, ModelData.EMPTY);
|
ModelData modelData = modelDataLookup.apply(pos);
|
||||||
modelData = model.getModelData(renderWorld, pos, state, modelData);
|
modelData = model.getModelData(renderWorld, pos, state, modelData);
|
||||||
random.setSeed(seed);
|
random.setSeed(seed);
|
||||||
ChunkRenderTypeSet renderTypes = model.getRenderTypes(state, random, modelData);
|
ChunkRenderTypeSet renderTypes = model.getRenderTypes(state, random, modelData);
|
||||||
|
|
||||||
for (RenderType renderType : renderTypes) {
|
for (RenderType renderType : renderTypes) {
|
||||||
int layerIndex = renderType.getChunkLayerId();
|
int layerIndex = renderType.getChunkLayerId();
|
||||||
|
|
||||||
shadeSeparatingWrapper.prepare(shadedBuffers[layerIndex], unshadedBuffers[layerIndex]);
|
shadeSeparatingWrapper.prepare(shadedBuffers[layerIndex], unshadedBuffers[layerIndex]);
|
||||||
|
|
||||||
poseStack.pushPose();
|
poseStack.pushPose();
|
||||||
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
|
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
|
||||||
blockRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, shadeSeparatingWrapper, true, random, seed, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
blockRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, shadeSeparatingWrapper, true, random, seed, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
||||||
poseStack.popPose();
|
poseStack.popPose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelBlockRenderer.clearCache();
|
ModelBlockRenderer.clearCache();
|
||||||
|
|
||||||
shadeSeparatingWrapper.clear();
|
shadeSeparatingWrapper.clear();
|
||||||
|
transformingWrapper.clear();
|
||||||
|
|
||||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||||
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
||||||
|
@ -258,6 +292,7 @@ public final class BakedModelBufferer {
|
||||||
public final RandomSource random = RandomSource.createNewThreadLocalInstance();
|
public final RandomSource random = RandomSource.createNewThreadLocalInstance();
|
||||||
|
|
||||||
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
|
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
|
||||||
|
public final TransformingVertexConsumer transformingWrapper = new TransformingVertexConsumer();
|
||||||
|
|
||||||
public final BufferBuilder[] shadedBuffers = new BufferBuilder[CHUNK_LAYER_AMOUNT];
|
public final BufferBuilder[] shadedBuffers = new BufferBuilder[CHUNK_LAYER_AMOUNT];
|
||||||
public final BufferBuilder[] unshadedBuffers = new BufferBuilder[CHUNK_LAYER_AMOUNT];
|
public final BufferBuilder[] unshadedBuffers = new BufferBuilder[CHUNK_LAYER_AMOUNT];
|
||||||
|
|
|
@ -23,22 +23,17 @@ import net.minecraftforge.client.model.data.ModelData;
|
||||||
|
|
||||||
public class BakedModelBuilder {
|
public class BakedModelBuilder {
|
||||||
private final BakedModel bakedModel;
|
private final BakedModel bakedModel;
|
||||||
private boolean shadeSeparated = true;
|
|
||||||
private BlockAndTintGetter renderWorld;
|
private BlockAndTintGetter renderWorld;
|
||||||
private BlockState blockState;
|
private BlockState blockState;
|
||||||
private PoseStack poseStack;
|
private PoseStack poseStack;
|
||||||
private ModelData modelData;
|
private ModelData modelData;
|
||||||
|
private boolean shadeSeparated = true;
|
||||||
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||||
|
|
||||||
public BakedModelBuilder(BakedModel bakedModel) {
|
public BakedModelBuilder(BakedModel bakedModel) {
|
||||||
this.bakedModel = bakedModel;
|
this.bakedModel = bakedModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BakedModelBuilder disableShadeSeparation() {
|
|
||||||
shadeSeparated = false;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BakedModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
public BakedModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
||||||
this.renderWorld = renderWorld;
|
this.renderWorld = renderWorld;
|
||||||
return this;
|
return this;
|
||||||
|
@ -59,6 +54,11 @@ public class BakedModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BakedModelBuilder disableShadeSeparation() {
|
||||||
|
shadeSeparated = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public BakedModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
public BakedModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
||||||
this.materialFunc = materialFunc;
|
this.materialFunc = materialFunc;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -21,21 +21,16 @@ import net.minecraftforge.client.model.data.ModelData;
|
||||||
|
|
||||||
public class BlockModelBuilder {
|
public class BlockModelBuilder {
|
||||||
private final BlockState state;
|
private final BlockState state;
|
||||||
private boolean shadeSeparated = true;
|
|
||||||
private BlockAndTintGetter renderWorld;
|
private BlockAndTintGetter renderWorld;
|
||||||
private PoseStack poseStack;
|
private PoseStack poseStack;
|
||||||
private ModelData modelData;
|
private ModelData modelData;
|
||||||
|
private boolean shadeSeparated = true;
|
||||||
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||||
|
|
||||||
public BlockModelBuilder(BlockState state) {
|
public BlockModelBuilder(BlockState state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelBuilder disableShadeSeparation() {
|
|
||||||
shadeSeparated = false;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
public BlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
||||||
this.renderWorld = renderWorld;
|
this.renderWorld = renderWorld;
|
||||||
return this;
|
return this;
|
||||||
|
@ -51,6 +46,11 @@ public class BlockModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockModelBuilder disableShadeSeparation() {
|
||||||
|
shadeSeparated = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public BlockModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
public BlockModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
||||||
this.materialFunc = materialFunc;
|
this.materialFunc = materialFunc;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package com.jozufozu.flywheel.lib.model.baked;
|
package com.jozufozu.flywheel.lib.model.baked;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
|
@ -20,29 +18,20 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
|
||||||
import net.minecraftforge.client.model.data.ModelData;
|
import net.minecraftforge.client.model.data.ModelData;
|
||||||
|
|
||||||
public class MultiBlockModelBuilder {
|
public class MultiBlockModelBuilder {
|
||||||
private final Collection<StructureTemplate.StructureBlockInfo> blocks;
|
private final BlockAndTintGetter renderWorld;
|
||||||
private boolean shadeSeparated = true;
|
private final Iterable<BlockPos> positions;
|
||||||
private BlockAndTintGetter renderWorld;
|
|
||||||
private PoseStack poseStack;
|
private PoseStack poseStack;
|
||||||
private Map<BlockPos, ModelData> modelDataMap;
|
private Function<BlockPos, ModelData> modelDataLookup;
|
||||||
|
private boolean renderFluids = false;
|
||||||
|
private boolean shadeSeparated = true;
|
||||||
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||||
|
|
||||||
public MultiBlockModelBuilder(Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
public MultiBlockModelBuilder(BlockAndTintGetter renderWorld, Iterable<BlockPos> positions) {
|
||||||
this.blocks = blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MultiBlockModelBuilder disableShadeSeparation() {
|
|
||||||
shadeSeparated = false;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MultiBlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
|
||||||
this.renderWorld = renderWorld;
|
this.renderWorld = renderWorld;
|
||||||
return this;
|
this.positions = positions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultiBlockModelBuilder poseStack(PoseStack poseStack) {
|
public MultiBlockModelBuilder poseStack(PoseStack poseStack) {
|
||||||
|
@ -50,8 +39,18 @@ public class MultiBlockModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultiBlockModelBuilder modelDataMap(Map<BlockPos, ModelData> modelDataMap) {
|
public MultiBlockModelBuilder modelDataLookup(Function<BlockPos, ModelData> modelDataLookup) {
|
||||||
this.modelDataMap = modelDataMap;
|
this.modelDataLookup = modelDataLookup;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiBlockModelBuilder enableFluidRendering() {
|
||||||
|
renderFluids = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiBlockModelBuilder disableShadeSeparation() {
|
||||||
|
shadeSeparated = false;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,11 +60,8 @@ public class MultiBlockModelBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TessellatedModel build() {
|
public TessellatedModel build() {
|
||||||
if (renderWorld == null) {
|
if (modelDataLookup == null) {
|
||||||
renderWorld = VirtualEmptyBlockGetter.INSTANCE;
|
modelDataLookup = pos -> ModelData.EMPTY;
|
||||||
}
|
|
||||||
if (modelDataMap == null) {
|
|
||||||
modelDataMap = Collections.emptyMap();
|
|
||||||
}
|
}
|
||||||
if (materialFunc == null) {
|
if (materialFunc == null) {
|
||||||
materialFunc = ModelUtil::getMaterial;
|
materialFunc = ModelUtil::getMaterial;
|
||||||
|
@ -83,7 +79,7 @@ public class MultiBlockModelBuilder {
|
||||||
out.add(new Model.ConfiguredMesh(material, mesh));
|
out.add(new Model.ConfiguredMesh(material, mesh));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
BakedModelBufferer.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, modelDataMap, resultConsumer);
|
BakedModelBufferer.bufferMultiBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, positions.iterator(), renderWorld, poseStack, modelDataLookup, renderFluids, resultConsumer);
|
||||||
} else {
|
} else {
|
||||||
ResultConsumer resultConsumer = (renderType, data) -> {
|
ResultConsumer resultConsumer = (renderType, data) -> {
|
||||||
Material material = materialFunc.apply(renderType, true);
|
Material material = materialFunc.apply(renderType, true);
|
||||||
|
@ -94,7 +90,7 @@ public class MultiBlockModelBuilder {
|
||||||
out.add(new Model.ConfiguredMesh(material, mesh));
|
out.add(new Model.ConfiguredMesh(material, mesh));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
BakedModelBufferer.bufferMultiBlock(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, modelDataMap, resultConsumer);
|
BakedModelBufferer.bufferMultiBlock(ModelUtil.VANILLA_RENDERER, positions.iterator(), renderWorld, poseStack, modelDataLookup, renderFluids, resultConsumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TessellatedModel(out.build(), shadeSeparated);
|
return new TessellatedModel(out.build(), shadeSeparated);
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package com.jozufozu.flywheel.lib.model.baked;
|
||||||
|
|
||||||
|
import org.joml.Matrix3f;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.lib.math.MatrixMath;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
|
||||||
|
class TransformingVertexConsumer implements VertexConsumer {
|
||||||
|
private VertexConsumer delegate;
|
||||||
|
private PoseStack poseStack;
|
||||||
|
|
||||||
|
public void prepare(VertexConsumer delegate, PoseStack poseStack) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.poseStack = poseStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
delegate = null;
|
||||||
|
poseStack = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VertexConsumer vertex(double x, double y, double z) {
|
||||||
|
Matrix4f matrix = poseStack.last().pose();
|
||||||
|
float fx = (float) x;
|
||||||
|
float fy = (float) y;
|
||||||
|
float fz = (float) z;
|
||||||
|
delegate.vertex(
|
||||||
|
MatrixMath.transformPositionX(matrix, fx, fy, fz),
|
||||||
|
MatrixMath.transformPositionY(matrix, fx, fy, fz),
|
||||||
|
MatrixMath.transformPositionZ(matrix, fx, fy, fz));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VertexConsumer color(int red, int green, int blue, int alpha) {
|
||||||
|
delegate.color(red, green, blue, alpha);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VertexConsumer uv(float u, float v) {
|
||||||
|
delegate.uv(u, v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VertexConsumer overlayCoords(int u, int v) {
|
||||||
|
delegate.overlayCoords(u, v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VertexConsumer uv2(int u, int v) {
|
||||||
|
delegate.uv2(u, v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VertexConsumer normal(float x, float y, float z) {
|
||||||
|
Matrix3f matrix = poseStack.last().normal();
|
||||||
|
float fx = (float) x;
|
||||||
|
float fy = (float) y;
|
||||||
|
float fz = (float) z;
|
||||||
|
delegate.normal(
|
||||||
|
MatrixMath.transformNormalX(matrix, fx, fy, fz),
|
||||||
|
MatrixMath.transformNormalY(matrix, fx, fy, fz),
|
||||||
|
MatrixMath.transformNormalZ(matrix, fx, fy, fz));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endVertex() {
|
||||||
|
delegate.endVertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void defaultColor(int red, int green, int blue, int alpha) {
|
||||||
|
delegate.defaultColor(red, green, blue, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unsetDefaultColor() {
|
||||||
|
delegate.unsetDefaultColor();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.jozufozu.flywheel.lib.model.baked;
|
||||||
|
|
||||||
|
import java.util.function.ToIntFunction;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
|
import net.minecraft.world.level.ColorResolver;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.biome.Biomes;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
|
||||||
|
public abstract class VirtualBlockGetter implements BlockAndTintGetter {
|
||||||
|
protected final VirtualLightEngine lightEngine;
|
||||||
|
|
||||||
|
public VirtualBlockGetter(ToIntFunction<BlockPos> blockLightFunc, ToIntFunction<BlockPos> skyLightFunc) {
|
||||||
|
lightEngine = new VirtualLightEngine(blockLightFunc, skyLightFunc, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FluidState getFluidState(BlockPos pos) {
|
||||||
|
return getBlockState(pos).getFluidState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getShade(Direction direction, boolean shaded) {
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LevelLightEngine getLightEngine() {
|
||||||
|
return lightEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlockTint(BlockPos pos, ColorResolver resolver) {
|
||||||
|
Biome plainsBiome = Minecraft.getInstance().getConnection().registryAccess().registryOrThrow(Registries.BIOME).getOrThrow(Biomes.PLAINS);
|
||||||
|
return resolver.getColor(plainsBiome, pos.getX(), pos.getZ());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,34 +1,25 @@
|
||||||
package com.jozufozu.flywheel.lib.model.baked;
|
package com.jozufozu.flywheel.lib.model.baked;
|
||||||
|
|
||||||
|
import java.util.function.ToIntFunction;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.core.SectionPos;
|
|
||||||
import net.minecraft.core.registries.Registries;
|
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
|
||||||
import net.minecraft.world.level.ChunkPos;
|
|
||||||
import net.minecraft.world.level.ColorResolver;
|
|
||||||
import net.minecraft.world.level.LightLayer;
|
|
||||||
import net.minecraft.world.level.biome.Biome;
|
|
||||||
import net.minecraft.world.level.biome.Biomes;
|
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.DataLayer;
|
|
||||||
import net.minecraft.world.level.chunk.LightChunk;
|
|
||||||
import net.minecraft.world.level.chunk.LightChunkGetter;
|
|
||||||
import net.minecraft.world.level.lighting.LayerLightEventListener;
|
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import net.minecraft.world.level.material.Fluids;
|
import net.minecraft.world.level.material.Fluids;
|
||||||
|
|
||||||
public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
|
public class VirtualEmptyBlockGetter extends VirtualBlockGetter {
|
||||||
public static final VirtualEmptyBlockGetter INSTANCE = new StaticLightImpl(0, 15);
|
public static final VirtualEmptyBlockGetter INSTANCE = new VirtualEmptyBlockGetter(p -> 0, p -> 15);
|
||||||
public static final VirtualEmptyBlockGetter FULL_BRIGHT = new StaticLightImpl(15, 15);
|
public static final VirtualEmptyBlockGetter FULL_BRIGHT = new VirtualEmptyBlockGetter(p -> 15, p -> 15);
|
||||||
public static final VirtualEmptyBlockGetter FULL_DARK = new StaticLightImpl(0, 0);
|
public static final VirtualEmptyBlockGetter FULL_DARK = new VirtualEmptyBlockGetter(p -> 0, p -> 0);
|
||||||
|
|
||||||
|
public VirtualEmptyBlockGetter(ToIntFunction<BlockPos> blockLightFunc, ToIntFunction<BlockPos> skyLightFunc) {
|
||||||
|
super(blockLightFunc, skyLightFunc);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean is(BlockAndTintGetter blockGetter) {
|
public static boolean is(BlockAndTintGetter blockGetter) {
|
||||||
return blockGetter instanceof VirtualEmptyBlockGetter;
|
return blockGetter instanceof VirtualEmptyBlockGetter;
|
||||||
|
@ -36,110 +27,27 @@ public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
default BlockEntity getBlockEntity(BlockPos pos) {
|
public final BlockEntity getBlockEntity(BlockPos pos) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default BlockState getBlockState(BlockPos pos) {
|
public final BlockState getBlockState(BlockPos pos) {
|
||||||
return Blocks.AIR.defaultBlockState();
|
return Blocks.AIR.defaultBlockState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default FluidState getFluidState(BlockPos pos) {
|
public final FluidState getFluidState(BlockPos pos) {
|
||||||
return Fluids.EMPTY.defaultFluidState();
|
return Fluids.EMPTY.defaultFluidState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default int getHeight() {
|
public final int getHeight() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default int getMinBuildHeight() {
|
public final int getMinBuildHeight() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
default float getShade(Direction direction, boolean shaded) {
|
|
||||||
return 1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default int getBlockTint(BlockPos pos, ColorResolver resolver) {
|
|
||||||
Biome plainsBiome = Minecraft.getInstance().getConnection().registryAccess().registryOrThrow(Registries.BIOME).getOrThrow(Biomes.PLAINS);
|
|
||||||
return resolver.getColor(plainsBiome, pos.getX(), pos.getZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class StaticLightImpl implements VirtualEmptyBlockGetter {
|
|
||||||
private final LevelLightEngine lightEngine;
|
|
||||||
|
|
||||||
public StaticLightImpl(int blockLight, int skyLight) {
|
|
||||||
lightEngine = new LevelLightEngine(new LightChunkGetter() {
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public LightChunk getChunkForLighting(int x, int z) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockGetter getLevel() {
|
|
||||||
return StaticLightImpl.this;
|
|
||||||
}
|
|
||||||
}, false, false) {
|
|
||||||
private final LayerLightEventListener blockListener = createStaticListener(blockLight);
|
|
||||||
private final LayerLightEventListener skyListener = createStaticListener(skyLight);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LayerLightEventListener getLayerListener(LightLayer layer) {
|
|
||||||
return layer == LightLayer.BLOCK ? blockListener : skyListener;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static LayerLightEventListener createStaticListener(int light) {
|
|
||||||
return new LayerLightEventListener() {
|
|
||||||
@Override
|
|
||||||
public void checkBlock(BlockPos pos) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasLightWork() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int runLightUpdates() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSectionStatus(SectionPos pos, boolean isSectionEmpty) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLightEnabled(ChunkPos pos, boolean lightEnabled) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void propagateLightSources(ChunkPos pos) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataLayer getDataLayerData(SectionPos pos) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLightValue(BlockPos pos) {
|
|
||||||
return light;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LevelLightEngine getLightEngine() {
|
|
||||||
return lightEngine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.jozufozu.flywheel.lib.model.baked;
|
||||||
|
|
||||||
|
import java.util.function.ToIntFunction;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
import net.minecraft.world.level.chunk.DataLayer;
|
||||||
|
import net.minecraft.world.level.chunk.LightChunk;
|
||||||
|
import net.minecraft.world.level.chunk.LightChunkGetter;
|
||||||
|
import net.minecraft.world.level.lighting.LayerLightEventListener;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
|
||||||
|
public final class VirtualLightEngine extends LevelLightEngine {
|
||||||
|
private final LayerLightEventListener blockListener;
|
||||||
|
private final LayerLightEventListener skyListener;
|
||||||
|
|
||||||
|
public VirtualLightEngine(ToIntFunction<BlockPos> blockLightFunc, ToIntFunction<BlockPos> skyLightFunc, BlockGetter level) {
|
||||||
|
super(new LightChunkGetter() {
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public LightChunk getChunkForLighting(int x, int z) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockGetter getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
}, false, false);
|
||||||
|
|
||||||
|
blockListener = new VirtualLayerLightEventListener(blockLightFunc);
|
||||||
|
skyListener = new VirtualLayerLightEventListener(skyLightFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LayerLightEventListener getLayerListener(LightLayer layer) {
|
||||||
|
return layer == LightLayer.BLOCK ? blockListener : skyListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawBrightness(BlockPos pos, int amount) {
|
||||||
|
int i = skyListener.getLightValue(pos) - amount;
|
||||||
|
int j = blockListener.getLightValue(pos);
|
||||||
|
return Math.max(j, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class VirtualLayerLightEventListener implements LayerLightEventListener {
|
||||||
|
private final ToIntFunction<BlockPos> lightFunc;
|
||||||
|
|
||||||
|
public VirtualLayerLightEventListener(ToIntFunction<BlockPos> lightFunc) {
|
||||||
|
this.lightFunc = lightFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkBlock(BlockPos pos) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasLightWork() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int runLightUpdates() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSectionStatus(SectionPos pos, boolean isSectionEmpty) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLightEnabled(ChunkPos pos, boolean lightEnabled) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void propagateLightSources(ChunkPos pos) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataLayer getDataLayerData(SectionPos pos) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightValue(BlockPos pos) {
|
||||||
|
return lightFunc.applyAsInt(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
package com.jozufozu.flywheel.lib.vertex;
|
|
||||||
|
|
||||||
import org.joml.Matrix3f;
|
|
||||||
import org.joml.Matrix4f;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
|
||||||
import com.jozufozu.flywheel.lib.math.MatrixMath;
|
|
||||||
|
|
||||||
public final class VertexTransformations {
|
|
||||||
private VertexTransformations() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void transformPos(MutableVertexList vertexList, int index, Matrix4f matrix) {
|
|
||||||
float x = vertexList.x(index);
|
|
||||||
float y = vertexList.y(index);
|
|
||||||
float z = vertexList.z(index);
|
|
||||||
vertexList.x(index, MatrixMath.transformPositionX(matrix, x, y, z));
|
|
||||||
vertexList.y(index, MatrixMath.transformPositionY(matrix, x, y, z));
|
|
||||||
vertexList.z(index, MatrixMath.transformPositionZ(matrix, x, y, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assumes the matrix preserves scale.
|
|
||||||
*/
|
|
||||||
public static void transformNormal(MutableVertexList vertexList, int index, Matrix3f matrix) {
|
|
||||||
float nx = vertexList.normalX(index);
|
|
||||||
float ny = vertexList.normalY(index);
|
|
||||||
float nz = vertexList.normalZ(index);
|
|
||||||
float tnx = MatrixMath.transformNormalX(matrix, nx, ny, nz);
|
|
||||||
float tny = MatrixMath.transformNormalY(matrix, nx, ny, nz);
|
|
||||||
float tnz = MatrixMath.transformNormalZ(matrix, nx, ny, nz);
|
|
||||||
// seems to be the case that sqrLength is always ~1.0
|
|
||||||
// float sqrLength = fma(tnx, tnx, fma(tny, tny, tnz * tnz));
|
|
||||||
// if (sqrLength != 0) {
|
|
||||||
// float f = invsqrt(sqrLength);
|
|
||||||
// tnx *= f;
|
|
||||||
// tny *= f;
|
|
||||||
// tnz *= f;
|
|
||||||
// }
|
|
||||||
vertexList.normalX(index, tnx);
|
|
||||||
vertexList.normalY(index, tny);
|
|
||||||
vertexList.normalZ(index, tnz);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@
|
||||||
void flw_instanceVertex(in FlwInstance i) {
|
void flw_instanceVertex(in FlwInstance i) {
|
||||||
flw_vertexPos = vec4(rotateByQuaternion(flw_vertexPos.xyz - i.pivot, i.rotation) + i.pivot + i.position, 1.0);
|
flw_vertexPos = vec4(rotateByQuaternion(flw_vertexPos.xyz - i.pivot, i.rotation) + i.pivot + i.position, 1.0);
|
||||||
flw_vertexNormal = rotateByQuaternion(flw_vertexNormal, i.rotation);
|
flw_vertexNormal = rotateByQuaternion(flw_vertexNormal, i.rotation);
|
||||||
flw_vertexColor = i.color;
|
flw_vertexColor *= i.color;
|
||||||
flw_vertexOverlay = i.overlay;
|
flw_vertexOverlay = i.overlay;
|
||||||
flw_vertexLight = i.light / 15.;
|
flw_vertexLight = i.light / 15.;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,4 @@ void flw_instanceVertex(in FlwInstance i) {
|
||||||
flw_vertexTexCoord = (flw_vertexPos.xz - i.entityPosXZ) * 0.5 / i.radius + 0.5;
|
flw_vertexTexCoord = (flw_vertexPos.xz - i.entityPosXZ) * 0.5 / i.radius + 0.5;
|
||||||
|
|
||||||
flw_vertexColor.a = i.alpha;
|
flw_vertexColor.a = i.alpha;
|
||||||
// no overlay
|
|
||||||
flw_vertexOverlay = ivec2(0, 10);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
void flw_instanceVertex(in FlwInstance i) {
|
void flw_instanceVertex(in FlwInstance i) {
|
||||||
flw_vertexPos = i.pose * flw_vertexPos;
|
flw_vertexPos = i.pose * flw_vertexPos;
|
||||||
flw_vertexNormal = i.normal * flw_vertexNormal;
|
flw_vertexNormal = i.normal * flw_vertexNormal;
|
||||||
flw_vertexColor = i.color;
|
flw_vertexColor *= i.color;
|
||||||
flw_vertexOverlay = i.overlay;
|
flw_vertexOverlay = i.overlay;
|
||||||
flw_vertexLight = i.light / 15.;
|
flw_vertexLight = i.light / 15.;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue