IModel can now depend on a variant definition (ModelResourceLocation); added MultiLayerModel - simple model that'll render correctly in multiple layers + example of using it.

This commit is contained in:
RainWarrior committed 2015-12-15 21:49:19 +03:00
1 parent d6ee373e87
commit 86c09722a0
8 files changed
+374 -18

No files matched your search

@@ -68,6 +68,24 @@ public interface IPerspectiveAwareModel extends IFlexibleBakedModel
return builder.build();
}
public static Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(IFlexibleBakedModel model, ImmutableMap<TransformType, TRSRTransformation> transforms, TransformType cameraTransformType)
{
TRSRTransformation tr = transforms.get(cameraTransformType);
Matrix4f mat = null;
if(tr != null && tr != TRSRTransformation.identity()) mat = TRSRTransformation.blockCornerToCenter(tr).getMatrix();
return Pair.of(model, mat);
}
public static Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(IFlexibleBakedModel model, IModelState state, TransformType cameraTransformType)
{
TRSRTransformation tr = state.apply(Optional.of(cameraTransformType)).or(TRSRTransformation.identity());
if(tr != TRSRTransformation.identity())
{
return Pair.of(model, TRSRTransformation.blockCornerToCenter(tr).getMatrix());
}
return Pair.of(model, null);
}
public boolean isAmbientOcclusion() { return parent.isAmbientOcclusion(); }
public boolean isGui3d() { return parent.isGui3d(); }
public boolean isBuiltInRenderer() { return parent.isBuiltInRenderer(); }
@@ -80,10 +98,7 @@ public interface IPerspectiveAwareModel extends IFlexibleBakedModel
@Override
public Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
{
TRSRTransformation tr = transforms.get(cameraTransformType);
Matrix4f mat = null;
if(tr != null && tr != TRSRTransformation.identity()) mat = TRSRTransformation.blockCornerToCenter(tr).getMatrix();
return Pair.of(this, mat);
return handlePerspective(this, transforms, cameraTransformType);
}
}
}
@@ -227,8 +227,14 @@ public class ModelLoader extends ModelBakery
IModel model = ModelLoaderRegistry.getModel(location);
for (ResourceLocation dep : model.getDependencies())
{
getModel(dep);
if(dep instanceof ModelResourceLocation)
{
loadVariants(ImmutableList.of((ModelResourceLocation)dep));
}
else
{
getModel(dep);
}
}
textures.addAll(model.getTextures());
}
@@ -33,6 +33,7 @@ public class ModelLoaderRegistry
registerLoader(OBJLoader.instance);
registerLoader(ModelFluid.FluidLoader.instance);
registerLoader(ItemLayerModel.Loader.instance);
registerLoader(MultiLayerModel.Loader.instance);
}
/*
@@ -0,0 +1,261 @@
package net.minecraftforge.client.model;
import java.util.Collection;
import java.util.List;
import javax.vecmath.Matrix4f;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumWorldBlockLayer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.client.model.ItemLayerModel.BakedModel;
import net.minecraftforge.fml.common.FMLLog;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class MultiLayerModel implements IModelCustomData
{
public static final MultiLayerModel instance = new MultiLayerModel(ImmutableMap.of());
private final ImmutableMap<Optional<EnumWorldBlockLayer>, ModelResourceLocation> models;
public MultiLayerModel(ImmutableMap<Optional<EnumWorldBlockLayer>, ModelResourceLocation> models)
{
this.models = models;
}
@Override
public Collection<ResourceLocation> getDependencies()
{
return ImmutableList.<ResourceLocation>copyOf(models.values());
}
@Override
public Collection<ResourceLocation> getTextures()
{
return ImmutableList.of();
}
@Override
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
{
return new MultiLayerBakedModel(models, format, IPerspectiveAwareModel.MapWrapper.getTransforms(state));
}
@Override
public IModelState getDefaultState()
{
return TRSRTransformation.identity();
}
@Override
public IModel process(ImmutableMap<String, String> customData)
{
ImmutableMap.Builder<Optional<EnumWorldBlockLayer>, ModelResourceLocation> builder = ImmutableMap.builder();
for(String key : customData.keySet())
{
if("base".equals(key))
{
builder.put(Optional.absent(), getLocation(customData.get(key)));
}
for(EnumWorldBlockLayer layer : EnumWorldBlockLayer.values())
{
if(layer.toString().equals(key))
{
builder.put(Optional.of(layer), getLocation(customData.get(key)));
}
}
}
ImmutableMap<Optional<EnumWorldBlockLayer>, ModelResourceLocation> models = builder.build();
if(models.isEmpty()) return instance;
return new MultiLayerModel(models);
}
private ModelResourceLocation getLocation(String json)
{
JsonElement e = new JsonParser().parse(json);
if(e.isJsonPrimitive() && e.getAsJsonPrimitive().isString())
{
return new ModelResourceLocation(e.getAsString());
}
FMLLog.severe("Expect ModelResourceLocation, got: ", json);
return new ModelResourceLocation("builtin/missing", "missing");
}
public static class MultiLayerBakedModel implements IFlexibleBakedModel, ISmartBlockModel, IPerspectiveAwareModel
{
private final ImmutableMap<Optional<EnumWorldBlockLayer>, ModelResourceLocation> models;
private final VertexFormat format;
private final ImmutableMap<TransformType, TRSRTransformation> cameraTransforms;;
private IBakedModel base;
private ImmutableMap<EnumWorldBlockLayer, IBakedModel> bakedModels;
private ImmutableMap<Optional<EnumFacing>, ImmutableList<BakedQuad>> quads;
public MultiLayerBakedModel(ImmutableMap<Optional<EnumWorldBlockLayer>, ModelResourceLocation> models, VertexFormat format, ImmutableMap<TransformType, TRSRTransformation> cameraTransforms)
{
this.models = models;
this.format = format;
this.cameraTransforms = cameraTransforms;
}
private void compute()
{
if(base == null)
{
ModelManager manager = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelManager();
base = getModel(manager, Optional.absent());
ImmutableMap.Builder<EnumWorldBlockLayer, IBakedModel> builder = ImmutableMap.builder();
for(EnumWorldBlockLayer layer : EnumWorldBlockLayer.values())
{
if(models.containsKey(Optional.of(layer)))
{
builder.put(layer, getModel(manager, Optional.of(layer)));
}
}
bakedModels = builder.build();
ImmutableMap.Builder<Optional<EnumFacing>, ImmutableList<BakedQuad>> quadBuilder = ImmutableMap.builder();
quadBuilder.put(Optional.absent(), buildQuads(Optional.absent()));
for(EnumFacing side: EnumFacing.values())
{
quadBuilder.put(Optional.of(side), buildQuads(Optional.of(side)));
}
quads = quadBuilder.build();
}
}
private IBakedModel getModel(ModelManager manager, Optional<EnumWorldBlockLayer> layer)
{
ModelResourceLocation loc = models.get(layer);
if(loc == null)
{
loc = new ModelResourceLocation("builtin/missing", "missing");
}
return manager.getModel(loc);
}
private ImmutableList<BakedQuad> buildQuads(Optional<EnumFacing> side)
{
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
for(IBakedModel model : bakedModels.values())
{
if(side.isPresent())
{
builder.addAll(model.getFaceQuads(side.get()));
}
else
{
builder.addAll(model.getGeneralQuads());
}
}
return builder.build();
}
@Override
public List<BakedQuad> getFaceQuads(EnumFacing side)
{
compute();
return quads.get(Optional.of(side));
}
@Override
public List<BakedQuad> getGeneralQuads()
{
compute();
return quads.get(Optional.absent());
}
@Override
public boolean isAmbientOcclusion()
{
compute();
return base.isAmbientOcclusion();
}
@Override
public boolean isGui3d()
{
compute();
return base.isGui3d();
}
@Override
public boolean isBuiltInRenderer()
{
compute();
return base.isBuiltInRenderer();
}
@Override
public TextureAtlasSprite getTexture()
{
compute();
return base.getTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return ItemCameraTransforms.DEFAULT;
}
@Override
public IBakedModel handleBlockState(IBlockState state)
{
compute();
return bakedModels.get(MinecraftForgeClient.getRenderLayer());
}
@Override
public VertexFormat getFormat()
{
return format;
}
@Override
public Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
{
return IPerspectiveAwareModel.MapWrapper.handlePerspective(this, cameraTransforms, cameraTransformType);
}
}
public static enum Loader implements ICustomModelLoader
{
instance;
public void onResourceManagerReload(IResourceManager resourceManager) {}
public boolean accepts(ResourceLocation modelLocation)
{
return modelLocation.getResourceDomain().equals("forge") && (
modelLocation.getResourcePath().equals("multi-layer") ||
modelLocation.getResourcePath().equals("models/block/multi-layer") ||
modelLocation.getResourcePath().equals("models/item/multi-layer"));
}
public IModel loadModel(ResourceLocation modelLocation)
{
return MultiLayerModel.instance;
}
}
}
@@ -995,12 +995,7 @@ public class B3DLoader implements ICustomModelLoader
public Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
{
TRSRTransformation tr = state.apply(Optional.of(cameraTransformType)).or(TRSRTransformation.identity());
if(tr != TRSRTransformation.identity())
{
return Pair.of(this, TRSRTransformation.blockCornerToCenter(tr).getMatrix());
}
return Pair.of(this, null);
return IPerspectiveAwareModel.MapWrapper.handlePerspective(this, state, cameraTransformType);
}
}
}
@@ -1575,12 +1575,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
@Override
public Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
{
TRSRTransformation tr = state.apply(Optional.of(cameraTransformType)).or(TRSRTransformation.identity());
if(tr != TRSRTransformation.identity())
{
return Pair.of(this, TRSRTransformation.blockCornerToCenter(tr).getMatrix());
}
return Pair.of(this, null);
return IPerspectiveAwareModel.MapWrapper.handlePerspective(this, state, cameraTransformType);
}
@Override