From 0809ac5625cfb6eef89db1676c017ae585e8c67d Mon Sep 17 00:00:00 2001 From: elix-x Date: Tue, 5 Jul 2016 19:43:51 +0200 Subject: [PATCH] Implemented automatic rotation Implemented automatic rotation for all tile blocks. You can still use facing properties in model files, if you want to. Also, some added some fixes and improvements. --- src/main/java/appeng/client/ClientHelper.java | 5 +- .../render/model/AEIgnoringStateMapper.java | 1 + .../model/CachingRotatingBakedModel.java | 273 ++++++++++++++++++ .../client/render/model/UVLModelLoader.java | 2 +- .../core/features/AEBlockFeatureHandler.java | 8 + .../features/AECableBusFeatureHandler.java | 8 + .../features/AETileBlockFeatureHandler.java | 18 ++ .../appeng/core/features/IFeatureHandler.java | 6 + .../core/features/ItemFeatureHandler.java | 8 + .../features/StairBlockFeatureHandler.java | 8 + .../blockstates/tile.BlockGrinder.ignore.json | 1 + .../blockstates/tile.BlockGrinder.json | 5 +- 12 files changed, 337 insertions(+), 6 deletions(-) create mode 100644 src/main/java/appeng/client/render/model/CachingRotatingBakedModel.java diff --git a/src/main/java/appeng/client/ClientHelper.java b/src/main/java/appeng/client/ClientHelper.java index 04f6c3ac..c8ff2fb8 100644 --- a/src/main/java/appeng/client/ClientHelper.java +++ b/src/main/java/appeng/client/ClientHelper.java @@ -378,7 +378,10 @@ public class ClientHelper extends ServerHelper @SubscribeEvent public void onModelBakeEvent( final ModelBakeEvent event ) { - + for( IAEFeature feature : Api.INSTANCE.definitions().getFeatureRegistry().getRegisteredFeatures() ) + { + feature.handler().registerCustomModelOverride(event.getModelRegistry()); + } } @SubscribeEvent diff --git a/src/main/java/appeng/client/render/model/AEIgnoringStateMapper.java b/src/main/java/appeng/client/render/model/AEIgnoringStateMapper.java index 1096cba4..c60288a9 100644 --- a/src/main/java/appeng/client/render/model/AEIgnoringStateMapper.java +++ b/src/main/java/appeng/client/render/model/AEIgnoringStateMapper.java @@ -39,6 +39,7 @@ public class AEIgnoringStateMapper extends StateMapperBase implements IResourceM { try { + ignored.clear(); ignored.addAll( IOUtils.readLines( resourceManager.getResource( ignoredRL ).getInputStream() ) ); } catch( IOException e ) diff --git a/src/main/java/appeng/client/render/model/CachingRotatingBakedModel.java b/src/main/java/appeng/client/render/model/CachingRotatingBakedModel.java new file mode 100644 index 00000000..6683adb2 --- /dev/null +++ b/src/main/java/appeng/client/render/model/CachingRotatingBakedModel.java @@ -0,0 +1,273 @@ + +package appeng.client.render.model; + + +import java.util.ArrayList; +import java.util.List; + +import javax.vecmath.Matrix4f; +import javax.vecmath.Vector3f; +import javax.vecmath.Vector4f; + +import com.google.common.base.Objects; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.block.model.BakedQuad; +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 net.minecraftforge.client.model.pipeline.IVertexConsumer; +import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer; +import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; +import net.minecraftforge.common.model.TRSRTransformation; + +import appeng.block.AEBaseTileBlock; + + +public class CachingRotatingBakedModel implements IBakedModel +{ + + private final IBakedModel parent; + private final LoadingCache, List> quadCache; + + public CachingRotatingBakedModel( IBakedModel parent ) + { + this.parent = parent; + // 6 (DUNSWE) * 6 (DUNSWE) * 7 (DUNSWE + null) = 252 + this.quadCache = CacheBuilder.newBuilder().maximumSize( 252 ).build( new CacheLoader, List>(){ + + @Override + public List load( Pair key ) throws Exception + { + final EnumFacing forward = key.getLeft().getValue( AEBaseTileBlock.AE_BLOCK_FORWARD ); + final EnumFacing up = key.getLeft().getValue( AEBaseTileBlock.AE_BLOCK_UP ); + final Matrix4f mat = FacingToRotation.get( forward, up ).getMat(); + + List original = CachingRotatingBakedModel.this.parent.getQuads( key.getLeft(), key.getRight(), 0 ); + List rotated = new ArrayList<>(); + for( BakedQuad quad : original ) + { + VertexFormat format = quad.getFormat(); + UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( format ); + VertexRotator rot = new VertexRotator( mat ); + rot.setParent( builder ); + quad.pipe( rot ); + rotated.add( builder.build() ); + } + return rotated; + } + + } ); + } + + @Override + public boolean isAmbientOcclusion() + { + return parent.isAmbientOcclusion(); + } + + @Override + public boolean isGui3d() + { + return parent.isGui3d(); + } + + @Override + public boolean isBuiltInRenderer() + { + return parent.isBuiltInRenderer(); + } + + @Override + public TextureAtlasSprite getParticleTexture() + { + return parent.getParticleTexture(); + } + + @Override + public ItemCameraTransforms getItemCameraTransforms() + { + return parent.getItemCameraTransforms(); + } + + @Override + public ItemOverrideList getOverrides() + { + return parent.getOverrides(); + } + + @Override + public List getQuads( IBlockState state, EnumFacing side, long rand ) + { + if( state == null ) + { + return parent.getQuads( state, side, rand ); + } + return quadCache.getUnchecked( new ImmutablePair( state, side ) ); + } + + public enum FacingToRotation + { + + // DUNSWE + //@formatter:off + DOWN_DOWN ( new Vector3f( 0, 0, 0 ) ), //NOOP + DOWN_UP ( new Vector3f( 0, 0, 0 ) ), //NOOP + DOWN_NORTH ( new Vector3f( -90, 0, 0 ) ), + DOWN_SOUTH ( new Vector3f( -90, 0, 180 ) ), + DOWN_WEST ( new Vector3f( -90, 0, 90 ) ), + DOWN_EAST ( new Vector3f( -90, 0, -90 ) ), + UP_DOWN ( new Vector3f( 0, 0, 0 ) ), //NOOP + UP_UP ( new Vector3f( 0, 0, 0 ) ), //NOOP + UP_NORTH ( new Vector3f( 90, 0, 180 ) ), + UP_SOUTH ( new Vector3f( 90, 0, 0 ) ), + UP_WEST ( new Vector3f( 90, 0, 90 ) ), + UP_EAST ( new Vector3f( 90, 0, -90 ) ), + NORTH_DOWN ( new Vector3f( 0, 0, 180 ) ), + NORTH_UP ( new Vector3f( 0, 0, 0 ) ), + NORTH_NORTH ( new Vector3f( 0, 0, 0 ) ), //NOOP + NORTH_SOUTH ( new Vector3f( 0, 0, 0 ) ), //NOOP + NORTH_WEST ( new Vector3f( 0, 0, 90 ) ), + NORTH_EAST ( new Vector3f( 0, 0, -90 ) ), + SOUTH_DOWN ( new Vector3f( 0, 180, 180 ) ), + SOUTH_UP ( new Vector3f( 0, 180, 0 ) ), + SOUTH_NORTH ( new Vector3f( 0, 0, 0 ) ), //NOOP + SOUTH_SOUTH ( new Vector3f( 0, 0, 0 ) ), //NOOP + SOUTH_WEST ( new Vector3f( 0, 180, -90 ) ), + SOUTH_EAST ( new Vector3f( 0, 180, 90 ) ), + WEST_DOWN ( new Vector3f( 0, 90, 180 ) ), + WEST_UP ( new Vector3f( 0, 90, 0 ) ), + WEST_NORTH ( new Vector3f( 0, 90, -90 ) ), + WEST_SOUTH ( new Vector3f( 0, 90, 90 ) ), + WEST_WEST ( new Vector3f( 0, 0, 0 ) ), //NOOP + WEST_EAST ( new Vector3f( 0, 0, 0 ) ), //NOOP + EAST_DOWN ( new Vector3f( 0, -90, 180 ) ), + EAST_UP ( new Vector3f( 0, -90, 0 ) ), + EAST_NORTH ( new Vector3f( 0, -90, 90 ) ), + EAST_SOUTH ( new Vector3f( 0, -90, -90 ) ), + EAST_WEST ( new Vector3f( 0, 0, 0 ) ), //NOOP + EAST_EAST ( new Vector3f( 0, 0, 0 ) ); //NOOP + //@formatter:on + + private final Matrix4f mat; + + private FacingToRotation( Vector3f rot ) + { + this.mat = TRSRTransformation.toVecmath( new org.lwjgl.util.vector.Matrix4f().rotate( (float) Math.toRadians( rot.x ), new org.lwjgl.util.vector.Vector3f( 1, 0, 0 ) ).rotate( (float) Math.toRadians( rot.y ), new org.lwjgl.util.vector.Vector3f( 0, 1, 0 ) ).rotate( (float) Math.toRadians( rot.z ), new org.lwjgl.util.vector.Vector3f( 0, 0, 1 ) ) ); + } + + public Matrix4f getMat() + { + return new Matrix4f( this.mat ); + } + + public static FacingToRotation get( EnumFacing forward, EnumFacing up ) + { + return values()[forward.ordinal() * 6 + up.ordinal()]; + } + + } + + public class VertexRotator extends QuadGatheringTransformer + { + private final Matrix4f mat; + + public VertexRotator( Matrix4f mat ) + { + this.mat = mat; + } + + @Override + public void setParent( IVertexConsumer parent ) + { + super.setParent( parent ); + if( Objects.equal( getVertexFormat(), parent.getVertexFormat() ) ) + { + return; + } + setVertexFormat( parent.getVertexFormat() ); + } + + @Override + protected void processQuad() + { + VertexFormat format = parent.getVertexFormat(); + int count = format.getElementCount(); + + for( int v = 0; v < 4; v++ ) + { + for( int e = 0; e < count; e++ ) + { + VertexFormatElement element = format.getElement( e ); + if( element.getUsage() == VertexFormatElement.EnumUsage.POSITION ) + { + parent.put( e, transform( quadData[e][v] ) ); + } + else + { + parent.put( e, quadData[e][v] ); + } + } + } + } + + private float[] transform( float[] fs ) + { + switch( fs.length ) + { + case 3: + Vector3f vec = new Vector3f( fs[0], fs[1], fs[2] ); + vec.x -= 0.5f; + vec.y -= 0.5f; + vec.z -= 0.5f; + mat.transform( vec ); + vec.x += 0.5f; + vec.y += 0.5f; + vec.z += 0.5f; + return new float[] { vec.x, vec.y, vec.z }; + case 4: + Vector4f vecc = new Vector4f( fs[0], fs[1], fs[2], fs[3] ); + vecc.x -= 0.5f; + vecc.y -= 0.5f; + vecc.z -= 0.5f; + mat.transform( vecc ); + vecc.x += 0.5f; + vecc.y += 0.5f; + vecc.z += 0.5f; + return new float[] { vecc.x, vecc.y, vecc.z, vecc.w }; + + default: + return fs; + } + } + + public void setQuadTint( int tint ) + { + + } + + @Override + public void setQuadOrientation( EnumFacing orientation ) + { + + } + + @Override + public void setApplyDiffuseLighting( boolean diffuse ) + { + + } + + } + +} diff --git a/src/main/java/appeng/client/render/model/UVLModelLoader.java b/src/main/java/appeng/client/render/model/UVLModelLoader.java index f530b427..b24cec46 100644 --- a/src/main/java/appeng/client/render/model/UVLModelLoader.java +++ b/src/main/java/appeng/client/render/model/UVLModelLoader.java @@ -308,7 +308,7 @@ public enum UVLModelLoader implements ICustomModelLoader }; trans.setParent( builder ); - LightUtil.putBakedQuad( trans, quad ); + quad.pipe( trans ); return builder.build(); } else diff --git a/src/main/java/appeng/core/features/AEBlockFeatureHandler.java b/src/main/java/appeng/core/features/AEBlockFeatureHandler.java index 614d1055..3799ccc8 100644 --- a/src/main/java/appeng/core/features/AEBlockFeatureHandler.java +++ b/src/main/java/appeng/core/features/AEBlockFeatureHandler.java @@ -24,10 +24,12 @@ import java.util.EnumSet; import com.google.common.base.Optional; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.resources.IReloadableResourceManager; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.IRegistry; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.relauncher.Side; @@ -110,4 +112,10 @@ public final class AEBlockFeatureHandler implements IFeatureHandler ModelLoader.setCustomStateMapper( this.featured, mapper ); ( (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager() ).registerReloadListener( mapper ); } + + @Override + public void registerCustomModelOverride( IRegistry modelRegistry ) + { + + } } diff --git a/src/main/java/appeng/core/features/AECableBusFeatureHandler.java b/src/main/java/appeng/core/features/AECableBusFeatureHandler.java index d2db54fb..846e3920 100644 --- a/src/main/java/appeng/core/features/AECableBusFeatureHandler.java +++ b/src/main/java/appeng/core/features/AECableBusFeatureHandler.java @@ -24,10 +24,12 @@ import java.util.EnumSet; import com.google.common.base.Optional; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.IRegistry; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.relauncher.Side; @@ -113,4 +115,10 @@ public final class AECableBusFeatureHandler implements IFeatureHandler { } + + @Override + public void registerCustomModelOverride( IRegistry modelRegistry ) + { + + } } diff --git a/src/main/java/appeng/core/features/AETileBlockFeatureHandler.java b/src/main/java/appeng/core/features/AETileBlockFeatureHandler.java index cac26bfd..2b38f821 100644 --- a/src/main/java/appeng/core/features/AETileBlockFeatureHandler.java +++ b/src/main/java/appeng/core/features/AETileBlockFeatureHandler.java @@ -20,14 +20,18 @@ package appeng.core.features; import java.util.EnumSet; +import java.util.Set; import com.google.common.base.Optional; +import com.google.common.collect.Sets; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.resources.IReloadableResourceManager; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.IRegistry; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.relauncher.Side; @@ -35,6 +39,7 @@ import net.minecraftforge.fml.relauncher.Side; import appeng.api.definitions.ITileDefinition; import appeng.block.AEBaseTileBlock; import appeng.client.render.model.AEIgnoringStateMapper; +import appeng.client.render.model.CachingRotatingBakedModel; import appeng.core.AppEng; import appeng.core.CommonHelper; import appeng.core.CreativeTab; @@ -116,4 +121,17 @@ public final class AETileBlockFeatureHandler implements IFeatureHandler ModelLoader.setCustomStateMapper( this.featured, mapper ); ( (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager() ).registerReloadListener( mapper ); } + + @Override + public void registerCustomModelOverride( IRegistry modelRegistry ) + { + Set keys = Sets.newHashSet( modelRegistry.getKeys() ); + for( ModelResourceLocation model : keys ) + { + if( model.getResourcePath().equals( registryName.getResourcePath() ) ) + { + modelRegistry.putObject( model, new CachingRotatingBakedModel( modelRegistry.getObject( model ) ) ); + } + } + } } diff --git a/src/main/java/appeng/core/features/IFeatureHandler.java b/src/main/java/appeng/core/features/IFeatureHandler.java index 4ca27e12..555429af 100644 --- a/src/main/java/appeng/core/features/IFeatureHandler.java +++ b/src/main/java/appeng/core/features/IFeatureHandler.java @@ -19,6 +19,9 @@ package appeng.core.features; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.util.registry.IRegistry; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -38,4 +41,7 @@ public interface IFeatureHandler @SideOnly( Side.CLIENT ) void registerStateMapper(); + + @SideOnly( Side.CLIENT ) + void registerCustomModelOverride( IRegistry modelRegistry ); } diff --git a/src/main/java/appeng/core/features/ItemFeatureHandler.java b/src/main/java/appeng/core/features/ItemFeatureHandler.java index bfa163a0..e17f0fae 100644 --- a/src/main/java/appeng/core/features/ItemFeatureHandler.java +++ b/src/main/java/appeng/core/features/ItemFeatureHandler.java @@ -24,10 +24,12 @@ import java.util.EnumSet; import com.google.common.base.Optional; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.item.Item; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.IRegistry; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.relauncher.Side; @@ -119,4 +121,10 @@ public final class ItemFeatureHandler implements IFeatureHandler { } + + @Override + public void registerCustomModelOverride( IRegistry modelRegistry ) + { + + } } diff --git a/src/main/java/appeng/core/features/StairBlockFeatureHandler.java b/src/main/java/appeng/core/features/StairBlockFeatureHandler.java index 6d7019a0..d96cc8a2 100644 --- a/src/main/java/appeng/core/features/StairBlockFeatureHandler.java +++ b/src/main/java/appeng/core/features/StairBlockFeatureHandler.java @@ -25,12 +25,14 @@ import com.google.common.base.Optional; import net.minecraft.block.BlockStairs; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.resources.IReloadableResourceManager; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.IRegistry; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.relauncher.Side; @@ -106,4 +108,10 @@ public class StairBlockFeatureHandler implements IFeatureHandler ModelLoader.setCustomStateMapper( this.stairs, mapper ); ( (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager() ).registerReloadListener( mapper ); } + + @Override + public void registerCustomModelOverride( IRegistry modelRegistry ) + { + + } } diff --git a/src/main/resources/assets/appliedenergistics2/blockstates/tile.BlockGrinder.ignore.json b/src/main/resources/assets/appliedenergistics2/blockstates/tile.BlockGrinder.ignore.json index 4d3e85f2..5426f2f9 100644 --- a/src/main/resources/assets/appliedenergistics2/blockstates/tile.BlockGrinder.ignore.json +++ b/src/main/resources/assets/appliedenergistics2/blockstates/tile.BlockGrinder.ignore.json @@ -1 +1,2 @@ +forward up \ No newline at end of file diff --git a/src/main/resources/assets/appliedenergistics2/blockstates/tile.BlockGrinder.json b/src/main/resources/assets/appliedenergistics2/blockstates/tile.BlockGrinder.json index 2cf0a470..5a9002e6 100644 --- a/src/main/resources/assets/appliedenergistics2/blockstates/tile.BlockGrinder.json +++ b/src/main/resources/assets/appliedenergistics2/blockstates/tile.BlockGrinder.json @@ -1,8 +1,5 @@ { "variants": { - "forward=north": { "model": "appliedenergistics2:tile.BlockGrinder" }, - "forward=south": { "model": "appliedenergistics2:tile.BlockGrinder", "y": 180 }, - "forward=west": { "model": "appliedenergistics2:tile.BlockGrinder", "y": 270 }, - "forward=east": { "model": "appliedenergistics2:tile.BlockGrinder", "y": 90 } + "normal": { "model": "appliedenergistics2:tile.BlockGrinder"} } }