From 86dbed66af372eca3f923ba0bc586692744c2d84 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Wed, 25 Aug 2021 12:53:43 -0700 Subject: [PATCH] Instanced Minecarts - Rotations in PartBuilder - BlockModels are always UNLIT_MODEL format --- .../backend/material/InstanceMaterial.java | 7 +- .../flywheel/core/model/BlockModel.java | 18 +- .../flywheel/core/model/PartBuilder.java | 97 +++++++++-- .../flywheel/vanilla/MinecartInstance.java | 155 ++++++++++++++++++ .../flywheel/vanilla/VanillaInstances.java | 11 ++ 5 files changed, 255 insertions(+), 33 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java 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 6ef2f9ba0..5576d3fb2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/material/InstanceMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/material/InstanceMaterial.java @@ -4,7 +4,6 @@ import java.util.function.Supplier; import com.jozufozu.flywheel.backend.instancing.InstanceData; import com.jozufozu.flywheel.backend.instancing.Instancer; -import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.core.model.BlockModel; import com.jozufozu.flywheel.core.model.IModel; @@ -26,7 +25,7 @@ public interface InstanceMaterial { Instancer model(Object key, Supplier modelSupplier); default Instancer getModel(PartialModel partial, BlockState referenceState) { - return model(partial, () -> new BlockModel(Formats.UNLIT_MODEL, partial.get(), referenceState)); + return model(partial, () -> new BlockModel(partial.get(), referenceState)); } default Instancer getModel(PartialModel partial, BlockState referenceState, Direction dir) { @@ -34,10 +33,10 @@ public interface InstanceMaterial { } default Instancer getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier modelTransform) { - return model(Pair.of(dir, partial), () -> new BlockModel(Formats.UNLIT_MODEL, partial.get(), referenceState, modelTransform.get())); + return model(Pair.of(dir, partial), () -> new BlockModel(partial.get(), referenceState, modelTransform.get())); } default Instancer getModel(BlockState toRender) { - return model(toRender, () -> new BlockModel(Formats.UNLIT_MODEL, toRender)); + return model(toRender, () -> new BlockModel(toRender)); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java index 8ddb4aed2..e582ac228 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java @@ -6,8 +6,7 @@ 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.core.Formats; import com.jozufozu.flywheel.util.BufferBuilderReader; import com.jozufozu.flywheel.util.VirtualEmptyModelData; import com.mojang.blaze3d.matrix.MatrixStack; @@ -31,26 +30,23 @@ public class BlockModel implements IModel { private final BufferBuilderReader reader; - private final VertexFormat modelFormat; - - public BlockModel(VertexFormat modelFormat, BlockState state) { - this(modelFormat, Minecraft.getInstance() + public BlockModel(BlockState state) { + this(Minecraft.getInstance() .getBlockRenderer() .getBlockModel(state), state); } - public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState) { - this(modelFormat, model, referenceState, IDENTITY); + public BlockModel(IBakedModel model, BlockState referenceState) { + this(model, referenceState, IDENTITY); } - public BlockModel(VertexFormat modelFormat, IBakedModel model, BlockState referenceState, MatrixStack ms) { - this.modelFormat = modelFormat; + public BlockModel(IBakedModel model, BlockState referenceState, MatrixStack ms) { reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms)); } @Override public VertexFormat format() { - return modelFormat; + return Formats.UNLIT_MODEL; } @Override 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 f7a4bfe8e..74759a800 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/PartBuilder.java @@ -11,6 +11,8 @@ import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.Direction; +import net.minecraft.util.math.vector.Matrix3f; +import net.minecraft.util.math.vector.Quaternion; import net.minecraft.util.math.vector.Vector3f; public class PartBuilder { @@ -62,6 +64,11 @@ public class PartBuilder { boolean invertYZ; + boolean useRotation; + float rotationX; + float rotationY; + float rotationZ; + final PartBuilder partBuilder; CuboidBuilder(PartBuilder partBuilder) { @@ -96,6 +103,36 @@ public class PartBuilder { return this; } + public CuboidBuilder shift(float x, float y, float z) { + posX1 = posX1 - x; + posY1 = posY1 - y; + posZ1 = posZ1 - z; + posX2 = posX2 - x; + posY2 = posY2 - y; + posZ2 = posZ2 - z; + return this; + } + + public CuboidBuilder rotate(float x, float y, float z) { + useRotation = true; + this.rotationX = x; + this.rotationY = y; + this.rotationZ = z; + return this; + } + + public CuboidBuilder rotateX(float x) { + useRotation = true; + this.rotationX = x; + return this; + } + + public CuboidBuilder rotateY(float y) { + useRotation = true; + this.rotationY = y; + return this; + } + public CuboidBuilder sprite(TextureAtlasSprite sprite) { this.sprite = sprite; return this; @@ -130,6 +167,7 @@ public class PartBuilder { float posY2 = this.posY2 / 16f; float posZ2 = this.posZ2 / 16f; + Vector3f lll = new Vector3f(posX1, posY1, posZ1); Vector3f hll = new Vector3f(posX2, posY1, posZ1); Vector3f hhl = new Vector3f(posX2, posY2, posZ1); @@ -138,6 +176,32 @@ public class PartBuilder { Vector3f hlh = new Vector3f(posX2, posY1, posZ2); Vector3f hhh = new Vector3f(posX2, posY2, posZ2); Vector3f lhh = new Vector3f(posX1, posY2, posZ2); + + Vector3f down = Direction.DOWN.step(); + Vector3f up = Direction.UP.step(); + Vector3f west = Direction.WEST.step(); + Vector3f north = Direction.NORTH.step(); + Vector3f east = Direction.EAST.step(); + Vector3f south = Direction.SOUTH.step(); + + if (useRotation) { + Matrix3f matrix3f = new Matrix3f(new Quaternion(rotationX, rotationY, rotationZ, false)); + lll.transform(matrix3f); + hll.transform(matrix3f); + hhl.transform(matrix3f); + lhl.transform(matrix3f); + llh.transform(matrix3f); + hlh.transform(matrix3f); + hhh.transform(matrix3f); + lhh.transform(matrix3f); + down.transform(matrix3f); + up.transform(matrix3f); + west.transform(matrix3f); + north.transform(matrix3f); + east.transform(matrix3f); + south.transform(matrix3f); + } + float f4 = getU((float)textureOffsetU); float f5 = getU((float)textureOffsetU + sizeZ); float f6 = getU((float)textureOffsetU + sizeZ + sizeX); @@ -149,27 +213,24 @@ public class PartBuilder { float f12 = getV((float)textureOffsetV + sizeZ + sizeY); if (invertYZ) { - quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, Direction.DOWN); - quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, Direction.UP); - quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, Direction.WEST); - quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, Direction.NORTH); - quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, Direction.EAST); - quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, Direction.SOUTH); + quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, down); + quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, up); + quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, west); + quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, north); + quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, east); + quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, south); } else { - quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, Direction.DOWN); - quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, Direction.UP); - quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, Direction.WEST); - quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, Direction.NORTH); - quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, Direction.EAST); - quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, Direction.SOUTH); + quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, down); + quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, up); + quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, west); + quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, north); + quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, east); + quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, south); } } - public void quad(VecBuffer buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Direction dir) { - - Vector3f normal = dir.step(); - + public void quad(VecBuffer buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) { buffer.putVec3(vertices[0].x(), vertices[0].y(), vertices[0].z()).putVec3(nb(normal.x()), nb(normal.y()), nb(normal.z())).putVec2(maxU, minV); buffer.putVec3(vertices[1].x(), vertices[1].y(), vertices[1].z()).putVec3(nb(normal.x()), nb(normal.y()), nb(normal.z())).putVec2(minU, minV); buffer.putVec3(vertices[2].x(), vertices[2].y(), vertices[2].z()).putVec3(nb(normal.x()), nb(normal.y()), nb(normal.z())).putVec2(minU, maxV); @@ -181,14 +242,14 @@ public class PartBuilder { if (sprite != null) return sprite.getU(u * 16 / partBuilder.sizeU); else - return u; + return u / partBuilder.sizeU; } public float getV(float v) { if (sprite != null) return sprite.getV(v * 16 / partBuilder.sizeV); else - return v; + return v / partBuilder.sizeV; } } diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java new file mode 100644 index 000000000..28d922fcd --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java @@ -0,0 +1,155 @@ +package com.jozufozu.flywheel.vanilla; + +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.backend.model.ModelPool; +import com.jozufozu.flywheel.backend.state.TextureRenderState; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.core.model.BlockModel; +import com.jozufozu.flywheel.core.model.IModel; +import com.jozufozu.flywheel.core.model.ModelPart; +import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; + +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.entity.item.minecart.AbstractMinecartEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.math.vector.Vector3f; + +public class MinecartInstance extends EntityInstance implements IDynamicInstance { + + private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png"); + + MatrixTransformStack stack = new MatrixTransformStack(); + + private final ModelData body; + private final ModelData contents; + + public MinecartInstance(MaterialManager materialManager, T entity) { + super(materialManager, entity); + + contents = getContents(); + body = getBody(); + } + + @Override + public void beginFrame() { + stack.setIdentity(); + float pt = AnimationTickHolder.getPartialTicks(); + + stack.translate( + MathHelper.lerp(pt, entity.xOld, entity.getX()), + MathHelper.lerp(pt, entity.yOld, entity.getY()), + MathHelper.lerp(pt, entity.zOld, entity.getZ()) + ); + + + float yaw = MathHelper.lerp(pt, entity.yRotO, entity.yRot); + + long i = (long)entity.getId() * 493286711L; + i = i * i * 4392167121L + i * 98761L; + float f = (((float)(i >> 16 & 7L) + 0.5F) / 8 - 0.5F) * 0.004F; + float f1 = (((float)(i >> 20 & 7L) + 0.5F) / 8 - 0.5F) * 0.004F; + float f2 = (((float)(i >> 24 & 7L) + 0.5F) / 8 - 0.5F) * 0.004F; + stack.translate(f, f1, f2); + stack.nudge(entity.getId()); + double d0 = MathHelper.lerp(pt, entity.xOld, entity.getX()); + double d1 = MathHelper.lerp(pt, entity.yOld, entity.getY()); + double d2 = MathHelper.lerp(pt, entity.zOld, entity.getZ()); + Vector3d vector3d = entity.getPos(d0, d1, d2); + float f3 = MathHelper.lerp(pt, entity.xRotO, entity.xRot); + if (vector3d != null) { + Vector3d vector3d1 = entity.getPosOffs(d0, d1, d2, 0.3F); + Vector3d vector3d2 = entity.getPosOffs(d0, d1, d2, -0.3F); + if (vector3d1 == null) { + vector3d1 = vector3d; + } + + if (vector3d2 == null) { + vector3d2 = vector3d; + } + + stack.translate(vector3d.x - d0, (vector3d1.y + vector3d2.y) / 2.0D - d1, vector3d.z - d2); + Vector3d vector3d3 = vector3d2.add(-vector3d1.x, -vector3d1.y, -vector3d1.z); + if (vector3d3.length() != 0.0D) { + vector3d3 = vector3d3.normalize(); + yaw = (float)(Math.atan2(vector3d3.z, vector3d3.x) * 180.0D / Math.PI); + f3 = (float)(Math.atan(vector3d3.y) * 73.0D); + } + } + + stack.translate(0.0D, 0.375D, 0.0D); + stack.multiply(Vector3f.YP.rotationDegrees(180 - yaw)); + stack.multiply(Vector3f.ZP.rotationDegrees(-f3)); + float f5 = (float)entity.getHurtTime() - pt; + float f6 = entity.getDamage() - pt; + if (f6 < 0) { + f6 = 0; + } + + if (f5 > 0) { + stack.multiply(Vector3f.XP.rotationDegrees(MathHelper.sin(f5) * f5 * f6 / 10 * (float)entity.getHurtDir())); + } + + int j = entity.getDisplayOffset(); + if (contents != null) { + stack.push(); + stack.scale(0.75F); + stack.translate(-0.5D, (float)(j - 8) / 16, 0.5D); + stack.multiply(Vector3f.YP.rotationDegrees(90)); + contents.setTransform(stack.unwrap()); + stack.pop(); + } + + body.setTransform(stack.unwrap()); + } + + @Override + public void updateLight() { + if (contents == null) + relight(getWorldPosition(), body); + else + relight(getWorldPosition(), body, contents); + } + + @Override + public void remove() { + body.delete(); + if (contents != null) contents.delete(); + } + + private ModelData getContents() { + BlockState blockstate = entity.getDisplayBlockState(); + + if (blockstate.getRenderShape() == BlockRenderType.INVISIBLE) + return null; + + return materialManager.defaultSolid() + .material(Materials.TRANSFORMED) + .getModel(blockstate) + .createInstance(); + } + + private ModelData getBody() { + return materialManager.solid(TextureRenderState.get(MINECART_LOCATION)) + .material(Materials.TRANSFORMED) + .model(entity.getType(), this::getBodyModel) + .createInstance(); + } + + private IModel getBodyModel() { + int y = -3; + return ModelPart.builder(64, 32) + .cuboid().invertYZ().start(-10, -8, -y).size(20, 16, 2).textureOffset(0, 10).rotateX(((float)Math.PI / 2F)).endCuboid() + .cuboid().invertYZ().start(-8, y, -10).size(16, 8, 2).rotateY(((float)Math.PI * 1.5F)).endCuboid() + .cuboid().invertYZ().start(-8, y, -10).size(16, 8, 2).rotateY(((float)Math.PI / 2F)).endCuboid() + .cuboid().invertYZ().start(-8, y, -8).size(16, 8, 2).rotateY((float)Math.PI).endCuboid() + .cuboid().invertYZ().start(-8, y, -8).size(16, 8, 2).endCuboid() + .build(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java b/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java index bd8c84d21..99ec95d9f 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java @@ -2,6 +2,7 @@ package com.jozufozu.flywheel.vanilla; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import net.minecraft.entity.EntityType; import net.minecraft.tileentity.TileEntityType; /** @@ -46,5 +47,15 @@ public class VanillaInstances { r.tile(TileEntityType.SHULKER_BOX) .setSkipRender(true) .factory(ShulkerBoxInstance::new); + + r.entity(EntityType.MINECART) + .setSkipRender(true) + .factory(MinecartInstance::new); + r.entity(EntityType.HOPPER_MINECART) + .setSkipRender(true) + .factory(MinecartInstance::new); + r.entity(EntityType.FURNACE_MINECART) + .setSkipRender(true) + .factory(MinecartInstance::new); } }