Skip to content

Commit

Permalink
Strike a pose
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
Jozufozu committed Sep 15, 2024
1 parent 6f2b8fd commit 41e0aa6
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public final class InstanceTypes {
.vector("overlay", IntegerRepr.SHORT, 2)
.vector("light", FloatRepr.UNSIGNED_SHORT, 2)
.matrix("pose", FloatRepr.FLOAT, 4)
.matrix("normal", FloatRepr.FLOAT, 3)
.build())
.writer((ptr, instance) -> {
MemoryUtil.memPutByte(ptr, instance.red);
Expand All @@ -27,12 +26,33 @@ public final class InstanceTypes {
ExtraMemoryOps.put2x16(ptr + 4, instance.overlay);
ExtraMemoryOps.put2x16(ptr + 8, instance.light);
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"))
.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)
.vector("light", FloatRepr.UNSIGNED_SHORT, 2)
.matrix("pose", FloatRepr.FLOAT, 4)
.matrix("normal", FloatRepr.FLOAT, 3)
.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);
ExtraMemoryOps.putMatrix3f(ptr + 76, instance.normal);
})
.vertexShader(Flywheel.rl("instance/posed.vert"))
.cullShader(Flywheel.rl("instance/cull/posed.glsl"))
.register();

public static final InstanceType<OrientedInstance> ORIENTED = SimpleInstanceType.builder(OrientedInstance::new)
.layout(LayoutBuilder.create()
.vector("color", FloatRepr.NORMALIZED_UNSIGNED_BYTE, 4)
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}

Expand All @@ -49,33 +32,17 @@ public TransformedInstance translate(float x, float y, float z) {
@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;
}

Expand All @@ -85,7 +52,6 @@ public TransformedInstance setTransform(PoseStack stack) {

public TransformedInstance setIdentityTransform() {
model.identity();
normal.identity();
return this;
}

Expand All @@ -98,7 +64,6 @@ public TransformedInstance setIdentityTransform() {
*/
public TransformedInstance setZeroTransform() {
model.zero();
normal.zero();
return this;
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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.
Expand Down

0 comments on commit 41e0aa6

Please sign in to comment.