Preparations for the Animation system.

Changes to the Model API - IModelState now works with Optional. Handling of parts of the model is not optional, and coordinate space/result interpretation is up to the caller. IModel doesn't extend IModelPart by default anymore; MapModelState uses composition to achieve previous functionality, IModelPart implementations are disjoint now. Updated perspective handing to the new API, removed IPerspectiveState (MapModelState is now the same thing). Perspective transforms for the default fluid model.
This commit is contained in:
RainWarrior 2015-12-03 22:38:08 +03:00
parent 9032f7e37e
commit d6ee373e87
25 changed files with 553 additions and 248 deletions

View file

@ -12,3 +12,12 @@
public class ItemCameraTransforms
{
public static final ItemCameraTransforms field_178357_a = new ItemCameraTransforms();
@@ -117,7 +121,7 @@
}
@SideOnly(Side.CLIENT)
- public static enum TransformType
+ public static enum TransformType implements net.minecraftforge.client.model.IModelPart
{
NONE,
THIRD_PERSON,

View file

@ -12,7 +12,7 @@
+@Deprecated
+public class ItemTransformVec3f implements net.minecraftforge.client.model.IModelState
{
+ public net.minecraftforge.client.model.TRSRTransformation apply(net.minecraftforge.client.model.IModelPart part) { return new net.minecraftforge.client.model.TRSRTransformation(this); }
+ public com.google.common.base.Optional<net.minecraftforge.client.model.TRSRTransformation> apply(com.google.common.base.Optional<? extends net.minecraftforge.client.model.IModelPart> part) { return net.minecraftforge.client.ForgeHooksClient.applyTransform(this, part); }
public static final ItemTransformVec3f field_178366_a = new ItemTransformVec3f(new Vector3f(), new Vector3f(), new Vector3f(1.0F, 1.0F, 1.0F));
public final Vector3f field_178364_b;
public final Vector3f field_178365_c;

View file

@ -14,7 +14,7 @@
}
}
+
+ public net.minecraftforge.client.model.TRSRTransformation apply(net.minecraftforge.client.model.IModelPart part) { return new net.minecraftforge.client.model.TRSRTransformation(getMatrix()); }
+ public com.google.common.base.Optional<net.minecraftforge.client.model.TRSRTransformation> apply(com.google.common.base.Optional<? extends net.minecraftforge.client.model.IModelPart> part) { return net.minecraftforge.client.ForgeHooksClient.applyTransform(getMatrix(), part); }
+ public javax.vecmath.Matrix4f getMatrix() { return net.minecraftforge.client.ForgeHooksClient.getMatrix(this); }
+ public EnumFacing rotate(EnumFacing facing) { return func_177523_a(facing); }
+ public int rotate(EnumFacing facing, int vertexIndex) { return func_177520_a(facing, vertexIndex); }

View file

@ -70,6 +70,8 @@ import net.minecraftforge.client.event.RenderHandEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.event.sound.PlaySoundEvent;
import net.minecraftforge.client.model.IFlexibleBakedModel;
import net.minecraftforge.client.model.IModelPart;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.TRSRTransformation;
@ -82,8 +84,8 @@ import net.minecraftforge.fml.common.FMLLog;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import com.google.common.base.Optional;
import com.google.common.collect.Maps;
@SuppressWarnings("deprecation")
@ -111,7 +113,7 @@ public class ForgeHooksClient
if (block != null && block.isBed(world, pos, entity))
{
GL11.glRotatef((float)(block.getBedDirection(world, pos).getHorizontalIndex() * 90), 0.0F, 1.0F, 0.0F);
glRotatef((float)(block.getBedDirection(world, pos).getHorizontalIndex() * 90), 0.0F, 1.0F, 0.0F);
}
}
@ -378,7 +380,7 @@ public class ForgeHooksClient
{
if(model instanceof IPerspectiveAwareModel)
{
Pair<IBakedModel, Matrix4f> pair = ((IPerspectiveAwareModel)model).handlePerspective(cameraTransformType);
Pair<? extends IFlexibleBakedModel, Matrix4f> pair = ((IPerspectiveAwareModel)model).handlePerspective(cameraTransformType);
if(pair.getRight() != null) multiplyCurrentGlMatrix(pair.getRight());
return pair.getLeft();
@ -402,7 +404,7 @@ public class ForgeHooksClient
matrixBuf.put(t);
}
matrixBuf.flip();
GL11.glMultMatrix(matrixBuf);
glMultMatrix(matrixBuf);
}
// moved and expanded from WorldVertexBufferUploader.draw
@ -523,7 +525,7 @@ public class ForgeHooksClient
Class<? extends TileEntity> tileClass = tileItemMap.get(Pair.of(item, metadata));
if (tileClass != null)
{
TileEntitySpecialRenderer<TileEntity> r = TileEntityRendererDispatcher.instance.getSpecialRendererByClass(tileClass);
TileEntitySpecialRenderer<?> r = TileEntityRendererDispatcher.instance.getSpecialRendererByClass(tileClass);
if (r != null)
{
r.renderTileEntityAt(null, 0, 0, 0, 0, -1);
@ -562,4 +564,16 @@ public class ForgeHooksClient
faceData[i * 7 + 6] = x | (y << 0x08) | (z << 0x10);
}
}
public static Optional<TRSRTransformation> applyTransform(ItemTransformVec3f transform, Optional<? extends IModelPart> part)
{
if(part.isPresent()) return Optional.absent();
return Optional.of(new TRSRTransformation(transform));
}
public static Optional<TRSRTransformation> applyTransform(Matrix4f matrix, Optional<? extends IModelPart> part)
{
if(part.isPresent()) return Optional.absent();
return Optional.of(new TRSRTransformation(matrix));
}
}

View file

@ -193,7 +193,7 @@ public class BlockStateLoader
IModelState partState = new ModelStateComposition(baseTr, part.getState());
if (part.isUVLock()) partState = new ModelLoader.UVLock(partState);
models.put(entry.getKey(), Pair.of(runModelHooks(model, part.getTextures(), part.getCustomData()), partState));
models.put(entry.getKey(), Pair.<IModel, IModelState>of(runModelHooks(model, part.getTextures(), part.getCustomData()), partState));
}
return new MultiModel(getModelLocation(), hasBase ? base : null, baseTr, models.build());

View file

