From 5281b907560eca1a13c15e2d30e3ebf6ef3f8ce7 Mon Sep 17 00:00:00 2001
From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com>
Date: Sat, 31 May 2025 12:19:20 -0700
Subject: [PATCH] Finalize 1.21.5 FRAPI port and other improvements (#4650)
* Allow using sprite finder during model baking
- Allow retrieving sprite finders from ErrorCollectingSpriteGetter, SpriteLoader.StitchResult, and SpriteAtlasManager.AtlasPreparation via new interface injections
- Deprecate SpriteFinder.get in favor of interface injected method for consistency with other methods
- Ensure lazily initialization of sprite finders is completely thread safe
- Provide a default implementation for MutableQuadView/QuadEmitter.spriteBake
- Improve some documentation
* Add ModelBakeSettingsHelper
- Respect passed ModelBakeSettings in testmod custom Geometry implementations
- Add axis block state property to testmod octagonal column block and rotate model to test ModelBakeSettings application
* Make AoCalculator.vanillaFullFace work regardless of vertex order
- Use vertex map for cubic faces during enhanced light as well now that it works regardless of vertex order and is faster than using weights
- Fix typos in AoFaceData
* Finalization
- Remove Experimental annotations
- Deprecate Renderer.emitBlockModelPartQuads for removal
- Fix GeometryBakedModel.emitQuads not applying instance AO boolean
- Add RenderLayerHelper.movingDelegate/entityDelegate and use them where appropriate
- Clarify some javadoc
---
.../loading/BakedModelFeatureRenderer.java | 2 +-
.../fabric/api/renderer/v1/Renderer.java | 2 +-
.../api/renderer/v1/mesh/MutableQuadView.java | 31 ++-
.../api/renderer/v1/mesh/QuadEmitter.java | 5 +-
.../v1/model/FabricBlockModelPart.java | 11 +-
.../v1/model/FabricBlockStateModel.java | 2 +-
.../renderer/v1/model/MeshBakedGeometry.java | 13 +-
.../v1/model/ModelBakeSettingsHelper.java | 234 ++++++++++++++++++
.../api/renderer/v1/model/ModelHelper.java | 12 +-
.../api/renderer/v1/model/SpriteFinder.java | 49 ++--
.../v1/render/FabricBlockModelRenderer.java | 2 +-
.../v1/render/FabricBlockRenderManager.java | 2 +-
.../v1/render/FabricLayerRenderState.java | 3 +-
.../renderer/v1/render/RenderLayerHelper.java | 17 ++
.../v1/sprite/FabricAtlasPreparation.java | 33 +++
.../FabricErrorCollectingSpriteGetter.java | 34 +++
.../v1/sprite/FabricSpriteAtlasTexture.java | 44 ++++
.../v1/sprite/FabricStitchResult.java | 33 +++
.../fabric/impl/renderer/QuadSpriteBaker.java | 17 +-
.../impl/renderer/SpriteFinderImpl.java | 58 ++---
.../impl/renderer/StitchResultExtension.java | 26 ++
.../block/model/GeometryBakedModelMixin.java | 26 +-
.../FallingBlockEntityRendererMixin.java | 2 +-
.../PistonBlockEntityRendererMixin.java | 2 +-
.../SnowGolemPumpkinFeatureRendererMixin.java | 2 +-
.../client/item/BasicItemModelMixin.java | 3 +-
.../sprite/BakedModelManager1Mixin.java | 41 +++
.../ErrorCollectingSpriteGetterMixin.java | 27 ++
...riteAtlasManagerAtlasPreparationMixin.java | 39 +++
.../{ => sprite}/SpriteAtlasTextureMixin.java | 42 +++-
.../sprite/SpriteLoaderStitchResultMixin.java | 70 ++++++
.../fabric-renderer-api-v1.mixins.json | 8 +-
.../src/client/resources/fabric.mod.json | 6 +-
.../test/renderer/OctagonalColumnBlock.java | 4 +-
.../test/renderer/client/FrameGeometry.java | 3 +
.../client/OctagonalColumnGeometry.java | 3 +
.../test/renderer/client/PillarGeometry.java | 3 +
.../blockstates/octagonal_column.json | 26 +-
.../indigo/renderer/IndigoRenderer.java | 2 +-
.../indigo/renderer/aocalc/AoCalculator.java | 65 +++--
.../client/indigo/renderer/aocalc/AoFace.java | 5 +-
.../indigo/renderer/aocalc/AoFaceData.java | 32 ++-
.../renderer/helper/GeometryHelper.java | 86 +++++--
.../renderer/mesh/MutableQuadViewImpl.java | 8 -
.../renderer/render/ItemRenderContext.java | 4 +-
.../renderer/BlockRenderManagerMixin.java | 2 +-
46 files changed, 952 insertions(+), 189 deletions(-)
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelBakeSettingsHelper.java
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricAtlasPreparation.java
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricErrorCollectingSpriteGetter.java
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricSpriteAtlasTexture.java
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricStitchResult.java
rename fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/helper/TextureHelper.java => fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/QuadSpriteBaker.java (93%)
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/StitchResultExtension.java
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/renderer/client/sprite/BakedModelManager1Mixin.java
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/renderer/client/sprite/ErrorCollectingSpriteGetterMixin.java
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/renderer/client/sprite/SpriteAtlasManagerAtlasPreparationMixin.java
rename fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/renderer/client/{ => sprite}/SpriteAtlasTextureMixin.java (52%)
create mode 100644 fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/renderer/client/sprite/SpriteLoaderStitchResultMixin.java
diff --git a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelFeatureRenderer.java b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelFeatureRenderer.java
index d7dd6b92a9..8e8cdcd324 100644
--- a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelFeatureRenderer.java
+++ b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelFeatureRenderer.java
@@ -53,7 +53,7 @@ public class BakedModelFeatureRenderer vertexConsumers.getBuffer(RenderLayerHelper.getEntityBlockLayer(layer)), model, 1, 1, 1, light, OverlayTexture.DEFAULT_UV, EmptyBlockRenderView.INSTANCE, BlockPos.ORIGIN, Blocks.AIR.getDefaultState());
+ FabricBlockModelRenderer.render(matrices.peek(), RenderLayerHelper.entityDelegate(vertexConsumers), model, 1, 1, 1, light, OverlayTexture.DEFAULT_UV, EmptyBlockRenderView.INSTANCE, BlockPos.ORIGIN, Blocks.AIR.getDefaultState());
matrices.pop();
}
}
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/Renderer.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/Renderer.java
index f7095268c5..6774093f4b 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/Renderer.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/Renderer.java
@@ -146,7 +146,7 @@ public interface Renderer {
/**
* @see FabricBlockModelPart#emitQuads(QuadEmitter, Predicate)
*/
- @ApiStatus.Experimental
+ @Deprecated(forRemoval = true)
@ApiStatus.OverrideOnly
default void emitBlockModelPartQuads(BlockModelPart modelPart, QuadEmitter emitter, Predicate<@Nullable Direction> cullTest) {
VanillaBlockModelPartEncoder.emitQuads(modelPart, emitter, cullTest);
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/mesh/MutableQuadView.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/mesh/MutableQuadView.java
index f9aba41ed8..785c54ea41 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/mesh/MutableQuadView.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/mesh/MutableQuadView.java
@@ -29,6 +29,7 @@ import net.minecraft.util.math.Direction;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder;
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
+import net.fabricmc.fabric.impl.renderer.QuadSpriteBaker;
/**
* A mutable {@link QuadView} instance. The base interface for
@@ -41,46 +42,47 @@ import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
*/
public interface MutableQuadView extends QuadView {
/**
- * Causes texture to appear with no rotation.
+ * When enabled, causes texture to appear with no rotation. This is the default and does not have to be specified
+ * explicitly. Can be overridden by other rotation flags.
* Pass in bakeFlags parameter to {@link #spriteBake(Sprite, int)}.
*/
int BAKE_ROTATE_NONE = 0;
/**
- * Causes texture to appear rotated 90 deg. clockwise relative to nominal face.
+ * When enabled, causes texture to appear rotated 90 degrees clockwise.
* Pass in bakeFlags parameter to {@link #spriteBake(Sprite, int)}.
*/
int BAKE_ROTATE_90 = 1;
/**
- * Causes texture to appear rotated 180 deg. relative to nominal face.
+ * When enabled, causes texture to appear rotated 180 degrees.
* Pass in bakeFlags parameter to {@link #spriteBake(Sprite, int)}.
*/
int BAKE_ROTATE_180 = 2;
/**
- * Causes texture to appear rotated 270 deg. clockwise relative to nominal face.
+ * When enabled, causes texture to appear rotated 270 degrees clockwise.
* Pass in bakeFlags parameter to {@link #spriteBake(Sprite, int)}.
*/
int BAKE_ROTATE_270 = 3;
/**
- * When enabled, texture coordinate are assigned based on vertex position.
- * Any existing UV coordinates will be replaced.
+ * When enabled, texture coordinates are assigned based on vertex positions and the
+ * {@linkplain #nominalFace() nominal face}.
+ * Any existing UV coordinates will be replaced and the {@link #BAKE_NORMALIZED} flag will be ignored.
* Pass in bakeFlags parameter to {@link #spriteBake(Sprite, int)}.
*
- *
UV lock always derives texture coordinates based on nominal face, even
- * when the quad is not co-planar with that face, and the result is
- * the same as if the quad were projected onto the nominal face, which
- * is usually the desired result.
+ *
UV lock derives texture coordinates based on {@linkplain #nominalFace() nominal face} by projecting the quad
+ * onto it, even when the quad is not co-planar with it. This flag is ignored if the normal face is {@code null}.
*/
int BAKE_LOCK_UV = 4;
/**
- * When set, U texture coordinates for the given sprite are
+ * When enabled, U texture coordinates for the given sprite are
* flipped as part of baking. Can be useful for some randomization
* and texture mapping scenarios. Results are different from what
- * can be obtained via rotation and both can be applied.
+ * can be obtained via rotation and both can be applied. Any
+ * rotation is applied before this flag.
* Pass in bakeFlags parameter to {@link #spriteBake(Sprite, int)}.
*/
int BAKE_FLIP_U = 8;
@@ -168,7 +170,10 @@ public interface MutableQuadView extends QuadView {
* Can handle UV locking, rotation, interpolation, etc. Control this behavior
* by passing additive combinations of the BAKE_ flags defined in this interface.
*/
- MutableQuadView spriteBake(Sprite sprite, int bakeFlags);
+ default MutableQuadView spriteBake(Sprite sprite, int bakeFlags) {
+ QuadSpriteBaker.bakeSprite(this, sprite, bakeFlags);
+ return this;
+ }
/**
* Accept vanilla lightmap values. Input values will override lightmap values
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/mesh/QuadEmitter.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/mesh/QuadEmitter.java
index f0d7a1a284..a5bbe65b4c 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/mesh/QuadEmitter.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/mesh/QuadEmitter.java
@@ -78,7 +78,10 @@ public interface QuadEmitter extends MutableQuadView {
}
@Override
- QuadEmitter spriteBake(Sprite sprite, int bakeFlags);
+ default QuadEmitter spriteBake(Sprite sprite, int bakeFlags) {
+ MutableQuadView.super.spriteBake(sprite, bakeFlags);
+ return this;
+ }
default QuadEmitter uvUnitSquare() {
uv(0, 0, 0);
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBlockModelPart.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBlockModelPart.java
index 483232a049..ea4bf5f583 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBlockModelPart.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBlockModelPart.java
@@ -18,7 +18,6 @@ package net.fabricmc.fabric.api.renderer.v1.model;
import java.util.function.Predicate;
-import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import net.minecraft.block.BlockState;
@@ -32,15 +31,15 @@ import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
/**
- * Note: This interface is automatically implemented on all block model parts via Mixin and interface injection.
+ * Note: This interface is automatically implemented on {@link BlockModelPart} via Mixin and interface injection.
*/
-@ApiStatus.Experimental
public interface FabricBlockModelPart {
/**
* Produces this model part's geometry. This method must be called instead of
- * {@link BlockModelPart#getQuads(Direction)}; the vanilla method should be considered deprecated as it may not
- * produce accurate results. However, it is acceptable for a custom model part to only implement the vanilla
- * method as the default implementation of this method will delegate to the vanilla method.
+ * {@link BlockModelPart#getQuads(Direction)} and {@link BlockModelPart#useAmbientOcclusion()}; the vanilla methods
+ * should be considered deprecated as they may not produce accurate results. However, it is acceptable for a
+ * custom model part to only implement the vanilla methods as the default implementation of this method will
+ * delegate to the vanilla methods.
*
*
This method mainly exists for convenience when interacting with parts implemented and produced by vanilla
* code. Custom models should generally override
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBlockStateModel.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBlockStateModel.java
index 187e17c2dd..32cbd2dd41 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBlockStateModel.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/FabricBlockStateModel.java
@@ -41,7 +41,7 @@ import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
*
*
Implementors should have a look at {@link ModelHelper} as it contains many useful functions.
*
- *
Note: This interface is automatically implemented on all block state models via Mixin and interface injection.
+ *
Note: This interface is automatically implemented on {@link BlockStateModel} via Mixin and interface injection.
*/
public interface FabricBlockStateModel {
/**
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/MeshBakedGeometry.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/MeshBakedGeometry.java
index 596bbf5a88..35a451a127 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/MeshBakedGeometry.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/MeshBakedGeometry.java
@@ -18,21 +18,24 @@ package net.fabricmc.fabric.api.renderer.v1.model;
import java.util.List;
-import org.jetbrains.annotations.ApiStatus;
-
import net.minecraft.client.render.model.BakedGeometry;
import net.minecraft.client.render.model.BakedQuad;
+import net.minecraft.client.render.model.Baker;
+import net.minecraft.client.render.model.Geometry;
+import net.minecraft.client.render.model.ModelBakeSettings;
+import net.minecraft.client.render.model.ModelTextures;
+import net.minecraft.client.render.model.SimpleModel;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
/**
- * A special {@link BakedGeometry} which hides a {@link Mesh} instead of using {@link BakedQuad}s. Instances of this
- * class always return empty lists from inherited methods.
+ * A special {@link BakedGeometry} which hides a {@link Mesh} instead of using {@link BakedQuad}s. Useful for custom
+ * implementations of {@link Geometry#bake(ModelTextures, Baker, ModelBakeSettings, SimpleModel)} that want to return a
+ * mesh. Instances of this class always return empty lists from inherited methods.
*
*
Any code that interacts with {@link BakedGeometry} should first check {@code instanceof MeshBakedGeometry} and use
* {@link #getMesh()} if {@code true} or the vanilla methods otherwise.
*/
-@ApiStatus.Experimental
public final class MeshBakedGeometry extends BakedGeometry {
private final Mesh mesh;
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelBakeSettingsHelper.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelBakeSettingsHelper.java
new file mode 100644
index 0000000000..bf4efd9c7c
--- /dev/null
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelBakeSettingsHelper.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.api.renderer.v1.model;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+import org.joml.Matrix3f;
+import org.joml.Matrix4f;
+import org.joml.Matrix4fc;
+import org.joml.Vector3f;
+import org.joml.Vector4f;
+
+import net.minecraft.client.render.model.Geometry;
+import net.minecraft.client.render.model.ModelBakeSettings;
+import net.minecraft.client.render.model.ModelRotation;
+import net.minecraft.client.texture.Sprite;
+import net.minecraft.util.math.AffineTransformation;
+import net.minecraft.util.math.AffineTransformations;
+import net.minecraft.util.math.Direction;
+import net.minecraft.util.math.MatrixUtil;
+
+import net.fabricmc.fabric.api.renderer.v1.mesh.QuadTransform;
+
+/**
+ * Utilities to make it easier to work with {@link ModelBakeSettings}.
+ */
+public final class ModelBakeSettingsHelper {
+ private static final Direction[] DIRECTIONS = Direction.values();
+
+ private ModelBakeSettingsHelper() {
+ }
+
+ /**
+ * Creates a new {@link ModelBakeSettings} using the given transformation and enables UV lock if specified. Works
+ * exactly like {@link ModelRotation}, but allows an arbitrary transformation. Instances should be retained and
+ * reused, especially if UV lock is enabled, to avoid redoing costly computations.
+ */
+ public static ModelBakeSettings of(AffineTransformation transformation, boolean uvLock) {
+ Matrix4fc matrix = transformation.getMatrix();
+
+ if (MatrixUtil.isIdentity(matrix)) {
+ return ModelRotation.X0_Y0;
+ }
+
+ if (!uvLock) {
+ return new ModelBakeSettings() {
+ @Override
+ public AffineTransformation getRotation() {
+ return transformation;
+ }
+ };
+ }
+
+ Map faceTransformations = new EnumMap<>(Direction.class);
+ Map inverseFaceTransformations = new EnumMap<>(Direction.class);
+
+ for (Direction face : DIRECTIONS) {
+ Matrix4fc faceTransformation = AffineTransformations.getTransformed(transformation, face).getMatrix();
+ faceTransformations.put(face, faceTransformation);
+ inverseFaceTransformations.put(face, faceTransformation.invert(new Matrix4f()));
+ }
+
+ return new ModelBakeSettings() {
+ @Override
+ public AffineTransformation getRotation() {
+ return transformation;
+ }
+
+ @Override
+ public Matrix4fc forward(Direction face) {
+ return faceTransformations.get(face);
+ }
+
+ @Override
+ public Matrix4fc reverse(Direction face) {
+ return inverseFaceTransformations.get(face);
+ }
+ };
+ }
+
+ /**
+ * Creates a new {@link ModelBakeSettings} that is the product of the two given settings. Settings are represented
+ * by matrices, so this method follows the rules of matrix multiplication, namely that applying the resulting
+ * settings is (mostly) equivalent to applying the right settings and then the left settings. The only exception
+ * during standard application is cull face transformation, as the result must be clamped. Thus, applying a single
+ * premultiplied transformation generally yields better results than multiple applications.
+ */
+ public static ModelBakeSettings multiply(ModelBakeSettings left, ModelBakeSettings right) {
+ // Assumes face transformations are identity if main transformation is identity
+ if (MatrixUtil.isIdentity(left.getRotation().getMatrix())) {
+ return right;
+ } else if (MatrixUtil.isIdentity(right.getRotation().getMatrix())) {
+ return left;
+ }
+
+ AffineTransformation transformation = left.getRotation().multiply(right.getRotation());
+
+ boolean leftHasFaceTransformations = false;
+ boolean rightHasFaceTransformations = false;
+
+ // Assumes inverse face transformations are exactly inverse of regular face transformations
+ for (Direction face : DIRECTIONS) {
+ if (!leftHasFaceTransformations && !MatrixUtil.isIdentity(left.forward(face))) {
+ leftHasFaceTransformations = true;
+ }
+
+ if (!rightHasFaceTransformations && !MatrixUtil.isIdentity(right.forward(face))) {
+ rightHasFaceTransformations = true;
+ }
+ }
+
+ if (leftHasFaceTransformations & rightHasFaceTransformations) {
+ Map faceTransformations = new EnumMap<>(Direction.class);
+ Map inverseFaceTransformations = new EnumMap<>(Direction.class);
+
+ for (Direction face : DIRECTIONS) {
+ faceTransformations.put(face, left.forward(face).mul(right.forward(face), new Matrix4f()));
+ inverseFaceTransformations.put(face, right.reverse(face).mul(left.reverse(face), new Matrix4f()));
+ }
+
+ return new ModelBakeSettings() {
+ @Override
+ public AffineTransformation getRotation() {
+ return transformation;
+ }
+
+ @Override
+ public Matrix4fc forward(Direction face) {
+ return faceTransformations.get(face);
+ }
+
+ @Override
+ public Matrix4fc reverse(Direction face) {
+ return inverseFaceTransformations.get(face);
+ }
+ };
+ }
+
+ ModelBakeSettings faceTransformDelegate = leftHasFaceTransformations ? left : right;
+
+ return new ModelBakeSettings() {
+ @Override
+ public AffineTransformation getRotation() {
+ return transformation;
+ }
+
+ @Override
+ public Matrix4fc forward(Direction face) {
+ return faceTransformDelegate.forward(face);
+ }
+
+ @Override
+ public Matrix4fc reverse(Direction face) {
+ return faceTransformDelegate.reverse(face);
+ }
+ };
+ }
+
+ /**
+ * Creates a new {@link QuadTransform} that applies the given transformation. The sprite finder is used to look up
+ * the current sprite to correctly apply UV lock, if present in the transformation.
+ *
+ *
This method is most useful when creating custom implementations of {@link Geometry}, which receive a
+ * {@link ModelBakeSettings}.
+ */
+ public static QuadTransform asQuadTransform(ModelBakeSettings settings, SpriteFinder spriteFinder) {
+ Matrix4fc matrix = settings.getRotation().getMatrix();
+
+ // Assumes face transformations are identity if main transformation is identity
+ if (MatrixUtil.isIdentity(matrix)) {
+ return q -> true;
+ }
+
+ Matrix3f normalMatrix = matrix.normal(new Matrix3f());
+
+ Vector4f vec4 = new Vector4f();
+ Vector3f vec3 = new Vector3f();
+
+ return quad -> {
+ Direction lightFace = quad.lightFace();
+ Matrix4fc reverseMatrix = settings.reverse(lightFace);
+
+ if (!MatrixUtil.isIdentity(reverseMatrix)) {
+ Sprite sprite = spriteFinder.find(quad);
+
+ for (int vertexIndex = 0; vertexIndex < 4; vertexIndex++) {
+ float frameU = sprite.getFrameFromU(quad.u(vertexIndex));
+ float frameV = sprite.getFrameFromV(quad.v(vertexIndex));
+ vec3.set(frameU - 0.5f, frameV - 0.5f, 0.0f);
+ reverseMatrix.transformPosition(vec3);
+ frameU = vec3.x + 0.5f;
+ frameV = vec3.y + 0.5f;
+ quad.uv(vertexIndex, sprite.getFrameU(frameU), sprite.getFrameV(frameV));
+ }
+ }
+
+ for (int vertexIndex = 0; vertexIndex < 4; vertexIndex++) {
+ vec4.set(quad.x(vertexIndex) - 0.5f, quad.y(vertexIndex) - 0.5f, quad.z(vertexIndex) - 0.5f, 1.0f);
+ vec4.mul(matrix);
+ quad.pos(vertexIndex, vec4.x + 0.5f, vec4.y + 0.5f, vec4.z + 0.5f);
+
+ if (quad.hasNormal(vertexIndex)) {
+ quad.copyNormal(vertexIndex, vec3);
+ vec3.mul(normalMatrix);
+ vec3.normalize();
+ quad.normal(vertexIndex, vec3);
+ }
+ }
+
+ Direction cullFace = quad.cullFace();
+
+ if (cullFace != null) {
+ quad.cullFace(Direction.transform(matrix, cullFace));
+ }
+
+ return true;
+ };
+ }
+}
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelHelper.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelHelper.java
index e0639cac20..f74f6820be 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelHelper.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/ModelHelper.java
@@ -71,7 +71,7 @@ public final class ModelHelper {
*
Retrieves sprites from the block texture atlas via {@link SpriteFinder}.
*/
public static List[] toQuadLists(Mesh mesh) {
- SpriteFinder finder = SpriteFinder.get(MinecraftClient.getInstance().getBakedModelManager().getAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE));
+ SpriteFinder finder = MinecraftClient.getInstance().getBakedModelManager().getAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE).spriteFinder();
@SuppressWarnings("unchecked")
final ImmutableList.Builder[] builders = new ImmutableList.Builder[7];
@@ -80,12 +80,10 @@ public final class ModelHelper {
builders[i] = ImmutableList.builder();
}
- if (mesh != null) {
- mesh.forEach(q -> {
- Direction cullFace = q.cullFace();
- builders[cullFace == null ? NULL_FACE_ID : cullFace.getIndex()].add(q.toBakedQuad(finder.find(q)));
- });
- }
+ mesh.forEach(q -> {
+ Direction cullFace = q.cullFace();
+ builders[cullFace == null ? NULL_FACE_ID : cullFace.getIndex()].add(q.toBakedQuad(finder.find(q)));
+ });
@SuppressWarnings("unchecked")
List[] result = new List[7];
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/SpriteFinder.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/SpriteFinder.java
index 9c0c0d12e9..4ed0b54e4f 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/SpriteFinder.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/model/SpriteFinder.java
@@ -16,35 +16,42 @@
package net.fabricmc.fabric.api.renderer.v1.model;
+import java.util.function.Predicate;
+
import org.jetbrains.annotations.ApiStatus;
+import net.minecraft.block.BlockState;
+import net.minecraft.client.render.model.ErrorCollectingSpriteGetter;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.random.Random;
+import net.minecraft.world.BlockRenderView;
-import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
+import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
-import net.fabricmc.fabric.impl.renderer.SpriteFinderImpl;
+import net.fabricmc.fabric.api.renderer.v1.sprite.FabricAtlasPreparation;
+import net.fabricmc.fabric.api.renderer.v1.sprite.FabricErrorCollectingSpriteGetter;
+import net.fabricmc.fabric.api.renderer.v1.sprite.FabricSpriteAtlasTexture;
+import net.fabricmc.fabric.api.renderer.v1.sprite.FabricStitchResult;
/**
- * Indexes a texture atlas to allow fast lookup of Sprites from
- * baked vertex coordinates. Main use is for {@link Mesh}-based models
- * to generate vanilla quads on demand without tracking and retaining
- * the sprites that were baked into the mesh. In other words, this class
- * supplies the sprite parameter for {@link QuadView#toBakedQuad(Sprite)}.
+ * Indexes a texture atlas to allow fast lookup of {@link Sprite}s from baked texture coordinates.
+ *
+ *
Example use cases include interpolating the textures of a submodel's quads in
+ * {@link FabricBlockStateModel#emitQuads(QuadEmitter, BlockRenderView, BlockPos, BlockState, Random, Predicate)} or
+ * finding the sprite for use in {@link QuadView#toBakedQuad(Sprite)}.
+ *
+ *
A sprite finder can be retrieved from various vanilla objects. Always use
+ * {@link FabricErrorCollectingSpriteGetter#spriteFinder(Identifier)}, {@link FabricStitchResult#spriteFinder()}, or
+ * {@link FabricAtlasPreparation#spriteFinder()} whenever an applicable instance is available. For example, model
+ * baking is supplied with a {@link ErrorCollectingSpriteGetter}, so it should be used to retrieve the sprite finder.
+ * In most other cases, it is safe to use {@link FabricSpriteAtlasTexture#spriteFinder()}.
*/
@ApiStatus.NonExtendable
public interface SpriteFinder {
- /**
- * Retrieves or creates the finder for the given atlas.
- * Instances should not be retained as fields, or they must be
- * refreshed whenever there is a resource reload or other event
- * that causes atlas textures to be re-stitched.
- */
- static SpriteFinder get(SpriteAtlasTexture atlas) {
- return SpriteFinderImpl.get(atlas);
- }
-
/**
* Finds the atlas sprite containing the vertex centroid of the quad.
* Vertex centroid is essentially the mean u,v coordinate - the intent being
@@ -69,6 +76,14 @@ public interface SpriteFinder {
*/
Sprite find(float u, float v);
+ /**
+ * @deprecated Use {@link FabricSpriteAtlasTexture#spriteFinder()} instead.
+ */
+ @Deprecated
+ static SpriteFinder get(SpriteAtlasTexture atlas) {
+ return atlas.spriteFinder();
+ }
+
/**
* @deprecated Use {@link #find(QuadView)} instead.
*/
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricBlockModelRenderer.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricBlockModelRenderer.java
index 4fc3536201..e27058f53c 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricBlockModelRenderer.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricBlockModelRenderer.java
@@ -36,7 +36,7 @@ import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
/**
- * Note: This interface is automatically implemented on all block model renderers via Mixin and interface injection.
+ * Note: This interface is automatically implemented on {@link BlockModelRenderer} via Mixin and interface injection.
*/
public interface FabricBlockModelRenderer {
/**
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricBlockRenderManager.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricBlockRenderManager.java
index e3cbf5bffb..126456594e 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricBlockRenderManager.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricBlockRenderManager.java
@@ -33,7 +33,7 @@ import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
/**
- * Note: This interface is automatically implemented on all block render managers via Mixin and interface injection.
+ * Note: This interface is automatically implemented on {@link BlockRenderManager} via Mixin and interface injection.
*/
public interface FabricBlockRenderManager {
/**
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricLayerRenderState.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricLayerRenderState.java
index 3012030cd3..bbfa36dc60 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricLayerRenderState.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/FabricLayerRenderState.java
@@ -25,7 +25,8 @@ import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
/**
- * Note: This interface is automatically implemented on all layer render states via Mixin and interface injection.
+ * Note: This interface is automatically implemented on {@link ItemRenderState.LayerRenderState} via Mixin and interface
+ * injection.
*/
public interface FabricLayerRenderState {
/**
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/RenderLayerHelper.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/RenderLayerHelper.java
index 5ff3d4b474..60b2636bb9 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/RenderLayerHelper.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/render/RenderLayerHelper.java
@@ -20,6 +20,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.RenderLayers;
import net.minecraft.client.render.TexturedRenderLayers;
+import net.minecraft.client.render.VertexConsumerProvider;
public final class RenderLayerHelper {
private RenderLayerHelper() {
@@ -40,4 +41,20 @@ public final class RenderLayerHelper {
public static RenderLayer getEntityBlockLayer(RenderLayer chunkRenderLayer) {
return chunkRenderLayer == RenderLayer.getTranslucent() ? TexturedRenderLayers.getItemEntityTranslucentCull() : TexturedRenderLayers.getEntityCutout();
}
+
+ /**
+ * Wraps the given provider, converting {@linkplain RenderLayer#getBlockLayers() block layers} to render layers
+ * using {@link #getMovingBlockLayer(RenderLayer)}.
+ */
+ public static VertexConsumerProvider movingDelegate(VertexConsumerProvider vertexConsumers) {
+ return chunkRenderLayer -> vertexConsumers.getBuffer(RenderLayerHelper.getMovingBlockLayer(chunkRenderLayer));
+ }
+
+ /**
+ * Wraps the given provider, converting {@linkplain RenderLayer#getBlockLayers() block layers} to render layers
+ * using {@link #getEntityBlockLayer(RenderLayer)}.
+ */
+ public static VertexConsumerProvider entityDelegate(VertexConsumerProvider vertexConsumers) {
+ return chunkRenderLayer -> vertexConsumers.getBuffer(RenderLayerHelper.getEntityBlockLayer(chunkRenderLayer));
+ }
}
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricAtlasPreparation.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricAtlasPreparation.java
new file mode 100644
index 0000000000..8db5ce93cd
--- /dev/null
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricAtlasPreparation.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.api.renderer.v1.sprite;
+
+import net.minecraft.client.render.model.SpriteAtlasManager;
+
+import net.fabricmc.fabric.api.renderer.v1.model.SpriteFinder;
+
+/**
+ * Note: This interface is automatically implemented on {@link SpriteAtlasManager.AtlasPreparation} via Mixin and interface injection.
+ */
+public interface FabricAtlasPreparation {
+ /**
+ * {@return the sprite finder for this atlas preparation}
+ */
+ default SpriteFinder spriteFinder() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricErrorCollectingSpriteGetter.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricErrorCollectingSpriteGetter.java
new file mode 100644
index 0000000000..01c1e166ba
--- /dev/null
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricErrorCollectingSpriteGetter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.api.renderer.v1.sprite;
+
+import net.minecraft.client.render.model.ErrorCollectingSpriteGetter;
+import net.minecraft.util.Identifier;
+
+import net.fabricmc.fabric.api.renderer.v1.model.SpriteFinder;
+
+/**
+ * Note: This interface is automatically implemented on {@link ErrorCollectingSpriteGetter} via Mixin and interface injection.
+ */
+public interface FabricErrorCollectingSpriteGetter {
+ /**
+ * {@return the sprite finder for the given atlas ID}
+ */
+ default SpriteFinder spriteFinder(Identifier atlasId) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricSpriteAtlasTexture.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricSpriteAtlasTexture.java
new file mode 100644
index 0000000000..75da086eb9
--- /dev/null
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricSpriteAtlasTexture.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.api.renderer.v1.sprite;
+
+import net.minecraft.client.texture.SpriteAtlasTexture;
+import net.minecraft.client.texture.SpriteLoader;
+import net.minecraft.util.Identifier;
+
+import net.fabricmc.fabric.api.renderer.v1.model.SpriteFinder;
+
+/**
+ * Note: This interface is automatically implemented on {@link SpriteAtlasTexture} via Mixin and interface injection.
+ */
+public interface FabricSpriteAtlasTexture {
+ /**
+ * Retrieves the sprite finder for this atlas. The returned instance is only valid until the next call to
+ * {@link SpriteAtlasTexture#upload(SpriteLoader.StitchResult)}, and thus should not be persisted across resource
+ * reloads.
+ *
+ *
This method should not be used during a resource reload as this atlas will only be populated with new
+ * sprites towards the end of the resource reload. In this case, use
+ * {@link FabricErrorCollectingSpriteGetter#spriteFinder(Identifier)}, {@link FabricStitchResult#spriteFinder()},
+ * or {@link FabricAtlasPreparation#spriteFinder()} instead.
+ *
+ * @return the sprite finder for this atlas
+ */
+ default SpriteFinder spriteFinder() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricStitchResult.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricStitchResult.java
new file mode 100644
index 0000000000..76751f9c76
--- /dev/null
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/api/renderer/v1/sprite/FabricStitchResult.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.api.renderer.v1.sprite;
+
+import net.minecraft.client.texture.SpriteLoader;
+
+import net.fabricmc.fabric.api.renderer.v1.model.SpriteFinder;
+
+/**
+ * Note: This interface is automatically implemented on {@link SpriteLoader.StitchResult} via Mixin and interface injection.
+ */
+public interface FabricStitchResult {
+ /**
+ * {@return the sprite finder for this stitch result}
+ */
+ default SpriteFinder spriteFinder() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/helper/TextureHelper.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/QuadSpriteBaker.java
similarity index 93%
rename from fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/helper/TextureHelper.java
rename to fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/QuadSpriteBaker.java
index 4da833f9f0..4cd12d09b4 100644
--- a/fabric-renderer-indigo/src/client/java/net/fabricmc/fabric/impl/client/indigo/renderer/helper/TextureHelper.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/QuadSpriteBaker.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package net.fabricmc.fabric.impl.client.indigo.renderer.helper;
+package net.fabricmc.fabric.impl.renderer;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
@@ -23,11 +23,10 @@ import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
/**
* Handles most texture-baking use cases for model loaders and model libraries
- * via {@link #bakeSprite(MutableQuadView, Sprite, int)}. Also used by the API
- * itself to implement automatic block-breaking models for enhanced models.
+ * via {@link #bakeSprite(MutableQuadView, Sprite, int)}.
*/
-public final class TextureHelper {
- private TextureHelper() { }
+public final class QuadSpriteBaker {
+ private QuadSpriteBaker() { }
private static final float NORMALIZER = 1f / 16f;
@@ -101,11 +100,11 @@ public final class TextureHelper {
private static final VertexModifier[] UVLOCKERS = new VertexModifier[6];
static {
- UVLOCKERS[Direction.EAST.getIndex()] = (q, i) -> q.uv(i, 1 - q.z(i), 1 - q.y(i));
- UVLOCKERS[Direction.WEST.getIndex()] = (q, i) -> q.uv(i, q.z(i), 1 - q.y(i));
- UVLOCKERS[Direction.NORTH.getIndex()] = (q, i) -> q.uv(i, 1 - q.x(i), 1 - q.y(i));
- UVLOCKERS[Direction.SOUTH.getIndex()] = (q, i) -> q.uv(i, q.x(i), 1 - q.y(i));
UVLOCKERS[Direction.DOWN.getIndex()] = (q, i) -> q.uv(i, q.x(i), 1 - q.z(i));
UVLOCKERS[Direction.UP.getIndex()] = (q, i) -> q.uv(i, q.x(i), q.z(i));
+ UVLOCKERS[Direction.NORTH.getIndex()] = (q, i) -> q.uv(i, 1 - q.x(i), 1 - q.y(i));
+ UVLOCKERS[Direction.SOUTH.getIndex()] = (q, i) -> q.uv(i, q.x(i), 1 - q.y(i));
+ UVLOCKERS[Direction.WEST.getIndex()] = (q, i) -> q.uv(i, q.z(i), 1 - q.y(i));
+ UVLOCKERS[Direction.EAST.getIndex()] = (q, i) -> q.uv(i, 1 - q.z(i), 1 - q.y(i));
}
}
diff --git a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/SpriteFinderImpl.java b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/SpriteFinderImpl.java
index 8741f2a3a2..1d462e13c0 100644
--- a/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/SpriteFinderImpl.java
+++ b/fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/impl/renderer/SpriteFinderImpl.java
@@ -17,14 +17,12 @@
package net.fabricmc.fabric.impl.renderer;
import java.util.Map;
-import java.util.function.Consumer;
+import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import net.minecraft.client.texture.MissingSprite;
import net.minecraft.client.texture.Sprite;
-import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
@@ -43,12 +41,12 @@ public class SpriteFinderImpl implements SpriteFinder {
private static final Logger LOGGER = LoggerFactory.getLogger(SpriteFinderImpl.class);
private final Node root;
- private final SpriteAtlasTexture spriteAtlasTexture;
+ private final Sprite missingSprite;
private int badSpriteCount = 0;
- public SpriteFinderImpl(Map sprites, SpriteAtlasTexture spriteAtlasTexture) {
+ public SpriteFinderImpl(Map sprites, Sprite missingSprite) {
root = new Node(0.5f, 0.5f, 0.25f);
- this.spriteAtlasTexture = spriteAtlasTexture;
+ this.missingSprite = missingSprite;
sprites.values().forEach(root::add);
}
@@ -74,9 +72,14 @@ public class SpriteFinderImpl implements SpriteFinder {
final float midU;
final float midV;
final float cellRadius;
+
+ @Nullable
Object lowLow = null;
+ @Nullable
Object lowHigh = null;
+ @Nullable
Object highLow = null;
+ @Nullable
Object highHigh = null;
Node(float midU, float midV, float radius) {
@@ -105,36 +108,37 @@ public class SpriteFinderImpl implements SpriteFinder {
final boolean highV = sprite.getMaxV() > midV + EPS;
if (lowU && lowV) {
- addInner(sprite, lowLow, -1, -1, q -> lowLow = q);
+ lowLow = addInner(sprite, lowLow, -1, -1);
}
if (lowU && highV) {
- addInner(sprite, lowHigh, -1, 1, q -> lowHigh = q);
+ lowHigh = addInner(sprite, lowHigh, -1, 1);
}
if (highU && lowV) {
- addInner(sprite, highLow, 1, -1, q -> highLow = q);
+ highLow = addInner(sprite, highLow, 1, -1);
}
if (highU && highV) {
- addInner(sprite, highHigh, 1, 1, q -> highHigh = q);
+ highHigh = addInner(sprite, highHigh, 1, 1);
}
}
- private void addInner(Sprite sprite, Object quadrant, int uStep, int vStep, Consumer