Implement loader for ItemLayerModel.
Add support for specifying which layers are fullbright. Fix improper generation of model edge. - Thanks to iChun and KnightMiner for the fix suggestions.
This commit is contained in:
parent
0c0603dc91
commit
28f7b5d885
5 changed files with 124 additions and 33 deletions
|
@ -21,25 +21,31 @@ package net.minecraftforge.client.model;
|
|||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.JSONUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec2f;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
|
||||
import net.minecraftforge.client.model.pipeline.TRSRTransformer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
|
@ -59,15 +65,22 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
private static final Direction[] VERTICALS = {Direction.WEST, Direction.EAST};
|
||||
|
||||
private ImmutableList<Material> textures;
|
||||
|
||||
public ItemLayerModel(ImmutableList<Material> textures)
|
||||
{
|
||||
this.textures = textures;
|
||||
}
|
||||
private final ImmutableSet<Integer> fullbrightLayers;
|
||||
|
||||
public ItemLayerModel()
|
||||
{
|
||||
this.textures = null;
|
||||
this(null, ImmutableSet.of());
|
||||
}
|
||||
|
||||
public ItemLayerModel(ImmutableList<Material> textures)
|
||||
{
|
||||
this(textures, ImmutableSet.of());
|
||||
}
|
||||
|
||||
public ItemLayerModel(@Nullable ImmutableList<Material> textures, ImmutableSet<Integer> fullbrightLayers)
|
||||
{
|
||||
this.textures = textures;
|
||||
this.fullbrightLayers = fullbrightLayers;
|
||||
}
|
||||
|
||||
private static ImmutableList<Material> getTextures(IModelConfiguration model)
|
||||
|
@ -85,7 +98,7 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
{
|
||||
//TODO: Verify
|
||||
TransformationMatrix transform = modelTransform.getRotation();
|
||||
ImmutableList<BakedQuad> quads = getQuadsForSprites(textures, transform, spriteGetter);
|
||||
ImmutableList<BakedQuad> quads = getQuadsForSprites(textures, transform, spriteGetter, fullbrightLayers);
|
||||
TextureAtlasSprite particle = spriteGetter.apply(
|
||||
owner.isTexturePresent("particle") ? owner.resolveTexture("particle") : textures.get(0)
|
||||
);
|
||||
|
@ -94,17 +107,27 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
}
|
||||
|
||||
public static ImmutableList<BakedQuad> getQuadsForSprites(List<Material> textures, TransformationMatrix transform, Function<Material, TextureAtlasSprite> spriteGetter)
|
||||
{
|
||||
return getQuadsForSprites(textures, transform, spriteGetter, Collections.emptySet());
|
||||
}
|
||||
|
||||
public static ImmutableList<BakedQuad> getQuadsForSprites(List<Material> textures, TransformationMatrix transform, Function<Material, TextureAtlasSprite> spriteGetter, Set<Integer> fullbrights)
|
||||
{
|
||||
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
||||
for(int i = 0; i < textures.size(); i++)
|
||||
{
|
||||
TextureAtlasSprite tas = spriteGetter.apply(textures.get(i));
|
||||
builder.addAll(getQuadsForSprite(i, tas, transform));
|
||||
builder.addAll(getQuadsForSprite(i, tas, transform, fullbrights.contains(i)));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static ImmutableList<BakedQuad> getQuadsForSprite(int tint, TextureAtlasSprite sprite, TransformationMatrix transform)
|
||||
{
|
||||
return getQuadsForSprite(tint, sprite, transform, false);
|
||||
}
|
||||
|
||||
public static ImmutableList<BakedQuad> getQuadsForSprite(int tint, TextureAtlasSprite sprite, TransformationMatrix transform, boolean fullbright)
|
||||
{
|
||||
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
||||
|
||||
|
@ -124,7 +147,7 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
ptu = true;
|
||||
for(int u = 0; u < uMax; u++)
|
||||
{
|
||||
int alpha = sprite.getPixelRGBA(f, u, v) >> 24 & 0xFF;
|
||||
int alpha = sprite.getPixelRGBA(f, u, vMax - v - 1) >> 24 & 0xFF;
|
||||
boolean t = alpha / 255f <= 0.1f;
|
||||
|
||||
if (!t && alpha < 255)
|
||||
|
@ -195,7 +218,7 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
{
|
||||
// make quad [uStart, u]
|
||||
int off = facing == Direction.DOWN ? 1 : 0;
|
||||
builder.add(buildSideQuad(transform, facing, tint, sprite, uStart, v+off, u-uStart));
|
||||
builder.add(buildSideQuad(transform, facing, tint, sprite, uStart, v+off, u-uStart, fullbright));
|
||||
building = false;
|
||||
}
|
||||
else if (!building && face) // start new quad
|
||||
|
@ -209,7 +232,7 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
{
|
||||
// make quad [uStart, uEnd]
|
||||
int off = facing == Direction.DOWN ? 1 : 0;
|
||||
builder.add(buildSideQuad(transform, facing, tint, sprite, uStart, v+off, uEnd-uStart));
|
||||
builder.add(buildSideQuad(transform, facing, tint, sprite, uStart, v+off, uEnd-uStart, fullbright));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -242,7 +265,7 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
{
|
||||
// make quad [vStart, v]
|
||||
int off = facing == Direction.EAST ? 1 : 0;
|
||||
builder.add(buildSideQuad(transform, facing, tint, sprite, u+off, vStart, v-vStart));
|
||||
builder.add(buildSideQuad(transform, facing, tint, sprite, u+off, vStart, v-vStart, fullbright));
|
||||
building = false;
|
||||
}
|
||||
else if (!building && face) // start new quad
|
||||
|
@ -256,20 +279,20 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
{
|
||||
// make quad [vStart, vEnd]
|
||||
int off = facing == Direction.EAST ? 1 : 0;
|
||||
builder.add(buildSideQuad(transform, facing, tint, sprite, u+off, vStart, vEnd-vStart));
|
||||
builder.add(buildSideQuad(transform, facing, tint, sprite, u+off, vStart, vEnd-vStart, fullbright));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// front
|
||||
builder.add(buildQuad(transform, Direction.NORTH, sprite, tint,
|
||||
builder.add(buildQuad(transform, Direction.NORTH, sprite, tint, fullbright,
|
||||
0, 0, 7.5f / 16f, sprite.getMinU(), sprite.getMaxV(),
|
||||
0, 1, 7.5f / 16f, sprite.getMinU(), sprite.getMinV(),
|
||||
1, 1, 7.5f / 16f, sprite.getMaxU(), sprite.getMinV(),
|
||||
1, 0, 7.5f / 16f, sprite.getMaxU(), sprite.getMaxV()
|
||||
));
|
||||
// back
|
||||
builder.add(buildQuad(transform, Direction.SOUTH, sprite, tint,
|
||||
builder.add(buildQuad(transform, Direction.SOUTH, sprite, tint, fullbright,
|
||||
0, 0, 8.5f / 16f, sprite.getMinU(), sprite.getMaxV(),
|
||||
1, 0, 8.5f / 16f, sprite.getMaxU(), sprite.getMaxV(),
|
||||
1, 1, 8.5f / 16f, sprite.getMaxU(), sprite.getMinV(),
|
||||
|
@ -318,7 +341,7 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
}
|
||||
}
|
||||
|
||||
private static BakedQuad buildSideQuad(TransformationMatrix transform, Direction side, int tint, TextureAtlasSprite sprite, int u, int v, int size)
|
||||
private static BakedQuad buildSideQuad(TransformationMatrix transform, Direction side, int tint, TextureAtlasSprite sprite, int u, int v, int size, boolean fullbright)
|
||||
{
|
||||
final float eps = 1e-2f;
|
||||
|
||||
|
@ -357,7 +380,7 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
float v1 = 16f * (1f - y1 - dy);
|
||||
|
||||
return buildQuad(
|
||||
transform, remap(side), sprite, tint,
|
||||
transform, remap(side), sprite, tint, fullbright,
|
||||
x0, y0, z0, sprite.getInterpolatedU(u0), sprite.getInterpolatedV(v0),
|
||||
x1, y1, z0, sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1),
|
||||
x1, y1, z1, sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1),
|
||||
|
@ -371,7 +394,7 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
return side.getAxis() == Direction.Axis.Y ? side.getOpposite() : side;
|
||||
}
|
||||
|
||||
private static BakedQuad buildQuad(TransformationMatrix transform, Direction side, TextureAtlasSprite sprite, int tint,
|
||||
private static BakedQuad buildQuad(TransformationMatrix transform, Direction side, TextureAtlasSprite sprite, int tint, boolean fullbright,
|
||||
float x0, float y0, float z0, float u0, float v0,
|
||||
float x1, float y1, float z1, float u1, float v1,
|
||||
float x2, float y2, float z2, float u2, float v2,
|
||||
|
@ -381,24 +404,29 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
|
||||
builder.setQuadTint(tint);
|
||||
builder.setQuadOrientation(side);
|
||||
builder.setApplyDiffuseLighting(false);
|
||||
|
||||
boolean hasTransform = !transform.isIdentity();
|
||||
IVertexConsumer consumer = hasTransform ? new TRSRTransformer(builder, transform) : builder;
|
||||
|
||||
putVertex(consumer, side, x0, y0, z0, u0, v0);
|
||||
putVertex(consumer, side, x1, y1, z1, u1, v1);
|
||||
putVertex(consumer, side, x2, y2, z2, u2, v2);
|
||||
putVertex(consumer, side, x3, y3, z3, u3, v3);
|
||||
int uLight, vLight;
|
||||
uLight = vLight = fullbright ? 15 : 0;
|
||||
|
||||
putVertex(consumer, side, x0, y0, z0, u0, v0, uLight, vLight);
|
||||
putVertex(consumer, side, x1, y1, z1, u1, v1, uLight, vLight);
|
||||
putVertex(consumer, side, x2, y2, z2, u2, v2, uLight, vLight);
|
||||
putVertex(consumer, side, x3, y3, z3, u3, v3, uLight, vLight);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static void putVertex(IVertexConsumer consumer, Direction side, float x, float y, float z, float u, float v)
|
||||
private static void putVertex(IVertexConsumer consumer, Direction side, float x, float y, float z, float u, float v, int uLight, int vLight)
|
||||
{
|
||||
VertexFormat format = consumer.getVertexFormat();
|
||||
for(int e = 0; e < format.getElements().size(); e++)
|
||||
{
|
||||
switch(format.getElements().get(e).getUsage())
|
||||
VertexFormatElement element = format.getElements().get(e);
|
||||
outer:switch(element.getUsage())
|
||||
{
|
||||
case POSITION:
|
||||
consumer.put(e, x, y, z, 1f);
|
||||
|
@ -413,10 +441,14 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
consumer.put(e, offX, offY, offZ, 0f);
|
||||
break;
|
||||
case UV:
|
||||
if(format.getElements().get(e).getIndex() == 0)
|
||||
switch(element.getIndex())
|
||||
{
|
||||
case 0:
|
||||
consumer.put(e, u, v, 0f, 1f);
|
||||
break;
|
||||
break outer;
|
||||
case 2:
|
||||
consumer.put(e, (uLight<<4)/32768.0f, (vLight<<4)/32768.0f, 0, 1);
|
||||
break outer;
|
||||
}
|
||||
// else fallthrough to default
|
||||
default:
|
||||
|
@ -425,4 +457,30 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Loader implements IModelLoader<ItemLayerModel>
|
||||
{
|
||||
public static final Loader INSTANCE = new Loader();
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(IResourceManager resourceManager)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemLayerModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents)
|
||||
{
|
||||
ImmutableSet.Builder<Integer> fullbrightLayers = ImmutableSet.builder();
|
||||
if (modelContents.has("fullbright_layers"))
|
||||
{
|
||||
JsonArray arr = JSONUtils.getJsonArray(modelContents, "fullbright_layers");
|
||||
for(int i=0;i<arr.size();i++)
|
||||
{
|
||||
fullbrightLayers.add(arr.get(i).getAsInt());
|
||||
}
|
||||
}
|
||||
return new ItemLayerModel(null, fullbrightLayers.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ public class ModelLoaderRegistry
|
|||
registerLoader(new ResourceLocation("forge","bucket"), DynamicBucketModel.Loader.INSTANCE);
|
||||
registerLoader(new ResourceLocation("forge","composite"), CompositeModel.Loader.INSTANCE);
|
||||
registerLoader(new ResourceLocation("forge","multi-layer"), MultiLayerModel.Loader.INSTANCE);
|
||||
registerLoader(new ResourceLocation("forge","item-layers"), ItemLayerModel.Loader.INSTANCE);
|
||||
|
||||
// TODO: Implement as new model loaders
|
||||
//registerLoader(new ResourceLocation("forge:b3d"), new ModelLoaderAdapter(B3DLoader.INSTANCE));
|
||||
|
|
|
@ -118,6 +118,10 @@ public class NewModelLoaderTest
|
|||
new Item(new Item.Properties().group(ItemGroup.MISC))
|
||||
);
|
||||
|
||||
public static RegistryObject<Item> item_layers = ITEMS.register("item_layers", () ->
|
||||
new Item(new Item.Properties().group(ItemGroup.MISC))
|
||||
);
|
||||
|
||||
public NewModelLoaderTest()
|
||||
{
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug.client.rendering;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"parent": "forge:item/default",
|
||||
"loader": "forge:item-layers",
|
||||
"textures": {
|
||||
"layer0": "minecraft:item/coal",
|
||||
"layer1": "minecraft:item/stick"
|
||||
},
|
||||
"fullbright_layers": [ 1 ]
|
||||
}
|
Loading…
Reference in a new issue