@ -467,40 +467,40 @@ public class ForgeBlockStateV1 extends Marker
}
else if (transform.equals("forge:default-block"))
{
IModelState thirdperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
TRSRTransformation thirdperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
new Vector3f(0, 1.5f / 16, -2.75f / 16),
TRSRTransformation.quatFromYXZDegrees(new Vector3f(10, -45, 170)),
new Vector3f(0.375f, 0.375f, 0.375f),
null));
ret.state = Optional.<IModelState>of(new IPerspectiveState.Impl(TRSRTransformation.identity(), ImmutableMap.of(TransformType.THIRD_PERSON, thirdperson)));
ret.state = Optional.<IModelState>of(new SimpleModelState(ImmutableMap.of(TransformType.THIRD_PERSON, thirdperson)));
}
else if (transform.equals("forge:default-item"))
{
IModelState thirdperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
TRSRTransformation thirdperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
new Vector3f(0, 1f / 16, -3f / 16),
TRSRTransformation.quatFromYXZDegrees(new Vector3f(-90, 0, 0)),
new Vector3f(0.55f, 0.55f, 0.55f),
null));
IModelState firstperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
TRSRTransformation firstperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
new Vector3f(0, 4f / 16, 2f / 16),
TRSRTransformation.quatFromYXZDegrees(new Vector3f(0, -135, 25)),
new Vector3f(1.7f, 1.7f, 1.7f),
null));
ret.state = Optional.<IModelState>of(new IPerspectiveState.Impl(TRSRTransformation.identity(), ImmutableMap.of(TransformType.THIRD_PERSON, thirdperson, TransformType.FIRST_PERSON, firstperson)));
ret.state = Optional.<IModelState>of(new SimpleModelState(ImmutableMap.of(TransformType.THIRD_PERSON, thirdperson, TransformType.FIRST_PERSON, firstperson)));
}
else if (transform.equals("forge:default-tool"))
{
IModelState thirdperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
TRSRTransformation thirdperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
new Vector3f(0, 1.25f / 16, -3.5f / 16),
TRSRTransformation.quatFromYXZDegrees(new Vector3f(0, 90, -35)),
new Vector3f(0.85f, 0.85f, 0.85f),
null));
IModelState firstperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
TRSRTransformation firstperson = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(
new Vector3f(0, 4f / 16, 2f / 16),
TRSRTransformation.quatFromYXZDegrees(new Vector3f(0, -135, 25)),
new Vector3f(1.7f, 1.7f, 1.7f),
null));
ret.state = Optional.<IModelState>of(new IPerspectiveState.Impl(TRSRTransformation.identity(), ImmutableMap.of(TransformType.THIRD_PERSON, thirdperson, TransformType.FIRST_PERSON, firstperson)));
ret.state = Optional.<IModelState>of(new SimpleModelState(ImmutableMap.of(TransformType.THIRD_PERSON, thirdperson, TransformType.FIRST_PERSON, firstperson)));
}
else
{
@ -522,7 +522,7 @@ public class ForgeBlockStateV1 extends Marker
else
{
JsonObject transform = json.get("transform").getAsJsonObject();
EnumMap<TransformType, IModelState> transforms = Maps.newEnumMap(TransformType.class);
EnumMap<TransformType, TRSRTransformation> transforms = Maps.newEnumMap(TransformType.class);
if(transform.has("thirdperson"))
{
TRSRTransformation t = context.deserialize(transform.get("thirdperson"), TRSRTransformation.class);
@ -582,7 +582,7 @@ public class ForgeBlockStateV1 extends Marker
}
else
{
state = new IPerspectiveState.Impl(base, Maps.immutableEnumMap(transforms));
state = new SimpleModelState(Maps.immutableEnumMap(transforms), Optional.of(base));
}
ret.state = Optional.of(state);
}

View file

@ -12,7 +12,7 @@ import com.google.common.base.Function;
* Interface for models that can be baked
* (possibly to different vertex formats and with different state).
*/
public interface IModel extends IModelPart
public interface IModel
{
/*
* Returns all model locations that this model depends on.

View file

@ -1,16 +1,17 @@
package net.minecraftforge.client.model;
import com.google.common.base.Function;
import com.google.common.base.Optional;
/*
* Represents the dynamic information associated with the model.
* Common use case is (possibly interpolated) animation frame.
*/
public interface IModelState extends Function<IModelPart, TRSRTransformation>
public interface IModelState
{
/*
* returns the transformation (in the local coordinates) that needs to be applied to the specific part of the model.
* Returns the transformation that needs to be applied to the specific part of the model.
* Coordinate system is determined by the part type.
* if no part is provided, global model transformation is returned.
*/
@Override
TRSRTransformation apply(IModelPart part);
}
Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part);
}

View file

@ -9,27 +9,26 @@ 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.model.IBakedModel;
import net.minecraft.util.EnumFacing;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
/*
* Model that changes based on the rendering perspective
* (first-person, GUI, e.t.c - see TransformType)
*/
@SuppressWarnings("deprecation")
public interface IPerspectiveAwareModel extends IBakedModel
public interface IPerspectiveAwareModel extends IFlexibleBakedModel
{
/*
* Returns the pair of the model for the given perspective, and the matrix
* that should be applied to the GL state before rendering it (matrix may be null).
*/
Pair<IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType);
Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType);
public static class MapWrapper implements IFlexibleBakedModel, IPerspectiveAwareModel
public static class MapWrapper implements IPerspectiveAwareModel
{
private final IFlexibleBakedModel parent;
private final ImmutableMap<TransformType, TRSRTransformation> transforms;
@ -40,17 +39,31 @@ public interface IPerspectiveAwareModel extends IBakedModel
this.transforms = transforms;
}
public MapWrapper(IFlexibleBakedModel parent, IPerspectiveState state, IModelPart part)
public MapWrapper(IFlexibleBakedModel parent, IModelState state)
{
this(parent, getTransforms(state, part));
this(parent, getTransforms(state));
}
public static ImmutableMap<TransformType, TRSRTransformation> getTransforms(IPerspectiveState state, IModelPart part)
public static ImmutableMap<TransformType, TRSRTransformation> getTransforms(IModelState state)
{
ImmutableMap.Builder<TransformType, TRSRTransformation> builder = ImmutableMap.builder();
for(TransformType type : TransformType.values())
{
builder.put(type, state.forPerspective(type).apply(part));
Optional<TRSRTransformation> tr = state.apply(Optional.of(type));
if(tr.isPresent())
{
builder.put(type, tr.get());
}
}
return builder.build();
}
public static ImmutableMap<TransformType, TRSRTransformation> getTransforms(ItemCameraTransforms transforms)
{
ImmutableMap.Builder<TransformType, TRSRTransformation> builder = ImmutableMap.builder();
for(TransformType type : TransformType.values())
{
builder.put(type, new TRSRTransformation(transforms.func_181688_b(type)));
}
return builder.build();
}
@ -65,12 +78,12 @@ public interface IPerspectiveAwareModel extends IBakedModel
public VertexFormat getFormat() { return parent.getFormat(); }
@Override
public Pair<IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
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((IBakedModel)this, mat);
return Pair.of(this, mat);
}
}
}

View file

