From 721b3b863350d403295e74cab60b5bfc399e2514 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Fri, 23 Jul 2021 12:26:32 -0700 Subject: [PATCH] Basic model abstraction - Stop providing a buffered model supplier - Instead, provide an IModel supplier - IModel exposes basic properties of models - IModel exposes a method to copy the model to a VecBuffer --- .../backend/instancing/Instancer.java | 8 +- .../backend/material/InstanceMaterial.java | 74 ++----------- .../flywheel/core/model/BlockModel.java | 101 ++++++++++++++++++ .../jozufozu/flywheel/core/model/IModel.java | 26 +++++ .../flywheel/core/model/ModelPart.java | 47 +++++++- .../flywheel/core/model/ModelUtil.java | 21 ++++ .../flywheel/core/model/PartBuilder.java | 37 ++----- .../flywheel/core/model/package-info.java | 6 ++ .../flywheel/vanilla/BellInstance.java | 2 +- .../flywheel/vanilla/ChestInstance.java | 4 +- .../flywheel/vanilla/ShulkerBoxInstance.java | 4 +- 11 files changed, 225 insertions(+), 105 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/model/IModel.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/model/package-info.java diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java index 5b01e7497..3bb08d58e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java @@ -15,6 +15,8 @@ import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; import com.jozufozu.flywheel.backend.material.MaterialSpec; import com.jozufozu.flywheel.backend.model.BufferedModel; +import com.jozufozu.flywheel.core.model.IModel; +import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.util.AttribUtil; import net.minecraft.util.math.vector.Vector3i; @@ -23,7 +25,7 @@ public class Instancer { public final Supplier originCoordinate; - protected final Supplier gen; + protected final Supplier gen; protected BufferedModel model; protected final VertexFormat instanceFormat; @@ -40,7 +42,7 @@ public class Instancer { boolean anyToRemove; boolean anyToUpdate; - public Instancer(Supplier model, Supplier originCoordinate, MaterialSpec spec) { + public Instancer(Supplier model, Supplier originCoordinate, MaterialSpec spec) { this.gen = model; this.factory = spec.getInstanceFactory(); this.instanceFormat = spec.getInstanceFormat(); @@ -71,7 +73,7 @@ public class Instancer { } private void init() { - model = gen.get(); + model = ModelUtil.getIndexedModel(gen.get()); initialized = true; if (model.getVertexCount() <= 0) diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/InstanceMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/material/InstanceMaterial.java index 119b7ea9f..cc647c28b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/material/InstanceMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/material/InstanceMaterial.java @@ -3,38 +3,32 @@ package com.jozufozu.flywheel.backend.material; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.Arrays; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; import java.util.function.Supplier; import org.apache.commons.lang3.tuple.Pair; -import org.lwjgl.opengl.GL11; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.instancing.InstanceData; import com.jozufozu.flywheel.backend.instancing.Instancer; import com.jozufozu.flywheel.backend.model.BufferedModel; import com.jozufozu.flywheel.backend.model.IndexedModel; import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.util.BufferBuilderReader; +import com.jozufozu.flywheel.core.model.BlockModel; +import com.jozufozu.flywheel.core.model.IModel; import com.jozufozu.flywheel.util.RenderUtil; -import com.jozufozu.flywheel.util.VirtualEmptyModelData; import com.mojang.blaze3d.matrix.MatrixStack; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BlockModelRenderer; import net.minecraft.client.renderer.BlockRendererDispatcher; -import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.model.IBakedModel; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3i; public class InstanceMaterial { @@ -100,7 +94,7 @@ public class InstanceMaterial { return model(toRender, () -> buildModel(toRender)); } - public Instancer model(Object key, Supplier supplier) { + public Instancer model(Object key, Supplier supplier) { try { return models.get(key, () -> new Instancer<>(supplier, originCoordinate, spec)); } catch (ExecutionException e) { @@ -109,70 +103,18 @@ public class InstanceMaterial { } } - private BufferedModel buildModel(BlockState renderedState) { + private IModel buildModel(BlockState renderedState) { BlockRendererDispatcher dispatcher = Minecraft.getInstance() .getBlockRenderer(); return buildModel(dispatcher.getBlockModel(renderedState), renderedState); } - private BufferedModel buildModel(IBakedModel model, BlockState renderedState) { + private IModel buildModel(IBakedModel model, BlockState renderedState) { return buildModel(model, renderedState, new MatrixStack()); } - private BufferedModel buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) { - BufferBuilderReader reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms)); + private IModel buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) { - int vertexCount = reader.getVertexCount(); - - ByteBuffer vertices = ByteBuffer.allocate(vertexCount * modelFormat.getStride()); - vertices.order(ByteOrder.nativeOrder()); - - for (int i = 0; i < vertexCount; i++) { - vertices.putFloat(reader.getX(i)); - vertices.putFloat(reader.getY(i)); - vertices.putFloat(reader.getZ(i)); - - vertices.put(reader.getNX(i)); - vertices.put(reader.getNY(i)); - vertices.put(reader.getNZ(i)); - - vertices.putFloat(reader.getU(i)); - vertices.putFloat(reader.getV(i)); - } - - ((Buffer) vertices).rewind(); - - // return new BufferedModel(GlPrimitive.QUADS, format, vertices, vertexCount); - - return IndexedModel.fromSequentialQuads(modelFormat, vertices, vertexCount); + return new BlockModel(modelFormat, model, referenceState, ms); } - - // DOWN, UP, NORTH, SOUTH, WEST, EAST, null - private static final Direction[] dirs; - - static { - Direction[] directions = Direction.values(); - - dirs = Arrays.copyOf(directions, directions.length + 1); - } - - public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) { - Minecraft mc = Minecraft.getInstance(); - BlockRendererDispatcher dispatcher = mc.getBlockRenderer(); - BlockModelRenderer blockRenderer = dispatcher.getModelRenderer(); - BufferBuilder builder = new BufferBuilder(512); - - // BakedQuadWrapper quadReader = new BakedQuadWrapper(); - // - // IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE); - // List quads = Arrays.stream(dirs) - // .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream()) - // .collect(Collectors.toList()); - - builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - blockRenderer.renderModel(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); - builder.end(); - return builder; - } - } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java new file mode 100644 index 000000000..114b6d488 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java @@ -0,0 +1,101 @@ +package com.jozufozu.flywheel.core.model; + +import java.util.Arrays; + +import javax.annotation.Nullable; + +import org.lwjgl.opengl.GL11; + +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.backend.model.ElementBuffer; +import com.jozufozu.flywheel.core.QuadConverter; +import com.jozufozu.flywheel.util.BufferBuilderReader; +import com.jozufozu.flywheel.util.VirtualEmptyModelData; +import com.mojang.blaze3d.matrix.MatrixStack; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockModelRenderer; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; + +public class BlockModel implements IModel { + private static final MatrixStack IDENTITY = new MatrixStack(); + + private final BufferBuilderReader reader; + + private final VertexFormat modelFormat; + + public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState) { + this(modelFormat, model, referenceState, IDENTITY); + } + + public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState, MatrixStack ms) { + this.modelFormat = modelFormat; + reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms)); + } + + @Override + public VertexFormat format() { + return modelFormat; + } + + @Override + public int vertexCount() { + return reader.getVertexCount(); + } + + @Override + public void buffer(VecBuffer buffer) { + + int vertexCount = vertexCount(); + + for (int i = 0; i < vertexCount; i++) { + buffer.putVec3(reader.getX(i), reader.getY(i), reader.getZ(i)); + + buffer.putVec3(reader.getNX(i), reader.getNY(i), reader.getNZ(i)); + + buffer.putVec2(reader.getU(i), reader.getV(i)); + } + } + + @Override + public ElementBuffer createEBO() { + return QuadConverter.getInstance() + .quads2Tris(vertexCount() / 4); + } + + public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) { + Minecraft mc = Minecraft.getInstance(); + BlockRendererDispatcher dispatcher = mc.getBlockRenderer(); + BlockModelRenderer blockRenderer = dispatcher.getModelRenderer(); + BufferBuilder builder = new BufferBuilder(512); + + // BakedQuadWrapper quadReader = new BakedQuadWrapper(); + // + // IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE); + // List quads = Arrays.stream(dirs) + // .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream()) + // .collect(Collectors.toList()); + + builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + blockRenderer.renderModel(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); + builder.end(); + return builder; + } + + // DOWN, UP, NORTH, SOUTH, WEST, EAST, null + private static final Direction[] dirs; + + static { + Direction[] directions = Direction.values(); + + dirs = Arrays.copyOf(directions, directions.length + 1); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/IModel.java b/src/main/java/com/jozufozu/flywheel/core/model/IModel.java new file mode 100644 index 000000000..4c3e9d027 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/IModel.java @@ -0,0 +1,26 @@ +package com.jozufozu.flywheel.core.model; + +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.backend.model.ElementBuffer; + +/** + * A model that can be rendered by flywheel. + */ +public interface IModel { + + /** + * Copy this model into the given buffer. + */ + void buffer(VecBuffer buffer); + + int vertexCount(); + + VertexFormat format(); + + ElementBuffer createEBO(); + + default int size() { + return vertexCount() * format().getStride(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java index 05ec25cdf..a7534600a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java @@ -1,8 +1,53 @@ package com.jozufozu.flywheel.core.model; -public class ModelPart { +import java.util.ArrayList; +import java.util.List; + +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.backend.model.ElementBuffer; +import com.jozufozu.flywheel.core.Formats; +import com.jozufozu.flywheel.core.QuadConverter; + +public class ModelPart implements IModel { + + private final List cuboids; + private int vertices; + + public ModelPart(List cuboids) { + this.cuboids = cuboids; + + vertices = 0; + + for (PartBuilder.CuboidBuilder cuboid : cuboids) { + vertices += cuboid.vertices(); + } + } public static PartBuilder builder(int sizeU, int sizeV) { return new PartBuilder(sizeU, sizeV); } + + @Override + public void buffer(VecBuffer buffer) { + for (PartBuilder.CuboidBuilder cuboid : cuboids) { + cuboid.buffer(buffer); + } + } + + @Override + public int vertexCount() { + return vertices; + } + + @Override + public VertexFormat format() { + return Formats.UNLIT_MODEL; + } + + @Override + public ElementBuffer createEBO() { + return QuadConverter.getInstance() + .quads2Tris(vertices / 4); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java new file mode 100644 index 000000000..3039e2218 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java @@ -0,0 +1,21 @@ +package com.jozufozu.flywheel.core.model; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.backend.model.IndexedModel; + +public class ModelUtil { + public static IndexedModel getIndexedModel(IModel blockModel) { + ByteBuffer vertices = ByteBuffer.allocate(blockModel.size()); + vertices.order(ByteOrder.nativeOrder()); + + blockModel.buffer(new VecBuffer(vertices)); + + ((Buffer) vertices).rewind(); + + return new IndexedModel(blockModel.format(), vertices, blockModel.vertexCount(), blockModel.createEBO()); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java index 3c143222e..801f18729 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java @@ -6,11 +6,9 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Set; +import java.util.function.Supplier; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; -import com.jozufozu.flywheel.backend.model.BufferedModel; -import com.jozufozu.flywheel.backend.model.IndexedModel; -import com.jozufozu.flywheel.core.Formats; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.Direction; @@ -18,23 +16,16 @@ import net.minecraft.util.math.vector.Vector3f; public class PartBuilder { - private float sizeU = 64.0F; - private float sizeV = 32.0F; + private final float sizeU; + private final float sizeV; private TextureAtlasSprite sprite; private final List cuboids = new ArrayList<>(); - public PartBuilder() { } - public PartBuilder(int sizeU, int sizeV) { - this.setTextureSize(sizeU, sizeV); - } - - public PartBuilder setTextureSize(int textureWidth, int textureHeight) { - this.sizeU = (float)textureWidth; - this.sizeV = (float)textureHeight; - return this; + this.sizeU = (float) sizeU; + this.sizeV = (float) sizeV; } public PartBuilder sprite(TextureAtlasSprite sprite) { @@ -46,22 +37,8 @@ public class PartBuilder { return new CuboidBuilder(this); } - public BufferedModel build() { - int vertices = 0; - - for (CuboidBuilder cuboid : cuboids) { - vertices += cuboid.vertices(); - } - - VecBuffer buffer = VecBuffer.allocate(vertices * Formats.UNLIT_MODEL.getStride()); - - for (CuboidBuilder cuboid : cuboids) { - cuboid.buffer(buffer); - } - - buffer.rewind(); - - return IndexedModel.fromSequentialQuads(Formats.UNLIT_MODEL, buffer.unwrap(), vertices); + public ModelPart build() { + return new ModelPart(cuboids); } private PartBuilder addCuboid(CuboidBuilder builder) { diff --git a/src/main/java/com/jozufozu/flywheel/core/model/package-info.java b/src/main/java/com/jozufozu/flywheel/core/model/package-info.java new file mode 100644 index 000000000..33950a9c0 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.jozufozu.flywheel.core.model; + +import javax.annotation.ParametersAreNonnullByDefault; + +import mcp.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java index 7419c229a..1392c32d9 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java @@ -64,7 +64,7 @@ public class BellInstance extends TileEntityInstance implements .createInstance(); } - private static BufferedModel createBellModel() { + private static ModelPart createBellModel() { return ModelPart.builder(32, 32) .sprite(BellTileEntityRenderer.BELL_RESOURCE_LOCATION.sprite()) .cuboid() diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java index ebf9dc822..1c54ea07f 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java @@ -134,7 +134,7 @@ public class ChestInstance extends TileEntityI .createInstance(); } - private BufferedModel getBaseModel() { + private ModelPart getBaseModel() { switch (chestType) { case LEFT: @@ -167,7 +167,7 @@ public class ChestInstance extends TileEntityI .build(); } - private BufferedModel getLidModel() { + private ModelPart getLidModel() { switch (chestType) { case LEFT: diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java index 59b5d5a0f..94c91571a 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java @@ -101,7 +101,7 @@ public class ShulkerBoxInstance extends TileEntityInstance .createInstance(); } - private BufferedModel makeBaseModel() { + private ModelPart makeBaseModel() { return ModelPart.builder(64, 64) .sprite(texture) .cuboid() @@ -112,7 +112,7 @@ public class ShulkerBoxInstance extends TileEntityInstance .build(); } - private BufferedModel makeLidModel() { + private ModelPart makeLidModel() { return ModelPart.builder(64, 64) .sprite(texture) .cuboid()