Strike a pose

- Rename TransformedInstance -> PosedInstance
- Add TransformedInstance, which does not have a normal matrix
- Use mat3(transpose(inverse(i.pose))) in the vertex shader, but for
  most cases that will be overkill
This commit is contained in:
Jozufozu 2024-09-14 21:46:49 -07:00
parent 6f2b8fd3fb
commit 41e0aa6bba
6 changed files with 143 additions and 41 deletions

View File

@ -12,6 +12,26 @@ import dev.engine_room.flywheel.lib.util.ExtraMemoryOps;
public final class InstanceTypes {
public static final InstanceType<TransformedInstance> TRANSFORMED = SimpleInstanceType.builder(TransformedInstance::new)
.layout(LayoutBuilder.create()
.vector("color", FloatRepr.NORMALIZED_UNSIGNED_BYTE, 4)
.vector("overlay", IntegerRepr.SHORT, 2)
.vector("light", FloatRepr.UNSIGNED_SHORT, 2)
.matrix("pose", FloatRepr.FLOAT, 4)
.build())
.writer((ptr, instance) -> {
MemoryUtil.memPutByte(ptr, instance.red);
MemoryUtil.memPutByte(ptr + 1, instance.green);
MemoryUtil.memPutByte(ptr + 2, instance.blue);
MemoryUtil.memPutByte(ptr + 3, instance.alpha);
ExtraMemoryOps.put2x16(ptr + 4, instance.overlay);
ExtraMemoryOps.put2x16(ptr + 8, instance.light);
ExtraMemoryOps.putMatrix4f(ptr + 12, instance.model);
})
.vertexShader(Flywheel.rl("instance/transformed.vert"))
.cullShader(Flywheel.rl("instance/cull/transformed.glsl"))
.register();
public static final InstanceType<PosedInstance> POSED = SimpleInstanceType.builder(PosedInstance::new)
.layout(LayoutBuilder.create()
.vector("color", FloatRepr.NORMALIZED_UNSIGNED_BYTE, 4)
.vector("overlay", IntegerRepr.SHORT, 2)
@ -29,8 +49,8 @@ public final class InstanceTypes {
ExtraMemoryOps.putMatrix4f(ptr + 12, instance.model);
ExtraMemoryOps.putMatrix3f(ptr + 76, instance.normal);
})
.vertexShader(Flywheel.rl("instance/transformed.vert"))
.cullShader(Flywheel.rl("instance/cull/transformed.glsl"))
.vertexShader(Flywheel.rl("instance/posed.vert"))
.cullShader(Flywheel.rl("instance/cull/posed.glsl"))
.register();
public static final InstanceType<OrientedInstance> ORIENTED = SimpleInstanceType.builder(OrientedInstance::new)

View File

@ -0,0 +1,104 @@
package dev.engine_room.flywheel.lib.instance;
import org.joml.Matrix3f;
import org.joml.Matrix3fc;
import org.joml.Matrix4f;
import org.joml.Matrix4fc;
import org.joml.Quaternionfc;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.engine_room.flywheel.api.instance.InstanceHandle;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.lib.transform.Transform;
import net.minecraft.util.Mth;
public class PosedInstance extends ColoredLitInstance implements Transform<PosedInstance> {
public final Matrix4f model = new Matrix4f();
public final Matrix3f normal = new Matrix3f();
public PosedInstance(InstanceType<? extends PosedInstance> type, InstanceHandle handle) {
super(type, handle);
}
@Override
public PosedInstance mulPose(Matrix4fc pose) {
this.model.mul(pose);
return this;
}
@Override
public PosedInstance mulNormal(Matrix3fc normal) {
this.normal.mul(normal);
return this;
}
@Override
public PosedInstance rotateAround(Quaternionfc quaternion, float x, float y, float z) {
model.rotateAround(quaternion, x, y, z);
normal.rotate(quaternion);
return this;
}
@Override
public PosedInstance translate(float x, float y, float z) {
model.translate(x, y, z);
return this;
}
@Override
public PosedInstance rotate(Quaternionfc quaternion) {
model.rotate(quaternion);
normal.rotate(quaternion);
return this;
}
@Override
public PosedInstance scale(float x, float y, float z) {
model.scale(x, y, z);
if (x == y && y == z) {
if (x < 0.0f) {
normal.scale(-1.0f);
}
return this;
}
float invX = 1.0f / x;
float invY = 1.0f / y;
float invZ = 1.0f / z;
float f = Mth.fastInvCubeRoot(Math.abs(invX * invY * invZ));
normal.scale(f * invX, f * invY, f * invZ);
return this;
}
public PosedInstance setTransform(PoseStack.Pose pose) {
model.set(pose.pose());
normal.set(pose.normal());
return this;
}
public PosedInstance setTransform(PoseStack stack) {
return setTransform(stack.last());
}
public PosedInstance setIdentityTransform() {
model.identity();
normal.identity();
return this;
}
/**
* Sets the transform matrices to be all zeros.
*
* <p>
* This will allow the GPU to quickly discard all geometry for this instance, effectively "turning it off".
* </p>
*/
public PosedInstance setZeroTransform() {
model.zero();
normal.zero();
return this;
}
}

View File

@ -1,42 +1,25 @@
package dev.engine_room.flywheel.lib.instance;
import org.joml.Matrix3f;
import org.joml.Matrix3fc;
import org.joml.Matrix4f;
import org.joml.Matrix4fc;
import org.joml.Quaternionfc;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.engine_room.flywheel.api.instance.InstanceHandle;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.lib.transform.Transform;
import net.minecraft.util.Mth;
import dev.engine_room.flywheel.lib.transform.Affine;
public class TransformedInstance extends ColoredLitInstance implements Transform<TransformedInstance> {
public class TransformedInstance extends ColoredLitInstance implements Affine<TransformedInstance> {
public final Matrix4f model = new Matrix4f();
public final Matrix3f normal = new Matrix3f();
public TransformedInstance(InstanceType<? extends TransformedInstance> type, InstanceHandle handle) {
super(type, handle);
}
@Override
public TransformedInstance mulPose(Matrix4fc pose) {
this.model.mul(pose);
return this;
}
@Override
public TransformedInstance mulNormal(Matrix3fc normal) {
this.normal.mul(normal);
return this;
}
@Override
public TransformedInstance rotateAround(Quaternionfc quaternion, float x, float y, float z) {
model.rotateAround(quaternion, x, y, z);
normal.rotate(quaternion);
return this;
}
@ -49,33 +32,17 @@ public class TransformedInstance extends ColoredLitInstance implements Transform
@Override
public TransformedInstance rotate(Quaternionfc quaternion) {
model.rotate(quaternion);
normal.rotate(quaternion);
return this;
}
@Override
public TransformedInstance scale(float x, float y, float z) {
model.scale(x, y, z);
if (x == y && y == z) {
if (x < 0.0f) {
normal.scale(-1.0f);
}
return this;
}
float invX = 1.0f / x;
float invY = 1.0f / y;
float invZ = 1.0f / z;
float f = Mth.fastInvCubeRoot(Math.abs(invX * invY * invZ));
normal.scale(f * invX, f * invY, f * invZ);
return this;
}
public TransformedInstance setTransform(PoseStack.Pose pose) {
model.set(pose.pose());
normal.set(pose.normal());
return this;
}
@ -85,7 +52,6 @@ public class TransformedInstance extends ColoredLitInstance implements Transform
public TransformedInstance setIdentityTransform() {
model.identity();
normal.identity();
return this;
}
@ -98,7 +64,6 @@ public class TransformedInstance extends ColoredLitInstance implements Transform
*/
public TransformedInstance setZeroTransform() {
model.zero();
normal.zero();
return this;
}
}

View File

@ -0,0 +1,5 @@
#include "flywheel:util/matrix.glsl"
void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout float radius) {
transformBoundingSphere(i.pose, center, radius);
}

View File

@ -0,0 +1,8 @@
void flw_instanceVertex(in FlwInstance i) {
flw_vertexPos = i.pose * flw_vertexPos;
flw_vertexNormal = i.normal * flw_vertexNormal;
flw_vertexColor *= i.color;
flw_vertexOverlay = i.overlay;
// Some drivers have a bug where uint over float division is invalid, so use an explicit cast.
flw_vertexLight = vec2(i.light) / 256.0;
}

View File

@ -1,6 +1,6 @@
void flw_instanceVertex(in FlwInstance i) {
flw_vertexPos = i.pose * flw_vertexPos;
flw_vertexNormal = i.normal * flw_vertexNormal;
flw_vertexNormal = mat3(transpose(inverse(i.pose))) * flw_vertexNormal;
flw_vertexColor *= i.color;
flw_vertexOverlay = i.overlay;
// Some drivers have a bug where uint over float division is invalid, so use an explicit cast.