@ -1,67 +0,0 @@
package net.minecraftforge.client.model;
import java.util.Map;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
/**
* IModelState that can change depending on the perspective.
*/
@SuppressWarnings("deprecation")
public interface IPerspectiveState extends IModelState
{
/**
* @return the additional state that needs to be applied for each part when in given perspective type.
*/
public IModelState forPerspective(TransformType type);
public static class Impl implements IPerspectiveState
{
private final IModelState parent;
private final ImmutableMap<TransformType, IModelState> states;
public Impl(IModelState parent, ImmutableMap<TransformType, IModelState> states)
{
this.parent = parent;
this.states = states;
}
public Impl(IModelState parent, ItemCameraTransforms transforms)
{
this(parent, getMap(transforms));
}
private static ImmutableMap<TransformType, IModelState> getMap(ItemCameraTransforms transforms)
{
Map<TransformType, IModelState> map = Maps.newHashMap();
for(TransformType type : TransformType.values())
{
map.put(type, transforms.func_181688_b(type));
}
return Maps.immutableEnumMap(map);
}
public TRSRTransformation apply(IModelPart part)
{
return parent.apply(part);
}
public IModelState forPerspective(TransformType type)
{
IModelState state = states.get(type);
if(state == null) state = TRSRTransformation.identity();
return state;
}
@Override
public String toString()
{
return Objects.toStringHelper(this.getClass()).add("parent", parent).add("states", states).toString();
}
}
}

View file

@ -1,9 +1,94 @@
package net.minecraftforge.client.model;
import java.util.List;
import javax.vecmath.Matrix4f;
import net.minecraft.block.state.IBlockState;
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.model.IBakedModel;
import net.minecraft.util.EnumFacing;
import org.apache.commons.lang3.tuple.Pair;
public interface ISmartBlockModel extends IBakedModel
{
IBakedModel handleBlockState(IBlockState state);
public static abstract class Wrapper implements ISmartBlockModel, IFlexibleBakedModel
{
protected final IFlexibleBakedModel parent;
public Wrapper(IFlexibleBakedModel parent)
{
this.parent = parent;
}
public List<BakedQuad> getFaceQuads(EnumFacing side)
{
return parent.getFaceQuads(side);
}
public List<BakedQuad> getGeneralQuads()
{
return parent.getGeneralQuads();
}
public boolean isAmbientOcclusion()
{
return parent.isAmbientOcclusion();
}
public boolean isGui3d()
{
return parent.isGui3d();
}
public boolean isBuiltInRenderer()
{
return parent.isBuiltInRenderer();
}
public TextureAtlasSprite getTexture()
{
return parent.getTexture();
}
public ItemCameraTransforms getItemCameraTransforms()
{
return parent.getItemCameraTransforms();
}
public VertexFormat getFormat()
{
return parent.getFormat();
}
}
public static abstract class PerspectiveWrapper extends Wrapper implements IPerspectiveAwareModel
{
protected final IPerspectiveAwareModel parent;
public PerspectiveWrapper(IPerspectiveAwareModel parent)
{
super(parent);
this.parent = parent;
}
public Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(TransformType type)
{
Pair<? extends IFlexibleBakedModel, Matrix4f> pair = parent.handlePerspective(type);
return Pair.of(new ISmartBlockModel.Wrapper(pair.getLeft())
{
public IBakedModel handleBlockState(IBlockState state)
{
return PerspectiveWrapper.this.handleBlockState(state);
}
}, pair.getRight());
}
}
}

View file

