Improve vertex transformation system

This migrates TurtleMultiModel's current vertex transformation system
into something more powerful and "correct". Namely, it has the following
improvements:

 - Handles all position formats (float, byte, etc...)
 - Correctly translates normals of quads
 - Reorders faces if the winding order is reversed
This commit is contained in:
SquidDev
2017-11-21 00:18:03 +00:00
parent 19e4c03d3a
commit ce7923d248
2 changed files with 286 additions and 99 deletions
@@ -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.ItemOverrideList;
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 javax.annotation.Nonnull;
import javax.vecmath.Matrix4f;
import javax.vecmath.Point3f;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -48,51 +45,36 @@ public class TurtleMultiModel implements IBakedModel
{
if( side != null )
{
if( !m_faceQuads.containsKey( side ) )
{
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 );
}
if( !m_faceQuads.containsKey( side ) ) m_faceQuads.put( side, buildQuads( state, side, rand ) );
return m_faceQuads.get( side );
}
else
{
if( m_generalQuads == null )
{
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;
}
if( m_generalQuads == null ) m_generalQuads = buildQuads( state, side, rand );
return m_generalQuads;
}
}
private List<BakedQuad> buildQuads( IBlockState state, EnumFacing side, long 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 )
{
ModelTransformer.transformQuadsTo( quads, m_leftUpgradeModel.getQuads( state, side, rand ), m_leftUpgradeTransform );
}
if( m_rightUpgradeModel != null )
{
ModelTransformer.transformQuadsTo( quads, m_rightUpgradeModel.getQuads( state, side, rand ), m_rightUpgradeTransform );
}
quads.trimToSize();
return quads;
}
@Override
public boolean isAmbientOcclusion()
{
@@ -132,63 +114,4 @@ public class TurtleMultiModel implements IBakedModel
{
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;
}
}