Split TransformStack interface

- Now individual components Translate Rotate and Scale
 - Internal change to ModelData, store matrices directly
 - Implement Translate Rotate and Scale for ModelData
 - Implement Translate and Rotate for OrientedData
 - Clean usages of ModelData to use new api when possible
 - WriteSafe and WriteUnsafe for matrices
This commit is contained in:
Jozufozu 2021-11-22 18:05:53 -08:00
parent f14aca4517
commit 0d2907e187
13 changed files with 316 additions and 218 deletions

View file

@ -1,24 +1,27 @@
package com.jozufozu.flywheel.core.materials.model;
import java.nio.FloatBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.materials.BasicData;
import com.jozufozu.flywheel.util.Attribute;
import com.jozufozu.flywheel.util.WriteSafe;
import com.jozufozu.flywheel.util.transform.Rotate;
import com.jozufozu.flywheel.util.transform.Scale;
import com.jozufozu.flywheel.util.transform.Translate;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
import com.mojang.math.Quaternion;
public class ModelData extends BasicData {
private static final float[] empty = new float[25];
import net.minecraft.util.Mth;
public final float[] matrices = empty.clone();
private final FloatBuffer wrap = FloatBuffer.wrap(matrices);
public class ModelData extends BasicData implements Translate<ModelData>, Rotate<ModelData>, Scale<ModelData> {
public final Matrix4f model = new Matrix4f();
public final Matrix3f normal = new Matrix3f();
public ModelData setTransform(PoseStack stack) {
this.wrap.position(0);
((Attribute)(Object) stack.last().pose()).append(this.wrap);
((Attribute)(Object) stack.last().normal()).append(this.wrap);
markDirty();
this.model.load(stack.last().pose());
this.normal.load(stack.last().normal());
return this;
}
@ -30,15 +33,63 @@ public class ModelData extends BasicData {
* </p>
*/
public ModelData setEmptyTransform() {
this.wrap.position(0)
.put(empty);
markDirty();
this.model.load(new Matrix4f());
this.normal.load(new Matrix3f());
return this;
}
public ModelData loadIdentity() {
markDirty();
this.model.setIdentity();
this.normal.setIdentity();
return this;
}
@Override
public void write(VecBuffer buf) {
super.write(buf);
buf.putFloatArray(matrices);
((WriteSafe) (Object) model).write(buf);
((WriteSafe) (Object) normal).write(buf);
}
@Override
public ModelData multiply(Quaternion quaternion) {
markDirty();
model.multiply(quaternion);
normal.mul(quaternion);
return this;
}
@Override
public ModelData scale(float pX, float pY, float pZ) {
markDirty();
model.multiply(Matrix4f.createScaleMatrix(pX, pY, pZ));
if (pX == pY && pY == pZ) {
if (pX > 0.0F) {
return this;
}
normal.mul(-1.0F);
}
float f = 1.0F / pX;
float f1 = 1.0F / pY;
float f2 = 1.0F / pZ;
float f3 = Mth.fastInvCubeRoot(f * f1 * f2);
normal.mul(Matrix3f.createScaleMatrix(f3 * f, f3 * f1, f3 * f2));
return this;
}
@Override
public ModelData translate(double x, double y, double z) {
markDirty();
model.multiplyWithTranslation((float) x, (float) y, (float) z);
return this;
}
}

View file

@ -6,6 +6,7 @@ import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.backend.struct.StructType;
import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.util.WriteUnsafe;
public class UnsafeModelWriter extends UnsafeBufferWriter<ModelData> {
@ -25,10 +26,9 @@ public class UnsafeModelWriter extends UnsafeBufferWriter<ModelData> {
addr += 6;
float[] matrices = d.matrices;
for (int i = 0; i < matrices.length; i++) {
MemoryUtil.memPutFloat(addr + i * 4L, matrices[i]);
}
((WriteUnsafe) (Object) d.model).writeUnsafe(addr);
addr += 4 * 16;
((WriteUnsafe) (Object) d.normal).writeUnsafe(addr);
advance();
}

View file

@ -2,6 +2,8 @@ package com.jozufozu.flywheel.core.materials.oriented;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.materials.BasicData;
import com.jozufozu.flywheel.util.transform.Rotate;
import com.jozufozu.flywheel.util.transform.Translate;
import com.jozufozu.flywheel.util.vec.Vec3;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
@ -83,6 +85,15 @@ public class OrientedData extends BasicData {
return this;
}
public OrientedData resetRotation() {
this.qX = 0;
this.qY = 0;
this.qZ = 0;
this.qW = 1;
markDirty();
return this;
}
@Override
public void write(VecBuffer buf) {
super.write(buf);

View file

@ -1,11 +1,12 @@
package com.jozufozu.flywheel.mixin.matrix;
import java.nio.FloatBuffer;
import org.lwjgl.system.MemoryUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import com.jozufozu.flywheel.util.Attribute;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.util.WriteSafe;
import com.jozufozu.flywheel.util.WriteUnsafe;
import com.mojang.math.Matrix3f;
import net.minecraftforge.api.distmarker.Dist;
@ -13,7 +14,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@Mixin(Matrix3f.class)
public abstract class Matrix3fMixin implements Attribute {
public abstract class Matrix3fMixin implements WriteUnsafe, WriteSafe {
@Shadow protected float m00;
@Shadow protected float m01;
@ -26,15 +27,28 @@ public abstract class Matrix3fMixin implements Attribute {
@Shadow protected float m22;
@Override
public void append(FloatBuffer buffer) {
buffer.put(m00);
buffer.put(m10);
buffer.put(m20);
buffer.put(m01);
buffer.put(m11);
buffer.put(m21);
buffer.put(m02);
buffer.put(m12);
buffer.put(m22);
public void writeUnsafe(long addr) {
MemoryUtil.memPutFloat(addr, m00);
MemoryUtil.memPutFloat(addr += 4L, m10);
MemoryUtil.memPutFloat(addr += 4L, m20);
MemoryUtil.memPutFloat(addr += 4L, m01);
MemoryUtil.memPutFloat(addr += 4L, m11);
MemoryUtil.memPutFloat(addr += 4L, m21);
MemoryUtil.memPutFloat(addr += 4L, m02);
MemoryUtil.memPutFloat(addr += 4L, m12);
MemoryUtil.memPutFloat(addr += 4L, m22);
}
@Override
public void write(VecBuffer buffer) {
buffer.putFloat(m00);
buffer.putFloat(m10);
buffer.putFloat(m20);
buffer.putFloat(m01);
buffer.putFloat(m11);
buffer.putFloat(m21);
buffer.putFloat(m02);
buffer.putFloat(m12);
buffer.putFloat(m22);
}
}

View file

@ -1,11 +1,12 @@
package com.jozufozu.flywheel.mixin.matrix;
import java.nio.FloatBuffer;
import org.lwjgl.system.MemoryUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import com.jozufozu.flywheel.util.Attribute;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.util.WriteSafe;
import com.jozufozu.flywheel.util.WriteUnsafe;
import com.mojang.math.Matrix4f;
import net.minecraftforge.api.distmarker.Dist;
@ -13,7 +14,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@Mixin(Matrix4f.class)
public abstract class Matrix4fMixin implements Attribute {
public abstract class Matrix4fMixin implements WriteUnsafe, WriteSafe {
@Shadow protected float m00;
@Shadow protected float m01;
@ -33,22 +34,42 @@ public abstract class Matrix4fMixin implements Attribute {
@Shadow protected float m33;
@Override
public void append(FloatBuffer buffer) {
buffer.put(m00);
buffer.put(m10);
buffer.put(m20);
buffer.put(m30);
buffer.put(m01);
buffer.put(m11);
buffer.put(m21);
buffer.put(m31);
buffer.put(m02);
buffer.put(m12);
buffer.put(m22);
buffer.put(m32);
buffer.put(m03);
buffer.put(m13);
buffer.put(m23);
buffer.put(m33);
public void writeUnsafe(long addr) {
MemoryUtil.memPutFloat(addr, m00);
MemoryUtil.memPutFloat(addr += 4L, m10);
MemoryUtil.memPutFloat(addr += 4L, m20);
MemoryUtil.memPutFloat(addr += 4L, m30);
MemoryUtil.memPutFloat(addr += 4L, m01);
MemoryUtil.memPutFloat(addr += 4L, m11);
MemoryUtil.memPutFloat(addr += 4L, m21);
MemoryUtil.memPutFloat(addr += 4L, m31);
MemoryUtil.memPutFloat(addr += 4L, m02);
MemoryUtil.memPutFloat(addr += 4L, m12);
MemoryUtil.memPutFloat(addr += 4L, m22);
MemoryUtil.memPutFloat(addr += 4L, m32);
MemoryUtil.memPutFloat(addr += 4L, m03);
MemoryUtil.memPutFloat(addr += 4L, m13);
MemoryUtil.memPutFloat(addr += 4L, m23);
MemoryUtil.memPutFloat(addr += 4L, m33);
}
@Override
public void write(VecBuffer buf) {
buf.putFloat(m00);
buf.putFloat(m10);
buf.putFloat(m20);
buf.putFloat(m30);
buf.putFloat(m01);
buf.putFloat(m11);
buf.putFloat(m21);
buf.putFloat(m31);
buf.putFloat(m02);
buf.putFloat(m12);
buf.putFloat(m22);
buf.putFloat(m32);
buf.putFloat(m03);
buf.putFloat(m13);
buf.putFloat(m23);
buf.putFloat(m33);
}
}

View file

@ -1,11 +0,0 @@
package com.jozufozu.flywheel.util;
import java.nio.FloatBuffer;
public interface Attribute {
/**
* Append the contents of this object to the given FloatBuffer.
*/
void append(FloatBuffer buffer);
}

View file

@ -0,0 +1,7 @@
package com.jozufozu.flywheel.util;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
public interface WriteSafe {
void write(VecBuffer buf);
}

View file

@ -0,0 +1,9 @@
package com.jozufozu.flywheel.util;
public interface WriteUnsafe {
/**
* Write the contents of this object into sequential memory starting at the given address.
*/
void writeUnsafe(long addr);
}

View file

@ -0,0 +1,72 @@
package com.jozufozu.flywheel.util.transform;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import net.minecraft.core.Direction;
public interface Rotate<Self> {
Self multiply(Quaternion quaternion);
default Self rotate(Direction axis, float radians) {
if (radians == 0)
return (Self) this;
return multiply(axis.step()
.rotation(radians));
}
default Self rotate(double angle, Direction.Axis axis) {
Vector3f vec =
axis == Direction.Axis.X ? Vector3f.XP : axis == Direction.Axis.Y ? Vector3f.YP : Vector3f.ZP;
return multiply(vec, angle);
}
default Self rotateX(double angle) {
return multiply(Vector3f.XP, angle);
}
default Self rotateY(double angle) {
return multiply(Vector3f.YP, angle);
}
default Self rotateZ(double angle) {
return multiply(Vector3f.ZP, angle);
}
default Self rotateXRadians(double angle) {
return multiplyRadians(Vector3f.XP, angle);
}
default Self rotateYRadians(double angle) {
return multiplyRadians(Vector3f.YP, angle);
}
default Self rotateZRadians(double angle) {
return multiplyRadians(Vector3f.ZP, angle);
}
default Self multiply(Vector3f axis, double angle) {
if (angle == 0)
return (Self) this;
return multiply(axis.rotationDegrees((float) angle));
}
default Self multiplyRadians(Vector3f axis, double angle) {
if (angle == 0)
return (Self) this;
return multiply(axis.rotation((float) angle));
}
default Self rotateToFace(Direction facing) {
switch (facing) {
case SOUTH -> multiply(Vector3f.YP.rotationDegrees(180));
case WEST -> multiply(Vector3f.YP.rotationDegrees(90));
case NORTH -> multiply(Vector3f.YP.rotationDegrees(0));
case EAST -> multiply(Vector3f.YP.rotationDegrees(270));
case UP -> multiply(Vector3f.XP.rotationDegrees(90));
case DOWN -> multiply(Vector3f.XN.rotationDegrees(90));
}
return (Self) this;
}
}

View file

@ -0,0 +1,9 @@
package com.jozufozu.flywheel.util.transform;
public interface Scale<Self> {
Self scale(float factorX, float factorY, float factorZ);
default Self scale(float factor) {
return scale(factor, factor, factor);
}
}

View file

@ -1,152 +1,7 @@
package com.jozufozu.flywheel.util.transform;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
public interface TransformStack {
Vec3 CENTER = new Vec3(0.5, 0.5, 0.5);
TransformStack translate(double x, double y, double z);
TransformStack multiply(Quaternion quaternion);
TransformStack scale(float factorX, float factorY, float factorZ);
public interface TransformStack extends Scale<TransformStack>, Translate<TransformStack>, Rotate<TransformStack> {
TransformStack push();
TransformStack pop();
default TransformStack scale(float factor) {
return scale(factor, factor, factor);
}
default TransformStack rotate(Direction axis, float radians) {
if (radians == 0)
return this;
return multiply(axis.step()
.rotation(radians));
}
default TransformStack rotate(double angle, Direction.Axis axis) {
Vector3f vec =
axis == Direction.Axis.X ? Vector3f.XP : axis == Direction.Axis.Y ? Vector3f.YP : Vector3f.ZP;
return multiply(vec, angle);
}
default TransformStack rotateX(double angle) {
return multiply(Vector3f.XP, angle);
}
default TransformStack rotateY(double angle) {
return multiply(Vector3f.YP, angle);
}
default TransformStack rotateZ(double angle) {
return multiply(Vector3f.ZP, angle);
}
default TransformStack rotateXRadians(double angle) {
return multiplyRadians(Vector3f.XP, angle);
}
default TransformStack rotateYRadians(double angle) {
return multiplyRadians(Vector3f.YP, angle);
}
default TransformStack rotateZRadians(double angle) {
return multiplyRadians(Vector3f.ZP, angle);
}
default TransformStack centre() {
return translateAll(0.5);
}
default TransformStack unCentre() {
return translateAll(-0.5);
}
default TransformStack translateAll(double v) {
return translate(v, v, v);
}
default TransformStack translateX(double x) {
return translate(x, 0, 0);
}
default TransformStack translateY(double y) {
return translate(0, y, 0);
}
default TransformStack translateZ(double z) {
return translate(0, 0, z);
}
default TransformStack translate(Vec3i vec) {
return translate(vec.getX(), vec.getY(), vec.getZ());
}
default TransformStack translate(Vec3 vec) {
return translate(vec.x, vec.y, vec.z);
}
default TransformStack translate(Vector3f vec) {
return translate(vec.x(), vec.y(), vec.z());
}
default TransformStack translateBack(Vec3 vec) {
return translate(-vec.x, -vec.y, -vec.z);
}
default TransformStack translateBack(Vec3i vec) {
return translate(-vec.getX(), -vec.getY(), -vec.getZ());
}
default TransformStack nudge(int id) {
long randomBits = (long) id * 31L * 493286711L;
randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L;
float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
return translate(xNudge, yNudge, zNudge);
}
default TransformStack multiply(Vector3f axis, double angle) {
if (angle == 0)
return this;
return multiply(axis.rotationDegrees((float) angle));
}
default TransformStack multiplyRadians(Vector3f axis, double angle) {
if (angle == 0)
return this;
return multiply(axis.rotation((float) angle));
}
default TransformStack rotateToFace(Direction facing) {
switch (facing) {
case SOUTH:
multiply(Vector3f.YP.rotationDegrees(180));
break;
case WEST:
multiply(Vector3f.YP.rotationDegrees(90));
break;
case NORTH:
multiply(Vector3f.YP.rotationDegrees(0));
break;
case EAST:
multiply(Vector3f.YP.rotationDegrees(270));
break;
case UP:
multiply(Vector3f.XP.rotationDegrees(90));
break;
case DOWN:
multiply(Vector3f.XN.rotationDegrees(90));
break;
}
return this;
}
}

View file

@ -0,0 +1,67 @@
package com.jozufozu.flywheel.util.transform;
import com.mojang.math.Vector3f;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
public interface Translate<Self> {
Self translate(double x, double y, double z);
default Self centre() {
return translateAll(0.5);
}
default Self unCentre() {
return translateAll(-0.5);
}
default Self translateAll(double v) {
return translate(v, v, v);
}
default Self translateX(double x) {
return translate(x, 0, 0);
}
default Self translateY(double y) {
return translate(0, y, 0);
}
default Self translateZ(double z) {
return translate(0, 0, z);
}
default Self translate(Vec3i vec) {
return translate(vec.getX(), vec.getY(), vec.getZ());
}
default Self translate(Vec3 vec) {
return translate(vec.x, vec.y, vec.z);
}
default Self translate(Vector3f vec) {
return translate(vec.x(), vec.y(), vec.z());
}
default Self translateBack(Vec3 vec) {
return translate(-vec.x, -vec.y, -vec.z);
}
default Self translateBack(double x, double y, double z) {
return translate(-x, -y, -z);
}
default Self translateBack(Vec3i vec) {
return translate(-vec.getX(), -vec.getY(), -vec.getZ());
}
default Self nudge(int id) {
long randomBits = (long) id * 31L * 493286711L;
randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L;
float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
return translate(xNudge, yNudge, zNudge);
}
}

View file

@ -31,7 +31,6 @@ import net.minecraft.world.level.block.state.properties.ChestType;
public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends TileEntityInstance<T> implements IDynamicInstance {
private final MatrixTransformStack stack = new MatrixTransformStack();
private final OrientedData body;
private final ModelData lid;
@ -57,9 +56,6 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends TileE
if (block instanceof AbstractChestBlock) {
// MatrixStack stack = new MatrixStack();
//
// stack.push();
float horizontalAngle = blockState.getValue(ChestBlock.FACING).toYRot();
baseRotation = Vector3f.YP.rotationDegrees(-horizontalAngle);
@ -92,7 +88,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends TileE
float angleX = -(progress * ((float) Math.PI / 2F));
stack.setIdentity()
lid.loadIdentity()
.translate(getInstancePosition())
.translate(0, 9f/16f, 0)
.centre()
@ -101,9 +97,6 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends TileE
.translate(0, 0, 1f / 16f)
.multiply(Vector3f.XP.rotation(angleX))
.translate(0, 0, -1f / 16f);
lid.setTransform(stack.unwrap());
}
@Override