@ -5,7 +5,6 @@ import java.util.BitSet;
import java.util.Collection;
import java.util.List;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector4f;
import net.minecraft.client.renderer.block.model.BakedQuad;
@ -15,20 +14,17 @@ import net.minecraft.client.renderer.block.model.ModelBlock;
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.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
import org.apache.commons.lang3.tuple.Pair;
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.common.collect.Maps;
@SuppressWarnings("deprecation")
public class ItemLayerModel implements IRetexturableModel {
public class ItemLayerModel implements IRetexturableModel
{
public static final ItemLayerModel instance = new ItemLayerModel(ImmutableList.<ResourceLocation>of());
@ -85,40 +81,33 @@ public class ItemLayerModel implements IRetexturableModel {
public IFlexibleBakedModel bake(IModelState state, final VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
{
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
final TRSRTransformation transform = state.apply(this);
Optional<TRSRTransformation> transform = state.apply(Optional.<IModelPart>absent());
for(int i = 0; i < textures.size(); i++)
{
TextureAtlasSprite sprite = bakedTextureGetter.apply(textures.get(i));
builder.addAll(getQuadsForSprite(i, sprite, format, transform));
}
TextureAtlasSprite particle = bakedTextureGetter.apply(textures.isEmpty() ? new ResourceLocation("missingno") : textures.get(0));
if(state instanceof IPerspectiveState)
ImmutableMap<TransformType, TRSRTransformation> map = IPerspectiveAwareModel.MapWrapper.getTransforms(state);
IFlexibleBakedModel ret = new BakedModel(builder.build(), particle, format);
if(map.isEmpty())
{
IPerspectiveState ps = (IPerspectiveState)state;
ImmutableMap<TransformType, TRSRTransformation> map = IPerspectiveAwareModel.MapWrapper.getTransforms(ps, this);
return new BakedModel(builder.build(), particle, format, Maps.immutableEnumMap(map));
return ret;
}
return new BakedModel(builder.build(), particle, format);
return new IPerspectiveAwareModel.MapWrapper(ret, map);
}
public static class BakedModel implements IFlexibleBakedModel, IPerspectiveAwareModel
public static class BakedModel implements IFlexibleBakedModel
{
private final ImmutableList<BakedQuad> quads;
private final TextureAtlasSprite particle;
private final VertexFormat format;
private final ImmutableMap<TransformType, TRSRTransformation> transforms;
public BakedModel(ImmutableList<BakedQuad> quads, TextureAtlasSprite particle, VertexFormat format)
{
this(quads, particle, format, ImmutableMap.<TransformType, TRSRTransformation>of());
}
public BakedModel(ImmutableList<BakedQuad> quads, TextureAtlasSprite particle, VertexFormat format, ImmutableMap<TransformType, TRSRTransformation> transforms)
{
this.quads = quads;
this.particle = particle;
this.format = format;
this.transforms = transforms;
}
public boolean isAmbientOcclusion() { return true; }
@ -129,18 +118,9 @@ public class ItemLayerModel implements IRetexturableModel {
public List<BakedQuad> getFaceQuads(EnumFacing side) { return ImmutableList.of(); }
public List<BakedQuad> getGeneralQuads() { return quads; }
public VertexFormat getFormat() { return format; }
@Override
public Pair<IBakedModel, 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((IBakedModel)this, mat);
}
}
public ImmutableList<BakedQuad> getQuadsForSprite(int tint, TextureAtlasSprite sprite, VertexFormat format, TRSRTransformation transform)
public ImmutableList<BakedQuad> getQuadsForSprite(int tint, TextureAtlasSprite sprite, VertexFormat format, Optional<TRSRTransformation> transform)
{
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
@ -215,7 +195,7 @@ public class ItemLayerModel implements IRetexturableModel {
return (pixels[u + (vMax - 1 - v) * uMax] >> 24 & 0xFF) == 0;
}
private static void addSideQuad(ImmutableList.Builder<BakedQuad> builder, BitSet faces, VertexFormat format, TRSRTransformation transform, EnumFacing side, int tint, TextureAtlasSprite sprite, int uMax, int vMax, int u, int v)
private static void addSideQuad(ImmutableList.Builder<BakedQuad> builder, BitSet faces, VertexFormat format, Optional<TRSRTransformation> transform, EnumFacing side, int tint, TextureAtlasSprite sprite, int uMax, int vMax, int u, int v)
{
int si = side.ordinal();
if(si > 4) si -= 2;
@ -227,7 +207,7 @@ public class ItemLayerModel implements IRetexturableModel {
}
}
private static BakedQuad buildSideQuad(VertexFormat format, TRSRTransformation transform, EnumFacing side, int tint, TextureAtlasSprite sprite, int u, int v)
private static BakedQuad buildSideQuad(VertexFormat format, Optional<TRSRTransformation> transform, EnumFacing side, int tint, TextureAtlasSprite sprite, int u, int v)
{
final float eps0 = 30e-5f;
final float eps1 = 45e-5f;
@ -308,7 +288,7 @@ public class ItemLayerModel implements IRetexturableModel {
}
private static final BakedQuad buildQuad(
VertexFormat format, TRSRTransformation transform, EnumFacing side, int tint,
VertexFormat format, Optional<TRSRTransformation> transform, EnumFacing side, int tint,
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,
@ -324,7 +304,7 @@ public class ItemLayerModel implements IRetexturableModel {
return builder.build();
}
private static void putVertex(UnpackedBakedQuad.Builder builder, VertexFormat format, TRSRTransformation transform, EnumFacing side, float x, float y, float z, float u, float v)
private static void putVertex(UnpackedBakedQuad.Builder builder, VertexFormat format, Optional<TRSRTransformation> transform, EnumFacing side, float x, float y, float z, float u, float v)
{
Vector4f vec = new Vector4f();
for(int e = 0; e < format.getElementCount(); e++)
@ -332,12 +312,19 @@ public class ItemLayerModel implements IRetexturableModel {
switch(format.getElement(e).getUsage())
{
case POSITION:
vec.x = x;
vec.y = y;
vec.z = z;
vec.w = 1;
transform.getMatrix().transform(vec);
builder.put(e, vec.x, vec.y, vec.z, vec.w);
if(transform.isPresent())
{
vec.x = x;
vec.y = y;
vec.z = z;
vec.w = 1;
transform.get().getMatrix().transform(vec);
builder.put(e, vec.x, vec.y, vec.z, vec.w);
}
else
{
builder.put(e, x, y, z, 1);
}
break;
case COLOR:
builder.put(e, 1f, 1f, 1f, 1f);

View file

@ -2,41 +2,78 @@ package net.minecraftforge.client.model;
import java.util.Map;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
/*
* Simple implementation of IModelState via a map and a default value.
* Simple implementation of IModelState via a map and a default value. Provides a full state for each part.
*/
public class MapModelState implements IModelState
{
private final ImmutableMap<IModelPart, IModelState> map;
private final ImmutableMap<Wrapper, IModelState> map;
private final IModelState def;
public MapModelState(Map<IModelPart, ? extends IModelState> map)
public MapModelState(Map<Wrapper, IModelState> map)
{
this(map, TRSRTransformation.identity());
}
public MapModelState(Map<IModelPart, ? extends IModelState> map, TRSRTransformation def)
public MapModelState(Map<Wrapper, IModelState> map, TRSRTransformation def)
{
this(map, (IModelState)def);
}
public MapModelState(Map<IModelPart, ? extends IModelState> map, IModelState def)
public MapModelState(Map<Wrapper, IModelState> map, IModelState def)
{
this.map = ImmutableMap.<IModelPart, IModelState>copyOf(map);
this.map = ImmutableMap.<Wrapper, IModelState>copyOf(map);
this.def = def;
}
public TRSRTransformation apply(IModelPart part)
public Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part)
{
if(!map.containsKey(part)) return def.apply(part);
return map.get(part).apply(part);
if(!part.isPresent() || !map.containsKey(part.get())) return def.apply(part);
return map.get(part.get()).apply(Optional.<IModelPart>absent());
}
public IModelState getState(IModelPart part)
public IModelState getState(Object obj)
{
if(!map.containsKey(part)) return def;
return map.get(part);
Wrapper w = wrap(obj);
if(!map.containsKey(w)) return def;
return map.get(w);
}
public static class Wrapper implements IModelPart
{
private final Object obj;
public Wrapper(Object obj)
{
this.obj = obj;
}
@Override
public int hashCode()
{
return obj.hashCode();
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Wrapper other = (Wrapper)obj;
return Objects.equal(this.obj, other.obj);
}
}
public static Wrapper wrap(Object obj)
{
return new Wrapper(obj);
}
}

View file

@ -5,9 +5,12 @@ import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import javax.vecmath.Vector4f;
import net.minecraft.block.state.IBlockState;
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;
@ -57,7 +60,13 @@ public class ModelFluid implements IModelCustomData
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
{
return new BakedFluid(state.apply(this), format, fluid.getColor(), bakedTextureGetter.apply(fluid.getStill()), bakedTextureGetter.apply(fluid.getFlowing()), fluid.isGaseous());
ImmutableMap<TransformType, TRSRTransformation> map = IPerspectiveAwareModel.MapWrapper.getTransforms(state);
IFlexibleBakedModel ret = new BakedFluid(state.apply(Optional.<IModelPart>absent()), format, fluid.getColor(), bakedTextureGetter.apply(fluid.getStill()), bakedTextureGetter.apply(fluid.getFlowing()), fluid.isGaseous());
if(map.isEmpty())
{
return ret;
}
return new IPerspectiveAwareModel.MapWrapper(ret, map);
}
public IModelState getDefaultState()
@ -91,7 +100,7 @@ public class ModelFluid implements IModelCustomData
private static final int z[] = { 0, 1, 1, 0 };
private static final float eps = 1e-3f;
private final TRSRTransformation transformation;
private final Optional<TRSRTransformation> transformation;
private final VertexFormat format;
private final int color;
private final TextureAtlasSprite still, flowing;
@ -99,12 +108,12 @@ public class ModelFluid implements IModelCustomData
private final Optional<IExtendedBlockState> state;
private final EnumMap<EnumFacing, List<BakedQuad>> faceQuads;
public BakedFluid(TRSRTransformation transformation, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, boolean gas)
public BakedFluid(Optional<TRSRTransformation> transformation, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, boolean gas)
{
this(transformation, format, color, still, flowing, gas, Optional.<IExtendedBlockState>absent());
}
public BakedFluid(TRSRTransformation transformation, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, boolean gas, Optional<IExtendedBlockState> stateOption)
public BakedFluid(Optional<TRSRTransformation> transformation, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, boolean gas, Optional<IExtendedBlockState> stateOption)
{
this.transformation = transformation;
this.format = format;
@ -237,7 +246,14 @@ public class ModelFluid implements IModelCustomData
switch(format.getElement(e).getUsage())
{
case POSITION:
builder.put(e, x - side.getDirectionVec().getX() * eps, y, z - side.getDirectionVec().getZ() * eps, 1f);
float[] data = new float[]{ x - side.getDirectionVec().getX() * eps, y, z - side.getDirectionVec().getZ() * eps, 1 };
if(transformation.isPresent())
{
Vector4f vec = new Vector4f(data);
transformation.get().getMatrix().transform(vec);
vec.get(data);
}
builder.put(e, data);
break;
case COLOR:
float d = LightUtil.diffuseLight(side);

View file

@ -24,6 +24,7 @@ import net.minecraft.client.renderer.ItemModelMesher;
import net.minecraft.client.renderer.block.model.BlockPart;
import net.minecraft.client.renderer.block.model.BlockPartFace;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.block.model.ItemModelGenerator;
import net.minecraft.client.renderer.block.model.ModelBlock;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition;
@ -55,6 +56,7 @@ import net.minecraftforge.fml.common.registry.RegistryDelegate;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@ -332,7 +334,14 @@ public class ModelLoader extends ModelBakery
throw new IllegalArgumentException("can't bake vanilla models to the format that doesn't fit into the default one: " + format);
}
ModelBlock model = this.model;
if(model == null) return getMissingModel().bake(state, format, bakedTextureGetter);
if(model == null) return getMissingModel().bake(getMissingModel().getDefaultState(), format, bakedTextureGetter);
List<TRSRTransformation> newTransforms = Lists.newArrayList();
for(int i = 0; i < model.getElements().size(); i++)
{
newTransforms.add(null);
}
ItemCameraTransforms transforms = model.func_181682_g();
boolean uvlock = false;
if(state instanceof UVLock)
@ -340,43 +349,58 @@ public class ModelLoader extends ModelBakery
uvlock = true;
state = ((UVLock)state).getParent();
}
IPerspectiveState perState = state instanceof IPerspectiveState ? (IPerspectiveState)state : new IPerspectiveState.Impl(state, transforms);
Map<TransformType, TRSRTransformation> tMap = Maps.newHashMap();
tMap.putAll(IPerspectiveAwareModel.MapWrapper.getTransforms(transforms));
tMap.putAll(IPerspectiveAwareModel.MapWrapper.getTransforms(state));
IModelState perState = new SimpleModelState(ImmutableMap.copyOf(tMap));
if(hasItemModel(model))
{
return new ItemLayerModel(model).bake(perState, format, bakedTextureGetter);
}
if(isCustomRenderer(model)) return new IFlexibleBakedModel.Wrapper(new BuiltInModel(transforms), format);
// TODO perspective awareness for this
return bakeNormal(model, perState, state.apply(this), format, bakedTextureGetter, uvlock);
return bakeNormal(model, perState, state.apply(Optional.<IModelPart>absent()).or(TRSRTransformation.identity()), newTransforms, format, bakedTextureGetter, uvlock);
}
private IFlexibleBakedModel bakeNormal(ModelBlock model, IPerspectiveState perState, TRSRTransformation state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter, boolean uvLocked)
private IFlexibleBakedModel bakeNormal(ModelBlock model, IModelState perState, final TRSRTransformation modelState, List<TRSRTransformation> newTransforms, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter, boolean uvLocked)
{
TextureAtlasSprite particle = bakedTextureGetter.apply(new ResourceLocation(model.resolveTextureName("particle")));
SimpleBakedModel.Builder builder = (new SimpleBakedModel.Builder(model)).setTexture(particle);
for(BlockPart part : (Iterable<BlockPart>)model.getElements())
for(int i = 0; i < model.getElements().size(); i++)
{
BlockPart part = model.getElements().get(i);
TRSRTransformation transformation = modelState;
if(newTransforms.get(i) != null)
{
transformation = transformation.compose(newTransforms.get(i));
}
for(Map.Entry<EnumFacing, BlockPartFace> e : (Iterable<Map.Entry<EnumFacing, BlockPartFace>>)part.mapFaces.entrySet())
{
TextureAtlasSprite textureatlassprite1 = bakedTextureGetter.apply(new ResourceLocation(model.resolveTextureName(e.getValue().texture)));
if (e.getValue().cullFace == null || !TRSRTransformation.isInteger(state.getMatrix()))
if (e.getValue().cullFace == null || !TRSRTransformation.isInteger(transformation.getMatrix()))
{
builder.addGeneralQuad(makeBakedQuad(part, e.getValue(), textureatlassprite1, e.getKey(), state, uvLocked));
builder.addGeneralQuad(makeBakedQuad(part, e.getValue(), textureatlassprite1, e.getKey(), transformation, uvLocked));
}
else
{
builder.addFaceQuad(state.rotate(e.getValue().cullFace), makeBakedQuad(part, e.getValue(), textureatlassprite1, e.getKey(), state, uvLocked));
builder.addFaceQuad(modelState.rotate(e.getValue().cullFace), makeBakedQuad(part, e.getValue(), textureatlassprite1, e.getKey(), transformation, uvLocked));
}
}
}
return new IPerspectiveAwareModel.MapWrapper(new IFlexibleBakedModel.Wrapper(builder.makeBakedModel(), format), perState, this);
return new ISmartBlockModel.PerspectiveWrapper(new IPerspectiveAwareModel.MapWrapper(new IFlexibleBakedModel.Wrapper(builder.makeBakedModel(), format), perState))
{
public IBakedModel handleBlockState(IBlockState state)
{
return VanillaModelWrapper.this.handleBlockState(parent, modelState, state);
}
};
}
public IModelState getDefaultState()
private IBakedModel handleBlockState(IFlexibleBakedModel model, TRSRTransformation modelState, IBlockState state)
{
return ModelRotation.X0_Y0;
return model;
}
@Override
@ -439,6 +463,11 @@ public class ModelLoader extends ModelBakery
return new VanillaModelWrapper(location, neweModel);
}
public IModelState getDefaultState()
{
return ModelRotation.X0_Y0;
}
}
public static class UVLock implements IModelState
@ -455,7 +484,7 @@ public class ModelLoader extends ModelBakery
return parent;
}
public TRSRTransformation apply(IModelPart part)
public Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part)
{
return parent.apply(part);
}
@ -503,7 +532,7 @@ public class ModelLoader extends ModelBakery
public WeightedRandomModel(ModelResourceLocation parent, Variants variants)
{
this.variants = variants.getVariants();
ImmutableMap.Builder<IModelPart, IModelState> builder = ImmutableMap.builder();
ImmutableMap.Builder<MapModelState.Wrapper, IModelState> builder = ImmutableMap.builder();
for (Variant v : (List<Variant>)variants.getVariants())
{
ResourceLocation loc = v.getModelLocation();
@ -533,14 +562,14 @@ public class ModelLoader extends ModelBakery
model = new WeightedPartWrapper(model);
models.add(model);
builder.put(model, v.getState());
builder.put(MapModelState.wrap(model), v.getState());
}
if (models.size() == 0) //If all variants are missing, add one with the missing model and default rotation.
{
IModel missing = getMissingModel();
models.add(missing);
builder.put(missing, TRSRTransformation.identity());
builder.put(MapModelState.wrap(missing), TRSRTransformation.identity());
}
defaultState = new MapModelState(builder.build());
@ -563,11 +592,11 @@ public class ModelLoader extends ModelBakery
return state;
}
private IModelState getState(IModelState state, IModelPart part)
private IModelState getState(IModelState state, IModel model)
{
if(state instanceof MapModelState)
{
return ((MapModelState)state).getState(part);
return ((MapModelState)state).getState(model);
}
return state;
}

View file

@ -1,5 +1,7 @@
package net.minecraftforge.client.model;
import com.google.common.base.Optional;
public class ModelStateComposition implements IModelState
{
private final IModelState first;
@ -11,8 +13,13 @@ public class ModelStateComposition implements IModelState
this.second = second;
}
public TRSRTransformation apply(IModelPart part)
public Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part)
{
return first.apply(part).compose(second.apply(part));
Optional<TRSRTransformation> f = first.apply(part), s = second.apply(part);
if(f.isPresent() && s.isPresent())
{
return Optional.of(f.get().compose(s.get()));
}
return f.or(s);
}
}

View file

@ -15,7 +15,6 @@ 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.model.IBakedModel;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.FMLLog;
@ -93,16 +92,8 @@ public class MultiModel implements IModel
ImmutableMap.Builder<TransformType, Pair<Baked, TRSRTransformation>> builder = ImmutableMap.builder();
for(TransformType type : TransformType.values())
{
Pair<IBakedModel, Matrix4f> p = perBase.handlePerspective(type);
IFlexibleBakedModel newBase;
if(p.getLeft() instanceof IFlexibleBakedModel)
{
newBase = (IFlexibleBakedModel)p.getLeft();
}
else
{
newBase = new IFlexibleBakedModel.Wrapper(p.getLeft(), base.getFormat());
}
Pair<? extends IFlexibleBakedModel, Matrix4f> p = perBase.handlePerspective(type);
IFlexibleBakedModel newBase = p.getLeft();
builder.put(type, Pair.of(new Baked(location, false, newBase, parts), new TRSRTransformation(p.getRight())));
}
transforms = builder.build();
@ -172,11 +163,11 @@ public class MultiModel implements IModel
}
@Override
public Pair<IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
public Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
{
if(transforms.isEmpty()) return Pair.<IBakedModel, Matrix4f>of(this, null);
if(transforms.isEmpty()) return Pair.of(this, null);
Pair<Baked, TRSRTransformation> p = transforms.get(cameraTransformType);
return Pair.of((IBakedModel)p.getLeft(), p.getRight().getMatrix());
return Pair.of(p.getLeft(), p.getRight().getMatrix());
}
}
@ -261,12 +252,6 @@ public class MultiModel implements IModel
return new Baked(location, true, bakedBase, mapBuilder.build());
}
@Override
public IModelState getDefaultState()
{
return baseState;
}
/**
* @return The base model of this MultiModel. May be null.
*/
@ -282,4 +267,10 @@ public class MultiModel implements IModel
{
return parts;
}
@Override
public IModelState getDefaultState()
{
return baseState;
}
}

