Fix JSON model root transforms (#9410)

This commit is contained in:
Dennis C authored and GitHub committed 2023-03-22 11:09:41 +01:00
1 parent c58d922324
commit 434c1ec4f8
5 files changed
+40 -20

No files matched your search

@@ -45,6 +45,7 @@ import net.minecraftforge.client.model.data.ModelProperty;
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
import net.minecraftforge.client.model.geometry.IGeometryLoader;
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
import net.minecraftforge.client.model.geometry.UnbakedGeometryHelper;
import net.minecraftforge.common.util.ConcatenatedListView;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -88,7 +89,7 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel>
var rootTransform = context.getRootTransform();
if (!rootTransform.isIdentity())
modelState = new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
modelState = UnbakedGeometryHelper.composeRootTransformIntoModelState(modelState, rootTransform);
var bakedPartsBuilder = ImmutableMap.<String, BakedModel>builder();
for (var entry : children.entrySet())
@@ -5,32 +5,26 @@
package net.minecraftforge.client.model;
import com.google.common.collect.Sets;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.mojang.datafixers.util.Pair;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import net.minecraft.client.renderer.block.model.BlockElement;
import net.minecraft.client.renderer.block.model.BlockElementFace;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBaker;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
import net.minecraftforge.client.model.geometry.IGeometryLoader;
import net.minecraftforge.client.model.geometry.SimpleUnbakedGeometry;
import net.minecraftforge.client.model.geometry.UnbakedGeometryHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -64,8 +58,10 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
// If there is a root transform, undo the ModelState transform, apply it, then re-apply the ModelState transform.
// This is necessary because of things like UV locking, which should only respond to the ModelState, and as such
// that is the only transform that should be applied during face bake.
var postTransform = context.getRootTransform().isIdentity() ? QuadTransformers.empty() :
QuadTransformers.applying(modelState.getRotation().compose(context.getRootTransform()).compose(modelState.getRotation().inverse()));
var postTransform = QuadTransformers.empty();
var rootTransform = context.getRootTransform();
if (!rootTransform.isIdentity())
postTransform = UnbakedGeometryHelper.applyRootTransform(modelState, rootTransform);
for (BlockElement element : elements)
{
@@ -72,7 +72,7 @@ public class ItemLayerModel implements IUnbakedGeometry<ItemLayerModel>
);
var rootTransform = context.getRootTransform();
if (!rootTransform.isIdentity())
modelState = new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
modelState = UnbakedGeometryHelper.composeRootTransformIntoModelState(modelState, rootTransform);
var normalRenderTypes = new RenderTypeGroup(RenderType.translucent(), ForgeRenderTypes.ITEM_UNSORTED_TRANSLUCENT.get());
CompositeModel.Baked.Builder builder = CompositeModel.Baked.builder(context, particle, overrides, context.getTransforms());
@@ -29,6 +29,8 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.model.ElementsModel;
import net.minecraftforge.client.model.ForgeFaceData;
import net.minecraftforge.client.model.IModelBuilder;
import net.minecraftforge.client.model.IQuadTransformer;
import net.minecraftforge.client.model.QuadTransformers;
import net.minecraftforge.client.model.SimpleModelState;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
@@ -268,4 +270,32 @@ public class UnbakedGeometryHelper
{
return FACE_BAKERY.bakeQuad(element.from, element.to, face, sprite, direction, state, element.rotation, element.shade, modelLocation);
}
/**
* Create an {@link IQuadTransformer} to apply a {@link Transformation} that undoes the {@link ModelState}
* transform (blockstate transform), applies the given root transform and then re-applies the
* blockstate transform.
*
* @return an {@code IQuadTransformer} that applies the root transform to a baked quad that already has the
* transformation of the given {@code ModelState} applied to it
*/
public static IQuadTransformer applyRootTransform(ModelState modelState, Transformation rootTransform)
{
// Move the origin of the ModelState transform and its inverse from the negative corner to the block center
// to replicate the way the ModelState transform is applied in the FaceBakery by moving the vertices such that
// the negative corner acts as the block center
Transformation transform = modelState.getRotation().applyOrigin(new Vector3f(.5F, .5F, .5F));
return QuadTransformers.applying(transform.compose(rootTransform).compose(transform.inverse()));
}
/**
* {@return a {@link ModelState} that combines the existing model state and the {@linkplain Transformation root transform}}
*/
public static ModelState composeRootTransformIntoModelState(ModelState modelState, Transformation rootTransform)
{
// Move the origin of the root transform as if the negative corner were the block center to match the way the
// ModelState transform is applied in the FaceBakery by moving the vertices to be centered on that corner
rootTransform = rootTransform.applyOrigin(new Vector3f(-.5F, -.5F, -.5F));
return new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
}
}
@@ -212,16 +212,9 @@ public final class TransformationHelper
elements.remove("origin");
}
if (!elements.isEmpty()) throw new JsonParseException("TRSR: can either have single 'matrix' key, or a combination of 'translation', 'rotation' OR 'left_rotation', 'scale', 'post-rotation' (legacy) OR 'right_rotation', 'origin'. Found: " + String.join(", ", elements));
Transformation matrix = new Transformation(translation, leftRot, scale, rightRot);
// Use a different origin if needed.
if (!TransformOrigin.CENTER.getVector().equals(origin))
{
Vector3f originFromCenter = new Vector3f(origin);
originFromCenter.sub(TransformOrigin.CENTER.getVector());
matrix = matrix.applyOrigin(originFromCenter);
}
return matrix;
Transformation matrix = new Transformation(translation, leftRot, scale, rightRot);
return matrix.applyOrigin(new Vector3f(origin));
}
private static Vector3f parseOrigin(JsonObject obj) {