mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-11-03 23:22:59 +00:00 
			
		
		
		
	Merge pull request #492 from SquidDev-CC/ComputerCraft/feature/fun-turtle-rendering
Improve vertex transformation system
This commit is contained in:
		@@ -0,0 +1,264 @@
 | 
				
			|||||||
 | 
					package dan200.computercraft.client.render;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import net.minecraft.client.renderer.block.model.BakedQuad;
 | 
				
			||||||
 | 
					import net.minecraft.client.renderer.texture.TextureAtlasSprite;
 | 
				
			||||||
 | 
					import net.minecraft.client.renderer.vertex.VertexFormat;
 | 
				
			||||||
 | 
					import net.minecraft.util.EnumFacing;
 | 
				
			||||||
 | 
					import net.minecraftforge.client.model.pipeline.IVertexConsumer;
 | 
				
			||||||
 | 
					import net.minecraftforge.client.model.pipeline.LightUtil;
 | 
				
			||||||
 | 
					import net.minecraftforge.client.model.pipeline.VertexTransformer;
 | 
				
			||||||
 | 
					import net.minecraftforge.common.model.TRSRTransformation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
 | 
					import javax.vecmath.Matrix4f;
 | 
				
			||||||
 | 
					import javax.vecmath.Point3f;
 | 
				
			||||||
 | 
					import javax.vecmath.Vector3f;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Transforms vertices of a model, remaining aware of winding order, and rearranging
 | 
				
			||||||
 | 
					 * vertices if needed.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public final class ModelTransformer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static final Matrix4f identity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        identity = new Matrix4f();
 | 
				
			||||||
 | 
					        identity.setIdentity();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private ModelTransformer()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void transformQuadsTo( List<BakedQuad> output, List<BakedQuad> input, Matrix4f transform )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if( transform == null || transform.equals( identity ) )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            output.addAll( input );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Matrix4f normalMatrix = new Matrix4f( transform );
 | 
				
			||||||
 | 
					            normalMatrix.invert();
 | 
				
			||||||
 | 
					            normalMatrix.transpose();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for( BakedQuad quad : input ) output.add( doTransformQuad( quad, transform, normalMatrix ) );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static BakedQuad transformQuad( BakedQuad input, Matrix4f transform )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if( transform == null || transform.equals( identity ) ) return input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Matrix4f normalMatrix = new Matrix4f( transform );
 | 
				
			||||||
 | 
					        normalMatrix.invert();
 | 
				
			||||||
 | 
					        normalMatrix.transpose();
 | 
				
			||||||
 | 
					        return doTransformQuad( input, transform, normalMatrix );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static BakedQuad doTransformQuad( BakedQuad input, Matrix4f positionMatrix, Matrix4f normalMatrix )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BakedQuadBuilder builder = new BakedQuadBuilder( input.getFormat() );
 | 
				
			||||||
 | 
					        NormalAwareTransformer transformer = new NormalAwareTransformer( builder, positionMatrix, normalMatrix );
 | 
				
			||||||
 | 
					        input.pipe( transformer );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if( transformer.areNormalsInverted() )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            builder.swap( 1, 3 );
 | 
				
			||||||
 | 
					            transformer.areNormalsInverted();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return builder.build();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A vertex transformer that tracks whether the normals have been inverted and so the vertices
 | 
				
			||||||
 | 
					     * should be reordered so backface culling works as expected.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static class NormalAwareTransformer extends VertexTransformer
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private final Matrix4f positionMatrix;
 | 
				
			||||||
 | 
					        private final Matrix4f normalMatrix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private int vertexIndex = 0, elementIndex = 0;
 | 
				
			||||||
 | 
					        private final Point3f[] before = new Point3f[ 4 ];
 | 
				
			||||||
 | 
					        private final Point3f[] after = new Point3f[ 4 ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public NormalAwareTransformer( IVertexConsumer parent, Matrix4f positionMatrix, Matrix4f normalMatrix )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            super( parent );
 | 
				
			||||||
 | 
					            this.positionMatrix = positionMatrix;
 | 
				
			||||||
 | 
					            this.normalMatrix = normalMatrix;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void setQuadOrientation( EnumFacing orientation )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            super.setQuadOrientation( orientation == null ? orientation : TRSRTransformation.rotate( positionMatrix, orientation ) );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void put( int element, @Nonnull float... data )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            switch( getVertexFormat().getElement( element ).getUsage() )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case POSITION:
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Point3f vec = new Point3f( data );
 | 
				
			||||||
 | 
					                    Point3f newVec = new Point3f();
 | 
				
			||||||
 | 
					                    positionMatrix.transform( vec, newVec );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    float[] newData = new float[ 4 ];
 | 
				
			||||||
 | 
					                    newVec.get( newData );
 | 
				
			||||||
 | 
					                    super.put( element, newData );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    before[ vertexIndex ] = vec;
 | 
				
			||||||
 | 
					                    after[ vertexIndex ] = newVec;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                case NORMAL:
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Vector3f vec = new Vector3f( data );
 | 
				
			||||||
 | 
					                    normalMatrix.transform( vec );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    float[] newData = new float[ 4 ];
 | 
				
			||||||
 | 
					                    vec.get( newData );
 | 
				
			||||||
 | 
					                    super.put( element, newData );
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    super.put( element, data );
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            elementIndex++;
 | 
				
			||||||
 | 
					            if( elementIndex == getVertexFormat().getElementCount() )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                vertexIndex++;
 | 
				
			||||||
 | 
					                elementIndex = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public boolean areNormalsInverted()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Vector3f temp1 = new Vector3f(), temp2 = new Vector3f();
 | 
				
			||||||
 | 
					            Vector3f crossBefore = new Vector3f(), crossAfter = new Vector3f();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Determine what cross product we expect to have
 | 
				
			||||||
 | 
					            temp1.sub( before[ 1 ], before[ 0 ] );
 | 
				
			||||||
 | 
					            temp2.sub( before[ 1 ], before[ 2 ] );
 | 
				
			||||||
 | 
					            crossBefore.cross( temp1, temp2 );
 | 
				
			||||||
 | 
					            normalMatrix.transform( crossBefore );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // And determine what cross product we actually have
 | 
				
			||||||
 | 
					            temp1.sub( after[ 1 ], after[ 0 ] );
 | 
				
			||||||
 | 
					            temp2.sub( after[ 1 ], after[ 2 ] );
 | 
				
			||||||
 | 
					            crossAfter.cross( temp1, temp2 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // If the angle between expected and actual cross product is greater than 
 | 
				
			||||||
 | 
					            // pi/2 radians then we will need to reorder our quads.
 | 
				
			||||||
 | 
					            return Math.abs( crossBefore.angle( crossAfter ) ) >= Math.PI / 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A vertex consumer which is capable of building {@link BakedQuad}s.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Equivalent to {@link net.minecraftforge.client.model.pipeline.UnpackedBakedQuad.Builder} but more memory
 | 
				
			||||||
 | 
					     * efficient.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * This also provides the ability to swap vertices through {@link #swap(int, int)} to allow reordering.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static class BakedQuadBuilder implements IVertexConsumer
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private final VertexFormat format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private final int[] vertexData;
 | 
				
			||||||
 | 
					        private int vertexIndex = 0, elementIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private EnumFacing orientation;
 | 
				
			||||||
 | 
					        private int quadTint;
 | 
				
			||||||
 | 
					        private boolean diffuse;
 | 
				
			||||||
 | 
					        private TextureAtlasSprite texture;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private BakedQuadBuilder( VertexFormat format )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.format = format;
 | 
				
			||||||
 | 
					            this.vertexData = new int[ format.getNextOffset() ];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Nonnull
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public VertexFormat getVertexFormat()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return format;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void setQuadTint( int tint )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.quadTint = tint;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void setQuadOrientation( @Nonnull EnumFacing orientation )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.orientation = orientation;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void setApplyDiffuseLighting( boolean diffuse )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.diffuse = diffuse;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void setTexture( @Nonnull TextureAtlasSprite texture )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.texture = texture;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void put( int element, @Nonnull float... data )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            LightUtil.pack( data, vertexData, format, vertexIndex, element );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            elementIndex++;
 | 
				
			||||||
 | 
					            if( elementIndex == getVertexFormat().getElementCount() )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                vertexIndex++;
 | 
				
			||||||
 | 
					                elementIndex = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void swap( int a, int b )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int length = vertexData.length / 4;
 | 
				
			||||||
 | 
					            for( int i = 0; i < length; i++ )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                int temp = vertexData[ a * length + i ];
 | 
				
			||||||
 | 
					                vertexData[ a * length + i ] = vertexData[ b * length + i ];
 | 
				
			||||||
 | 
					                vertexData[ b * length + i ] = temp;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public BakedQuad build()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if( elementIndex != 0 || vertexIndex != 4 )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                throw new IllegalStateException( "Got an unexpected number of elements/vertices" );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if( texture == null )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                throw new IllegalStateException( "Texture has not been set" );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return new BakedQuad( vertexData, quadTint, orientation, texture, diffuse, format );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -9,7 +9,6 @@ package dan200.computercraft.client.render;
 | 
				
			|||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
 | 
					import dan200.computercraft.api.turtle.ITurtleUpgrade;
 | 
				
			||||||
import dan200.computercraft.api.turtle.TurtleSide;
 | 
					import dan200.computercraft.api.turtle.TurtleSide;
 | 
				
			||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
					import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
				
			||||||
import dan200.computercraft.shared.computer.core.IComputer;
 | 
					 | 
				
			||||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
 | 
					import dan200.computercraft.shared.turtle.blocks.TileTurtle;
 | 
				
			||||||
import dan200.computercraft.shared.turtle.entity.TurtleVisionCamera;
 | 
					import dan200.computercraft.shared.turtle.entity.TurtleVisionCamera;
 | 
				
			||||||
import dan200.computercraft.shared.util.Holiday;
 | 
					import dan200.computercraft.shared.util.Holiday;
 | 
				
			||||||
@@ -121,18 +120,22 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
 | 
				
			|||||||
            GlStateManager.translate( posX + offset.x, posY + offset.y, posZ + offset.z );
 | 
					            GlStateManager.translate( posX + offset.x, posY + offset.y, posZ + offset.z );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Render the label
 | 
					            // Render the label
 | 
				
			||||||
            IComputer computer = turtle.getComputer();
 | 
					            String label = turtle.createProxy().getLabel();
 | 
				
			||||||
            String label = (computer != null) ? computer.getLabel() : null;
 | 
					 | 
				
			||||||
            if( label != null )
 | 
					            if( label != null )
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                renderLabel( turtle.getAccess().getPosition(), label );
 | 
					                renderLabel( turtle.getAccess().getPosition(), label );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Render the turtle
 | 
					            // Render the turtle
 | 
				
			||||||
            GlStateManager.translate( 0.5f, 0.0f, 0.5f );
 | 
					            GlStateManager.translate( 0.5f, 0.5f, 0.5f );
 | 
				
			||||||
            GlStateManager.rotate( 180.0f - yaw, 0.0f, 1.0f, 0.0f );
 | 
					            GlStateManager.rotate( 180.0f - yaw, 0.0f, 1.0f, 0.0f );
 | 
				
			||||||
            GlStateManager.translate( -0.5f, 0.0f, -0.5f );
 | 
					            if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // Flip the model and swap the cull face as winding order will have changed.
 | 
				
			||||||
 | 
					                GlStateManager.scale( 1.0f, -1.0f, 1.0f );
 | 
				
			||||||
 | 
					                GlStateManager.cullFace( GlStateManager.CullFace.FRONT );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            GlStateManager.translate( -0.5f, -0.5f, -0.5f );
 | 
				
			||||||
            // Render the turtle
 | 
					            // Render the turtle
 | 
				
			||||||
            int colour;
 | 
					            int colour;
 | 
				
			||||||
            ComputerFamily family;
 | 
					            ComputerFamily family;
 | 
				
			||||||
@@ -172,6 +175,7 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
 | 
				
			|||||||
        finally
 | 
					        finally
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            GlStateManager.popMatrix();
 | 
					            GlStateManager.popMatrix();
 | 
				
			||||||
 | 
					            GlStateManager.cullFace( GlStateManager.CullFace.BACK );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,13 +6,10 @@ import net.minecraft.client.renderer.block.model.IBakedModel;
 | 
				
			|||||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
 | 
					import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
 | 
				
			||||||
import net.minecraft.client.renderer.block.model.ItemOverrideList;
 | 
					import net.minecraft.client.renderer.block.model.ItemOverrideList;
 | 
				
			||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
 | 
					import net.minecraft.client.renderer.texture.TextureAtlasSprite;
 | 
				
			||||||
import net.minecraft.client.renderer.vertex.VertexFormat;
 | 
					 | 
				
			||||||
import net.minecraft.client.renderer.vertex.VertexFormatElement;
 | 
					 | 
				
			||||||
import net.minecraft.util.EnumFacing;
 | 
					import net.minecraft.util.EnumFacing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.annotation.Nonnull;
 | 
					import javax.annotation.Nonnull;
 | 
				
			||||||
import javax.vecmath.Matrix4f;
 | 
					import javax.vecmath.Matrix4f;
 | 
				
			||||||
import javax.vecmath.Point3f;
 | 
					 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
@@ -20,16 +17,17 @@ import java.util.Map;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class TurtleMultiModel implements IBakedModel
 | 
					public class TurtleMultiModel implements IBakedModel
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private IBakedModel m_baseModel;
 | 
					    private final IBakedModel m_baseModel;
 | 
				
			||||||
    private IBakedModel m_overlayModel;
 | 
					    private final IBakedModel m_overlayModel;
 | 
				
			||||||
    private IBakedModel m_leftUpgradeModel;
 | 
					    private final Matrix4f m_generalTransform;
 | 
				
			||||||
    private Matrix4f m_leftUpgradeTransform;
 | 
					    private final IBakedModel m_leftUpgradeModel;
 | 
				
			||||||
    private IBakedModel m_rightUpgradeModel;
 | 
					    private final Matrix4f m_leftUpgradeTransform;
 | 
				
			||||||
    private Matrix4f m_rightUpgradeTransform;
 | 
					    private final IBakedModel m_rightUpgradeModel;
 | 
				
			||||||
 | 
					    private final Matrix4f m_rightUpgradeTransform;
 | 
				
			||||||
    private List<BakedQuad> m_generalQuads;
 | 
					    private List<BakedQuad> m_generalQuads;
 | 
				
			||||||
    private Map<EnumFacing, List<BakedQuad>> m_faceQuads;
 | 
					    private Map<EnumFacing, List<BakedQuad>> m_faceQuads;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public TurtleMultiModel( IBakedModel baseModel, IBakedModel overlayModel, IBakedModel leftUpgradeModel, Matrix4f leftUpgradeTransform, IBakedModel rightUpgradeModel, Matrix4f rightUpgradeTransform )
 | 
					    public TurtleMultiModel( IBakedModel baseModel, IBakedModel overlayModel, Matrix4f generalTransform, IBakedModel leftUpgradeModel, Matrix4f leftUpgradeTransform, IBakedModel rightUpgradeModel, Matrix4f rightUpgradeTransform )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Get the models
 | 
					        // Get the models
 | 
				
			||||||
        m_baseModel = baseModel;
 | 
					        m_baseModel = baseModel;
 | 
				
			||||||
@@ -38,6 +36,7 @@ public class TurtleMultiModel implements IBakedModel
 | 
				
			|||||||
        m_leftUpgradeTransform = leftUpgradeTransform;
 | 
					        m_leftUpgradeTransform = leftUpgradeTransform;
 | 
				
			||||||
        m_rightUpgradeModel = rightUpgradeModel;
 | 
					        m_rightUpgradeModel = rightUpgradeModel;
 | 
				
			||||||
        m_rightUpgradeTransform = rightUpgradeTransform;
 | 
					        m_rightUpgradeTransform = rightUpgradeTransform;
 | 
				
			||||||
 | 
					        m_generalTransform = generalTransform;
 | 
				
			||||||
        m_generalQuads = null;
 | 
					        m_generalQuads = null;
 | 
				
			||||||
        m_faceQuads = new HashMap<>();
 | 
					        m_faceQuads = new HashMap<>();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -48,51 +47,52 @@ public class TurtleMultiModel implements IBakedModel
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if( side != null )
 | 
					        if( side != null )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if( !m_faceQuads.containsKey( side ) )
 | 
					            if( !m_faceQuads.containsKey( side ) ) m_faceQuads.put( side, buildQuads( state, side, rand ) );
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                ArrayList<BakedQuad> quads = new ArrayList<>();
 | 
					 | 
				
			||||||
                if( m_overlayModel != null )
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    quads.addAll( m_overlayModel.getQuads( state, side, rand ) );
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if( m_leftUpgradeModel != null )
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    quads.addAll( transformQuads( m_leftUpgradeModel.getQuads( state, side, rand ), m_leftUpgradeTransform ) );
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if( m_rightUpgradeModel != null )
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    quads.addAll( transformQuads( m_rightUpgradeModel.getQuads( state, side, rand ), m_rightUpgradeTransform ) );
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                quads.trimToSize();
 | 
					 | 
				
			||||||
                m_faceQuads.put( side, quads );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return m_faceQuads.get( side );
 | 
					            return m_faceQuads.get( side );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if( m_generalQuads == null )
 | 
					            if( m_generalQuads == null ) m_generalQuads = buildQuads( state, side, rand );
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                ArrayList<BakedQuad> quads = new ArrayList<>();
 | 
					 | 
				
			||||||
                quads.addAll( m_baseModel.getQuads( state, side, rand ) );
 | 
					 | 
				
			||||||
                if( m_overlayModel != null )
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    quads.addAll( m_overlayModel.getQuads( state, side, rand ) );
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if( m_leftUpgradeModel != null )
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    quads.addAll( transformQuads( m_leftUpgradeModel.getQuads( state, side, rand ), m_leftUpgradeTransform ) );
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if( m_rightUpgradeModel != null )
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    quads.addAll( transformQuads( m_rightUpgradeModel.getQuads( state, side, rand ), m_rightUpgradeTransform ) );
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                quads.trimToSize();
 | 
					 | 
				
			||||||
                m_generalQuads = quads;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return m_generalQuads;
 | 
					            return m_generalQuads;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private List<BakedQuad> buildQuads( IBlockState state, EnumFacing side, long rand )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ArrayList<BakedQuad> quads = new ArrayList<>();
 | 
				
			||||||
 | 
					        ModelTransformer.transformQuadsTo( quads, m_baseModel.getQuads( state, side, rand ), m_generalTransform );
 | 
				
			||||||
 | 
					        if( m_overlayModel != null )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ModelTransformer.transformQuadsTo( quads, m_overlayModel.getQuads( state, side, rand ), m_generalTransform );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if( m_overlayModel != null )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ModelTransformer.transformQuadsTo( quads, m_overlayModel.getQuads( state, side, rand ), m_generalTransform );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if( m_leftUpgradeModel != null )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Matrix4f upgradeTransform = m_generalTransform;
 | 
				
			||||||
 | 
					            if( m_leftUpgradeTransform != null )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                upgradeTransform = new Matrix4f( m_generalTransform );
 | 
				
			||||||
 | 
					                upgradeTransform.mul( m_leftUpgradeTransform );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ModelTransformer.transformQuadsTo( quads, m_leftUpgradeModel.getQuads( state, side, rand ), upgradeTransform );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if( m_rightUpgradeModel != null )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Matrix4f upgradeTransform = m_generalTransform;
 | 
				
			||||||
 | 
					            if( m_rightUpgradeTransform != null )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                upgradeTransform = new Matrix4f( m_generalTransform );
 | 
				
			||||||
 | 
					                upgradeTransform.mul( m_rightUpgradeTransform );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ModelTransformer.transformQuadsTo( quads, m_rightUpgradeModel.getQuads( state, side, rand ), upgradeTransform );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        quads.trimToSize();
 | 
				
			||||||
 | 
					        return quads;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean isAmbientOcclusion()
 | 
					    public boolean isAmbientOcclusion()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -132,63 +132,4 @@ public class TurtleMultiModel implements IBakedModel
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return ItemOverrideList.NONE;
 | 
					        return ItemOverrideList.NONE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private List<BakedQuad> transformQuads( List<BakedQuad> input, Matrix4f transform )
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if( transform == null || input.size() == 0 )
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return input;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            List<BakedQuad> output = new ArrayList<>( input.size() );
 | 
					 | 
				
			||||||
            for( BakedQuad quad : input )
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                output.add( transformQuad( quad, transform ) );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return output;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private BakedQuad transformQuad( BakedQuad quad, Matrix4f transform )
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        int[] vertexData = quad.getVertexData().clone();
 | 
					 | 
				
			||||||
        int offset = 0;
 | 
					 | 
				
			||||||
        BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), quad.getSprite(), quad.shouldApplyDiffuseLighting(), quad.getFormat() );
 | 
					 | 
				
			||||||
        VertexFormat format = copy.getFormat();
 | 
					 | 
				
			||||||
        for( int i=0; i<format.getElementCount(); ++i ) // For each vertex element
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            VertexFormatElement element = format.getElement( i );
 | 
					 | 
				
			||||||
            if( element.isPositionElement() &&
 | 
					 | 
				
			||||||
                element.getType() == VertexFormatElement.EnumType.FLOAT &&
 | 
					 | 
				
			||||||
                element.getElementCount() == 3 ) // When we find a position element
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                for( int j=0; j<4; ++j ) // For each corner of the quad
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    int start = offset + j * format.getNextOffset();
 | 
					 | 
				
			||||||
                    if( (start % 4) == 0 )
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        start = start / 4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Extract the position
 | 
					 | 
				
			||||||
                        Point3f pos = new Point3f(
 | 
					 | 
				
			||||||
                            Float.intBitsToFloat( vertexData[ start ] ),
 | 
					 | 
				
			||||||
                            Float.intBitsToFloat( vertexData[ start + 1 ] ),
 | 
					 | 
				
			||||||
                            Float.intBitsToFloat( vertexData[ start + 2 ] )
 | 
					 | 
				
			||||||
                        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Transform the position
 | 
					 | 
				
			||||||
                        transform.transform( pos );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Insert the position
 | 
					 | 
				
			||||||
                        vertexData[ start ] = Float.floatToRawIntBits( pos.x );
 | 
					 | 
				
			||||||
                        vertexData[ start + 1 ] = Float.floatToRawIntBits( pos.y );
 | 
					 | 
				
			||||||
                        vertexData[ start + 2 ] = Float.floatToRawIntBits( pos.z );
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            offset += element.getSize();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return copy;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,19 @@ import java.util.List;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class TurtleSmartItemModel implements IBakedModel, IResourceManagerReloadListener
 | 
					public class TurtleSmartItemModel implements IBakedModel, IResourceManagerReloadListener
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    private static final Matrix4f s_identity, s_flip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        s_identity = new Matrix4f();
 | 
				
			||||||
 | 
					        s_identity.setIdentity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        s_flip = new Matrix4f();
 | 
				
			||||||
 | 
					        s_flip.setIdentity();
 | 
				
			||||||
 | 
					        s_flip.m11 = -1; // Flip on the y axis
 | 
				
			||||||
 | 
					        s_flip.m13 = 1; // Models go from (0,0,0) to (1,1,1), so push back up.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static class TurtleModelCombination
 | 
					    private static class TurtleModelCombination
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public final ComputerFamily m_family;
 | 
					        public final ComputerFamily m_family;
 | 
				
			||||||
@@ -43,8 +56,9 @@ public class TurtleSmartItemModel implements IBakedModel, IResourceManagerReload
 | 
				
			|||||||
        public final ITurtleUpgrade m_rightUpgrade;
 | 
					        public final ITurtleUpgrade m_rightUpgrade;
 | 
				
			||||||
        public final ResourceLocation m_overlay;
 | 
					        public final ResourceLocation m_overlay;
 | 
				
			||||||
        public final boolean m_christmas;
 | 
					        public final boolean m_christmas;
 | 
				
			||||||
 | 
					        public final boolean m_flip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public TurtleModelCombination( ComputerFamily family, boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas )
 | 
					        public TurtleModelCombination( ComputerFamily family, boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas, boolean flip )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            m_family = family;
 | 
					            m_family = family;
 | 
				
			||||||
            m_colour = colour;
 | 
					            m_colour = colour;
 | 
				
			||||||
@@ -52,22 +66,26 @@ public class TurtleSmartItemModel implements IBakedModel, IResourceManagerReload
 | 
				
			|||||||
            m_rightUpgrade = rightUpgrade;
 | 
					            m_rightUpgrade = rightUpgrade;
 | 
				
			||||||
            m_overlay = overlay;
 | 
					            m_overlay = overlay;
 | 
				
			||||||
            m_christmas = christmas;
 | 
					            m_christmas = christmas;
 | 
				
			||||||
 | 
					            m_flip = flip;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public boolean equals( Object other )
 | 
					        public boolean equals( Object other )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if( other == this ) {
 | 
					            if( other == this )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if( other instanceof TurtleModelCombination ) {
 | 
					            if( other instanceof TurtleModelCombination )
 | 
				
			||||||
                TurtleModelCombination otherCombo = (TurtleModelCombination)other;
 | 
					            {
 | 
				
			||||||
 | 
					                TurtleModelCombination otherCombo = (TurtleModelCombination) other;
 | 
				
			||||||
                if( otherCombo.m_family == m_family &&
 | 
					                if( otherCombo.m_family == m_family &&
 | 
				
			||||||
                    otherCombo.m_colour == m_colour &&
 | 
					                    otherCombo.m_colour == m_colour &&
 | 
				
			||||||
                    otherCombo.m_leftUpgrade == m_leftUpgrade &&
 | 
					                    otherCombo.m_leftUpgrade == m_leftUpgrade &&
 | 
				
			||||||
                    otherCombo.m_rightUpgrade == m_rightUpgrade &&
 | 
					                    otherCombo.m_rightUpgrade == m_rightUpgrade &&
 | 
				
			||||||
                    Objects.equal( otherCombo.m_overlay, m_overlay ) &&
 | 
					                    Objects.equal( otherCombo.m_overlay, m_overlay ) &&
 | 
				
			||||||
                    otherCombo.m_christmas == m_christmas )
 | 
					                    otherCombo.m_christmas == m_christmas &&
 | 
				
			||||||
 | 
					                    otherCombo.m_flip == m_flip )
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return true;
 | 
					                    return true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -86,6 +104,7 @@ public class TurtleSmartItemModel implements IBakedModel, IResourceManagerReload
 | 
				
			|||||||
            result = prime * result + (m_rightUpgrade != null ? m_rightUpgrade.hashCode() : 0);
 | 
					            result = prime * result + (m_rightUpgrade != null ? m_rightUpgrade.hashCode() : 0);
 | 
				
			||||||
            result = prime * result + (m_overlay != null ? m_overlay.hashCode() : 0);
 | 
					            result = prime * result + (m_overlay != null ? m_overlay.hashCode() : 0);
 | 
				
			||||||
            result = prime * result + (m_christmas ? 1 : 0);
 | 
					            result = prime * result + (m_christmas ? 1 : 0);
 | 
				
			||||||
 | 
					            result = prime * result + (m_flip ? 1 : 0);
 | 
				
			||||||
            return result;
 | 
					            return result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -97,12 +116,12 @@ public class TurtleSmartItemModel implements IBakedModel, IResourceManagerReload
 | 
				
			|||||||
    public TurtleSmartItemModel()
 | 
					    public TurtleSmartItemModel()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        m_cachedModels = new HashMap<>();
 | 
					        m_cachedModels = new HashMap<>();
 | 
				
			||||||
        m_defaultCombination = new TurtleModelCombination( ComputerFamily.Normal, false, null, null, null, false );
 | 
					        m_defaultCombination = new TurtleModelCombination( ComputerFamily.Normal, false, null, null, null, false, false );
 | 
				
			||||||
        m_overrides = new ItemOverrideList( new ArrayList<>() )
 | 
					        m_overrides = new ItemOverrideList( new ArrayList<>() )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            @Nonnull
 | 
					            @Nonnull
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public IBakedModel handleItemState( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity)
 | 
					            public IBakedModel handleItemState( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity )
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                ItemTurtleBase turtle = (ItemTurtleBase) stack.getItem();
 | 
					                ItemTurtleBase turtle = (ItemTurtleBase) stack.getItem();
 | 
				
			||||||
                ComputerFamily family = turtle.getFamily( stack );
 | 
					                ComputerFamily family = turtle.getFamily( stack );
 | 
				
			||||||
@@ -111,7 +130,9 @@ public class TurtleSmartItemModel implements IBakedModel, IResourceManagerReload
 | 
				
			|||||||
                ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.Right );
 | 
					                ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.Right );
 | 
				
			||||||
                ResourceLocation overlay = turtle.getOverlay( stack );
 | 
					                ResourceLocation overlay = turtle.getOverlay( stack );
 | 
				
			||||||
                boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.Christmas;
 | 
					                boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.Christmas;
 | 
				
			||||||
                TurtleModelCombination combo = new TurtleModelCombination( family, colour != -1, leftUpgrade, rightUpgrade, overlay, christmas );
 | 
					                String label = turtle.getLabel( stack );
 | 
				
			||||||
 | 
					                boolean flip = label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" ));
 | 
				
			||||||
 | 
					                TurtleModelCombination combo = new TurtleModelCombination( family, colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
 | 
				
			||||||
                if( m_cachedModels.containsKey( combo ) )
 | 
					                if( m_cachedModels.containsKey( combo ) )
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return m_cachedModels.get( combo );
 | 
					                    return m_cachedModels.get( combo );
 | 
				
			||||||
@@ -147,27 +168,24 @@ public class TurtleSmartItemModel implements IBakedModel, IResourceManagerReload
 | 
				
			|||||||
        ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_family, combo.m_overlay, combo.m_christmas );
 | 
					        ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_family, combo.m_overlay, combo.m_christmas );
 | 
				
			||||||
        IBakedModel baseModel = modelManager.getModel( baseModelLocation );
 | 
					        IBakedModel baseModel = modelManager.getModel( baseModelLocation );
 | 
				
			||||||
        IBakedModel overlayModel = (overlayModelLocation != null) ? modelManager.getModel( baseModelLocation ) : null;
 | 
					        IBakedModel overlayModel = (overlayModelLocation != null) ? modelManager.getModel( baseModelLocation ) : null;
 | 
				
			||||||
 | 
					        Matrix4f transform = combo.m_flip ? s_flip : s_identity;
 | 
				
			||||||
        Pair<IBakedModel, Matrix4f> leftModel = (combo.m_leftUpgrade != null) ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null;
 | 
					        Pair<IBakedModel, Matrix4f> leftModel = (combo.m_leftUpgrade != null) ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null;
 | 
				
			||||||
        Pair<IBakedModel, Matrix4f> rightModel = (combo.m_rightUpgrade != null) ? combo.m_rightUpgrade.getModel( null, TurtleSide.Right ) : null;
 | 
					        Pair<IBakedModel, Matrix4f> rightModel = (combo.m_rightUpgrade != null) ? combo.m_rightUpgrade.getModel( null, TurtleSide.Right ) : null;
 | 
				
			||||||
        if( leftModel != null && rightModel != null )
 | 
					        if( leftModel != null && rightModel != null )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new TurtleMultiModel( baseModel, overlayModel, leftModel.getLeft(), leftModel.getRight(), rightModel.getLeft(), rightModel.getRight() );
 | 
					            return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel.getLeft(), leftModel.getRight(), rightModel.getLeft(), rightModel.getRight() );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if( leftModel != null )
 | 
					        else if( leftModel != null )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new TurtleMultiModel( baseModel, overlayModel, leftModel.getLeft(), leftModel.getRight(), null, null );
 | 
					            return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel.getLeft(), leftModel.getRight(), null, null );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if( rightModel != null )
 | 
					        else if( rightModel != null )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new TurtleMultiModel( baseModel, overlayModel, null, null, rightModel.getLeft(), rightModel.getRight() );
 | 
					            return new TurtleMultiModel( baseModel, overlayModel, transform, null, null, rightModel.getLeft(), rightModel.getRight() );
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if( overlayModel != null )
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return new TurtleMultiModel( baseModel, overlayModel, null, null, null, null );
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return baseModel;
 | 
					            return new TurtleMultiModel( baseModel, overlayModel, transform, null, null, null, null );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user