View file

@ -0,0 +1,30 @@
package net.minecraftforge.client.model;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
/*
* Simple implementation of IModelState via a map and a default value.
*/
public class SimpleModelState implements IModelState
{
private final ImmutableMap<? extends IModelPart, TRSRTransformation> map;
private final Optional<TRSRTransformation> def;
public SimpleModelState(ImmutableMap<? extends IModelPart, TRSRTransformation> map)
{
this(map, Optional.<TRSRTransformation>absent());
}
public SimpleModelState(ImmutableMap<? extends IModelPart, TRSRTransformation> map, Optional<TRSRTransformation> def)
{
this.map = map;
this.def = def;
}
public Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part)
{
if(!part.isPresent() || !map.containsKey(part.get())) return def;
return Optional.fromNullable(map.get(part.get()));
}
}

View file

@ -17,6 +17,7 @@ import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
/*
* Interpolation-friendly affine transformation.
@ -474,9 +475,13 @@ public class TRSRTransformation implements IModelState, ITransformation
return (Quat4f)rightRot.clone();
}
public TRSRTransformation apply(IModelPart part)
public Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part)
{
return this;
if(part.isPresent())
{
return Optional.absent();
}
return Optional.of(this);
}
public EnumFacing rotate(EnumFacing facing)

View file

@ -22,7 +22,6 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MathHelper;
@ -34,7 +33,6 @@ import net.minecraftforge.client.model.IModelCustomData;
import net.minecraftforge.client.model.IModelPart;
import net.minecraftforge.client.model.IModelState;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.client.model.IPerspectiveState;
import net.minecraftforge.client.model.IRetexturableModel;
import net.minecraftforge.client.model.ISmartBlockModel;
import net.minecraftforge.client.model.ISmartItemModel;
@ -59,6 +57,8 @@ import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
@ -260,13 +260,15 @@ public class B3DLoader implements ICustomModelLoader
return parent;
}
public TRSRTransformation apply(IModelPart part)
public Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part)
{
if(!(part instanceof PartWrapper<?>))
// TODO optionify better
if(!part.isPresent()) return parent.apply(part);
if(!(part.get() instanceof NodeJoint))
{
throw new IllegalArgumentException("B3DState can only be applied to b3d models");
return Optional.absent();
}
Node<?> node = ((PartWrapper<?>)part).getNode();
Node<?> node = ((NodeJoint)part.get()).getNode();
TRSRTransformation nodeTransform;
if(progress < 1e-5 || frame == nextFrame)
{
@ -281,11 +283,11 @@ public class B3DLoader implements ICustomModelLoader
nodeTransform = getNodeMatrix(node, frame);
nodeTransform = nodeTransform.slerp(getNodeMatrix(node, nextFrame), progress);
}
if(parent != null)
if(parent != null && node.getParent() == null)
{
return parent.apply(part).compose(nodeTransform);
return Optional.of(parent.apply(part).or(TRSRTransformation.identity()).compose(nodeTransform));
}
return nodeTransform;
return Optional.of(nodeTransform);
}
private static LoadingCache<Triple<Animation, Node<?>, Integer>, TRSRTransformation> cache = CacheBuilder.newBuilder()
@ -301,7 +303,7 @@ public class B3DLoader implements ICustomModelLoader
public TRSRTransformation getNodeMatrix(Node<?> node)
{
return cache.getUnchecked(Triple.<Animation, Node<?>, Integer>of(animation, node, frame));
return getNodeMatrix(node, frame);
}
public TRSRTransformation getNodeMatrix(Node<?> node, int frame)
@ -320,25 +322,102 @@ public class B3DLoader implements ICustomModelLoader
Node<?> parent = node.getParent();
if(parent != null)
{
// parent model-global current pose
TRSRTransformation pm = cache.getUnchecked(Triple.<Animation, Node<?>, Integer>of(animation, node.getParent(), frame));
ret = ret.compose(pm);
// joint offset in the parent coords
ret = ret.compose(new TRSRTransformation(parent.getPos(), parent.getRot(), parent.getScale(), null));
}
// current node local pose
ret = ret.compose(new TRSRTransformation(key.getPos(), key.getRot(), key.getScale(), null));
Matrix4f rm = new TRSRTransformation(node.getPos(), node.getRot(), node.getScale(), null).getMatrix();
// this part moved inside the model
// inverse bind of the curent node
/*Matrix4f rm = new TRSRTransformation(node.getPos(), node.getRot(), node.getScale(), null).getMatrix();
rm.invert();
ret = ret.compose(new TRSRTransformation(rm));
if(parent != null)
{
// inverse bind of the parent
rm = new TRSRTransformation(parent.getPos(), parent.getRot(), parent.getScale(), null).getMatrix();
rm.invert();
ret = ret.compose(new TRSRTransformation(rm));
}*/
// TODO cache
TRSRTransformation invBind = new NodeJoint(node).getInvBindPose();
ret = ret.compose(invBind);
}
else
{
Node<?> parent = node.getParent();
if(parent != null)
{
// parent model-global current pose
TRSRTransformation pm = cache.getUnchecked(Triple.<Animation, Node<?>, Integer>of(animation, node.getParent(), frame));
ret = ret.compose(pm);
// joint offset in the parent coords
ret = ret.compose(new TRSRTransformation(parent.getPos(), parent.getRot(), parent.getScale(), null));
}
ret = ret.compose(new TRSRTransformation(node.getPos(), node.getRot(), node.getScale(), null));
// TODO cache
TRSRTransformation invBind = new NodeJoint(node).getInvBindPose();
ret = ret.compose(invBind);
}
return ret;
}
}
public static class NodeJoint implements IModelPart
{
private final Node<?> node;
public NodeJoint(Node<?> node)
{
this.node = node;
}
public TRSRTransformation getInvBindPose()
{
Matrix4f m = new TRSRTransformation(node.getPos(), node.getRot(), node.getScale(), null).getMatrix();
m.invert();
TRSRTransformation pose = new TRSRTransformation(m);
if(node.getParent() != null)
{
TRSRTransformation parent = new NodeJoint(node.getParent()).getInvBindPose();
pose = pose.compose(parent);
}
return pose;
}
public Optional<NodeJoint> getParent()
{
// FIXME cache?
if(node.getParent() == null) return Optional.absent();
return Optional.of(new NodeJoint(node.getParent()));
}
public Node<?> getNode()
{
return node;
}
@Override
public int hashCode()
{
return node.hashCode();
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (!super.equals(obj)) return false;
if (getClass() != obj.getClass()) return false;
NodeJoint other = (NodeJoint) obj;
return Objects.equal(node, other.node);
}
}
public static enum B3DFrameProperty implements IUnlistedProperty<B3DState>
{
instance;
@ -760,10 +839,10 @@ public class B3DLoader implements ICustomModelLoader
Mesh mesh = (Mesh)node.getKind();
Collection<Face> faces = mesh.bake(new Function<Node<?>, Matrix4f>()
{
// gets transformation in global space
private final TRSRTransformation global = state.apply(Optional.<IModelPart>absent()).or(TRSRTransformation.identity());
public Matrix4f apply(Node<?> node)
{
return state.apply(PartWrapper.create(node)).getMatrix();
return global.compose(state.apply(Optional.of(new NodeJoint(node))).or(TRSRTransformation.identity())).getMatrix();
}
});
for(Face f : faces)
@ -914,13 +993,14 @@ public class B3DLoader implements ICustomModelLoader
return this;
}
public Pair<IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
public Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
{
if(state instanceof IPerspectiveState)
TRSRTransformation tr = state.apply(Optional.of(cameraTransformType)).or(TRSRTransformation.identity());
if(tr != TRSRTransformation.identity())
{
return Pair.of((IBakedModel)this, TRSRTransformation.blockCornerToCenter(((IPerspectiveState)state).forPerspective(cameraTransformType).apply(PartWrapper.create(node))).getMatrix());
return Pair.of(this, TRSRTransformation.blockCornerToCenter(tr).getMatrix());
}
return Pair.of((IBakedModel)this, null);
return Pair.of(this, null);
}
}
}

