Strip all Phase references, TODO/FUTURE roadmap notes, and internal planning comments from the codebase. Run Prettier for consistent formatting across all Java files.
107 lines
3.6 KiB
Java
107 lines
3.6 KiB
Java
package com.tiedup.remake.client.gltf;
|
|
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.model.PlayerModel;
|
|
import net.minecraft.client.player.AbstractClientPlayer;
|
|
import net.minecraft.client.renderer.MultiBufferSource;
|
|
import net.minecraft.client.renderer.entity.RenderLayerParent;
|
|
import net.minecraft.client.renderer.entity.layers.RenderLayer;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraftforge.api.distmarker.Dist;
|
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
import org.joml.Matrix4f;
|
|
|
|
/**
|
|
* RenderLayer that renders the glTF mesh (handcuffs) on the player.
|
|
* Only active when enabled and only renders on the local player.
|
|
* <p>
|
|
* Uses the live skinning path: reads live skeleton from HumanoidModel
|
|
* via {@link GltfLiveBoneReader}, following PlayerAnimator + bendy-lib rotations.
|
|
* Falls back to GLB-internal skinning via {@link GltfSkinningEngine} if live reading fails.
|
|
*/
|
|
@OnlyIn(Dist.CLIENT)
|
|
public class GltfRenderLayer
|
|
extends RenderLayer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>>
|
|
{
|
|
|
|
private static final Logger LOGGER = LogManager.getLogger("GltfPipeline");
|
|
|
|
private static final ResourceLocation CUFFS_MODEL =
|
|
ResourceLocation.fromNamespaceAndPath(
|
|
"tiedup",
|
|
"models/gltf/v2/handcuffs/cuffs_prototype.glb"
|
|
);
|
|
|
|
public GltfRenderLayer(
|
|
RenderLayerParent<
|
|
AbstractClientPlayer,
|
|
PlayerModel<AbstractClientPlayer>
|
|
> renderer
|
|
) {
|
|
super(renderer);
|
|
}
|
|
|
|
/**
|
|
* The Y translate offset to place the glTF mesh in the MC PoseStack.
|
|
* <p>
|
|
* After LivingEntityRenderer's scale(-1,-1,1) + translate(0,-1.501,0),
|
|
* the PoseStack origin is at the model top (1.501 blocks above feet), Y-down.
|
|
* The glTF mesh (MC-converted) has feet at Y=0 and head at Y≈-1.5.
|
|
* Translating by 1.501 maps glTF feet to PoseStack feet and head to top.
|
|
*/
|
|
private static final float ALIGNMENT_Y = 1.501f;
|
|
|
|
@Override
|
|
public void render(
|
|
PoseStack poseStack,
|
|
MultiBufferSource buffer,
|
|
int packedLight,
|
|
AbstractClientPlayer entity,
|
|
float limbSwing,
|
|
float limbSwingAmount,
|
|
float partialTick,
|
|
float ageInTicks,
|
|
float netHeadYaw,
|
|
float headPitch
|
|
) {
|
|
if (!GltfAnimationApplier.isEnabled()) return;
|
|
if (entity != Minecraft.getInstance().player) return;
|
|
|
|
GltfData data = GltfCache.get(CUFFS_MODEL);
|
|
if (data == null) return;
|
|
|
|
// Live path: read skeleton from HumanoidModel (after PlayerAnimator)
|
|
PlayerModel<AbstractClientPlayer> parentModel = this.getParentModel();
|
|
Matrix4f[] joints = GltfLiveBoneReader.computeJointMatricesFromModel(
|
|
parentModel,
|
|
data,
|
|
entity
|
|
);
|
|
if (joints == null) {
|
|
// Fallback to GLB-internal path if live reading fails
|
|
joints = GltfSkinningEngine.computeJointMatrices(data);
|
|
}
|
|
|
|
poseStack.pushPose();
|
|
|
|
// Align glTF mesh with MC model (feet-to-feet alignment)
|
|
poseStack.translate(0, ALIGNMENT_Y, 0);
|
|
|
|
GltfMeshRenderer.renderSkinned(
|
|
data,
|
|
joints,
|
|
poseStack,
|
|
buffer,
|
|
packedLight,
|
|
net.minecraft.client.renderer.entity.LivingEntityRenderer.getOverlayCoords(
|
|
entity,
|
|
0.0f
|
|
)
|
|
);
|
|
poseStack.popPose();
|
|
}
|
|
}
|