mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
Rendering tweaks and fixes: Part 4 (#9065)
This commit is contained in:
1 parent
97a9ca65f1
commit
2d3ee8a228
9 files changed
+82
-39
No files matched your search
@@ -23,10 +23,12 @@ import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.ChunkRenderTypeSet;
|
||||
import net.minecraftforge.client.RenderTypeGroup;
|
||||
@@ -169,6 +171,15 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel>
|
||||
return ConcatenatedListView.of(quadLists);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ModelData getModelData(@NotNull BlockAndTintGetter level, @NotNull BlockPos pos, @NotNull BlockState state, @NotNull ModelData modelData)
|
||||
{
|
||||
var builder = Data.builder();
|
||||
for (var entry : children.entrySet())
|
||||
builder.with(entry.getKey(), entry.getValue().getModelData(level, pos, state, Data.resolve(modelData, entry.getKey())));
|
||||
return modelData.derive().with(Data.PROPERTY, builder.build()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion()
|
||||
{
|
||||
|
||||
@@ -62,9 +62,11 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
|
||||
if (deprecatedLoader)
|
||||
LOGGER.warn("Model \"" + modelLocation + "\" is using the deprecated loader \"minecraft:elements\" instead of \"forge:elements\". This loader will be removed in 1.20.");
|
||||
|
||||
var rootTransform = context.getRootTransform();
|
||||
if (!rootTransform.isIdentity())
|
||||
modelState = new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
|
||||
// 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()));
|
||||
|
||||
for (BlockElement element : elements)
|
||||
{
|
||||
@@ -73,6 +75,7 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
|
||||
var face = element.faces.get(direction);
|
||||
var sprite = spriteGetter.apply(context.getMaterial(face.texture));
|
||||
var quad = BlockModel.bakeFace(element, face, sprite, direction, modelState, modelLocation);
|
||||
postTransform.processInPlace(quad);
|
||||
|
||||
if (face.cullForDirection == null)
|
||||
modelBuilder.addUnculledFace(quad);
|
||||
|
||||
@@ -64,7 +64,7 @@ public final class QuadTransformers {
|
||||
{
|
||||
int offset = i * IQuadTransformer.STRIDE + IQuadTransformer.NORMAL;
|
||||
int normalIn = vertices[offset];
|
||||
if ((normalIn >> 8) != 0)
|
||||
if ((normalIn & 0x00FFFFFF) != 0) // The ignored byte is padding and may be filled with user data
|
||||
{
|
||||
float x = ((byte) (normalIn & 0xFF)) / 127.0f;
|
||||
float y = ((byte) ((normalIn >> 8) & 0xFF)) / 127.0f;
|
||||
@@ -72,12 +72,11 @@ public final class QuadTransformers {
|
||||
|
||||
Vector3f pos = new Vector3f(x, y, z);
|
||||
transform.transformNormal(pos);
|
||||
pos.normalize();
|
||||
|
||||
vertices[offset] = (((byte) (x * 127.0f)) & 0xFF) |
|
||||
((((byte) (y * 127.0f)) & 0xFF) << 8) |
|
||||
((((byte) (z * 127.0f)) & 0xFF) << 16) |
|
||||
(normalIn & 0xFF000000);
|
||||
vertices[offset] = (((byte) (pos.x() * 127.0f)) & 0xFF) |
|
||||
((((byte) (pos.y() * 127.0f)) & 0xFF) << 8) |
|
||||
((((byte) (pos.z() * 127.0f)) & 0xFF) << 16) |
|
||||
(normalIn & 0xFF000000); // Restore padding, just in case
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -19,12 +19,13 @@ import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.BuiltInModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.RenderTypeGroup;
|
||||
import net.minecraftforge.client.model.ElementsModel;
|
||||
import net.minecraftforge.client.model.IModelBuilder;
|
||||
import net.minecraftforge.client.model.SimpleModelState;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -98,17 +99,30 @@ public class UnbakedGeometryHelper
|
||||
if (customModel != null)
|
||||
return customModel.bake(blockModel.customData, modelBakery, spriteGetter, modelState, blockModel.getOverrides(modelBakery, owner, spriteGetter), modelLocation);
|
||||
|
||||
Transformation rootTransform = blockModel.customData.getRootTransform();
|
||||
if (!rootTransform.isIdentity())
|
||||
modelState = new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
|
||||
|
||||
// Handle vanilla item models here, since vanilla has a shortcut for them
|
||||
if (blockModel.getRootModel() == ModelBakery.GENERATION_MARKER)
|
||||
return ITEM_MODEL_GENERATOR.generateBlockModel(spriteGetter, blockModel).bake(modelBakery, blockModel, spriteGetter, modelState, modelLocation, guiLight3d);
|
||||
|
||||
var renderTypeHint = blockModel.customData.getRenderTypeHint();
|
||||
var renderTypes = renderTypeHint != null ? blockModel.customData.getRenderType(renderTypeHint) : RenderTypeGroup.EMPTY;
|
||||
return blockModel.bakeVanilla(modelBakery, owner, spriteGetter, modelState, modelLocation, guiLight3d, renderTypes);
|
||||
return bakeVanilla(blockModel, modelBakery, owner, spriteGetter, modelState, modelLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for baking vanilla {@link BlockModel} instances.
|
||||
*
|
||||
* @deprecated Merge into the method above in 1.20 once the call from {@link BlockModel} is gone.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(forRemoval = true, since = "1.19.2")
|
||||
public static BakedModel bakeVanilla(BlockModel blockModel, ModelBakery modelBakery, BlockModel owner, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ResourceLocation modelLocation)
|
||||
{
|
||||
if (blockModel.getRootModel() == ModelBakery.BLOCK_ENTITY_MARKER)
|
||||
{
|
||||
var particleSprite = spriteGetter.apply(blockModel.getMaterial("particle"));
|
||||
return new BuiltInModel(blockModel.getTransforms(), blockModel.getOverrides(modelBakery, owner, spriteGetter), particleSprite, blockModel.getGuiLight().lightLikeBlock());
|
||||
}
|
||||
|
||||
var elementsModel = new ElementsModel(blockModel.getElements());
|
||||
return elementsModel.bake(blockModel.customData, modelBakery, spriteGetter, modelState, blockModel.getOverrides(modelBakery, owner, spriteGetter), modelLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,7 +68,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
new Vec2(1, 0),
|
||||
};
|
||||
|
||||
private final Map<String, ModelGroup> parts = Maps.newHashMap();
|
||||
private final Map<String, ModelGroup> parts = Maps.newLinkedHashMap();
|
||||
private final Set<String> rootComponentNames = Collections.unmodifiableSet(parts.keySet());
|
||||
private Set<String> allComponentNames;
|
||||
|
||||
@@ -402,8 +402,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
faceNormal = abs;
|
||||
}
|
||||
|
||||
var quad = new BakedQuad[1];
|
||||
var quadBaker = new QuadBakingVertexConsumer(q -> quad[0] = q);
|
||||
var quadBaker = new QuadBakingVertexConsumer.Buffered();
|
||||
|
||||
quadBaker.setSprite(texture);
|
||||
quadBaker.setTintIndex(tintIndex);
|
||||
@@ -516,7 +515,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
}
|
||||
}
|
||||
|
||||
return Pair.of(quad[0], cull);
|
||||
return Pair.of(quadBaker.getQuad(), cull);
|
||||
}
|
||||
|
||||
public CompositeRenderable bakeRenderable(IGeometryBakingContext configuration)
|
||||
@@ -582,7 +581,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
|
||||
public class ModelGroup extends ModelObject
|
||||
{
|
||||
final Map<String, ModelObject> parts = Maps.newHashMap();
|
||||
final Map<String, ModelObject> parts = Maps.newLinkedHashMap();
|
||||
|
||||
ModelGroup(String name)
|
||||
{
|
||||
@@ -652,9 +651,11 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
int tintIndex = mat.diffuseTintIndex;
|
||||
Vector4f colorTint = mat.diffuseColor;
|
||||
|
||||
var rootTransform = owner.getRootTransform();
|
||||
var transform = rootTransform.isIdentity() ? modelTransform.getRotation() : modelTransform.getRotation().compose(rootTransform);
|
||||
for (int[][] face : faces)
|
||||
{
|
||||
Pair<BakedQuad, Direction> quad = makeQuad(face, tintIndex, colorTint, mat.ambientColor, texture, modelTransform.getRotation());
|
||||
Pair<BakedQuad, Direction> quad = makeQuad(face, tintIndex, colorTint, mat.ambientColor, texture, transform);
|
||||
if (quad.getRight() == null)
|
||||
modelBuilder.addUnculledFace(quad.getLeft());
|
||||
else
|
||||
|
||||
+25
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.client.model.pipeline;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.blaze3d.vertex.VertexFormatElement;
|
||||
@@ -37,7 +38,7 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
|
||||
private final Consumer<BakedQuad> quadConsumer;
|
||||
|
||||
private int vertexIndex = 0;
|
||||
int vertexIndex = 0;
|
||||
private int[] quadData = new int[QUAD_DATA_SIZE];
|
||||
|
||||
private int tintIndex;
|
||||
@@ -167,4 +168,27 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
{
|
||||
this.hasAmbientOcclusion = hasAmbientOcclusion;
|
||||
}
|
||||
|
||||
public static class Buffered extends QuadBakingVertexConsumer
|
||||
{
|
||||
private final BakedQuad[] output;
|
||||
|
||||
public Buffered()
|
||||
{
|
||||
this(new BakedQuad[1]);
|
||||
}
|
||||
|
||||
private Buffered(BakedQuad[] output)
|
||||
{
|
||||
super(q -> output[0] = q);
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public BakedQuad getQuad()
|
||||
{
|
||||
var quad = Preconditions.checkNotNull(output[0], "No quad has been emitted. Vertices in buffer: " + vertexIndex);
|
||||
output[0] = null;
|
||||
return quad;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user