View file

@ -38,7 +38,6 @@ import net.minecraftforge.client.model.IModelCustomData;
import net.minecraftforge.client.model.IModelPart;
import net.minecraftforge.client.model.IModelState;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.client.model.IPerspectiveState;
import net.minecraftforge.client.model.IRetexturableModel;
import net.minecraftforge.client.model.ISmartBlockModel;
import net.minecraftforge.client.model.ISmartItemModel;
@ -54,6 +53,7 @@ import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Charsets;
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.common.collect.Lists;
@ -121,11 +121,6 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
return new OBJBakedModel(this, state, format, builder.build());
}
public TRSRTransformation getDefaultState()
{
return TRSRTransformation.identity();
}
public MaterialLibrary getMatLib()
{
return this.matLib;
@ -1108,13 +1103,13 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
this.faces = faces == null ? new LinkedHashSet<Face>() : faces;
}
public LinkedHashSet<Face> applyTransform(TRSRTransformation transform)
public LinkedHashSet<Face> applyTransform(Optional<TRSRTransformation> transform)
{
LinkedHashSet<Face> faceSet = new LinkedHashSet<Face>();
for (Face f : this.faces)
{
// if (minUVBounds != null && maxUVBounds != null) f.normalizeUVs(minUVBounds, maxUVBounds);
faceSet.add(f.bake(transform));
faceSet.add(f.bake(transform.or(TRSRTransformation.identity())));
}
return faceSet;
}
@ -1169,10 +1164,10 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
return parent;
}
public TRSRTransformation apply(IModelPart part)
public Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part)
{
if (parent != null) return parent.apply(part);
return new TRSRTransformation(EnumFacing.NORTH);
return Optional.absent();
}
public Map<String, Boolean> getVisibilityMap()
@ -1325,7 +1320,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
{
quads = Collections.synchronizedSet(new LinkedHashSet<BakedQuad>());
Set<Face> faces = Collections.synchronizedSet(new LinkedHashSet<Face>());
TRSRTransformation transform = TRSRTransformation.identity();
Optional<TRSRTransformation> transform = Optional.absent();
for (Group g : this.model.getMatLib().getGroups().values())
{
// g.minUVBounds = this.model.getMatLib().minUVBounds;
@ -1337,7 +1332,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
OBJState state = (OBJState) this.state;
if (state.parent != null)
{
transform = state.parent.apply(model);
transform = state.parent.apply(Optional.<IModelPart>absent());
}
//TODO: can this be replaced by updateStateVisibilityMap(OBJState)?
if (state.getGroupNamesFromMap().contains(Group.ALL))
@ -1374,7 +1369,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
}
else
{
transform = state.apply(model);
transform = state.apply(Optional.<IModelPart>absent());
faces.addAll(g.applyTransform(transform));
}
}
@ -1578,13 +1573,14 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
}
@Override
public Pair<IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
public Pair<? extends IFlexibleBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
{
if (state instanceof IPerspectiveState)
TRSRTransformation tr = state.apply(Optional.of(cameraTransformType)).or(TRSRTransformation.identity());
if(tr != TRSRTransformation.identity())
{
return Pair.of((IBakedModel) this, TRSRTransformation.blockCornerToCenter(((IPerspectiveState) state).forPerspective(cameraTransformType).apply(model)).getMatrix());
return Pair.of(this, TRSRTransformation.blockCornerToCenter(tr).getMatrix());
}
return Pair.of((IBakedModel) this, null);
return Pair.of(this, null);
}
@Override
@ -1605,4 +1601,10 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
this.modelLocation = modelLocation;
}
}
@Override
public IModelState getDefaultState()
{
return TRSRTransformation.identity();
}
}

