diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/FrameUniforms.java b/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/FrameUniforms.java index 3ed227033..5c65dd3f4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/FrameUniforms.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/uniform/FrameUniforms.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.backend.engine.uniform; +import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.lwjgl.system.MemoryUtil; @@ -7,16 +8,19 @@ import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.visualization.VisualizationManager; import com.jozufozu.flywheel.lib.math.MatrixMath; +import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.core.Vec3i; import net.minecraft.world.phys.Vec3; public class FrameUniforms implements UniformProvider { - public static final int SIZE = 232; + public static final int SIZE = 304; + @Nullable private RenderContext context; private final Matrix4f viewProjection = new Matrix4f(); + private final Matrix4f viewProjectionInverse = new Matrix4f(); public int byteSize() { return SIZE; @@ -28,6 +32,10 @@ public class FrameUniforms implements UniformProvider { @Override public void write(long ptr) { + if (context == null) { + return; + } + Vec3i renderOrigin = VisualizationManager.getOrThrow(context.level()) .getRenderOrigin(); var camera = context.camera(); @@ -45,27 +53,43 @@ public class FrameUniforms implements UniformProvider { Uniforms.frustumCapture = false; } - MatrixMath.writeUnsafe(viewProjection, ptr + 96); - writeVec3(ptr + 160, camX, camY, camZ); + ptr += 96; - var lookVector = camera.getLookVector(); - writeVec3(ptr + 176, lookVector.x, lookVector.y, lookVector.z); + ptr = writeMatrices(ptr); + + ptr = writeCamera(ptr, camX, camY, camZ, camera); - writeVec2(ptr + 192, camera.getXRot(), camera.getYRot()); var window = Minecraft.getInstance() .getWindow(); - - writeVec2(ptr + 200, window.getWidth(), window.getHeight()); + ptr = writeVec2(ptr, window.getWidth(), window.getHeight()); // default line width: net.minecraft.client.renderer.RenderStateShard.LineStateShard - MemoryUtil.memPutFloat(ptr + 208, Math.max(2.5F, (float) window.getWidth() / 1920.0F * 2.5F)); + MemoryUtil.memPutFloat(ptr, Math.max(2.5F, (float) window.getWidth() / 1920.0F * 2.5F)); + ptr += 4; - MemoryUtil.memPutInt(ptr + 212, getConstantAmbientLightFlag(context)); + MemoryUtil.memPutInt(ptr, getConstantAmbientLightFlag(context)); + ptr += 4; - writeTime(ptr + 216); + writeTime(ptr); } - private void writeTime(long ptr) { + private long writeMatrices(long ptr) { + MatrixMath.writeUnsafe(viewProjection, ptr); + MatrixMath.writeUnsafe(viewProjection.invert(viewProjectionInverse), ptr + 64); + return ptr + 128; + } + + private static long writeCamera(long ptr, float camX, float camY, float camZ, Camera camera) { + ptr = writeVec3(ptr, camX, camY, camZ); + + var lookVector = camera.getLookVector(); + ptr = writeVec3(ptr, lookVector.x, lookVector.y, lookVector.z); + + ptr = writeVec2(ptr, camera.getXRot(), camera.getYRot()); + return ptr; + } + + private long writeTime(long ptr) { int ticks = context.renderer() .getTicks(); float partialTick = context.partialTick(); @@ -76,18 +100,21 @@ public class FrameUniforms implements UniformProvider { MemoryUtil.memPutFloat(ptr + 4, partialTick); MemoryUtil.memPutFloat(ptr + 8, renderTicks); MemoryUtil.memPutFloat(ptr + 12, renderSeconds); + return ptr + 16; } - private static void writeVec3(long ptr, float camX, float camY, float camZ) { + private static long writeVec3(long ptr, float camX, float camY, float camZ) { MemoryUtil.memPutFloat(ptr, camX); MemoryUtil.memPutFloat(ptr + 4, camY); MemoryUtil.memPutFloat(ptr + 8, camZ); MemoryUtil.memPutFloat(ptr + 12, 0f); // empty component of vec4 because we don't trust std140 + return ptr + 16; } - private static void writeVec2(long ptr, float camX, float camY) { + private static long writeVec2(long ptr, float camX, float camY) { MemoryUtil.memPutFloat(ptr, camX); MemoryUtil.memPutFloat(ptr + 4, camY); + return ptr + 8; } private static int getConstantAmbientLightFlag(RenderContext context) { diff --git a/src/main/java/com/jozufozu/flywheel/lib/material/StandardMaterialShaders.java b/src/main/java/com/jozufozu/flywheel/lib/material/StandardMaterialShaders.java index a8a8aa3b0..bfea555bd 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/material/StandardMaterialShaders.java +++ b/src/main/java/com/jozufozu/flywheel/lib/material/StandardMaterialShaders.java @@ -12,7 +12,7 @@ public final class StandardMaterialShaders { public static final MaterialShaders WIREFRAME = MaterialShaders.REGISTRY.registerAndGet(new SimpleMaterialShaders(Flywheel.rl("material/wireframe.vert"), Flywheel.rl("material/wireframe.frag"))); - public static final MaterialShaders CENTERLINE = MaterialShaders.REGISTRY.registerAndGet(new SimpleMaterialShaders(Flywheel.rl("material/centerline.vert"), Flywheel.rl("material/centerline.frag"))); + public static final MaterialShaders LINE = MaterialShaders.REGISTRY.registerAndGet(new SimpleMaterialShaders(Flywheel.rl("material/lines.vert"), Flywheel.rl("material/lines.frag"))); private StandardMaterialShaders() { } diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/LineModelBuilder.java b/src/main/java/com/jozufozu/flywheel/lib/model/LineModelBuilder.java new file mode 100644 index 000000000..85f0bdd74 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/model/LineModelBuilder.java @@ -0,0 +1,159 @@ +package com.jozufozu.flywheel.lib.model; + +import org.joml.Vector4f; +import org.joml.Vector4fc; +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.api.model.IndexSequence; +import com.jozufozu.flywheel.api.model.Mesh; +import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.vertex.MutableVertexList; +import com.jozufozu.flywheel.api.vertex.VertexView; +import com.jozufozu.flywheel.lib.material.SimpleMaterial; +import com.jozufozu.flywheel.lib.material.StandardMaterialShaders; +import com.jozufozu.flywheel.lib.memory.MemoryBlock; +import com.jozufozu.flywheel.lib.vertex.FullVertexView; + +import net.minecraft.client.renderer.LightTexture; + +public class LineModelBuilder { + public static final Material MATERIAL = SimpleMaterial.builder() + .shaders(StandardMaterialShaders.LINE) + .backfaceCulling(false) + .diffuse(false) + .build(); + + private final VertexView vertices; + private MemoryBlock block; + private int vertexCount = 0; + + private LineModelBuilder(int segmentCount) { + this.vertices = new FullVertexView(); + this.block = MemoryBlock.malloc(segmentCount * 4 * FullVertexView.STRIDE); + vertices.ptr(block.ptr()); + } + + public static LineModelBuilder withCapacity(int segmentCount) { + return new LineModelBuilder(segmentCount); + } + + public LineModelBuilder line(float x1, float y1, float z1, float x2, float y2, float z2) { + ensureCapacity(vertexCount + 4); + + // We'll use the normal to figure out the orientation of the line in the vertex shader. + float dx = x2 - x1; + float dy = y2 - y1; + float dz = z2 - z1; + float length = (float) Math.sqrt(dx * dx + dy * dy + dz * dz); + float normalX = dx / length; + float normalY = dy / length; + float normalZ = dz / length; + + for (int i = 0; i < 2; i++) { + vertices.x(vertexCount + i, x1); + vertices.y(vertexCount + i, y1); + vertices.z(vertexCount + i, z1); + + vertices.x(vertexCount + 2 + i, x2); + vertices.y(vertexCount + 2 + i, y2); + vertices.z(vertexCount + 2 + i, z2); + } + + for (int i = 0; i < 4; i++) { + vertices.r(vertexCount + i, 1); + vertices.g(vertexCount + i, 1); + vertices.b(vertexCount + i, 1); + vertices.a(vertexCount + i, 1); + vertices.u(vertexCount + i, 0); + vertices.v(vertexCount + i, 0); + vertices.light(vertexCount + i, LightTexture.FULL_BRIGHT); + vertices.normalX(vertexCount + i, normalX); + vertices.normalY(vertexCount + i, normalY); + vertices.normalZ(vertexCount + i, normalZ); + } + + vertexCount += 4; + + return this; + } + + public Model build() { + vertices.vertexCount(vertexCount); + + var boundingSphere = ModelUtil.computeBoundingSphere(vertices); + boundingSphere.w += 0.1f; // make the bounding sphere a little bigger to account for line width + + var mesh = new LineMesh(vertexCount, vertices, block, boundingSphere); + + return new SingleMeshModel(mesh, MATERIAL); + } + + private void ensureCapacity(int vertexCount) { + if (vertexCount * FullVertexView.STRIDE > block.size()) { + this.block = block.realloc(vertexCount * FullVertexView.STRIDE); + vertices.ptr(block.ptr()); + } + } + + public static class LineMesh implements Mesh { + public static final IndexSequence INDEX_SEQUENCE = (ptr, count) -> { + int numVertices = 4 * (count / 6); + int baseVertex = 0; + while (baseVertex < numVertices) { + // triangle a + MemoryUtil.memPutInt(ptr, baseVertex); + MemoryUtil.memPutInt(ptr + 4, baseVertex + 1); + MemoryUtil.memPutInt(ptr + 8, baseVertex + 2); + // triangle b + MemoryUtil.memPutInt(ptr + 12, baseVertex + 3); + MemoryUtil.memPutInt(ptr + 16, baseVertex + 2); + MemoryUtil.memPutInt(ptr + 20, baseVertex + 1); + + baseVertex += 4; + ptr += 24; + } + }; + private final int vertexCount; + private final VertexView vertexView; + private final MemoryBlock data; + private final Vector4f boundingSphere; + + public LineMesh(int vertexCount, VertexView vertexView, MemoryBlock data, Vector4f boundingSphere) { + this.vertexCount = vertexCount; + this.vertexView = vertexView; + this.data = data; + this.boundingSphere = boundingSphere; + } + + @Override + public int vertexCount() { + return vertexCount; + } + + @Override + public void write(MutableVertexList vertexList) { + vertexView.writeAll(vertexList); + } + + @Override + public IndexSequence indexSequence() { + return INDEX_SEQUENCE; + } + + @Override + public int indexCount() { + return vertexCount / 2 * 3; + } + + @Override + public Vector4fc boundingSphere() { + return boundingSphere; + } + + @Override + public void delete() { + data.free(); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/components/BoundingBoxComponent.java b/src/main/java/com/jozufozu/flywheel/lib/visual/components/BoundingBoxComponent.java deleted file mode 100644 index 789deb3b2..000000000 --- a/src/main/java/com/jozufozu/flywheel/lib/visual/components/BoundingBoxComponent.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.jozufozu.flywheel.lib.visual.components; - -import org.joml.Quaternionf; -import org.joml.Vector4f; -import org.joml.Vector4fc; - -import com.jozufozu.flywheel.api.material.Material; -import com.jozufozu.flywheel.api.model.Model; -import com.jozufozu.flywheel.api.vertex.MutableVertexList; -import com.jozufozu.flywheel.api.visual.VisualFrameContext; -import com.jozufozu.flywheel.api.visualization.VisualizationContext; -import com.jozufozu.flywheel.lib.instance.InstanceTypes; -import com.jozufozu.flywheel.lib.instance.TransformedInstance; -import com.jozufozu.flywheel.lib.material.SimpleMaterial; -import com.jozufozu.flywheel.lib.material.StandardMaterialShaders; -import com.jozufozu.flywheel.lib.math.MoreMath; -import com.jozufozu.flywheel.lib.model.QuadMesh; -import com.jozufozu.flywheel.lib.model.SingleMeshModel; -import com.jozufozu.flywheel.lib.visual.EntityComponent; -import com.jozufozu.flywheel.lib.visual.SmartRecycler; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; - -public class BoundingBoxComponent implements EntityComponent { - private static final Material WIREFRAME = SimpleMaterial.builder() - .shaders(StandardMaterialShaders.WIREFRAME) - .backfaceCulling(false) - .build(); - - private static final Material CENTERLINE = SimpleMaterial.builder() - .shaders(StandardMaterialShaders.CENTERLINE) - .backfaceCulling(false) - .build(); - private static final Model BOX = new SingleMeshModel(BoundingBoxMesh.INSTANCE, WIREFRAME); - - // Should we try a single quad oriented to face the camera instead? - private static final Model LINE = new SingleMeshModel(BoundingBoxMesh.INSTANCE, CENTERLINE); - - private final VisualizationContext context; - private final Entity entity; - - private boolean showEyeBox; - - private final SmartRecycler recycler; - - public BoundingBoxComponent(VisualizationContext context, Entity entity) { - this.context = context; - this.entity = entity; - this.showEyeBox = entity instanceof LivingEntity; - - this.recycler = new SmartRecycler<>(this::createInstance); - } - - private TransformedInstance createInstance(Model model) { - TransformedInstance instance = context.instancerProvider() - .instancer(InstanceTypes.TRANSFORMED, model) - .createInstance(); - instance.setBlockLight(LightTexture.block(LightTexture.FULL_BLOCK)); - instance.setChanged(); - return instance; - } - - public BoundingBoxComponent showEyeBox(boolean renderEyeBox) { - this.showEyeBox = renderEyeBox; - return this; - } - - @Override - public void beginFrame(VisualFrameContext context) { - recycler.resetCount(); - - var shouldRenderHitBoxes = Minecraft.getInstance() - .getEntityRenderDispatcher() - .shouldRenderHitBoxes(); - if (shouldRenderHitBoxes && !entity.isInvisible() && !Minecraft.getInstance() - .showOnlyReducedInfo()) { - double entityX = Mth.lerp(context.partialTick(), entity.xOld, entity.getX()); - double entityY = Mth.lerp(context.partialTick(), entity.yOld, entity.getY()); - double entityZ = Mth.lerp(context.partialTick(), entity.zOld, entity.getZ()); - - var bbWidth = entity.getBbWidth(); - var bbHeight = entity.getBbHeight(); - var bbWidthHalf = bbWidth * 0.5; - recycler.get(BOX) - .loadIdentity() - .translate(entityX - bbWidthHalf, entityY, entityZ - bbWidthHalf) - .scale(bbWidth, bbHeight, bbWidth) - .setChanged(); - - // TODO: multipart entities, but forge seems to have an - // injection for them so we'll need platform specific code. - - if (showEyeBox) { - recycler.get(BOX) - .loadIdentity() - .translate(entityX - bbWidthHalf, entityY + entity.getEyeHeight() - 0.01, entityZ - bbWidthHalf) - .scale(bbWidth, 0.02f, bbWidth) - .setColor(255, 0, 0) - .setChanged(); - } - - var viewVector = entity.getViewVector(context.partialTick()); - - recycler.get(LINE) - .loadIdentity() - .translate(entityX, entityY + entity.getEyeHeight(), entityZ) - .rotate(new Quaternionf().rotateTo(0, 1, 0, (float) viewVector.x, (float) viewVector.y, (float) viewVector.z)) - .scale(0.02f, 2f, 0.02f) - .setColor(0, 0, 255) - .setChanged(); - } - - recycler.discardExtra(); - } - - @Override - public void delete() { - recycler.delete(); - } - - private static class BoundingBoxMesh implements QuadMesh { - private static final BoundingBoxMesh INSTANCE = new BoundingBoxMesh(); - private static final Vector4fc BOUNDING_SPHERE = new Vector4f(0.5f, 0.5f, 0.5f, MoreMath.SQRT_3_OVER_2); - - private BoundingBoxMesh() { - } - - @Override - public int vertexCount() { - return 24; - } - - @Override - public void write(MutableVertexList vertexList) { - // very cursed, maybe we should use vanilla ModelParts instead? - writeVertex(vertexList, 0, 0, 0, 0, 0, 0); - writeVertex(vertexList, 1, 1, 0, 0, 1, 0); - writeVertex(vertexList, 2, 1, 1, 0, 1, 1); - writeVertex(vertexList, 3, 0, 1, 0, 0, 1); - - writeVertex(vertexList, 4, 0, 0, 1, 0, 0); - writeVertex(vertexList, 5, 0, 0, 0, 1, 0); - writeVertex(vertexList, 6, 0, 1, 0, 1, 1); - writeVertex(vertexList, 7, 0, 1, 1, 0, 1); - - writeVertex(vertexList, 8, 0, 1, 0, 0, 0); - writeVertex(vertexList, 9, 1, 1, 0, 1, 0); - writeVertex(vertexList, 10, 1, 1, 1, 1, 1); - writeVertex(vertexList, 11, 0, 1, 1, 0, 1); - - writeVertex(vertexList, 12, 1, 0, 1, 0, 0); - writeVertex(vertexList, 13, 0, 0, 1, 1, 0); - writeVertex(vertexList, 14, 0, 1, 1, 1, 1); - writeVertex(vertexList, 15, 1, 1, 1, 0, 1); - - writeVertex(vertexList, 16, 1, 0, 0, 0, 0); - writeVertex(vertexList, 17, 1, 0, 1, 1, 0); - writeVertex(vertexList, 18, 1, 1, 1, 1, 1); - writeVertex(vertexList, 19, 1, 1, 0, 0, 1); - - writeVertex(vertexList, 20, 0, 0, 0, 0, 0); - writeVertex(vertexList, 21, 1, 0, 0, 1, 0); - writeVertex(vertexList, 22, 1, 0, 1, 1, 1); - writeVertex(vertexList, 23, 0, 0, 1, 0, 1); - } - - @Override - public Vector4fc boundingSphere() { - return BOUNDING_SPHERE; - } - - @Override - public void delete() { - } - - private static void writeVertex(MutableVertexList vertexList, int i, float x, float y, float z, float u, float v) { - vertexList.x(i, x); - vertexList.y(i, y); - vertexList.z(i, z); - vertexList.r(i, 1); - vertexList.g(i, 1); - vertexList.b(i, 1); - vertexList.u(i, u); - vertexList.v(i, v); - vertexList.light(i, LightTexture.FULL_BRIGHT); - vertexList.normalX(i, 0); - vertexList.normalY(i, 1); - vertexList.normalZ(i, 0); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/components/HitboxComponent.java b/src/main/java/com/jozufozu/flywheel/lib/visual/components/HitboxComponent.java new file mode 100644 index 000000000..455f0c75a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/visual/components/HitboxComponent.java @@ -0,0 +1,134 @@ +package com.jozufozu.flywheel.lib.visual.components; + +import org.joml.Quaternionf; + +import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.visual.VisualFrameContext; +import com.jozufozu.flywheel.api.visualization.VisualizationContext; +import com.jozufozu.flywheel.lib.instance.InstanceTypes; +import com.jozufozu.flywheel.lib.instance.TransformedInstance; +import com.jozufozu.flywheel.lib.model.LineModelBuilder; +import com.jozufozu.flywheel.lib.model.ModelHolder; +import com.jozufozu.flywheel.lib.visual.EntityComponent; +import com.jozufozu.flywheel.lib.visual.SmartRecycler; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; + +public class HitboxComponent implements EntityComponent { + // 010------110 + // /| /| + // / | / | + // 011------111 | + // | | | | + // | 000----|-100 + // | / | / + // |/ |/ + // 001------101 + private static final ModelHolder BOX = new ModelHolder(() -> LineModelBuilder.withCapacity(12) + // Starting from 0, 0, 0 + .line(0, 0, 0, 0, 0, 1) + .line(0, 0, 0, 0, 1, 0) + .line(0, 0, 0, 1, 0, 0) + // Starting from 0, 1, 1 + .line(0, 1, 1, 0, 1, 0) + .line(0, 1, 1, 0, 0, 1) + .line(0, 1, 1, 1, 1, 1) + // Starting from 1, 0, 1 + .line(1, 0, 1, 1, 0, 0) + .line(1, 0, 1, 1, 1, 1) + .line(1, 0, 1, 0, 0, 1) + // Starting from 1, 1, 0 + .line(1, 1, 0, 1, 1, 1) + .line(1, 1, 0, 1, 0, 0) + .line(1, 1, 0, 0, 1, 0) + .build()); + + private static final ModelHolder LINE = new ModelHolder(() -> LineModelBuilder.withCapacity(1) + .line(0, 0, 0, 0, 2, 0) + .build()); + + private final VisualizationContext context; + private final Entity entity; + + private boolean showEyeBox; + + private final SmartRecycler recycler; + + public HitboxComponent(VisualizationContext context, Entity entity) { + this.context = context; + this.entity = entity; + this.showEyeBox = entity instanceof LivingEntity; + + this.recycler = new SmartRecycler<>(this::createInstance); + } + + private TransformedInstance createInstance(Model model) { + TransformedInstance instance = context.instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, model) + .createInstance(); + instance.setBlockLight(LightTexture.block(LightTexture.FULL_BLOCK)); + instance.setChanged(); + return instance; + } + + public HitboxComponent showEyeBox(boolean renderEyeBox) { + this.showEyeBox = renderEyeBox; + return this; + } + + @Override + public void beginFrame(VisualFrameContext context) { + recycler.resetCount(); + + var shouldRenderHitBoxes = Minecraft.getInstance() + .getEntityRenderDispatcher() + .shouldRenderHitBoxes(); + if (shouldRenderHitBoxes && !entity.isInvisible() && !Minecraft.getInstance() + .showOnlyReducedInfo()) { + double entityX = Mth.lerp(context.partialTick(), entity.xOld, entity.getX()); + double entityY = Mth.lerp(context.partialTick(), entity.yOld, entity.getY()); + double entityZ = Mth.lerp(context.partialTick(), entity.zOld, entity.getZ()); + + var bbWidth = entity.getBbWidth(); + var bbHeight = entity.getBbHeight(); + var bbWidthHalf = bbWidth * 0.5; + recycler.get(BOX.get()) + .loadIdentity() + .translate(entityX - bbWidthHalf, entityY, entityZ - bbWidthHalf) + .scale(bbWidth, bbHeight, bbWidth) + .setChanged(); + + // TODO: multipart entities, but forge seems to have an + // injection for them so we'll need platform specific code. + + if (showEyeBox) { + recycler.get(BOX.get()) + .loadIdentity() + .translate(entityX - bbWidthHalf, entityY + entity.getEyeHeight() - 0.01, entityZ - bbWidthHalf) + .scale(bbWidth, 0.02f, bbWidth) + .setColor(255, 0, 0) + .setChanged(); + } + + var viewVector = entity.getViewVector(context.partialTick()); + + recycler.get(LINE.get()) + .loadIdentity() + .translate(entityX, entityY + entity.getEyeHeight(), entityZ) + .rotate(new Quaternionf().rotateTo(0, 1, 0, (float) viewVector.x, (float) viewVector.y, (float) viewVector.z)) + .setColor(0, 0, 255) + .setChanged(); + } + + recycler.discardExtra(); + } + + @Override + public void delete() { + recycler.delete(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java index 5b3a64c95..28e02ede4 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java @@ -15,8 +15,8 @@ import com.jozufozu.flywheel.lib.model.Models; import com.jozufozu.flywheel.lib.model.SingleMeshModel; import com.jozufozu.flywheel.lib.model.part.ModelPartConverter; import com.jozufozu.flywheel.lib.visual.SimpleEntityVisual; -import com.jozufozu.flywheel.lib.visual.components.BoundingBoxComponent; import com.jozufozu.flywheel.lib.visual.components.FireComponent; +import com.jozufozu.flywheel.lib.visual.components.HitboxComponent; import com.jozufozu.flywheel.lib.visual.components.ShadowComponent; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; @@ -63,7 +63,7 @@ public class MinecartVisual extends SimpleEntityVisu public void init(float partialTick) { addComponent(new ShadowComponent(visualizationContext, entity).radius(0.7f)); addComponent(new FireComponent(visualizationContext, entity)); - addComponent(new BoundingBoxComponent(visualizationContext, entity)); + addComponent(new HitboxComponent(visualizationContext, entity)); body = createBodyInstance(); blockState = entity.getDisplayBlockState(); @@ -210,6 +210,7 @@ public class MinecartVisual extends SimpleEntityVisu @Override protected void _delete() { + super._delete(); body.delete(); if (contents != null) { contents.delete(); diff --git a/src/main/resources/assets/flywheel/flywheel/internal/common.vert b/src/main/resources/assets/flywheel/flywheel/internal/common.vert index 4cd86566e..bb0b87f4d 100644 --- a/src/main/resources/assets/flywheel/flywheel/internal/common.vert +++ b/src/main/resources/assets/flywheel/flywheel/internal/common.vert @@ -9,6 +9,7 @@ void _flw_main(in FlwInstance instance) { flw_vertexNormal = normalize(flw_vertexNormal); - flw_distance = fogDistance(flw_vertexPos.xyz, flw_cameraPos.xyz, flw_fogShape); + flw_distance = fogDistance(flw_vertexPos.xyz, flw_cameraPos, flw_fogShape); + gl_Position = flw_viewProjection * flw_vertexPos; } diff --git a/src/main/resources/assets/flywheel/flywheel/internal/uniforms/frame.glsl b/src/main/resources/assets/flywheel/flywheel/internal/uniforms/frame.glsl index 84a2a09f0..21560821d 100644 --- a/src/main/resources/assets/flywheel/flywheel/internal/uniforms/frame.glsl +++ b/src/main/resources/assets/flywheel/flywheel/internal/uniforms/frame.glsl @@ -11,9 +11,12 @@ struct FrustumPlanes { layout(std140) uniform _FlwFrameUniforms { FrustumPlanes flw_frustumPlanes; + mat4 flw_viewProjection; - vec4 flw_cameraPos; - vec4 flw_cameraLook; + mat4 flw_viewProjectionInverse; + + vec4 _flw_cameraPos; + vec4 _flw_cameraLook; vec2 flw_cameraRot; vec2 flw_viewportSize; @@ -27,3 +30,6 @@ layout(std140) uniform _FlwFrameUniforms { float flw_renderTicks; float flw_renderSeconds; }; + +#define flw_cameraPos _flw_cameraPos.xyz +#define flw_cameraLook _flw_cameraLook.xyz diff --git a/src/main/resources/assets/flywheel/flywheel/material/centerline.frag b/src/main/resources/assets/flywheel/flywheel/material/centerline.frag deleted file mode 100644 index e40b80e60..000000000 --- a/src/main/resources/assets/flywheel/flywheel/material/centerline.frag +++ /dev/null @@ -1,10 +0,0 @@ -void flw_materialFragment() { - float toCenter = abs(flw_vertexTexCoord.s - 0.5); - - // multiply by fwidth to get the width of the edge in screen space - if (flw_defaultLineWidth * fwidth(toCenter) < toCenter) { - discard; - } - - flw_fragColor = flw_vertexColor; -} diff --git a/src/main/resources/assets/flywheel/flywheel/material/centerline.vert b/src/main/resources/assets/flywheel/flywheel/material/centerline.vert deleted file mode 100644 index 5d92e7ffb..000000000 --- a/src/main/resources/assets/flywheel/flywheel/material/centerline.vert +++ /dev/null @@ -1,2 +0,0 @@ -void flw_materialVertex() { -} diff --git a/src/main/resources/assets/flywheel/flywheel/material/lines.frag b/src/main/resources/assets/flywheel/flywheel/material/lines.frag new file mode 100644 index 000000000..b56f6eab3 --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/material/lines.frag @@ -0,0 +1,3 @@ +void flw_materialFragment() { + flw_fragColor = flw_vertexColor; +} diff --git a/src/main/resources/assets/flywheel/flywheel/material/lines.vert b/src/main/resources/assets/flywheel/flywheel/material/lines.vert new file mode 100644 index 000000000..352b8e32e --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/material/lines.vert @@ -0,0 +1,20 @@ +void flw_materialVertex() { + vec4 linePosStart = flw_viewProjection * flw_vertexPos; + vec4 linePosEnd = flw_viewProjection * (flw_vertexPos + vec4(flw_vertexNormal, 0.)); + + vec3 ndc1 = linePosStart.xyz / linePosStart.w; + vec3 ndc2 = linePosEnd.xyz / linePosEnd.w; + + vec2 lineScreenDirection = normalize((ndc2.xy - ndc1.xy) * flw_viewportSize); + vec2 lineOffset = vec2(-lineScreenDirection.y, lineScreenDirection.x) * flw_defaultLineWidth / flw_viewportSize; + + if (lineOffset.x < 0.0) { + lineOffset *= -1.0; + } + + if (gl_VertexID % 2 == 0) { + flw_vertexPos = flw_viewProjectionInverse * vec4((ndc1 + vec3(lineOffset, 0.)) * linePosStart.w, linePosStart.w); + } else { + flw_vertexPos = flw_viewProjectionInverse * vec4((ndc1 - vec3(lineOffset, 0.)) * linePosStart.w, linePosStart.w); + } +}