Skip to content

Commit

Permalink
Treeify bells and minecarts
Browse files Browse the repository at this point in the history
- Use InstanceTrees in BellVisual and MinecartVisual
- Use JOML Matrix4fStack instead of PoseStack
- Directly transform Matrix4f instead of using PoseStack to compute initial pose
  • Loading branch information
PepperCode1 committed Sep 15, 2024
1 parent ed727e7 commit 904933e
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 139 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public PosedInstance scale(float x, float y, float z) {
return this;
}

public PosedInstance setTransform(Matrix4fc pose, Matrix3fc normal) {
this.pose.set(pose);
this.normal.set(normal);
return this;
}

public PosedInstance setTransform(PoseStack.Pose pose) {
this.pose.set(pose.pose());
normal.set(pose.normal());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.engine_room.flywheel.lib.instance;

import org.joml.Matrix4f;
import org.joml.Matrix4fc;
import org.joml.Quaternionfc;

import com.mojang.blaze3d.vertex.PoseStack;
Expand Down Expand Up @@ -40,6 +41,11 @@ public TransformedInstance scale(float x, float y, float z) {
return this;
}

public TransformedInstance setTransform(Matrix4fc pose) {
this.pose.set(pose);
return this;
}

public TransformedInstance setTransform(PoseStack.Pose pose) {
this.pose.set(pose.pose());
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public void translateAndRotate(Affine<?> affine, Quaternionf tempQuaternion) {
affine.rotate(tempQuaternion.rotationZYX(zRot, yRot, xRot));
}

if (xScale != 1.0F || yScale != 1.0F || zScale != 1.0F) {
if (xScale != ModelPart.DEFAULT_SCALE || yScale != ModelPart.DEFAULT_SCALE || zScale != ModelPart.DEFAULT_SCALE) {
affine.scale(xScale, yScale, zScale);
}
}
Expand Down Expand Up @@ -300,13 +300,6 @@ public float zScale() {
return zScale;
}

public void pos(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
setChanged();
}

public void xPos(float x) {
this.x = x;
setChanged();
Expand All @@ -322,10 +315,10 @@ public void zPos(float z) {
setChanged();
}

public void rotation(float xRot, float yRot, float zRot) {
this.xRot = xRot;
this.yRot = yRot;
this.zRot = zRot;
public void pos(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
setChanged();
}

Expand All @@ -344,10 +337,10 @@ public void zRot(float zRot) {
setChanged();
}

public void scale(float xScale, float yScale, float zScale) {
this.xScale = xScale;
this.yScale = yScale;
this.zScale = zScale;
public void rotation(float xRot, float yRot, float zRot) {
this.xRot = xRot;
this.yRot = yRot;
this.zRot = zRot;
setChanged();
}

Expand All @@ -366,6 +359,13 @@ public void zScale(float zScale) {
setChanged();
}

public void scale(float xScale, float yScale, float zScale) {
this.xScale = xScale;
this.yScale = yScale;
this.zScale = zScale;
setChanged();
}

public void offsetPos(float xOffset, float yOffset, float zOffset) {
x += xOffset;
y += yOffset;
Expand All @@ -388,6 +388,10 @@ public void offsetZPos(float zOffset) {
setChanged();
}

public void offsetPos(Vector3fc offset) {
offsetPos(offset.x(), offset.y(), offset.z());
}

public void offsetRotation(float xOffset, float yOffset, float zOffset) {
xRot += xOffset;
yRot += yOffset;
Expand All @@ -410,6 +414,10 @@ public void offsetZRot(float zOffset) {
setChanged();
}

public void offsetRotation(Vector3fc offset) {
offsetRotation(offset.x(), offset.y(), offset.z());
}

public void offsetScale(float xOffset, float yOffset, float zOffset) {
xScale += xOffset;
yScale += yOffset;
Expand All @@ -432,14 +440,6 @@ public void offsetZScale(float zOffset) {
setChanged();
}

public void offsetPos(Vector3fc offset) {
offsetPos(offset.x(), offset.y(), offset.z());
}

public void offsetRotation(Vector3fc offset) {
offsetRotation(offset.x(), offset.y(), offset.z());
}

public void offsetScale(Vector3fc offset) {
offsetScale(offset.x(), offset.y(), offset.z());
}
Expand Down Expand Up @@ -491,6 +491,10 @@ public void copyTransform(ModelPart modelPart) {
setChanged();
}

private void setChanged() {
changed = true;
}

public void delete() {
if (instance != null) {
instance.delete();
Expand All @@ -500,10 +504,6 @@ public void delete() {
}
}

private void setChanged() {
changed = true;
}

@ApiStatus.Experimental
@FunctionalInterface
public interface ObjIntIntConsumer<T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ public boolean doDistanceLimitThisFrame(DynamicVisual.Context context) {
.shouldUpdate(pos.distToCenterSqr(context.camera().getPosition()));
}

protected int computePackedLight() {
return LevelRenderer.getLightColor(level, pos);
}

protected void relight(BlockPos pos, @Nullable FlatLit... instances) {
FlatLit.relight(LevelRenderer.getLightColor(level, pos), instances);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,14 @@ public boolean isVisible(FrustumIntersection frustum) {
return entity.noCulling || visibilityTester.check(frustum);
}

protected void relight(float partialTick, @Nullable FlatLit... instances) {
protected int computePackedLight(float partialTick) {
BlockPos pos = BlockPos.containing(entity.getLightProbePosition(partialTick));
int blockLight = entity.isOnFire() ? 15 : level.getBrightness(LightLayer.BLOCK, pos);
int skyLight = level.getBrightness(LightLayer.SKY, pos);
int light = LightTexture.pack(blockLight, skyLight);
FlatLit.relight(light, instances);
return LightTexture.pack(blockLight, skyLight);
}

protected void relight(float partialTick, @Nullable FlatLit... instances) {
FlatLit.relight(computePackedLight(partialTick), instances);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,22 @@

import java.util.function.Consumer;

import org.joml.AxisAngle4f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.joml.Matrix4f;
import org.joml.Matrix4fc;

import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
import dev.engine_room.flywheel.lib.instance.OrientedInstance;
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
import dev.engine_room.flywheel.lib.model.ModelHolder;
import dev.engine_room.flywheel.lib.model.SingleMeshModel;
import dev.engine_room.flywheel.lib.model.part.ModelPartConverter;
import dev.engine_room.flywheel.lib.model.RetexturedMesh;
import dev.engine_room.flywheel.lib.model.part.InstanceTree;
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.renderer.blockentity.BellRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.entity.BellBlockEntity;

Expand All @@ -27,27 +26,26 @@ public class BellVisual extends AbstractBlockEntityVisual<BellBlockEntity> imple
.mipmap(false)
.build();

private static final ModelHolder BELL_MODEL = new ModelHolder(() -> {
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION.sprite(), "bell_body"), MATERIAL);
});
private final InstanceTree instances;
private final InstanceTree bellBody;

private final OrientedInstance bell;
private final Matrix4fc initialPose;

private boolean wasShaking = false;

public BellVisual(VisualizationContext ctx, BellBlockEntity blockEntity, float partialTick) {
super(ctx, blockEntity, partialTick);

bell = createBellInstance().pivot(0.5f, 0.75f, 0.5f)
.position(getVisualPosition());
bell.setChanged();
TextureAtlasSprite sprite = BellRenderer.BELL_RESOURCE_LOCATION.sprite();
instances = InstanceTree.create(instancerProvider(), ModelLayers.BELL, (path, mesh) -> {
return new Model.ConfiguredMesh(MATERIAL, new RetexturedMesh(mesh, sprite));
});
bellBody = instances.childOrThrow("bell_body");

updateRotation(partialTick);
}
BlockPos visualPos = getVisualPosition();
initialPose = new Matrix4f().translate(visualPos.getX(), visualPos.getY(), visualPos.getZ());

private OrientedInstance createBellInstance() {
return instancerProvider().instancer(InstanceTypes.ORIENTED, BELL_MODEL.get())
.createInstance();
updateRotation(partialTick);
}

@Override
Expand All @@ -60,37 +58,46 @@ public void beginFrame(Context context) {
}

private void updateRotation(float partialTick) {
float xRot = 0;
float zRot = 0;

if (blockEntity.shaking) {
float ringTime = (float) blockEntity.ticks + partialTick;
float angle = Mth.sin(ringTime / (float) Math.PI) / (4.0F + ringTime / 3.0F);

Vector3f ringAxis = blockEntity.clickDirection.getCounterClockWise()
.step();

bell.rotation(new Quaternionf(new AxisAngle4f(angle, ringAxis)))
.setChanged();
switch (blockEntity.clickDirection) {
case NORTH -> xRot = -angle;
case SOUTH -> xRot = angle;
case EAST -> zRot = -angle;
case WEST -> zRot = angle;
}

wasShaking = true;
} else if (wasShaking) {
bell.rotation(new Quaternionf())
.setChanged();

wasShaking = false;
}

bellBody.xRot(xRot);
bellBody.zRot(zRot);
instances.updateInstancesStatic(initialPose);
}

@Override
public void updateLight(float partialTick) {
relight(bell);
int packedLight = computePackedLight();
instances.traverse(instance -> {
instance.light(packedLight)
.setChanged();
});
}

@Override
public void collectCrumblingInstances(Consumer<Instance> consumer) {
consumer.accept(bell);
instances.traverse(consumer);
}

@Override
protected void _delete() {
bell.delete();
instances.delete();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@
import java.util.function.Consumer;

import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import org.joml.Matrix4fc;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;

import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.material.CutoutShaders;
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
import dev.engine_room.flywheel.lib.model.RetexturedMesh;
import dev.engine_room.flywheel.lib.model.part.InstanceTree;
import dev.engine_room.flywheel.lib.transform.TransformStack;
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
Expand All @@ -29,7 +27,9 @@
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.AbstractChestBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.ChestBlock;
Expand All @@ -40,7 +40,7 @@
import net.minecraft.world.level.block.state.properties.ChestType;

public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends AbstractBlockEntityVisual<T> implements SimpleDynamicVisual {
private static final dev.engine_room.flywheel.api.material.Material MATERIAL = SimpleMaterial.builder()
private static final Material MATERIAL = SimpleMaterial.builder()
.cutout(CutoutShaders.ONE_TENTH)
.texture(Sheets.CHEST_SHEET)
.mipmap(false)
Expand Down Expand Up @@ -84,14 +84,7 @@ public ChestVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
lid = instances.childOrThrow("lid");
lock = instances.childOrThrow("lock");

PoseStack poseStack = new PoseStack();
TransformStack.of(poseStack).translate(getVisualPosition());
float horizontalAngle = blockState.getValue(ChestBlock.FACING).toYRot();
poseStack.translate(0.5F, 0.5F, 0.5F);
poseStack.mulPose(Axis.YP.rotationDegrees(-horizontalAngle));
poseStack.translate(-0.5F, -0.5F, -0.5F);
initialPose = poseStack.last().pose();

initialPose = createInitialPose();
neighborCombineResult = chestBlock.combine(blockState, level, pos, true);
lidProgress = neighborCombineResult.apply(ChestBlock.opennessCombiner(blockEntity));

Expand All @@ -112,6 +105,15 @@ private static boolean isChristmas() {
return calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DATE) >= 24 && calendar.get(Calendar.DATE) <= 26;
}

private Matrix4f createInitialPose() {
BlockPos visualPos = getVisualPosition();
float horizontalAngle = blockState.getValue(ChestBlock.FACING).toYRot();
return new Matrix4f().translate(visualPos.getX(), visualPos.getY(), visualPos.getZ())
.translate(0.5F, 0.5F, 0.5F)
.rotateY(-horizontalAngle * Mth.DEG_TO_RAD)
.translate(-0.5F, -0.5F, -0.5F);
}

@Override
public void setSectionCollector(SectionCollector sectionCollector) {
this.lightSections = sectionCollector;
Expand Down
Loading

0 comments on commit 904933e

Please sign in to comment.