View file

@ -17,9 +17,10 @@ import com.google.common.cache.LoadingCache;
public class LightUtil
{
private static final float s2 = (float)Math.pow(2, .5);
public static float diffuseLight(float x, float y, float z)
{
float s2 = (float)Math.pow(2, .5);
float y1 = y + 3 - 2 * s2;
return (x * x * 0.6f + (y1 * y1 * (3 + 2 * s2)) / 8 + z * z * 0.8f);
}

View file

@ -147,16 +147,6 @@ public class LayerBreakingTest
IFlexibleBakedModel solid;
IFlexibleBakedModel translucent;
@SuppressWarnings("unused")
private class DefState implements IModelState
{
@Override
public TRSRTransformation apply(IModelPart part)
{
return TRSRTransformation.identity();
}
};
@Override
public List<BakedQuad> getFaceQuads(EnumFacing p_177551_1_)
{

View file

@ -0,0 +1,39 @@
// vanilla json model, no modifications
{
"elements": [
{
"from": [ 0, 0, 0 ],
"to": [ 16, 4, 16 ],
"faces": {
"down": { "uv": [ 0, 0, 16, 16 ], "texture":"#base" },
"up": { "uv": [ 0, 0, 16, 16 ], "texture":"#base" },
"north": { "uv": [ 0, 0, 16, 4 ], "texture":"#front" },
"south": { "uv": [ 0, 0, 16, 4 ], "texture":"#front" },
"west": { "uv": [ 0, 0, 16, 4 ], "texture":"#front" },
"east": { "uv": [ 0, 0, 16, 4 ], "texture":"#front" }
}
},
{
"from": [ 4, 4, 4 ],
"to": [ 12, 8, 12 ],
"faces": {
"north": { "uv": [ 4, 4, 12, 8 ], "texture":"#chamber" },
"south": { "uv": [ 4, 4, 12, 8 ], "texture":"#chamber" },
"west": { "uv": [ 4, 4, 12, 8 ], "texture":"#chamber" },
"east": { "uv": [ 4, 4, 12, 8 ], "texture":"#chamber" }
}
},
{
"from": [ 4, 12, 4 ],
"to": [ 12, 16, 12 ],
"faces": {
"up": { "uv": [ 0, 0, 8, 8 ], "texture":"#trunk" },
"north": { "uv": [ 4, 12, 12, 16 ], "texture":"#trunk" },
"south": { "uv": [ 4, 12, 12, 16 ], "texture":"#trunk" },
"west": { "uv": [ 4, 12, 12, 16 ], "texture":"#trunk" },
"east": { "uv": [ 4, 12, 12, 16 ], "texture":"#trunk" }
}
}
]
}

View file

@ -0,0 +1,36 @@
{
"elements": [
{
"from": [ 0, 4, 0 ],
"to": [ 16, 8, 16 ],
"faces": {
"down": { "uv": [ 0, 0, 16, 16 ], "texture":"#base" },
"up": { "uv": [ 0, 0, 16, 16 ], "texture":"#base" },
"north": { "uv": [ 0, 4, 16, 8 ], "texture":"#front" },
"south": { "uv": [ 0, 4, 16, 8 ], "texture":"#front" },
"west": { "uv": [ 0, 4, 16, 8 ], "texture":"#front" },
"east": { "uv": [ 0, 4, 16, 8 ], "texture":"#front" }
}
},
{
"from": [ 4, 0, 4 ],
"to": [ 12, 4, 12 ],
"faces": {
"north": { "uv": [ 4, 8, 12, 12 ], "texture":"#chamber" },
"south": { "uv": [ 4, 8, 12, 12 ], "texture":"#chamber" },
"west": { "uv": [ 4, 8, 12, 12 ], "texture":"#chamber" },
"east": { "uv": [ 4, 8, 12, 12 ], "texture":"#chamber" }
}
},
{
"from": [ 4, 8, 4 ],
"to": [ 12, 12, 12 ],
"faces": {
"north": { "uv": [ 4, 8, 12, 12 ], "texture":"#trunk" },
"south": { "uv": [ 4, 8, 12, 12 ], "texture":"#trunk" },
"west": { "uv": [ 4, 8, 12, 12 ], "texture":"#trunk" },
"east": { "uv": [ 4, 8, 12, 12 ], "texture":"#trunk" }
}
}
]
}