mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-03 19:06:27 +01:00
Lines aren't too bad
- Add LineModelBuilder and use that instead of the manual mesh creation in HitboxComponent. - Clone mojang's line shader, adapted as a flywheel material. - Do not scale the view. - Set flw_vertexPos by multiplying by the inverse view projection. - Remove centerline material. - Use #define make padded vec3 uniforms available as actual vec3s. - Add flw_viewProjectionInverse to uniforms. - Minecarts actually delete the stuff from SimpleEntityVisual.
This commit is contained in:
parent
d5732bd788
commit
40a50642f3
12 changed files with 371 additions and 227 deletions
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<Model, TransformedInstance> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<Model, TransformedInstance> 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();
|
||||
}
|
||||
}
|
|
@ -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<T extends AbstractMinecart> 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<T extends AbstractMinecart> extends SimpleEntityVisu
|
|||
|
||||
@Override
|
||||
protected void _delete() {
|
||||
super._delete();
|
||||
body.delete();
|
||||
if (contents != null) {
|
||||
contents.delete();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
void flw_materialVertex() {
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
void flw_materialFragment() {
|
||||
flw_fragColor = flw_vertexColor;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue