From 6ddf60fab8e187f36066f1edb2845b490c9941e5 Mon Sep 17 00:00:00 2001 From: fscan Date: Sun, 29 Oct 2017 16:47:26 +0100 Subject: [PATCH] Improve Facade rendering (#3182) UV fix based on #2941 by @MoreThanHidden fixes #2679, fixes #2625 --- .../block/networking/BlockCableBus.java | 1 - .../client/render/DelegateBakedModel.java | 69 +++++++++++++++++++ .../render/FacadeDispatcherBakedModel.java | 32 ++------- .../appeng/client/render/FacadeItemModel.java | 34 +++++---- .../render/FacadeWithBlockBakedModel.java | 29 +------- .../render/cablebus/CableBusBakedModel.java | 2 +- .../client/render/cablebus/CubeBuilder.java | 67 +++++++++++++++++- .../client/render/cablebus/FacadeBuilder.java | 15 ++-- 8 files changed, 170 insertions(+), 79 deletions(-) create mode 100644 src/main/java/appeng/client/render/DelegateBakedModel.java diff --git a/src/main/java/appeng/block/networking/BlockCableBus.java b/src/main/java/appeng/block/networking/BlockCableBus.java index 926b84577..ad0cfef9c 100644 --- a/src/main/java/appeng/block/networking/BlockCableBus.java +++ b/src/main/java/appeng/block/networking/BlockCableBus.java @@ -101,7 +101,6 @@ public class BlockCableBus extends AEBaseTileBlock // this will actually be overwritten later through setupTile and the // combined layers this.setTileEntity( TileCableBus.class ); - this.useNeighborBrightness = true; } @Override diff --git a/src/main/java/appeng/client/render/DelegateBakedModel.java b/src/main/java/appeng/client/render/DelegateBakedModel.java new file mode 100644 index 000000000..93ca2fe74 --- /dev/null +++ b/src/main/java/appeng/client/render/DelegateBakedModel.java @@ -0,0 +1,69 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.client.render; + + +import javax.vecmath.Matrix4f; + +import org.apache.commons.lang3.tuple.Pair; + +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; + + +public abstract class DelegateBakedModel implements IBakedModel +{ + private IBakedModel baseModel; + + protected DelegateBakedModel( IBakedModel base ) + { + this.baseModel = base; + } + + @Override + public Pair handlePerspective( ItemCameraTransforms.TransformType type ) + { + Pair pair = this.baseModel.handlePerspective( type ); + return Pair.of( this, pair.getValue() ); + } + + @Override + public TextureAtlasSprite getParticleTexture() + { + return this.baseModel.getParticleTexture(); + } + + @Override + public ItemCameraTransforms getItemCameraTransforms() + { + return this.baseModel.getItemCameraTransforms(); + } + + @Override + public boolean isAmbientOcclusion() + { + return this.baseModel.isAmbientOcclusion(); + } + + public IBakedModel getBaseModel() + { + return this.baseModel; + } +} diff --git a/src/main/java/appeng/client/render/FacadeDispatcherBakedModel.java b/src/main/java/appeng/client/render/FacadeDispatcherBakedModel.java index c2af39fa6..6eac8a2c8 100644 --- a/src/main/java/appeng/client/render/FacadeDispatcherBakedModel.java +++ b/src/main/java/appeng/client/render/FacadeDispatcherBakedModel.java @@ -27,9 +27,7 @@ import javax.annotation.Nullable; 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.entity.EntityLivingBase; import net.minecraft.item.ItemStack; @@ -44,16 +42,13 @@ import appeng.items.parts.ItemFacade; * on the item stack. * A custom Item Override List is used to accomplish this. */ -public class FacadeDispatcherBakedModel implements IBakedModel +public class FacadeDispatcherBakedModel extends DelegateBakedModel { - - private final IBakedModel baseModel; - private final VertexFormat format; public FacadeDispatcherBakedModel( IBakedModel baseModel, VertexFormat format ) { - this.baseModel = baseModel; + super( baseModel ); this.format = format; } @@ -64,16 +59,10 @@ public class FacadeDispatcherBakedModel implements IBakedModel return Collections.emptyList(); } - @Override - public boolean isAmbientOcclusion() - { - return this.baseModel.isAmbientOcclusion(); - } - @Override public boolean isGui3d() { - return this.baseModel.isGui3d(); + return this.getBaseModel().isGui3d(); } @Override @@ -82,18 +71,6 @@ public class FacadeDispatcherBakedModel implements IBakedModel return false; } - @Override - public TextureAtlasSprite getParticleTexture() - { - return this.baseModel.getParticleTexture(); - } - - @Override - public ItemCameraTransforms getItemCameraTransforms() - { - return this.baseModel.getItemCameraTransforms(); - } - @Override public ItemOverrideList getOverrides() { @@ -112,7 +89,8 @@ public class FacadeDispatcherBakedModel implements IBakedModel IBlockState state = itemFacade.getTextureBlockState( stack ); ItemStack textureItem = itemFacade.getTextureItem( stack ); - return new FacadeWithBlockBakedModel( FacadeDispatcherBakedModel.this.baseModel, state, textureItem, FacadeDispatcherBakedModel.this.format ); + return new FacadeWithBlockBakedModel( FacadeDispatcherBakedModel.this + .getBaseModel(), state, textureItem, FacadeDispatcherBakedModel.this.format ); } }; } diff --git a/src/main/java/appeng/client/render/FacadeItemModel.java b/src/main/java/appeng/client/render/FacadeItemModel.java index dfbfea956..9f6b77e94 100644 --- a/src/main/java/appeng/client/render/FacadeItemModel.java +++ b/src/main/java/appeng/client/render/FacadeItemModel.java @@ -30,7 +30,6 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.IModel; import net.minecraftforge.client.model.ModelLoaderRegistry; import net.minecraftforge.common.model.IModelState; -import net.minecraftforge.common.model.TRSRTransformation; import appeng.core.AppEng; @@ -41,10 +40,27 @@ import appeng.core.AppEng; */ public class FacadeItemModel implements IModel { - // We use this to get the default item transforms and make our lives easier private static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/facade_base" ); + private IModel baseModel = null; + + private IModel getBaseModel() + { + if( this.baseModel == null ) + { + try + { + baseModel = ModelLoaderRegistry.getModel( MODEL_BASE ); + } + catch( Exception e ) + { + throw new RuntimeException( e ); + } + } + return this.baseModel; + } + @Override public Collection getDependencies() { @@ -60,17 +76,7 @@ public class FacadeItemModel implements IModel @Override public IBakedModel bake( IModelState state, VertexFormat format, Function bakedTextureGetter ) { - IModel baseModel; - try - { - baseModel = ModelLoaderRegistry.getModel( MODEL_BASE ); - } - catch( Exception e ) - { - throw new RuntimeException( e ); - } - - IBakedModel bakedBaseModel = baseModel.bake( state, format, bakedTextureGetter ); + IBakedModel bakedBaseModel = this.getBaseModel().bake( state, format, bakedTextureGetter ); return new FacadeDispatcherBakedModel( bakedBaseModel, format ); } @@ -78,6 +84,6 @@ public class FacadeItemModel implements IModel @Override public IModelState getDefaultState() { - return TRSRTransformation.identity(); + return getBaseModel().getDefaultState(); } } diff --git a/src/main/java/appeng/client/render/FacadeWithBlockBakedModel.java b/src/main/java/appeng/client/render/FacadeWithBlockBakedModel.java index 8d354fcf6..7ca637db7 100644 --- a/src/main/java/appeng/client/render/FacadeWithBlockBakedModel.java +++ b/src/main/java/appeng/client/render/FacadeWithBlockBakedModel.java @@ -29,9 +29,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.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.item.ItemStack; import net.minecraft.util.EnumFacing; @@ -44,11 +42,8 @@ import appeng.client.render.cablebus.FacadeBuilder; * This is the actual baked model that will combine the north face of a given block state * with the base facade item model to achieve what is then actually rendered on screen. */ -public class FacadeWithBlockBakedModel implements IBakedModel +public class FacadeWithBlockBakedModel extends DelegateBakedModel { - - private final IBakedModel baseModel; - private final IBlockState blockState; private final IBakedModel textureModel; @@ -59,7 +54,7 @@ public class FacadeWithBlockBakedModel implements IBakedModel public FacadeWithBlockBakedModel( IBakedModel baseModel, IBlockState blockState, ItemStack textureItem, VertexFormat format ) { - this.baseModel = baseModel; + super( baseModel ); this.blockState = blockState; this.textureItem = textureItem; this.textureModel = Minecraft.getMinecraft().getBlockRendererDispatcher().getModelForState( blockState ); @@ -88,13 +83,7 @@ public class FacadeWithBlockBakedModel implements IBakedModel } } - return this.baseModel.getQuads( state, side, rand ); - } - - @Override - public boolean isAmbientOcclusion() - { - return this.baseModel.isAmbientOcclusion(); + return this.getBaseModel().getQuads( state, side, rand ); } @Override @@ -109,18 +98,6 @@ public class FacadeWithBlockBakedModel implements IBakedModel return false; } - @Override - public TextureAtlasSprite getParticleTexture() - { - return this.baseModel.getParticleTexture(); - } - - @Override - public ItemCameraTransforms getItemCameraTransforms() - { - return this.baseModel.getItemCameraTransforms(); - } - @Override public ItemOverrideList getOverrides() { diff --git a/src/main/java/appeng/client/render/cablebus/CableBusBakedModel.java b/src/main/java/appeng/client/render/cablebus/CableBusBakedModel.java index b859910dc..0e0c5684b 100644 --- a/src/main/java/appeng/client/render/cablebus/CableBusBakedModel.java +++ b/src/main/java/appeng/client/render/cablebus/CableBusBakedModel.java @@ -336,7 +336,7 @@ public class CableBusBakedModel implements IBakedModel @Override public boolean isAmbientOcclusion() { - return false; + return true; } @Override diff --git a/src/main/java/appeng/client/render/cablebus/CubeBuilder.java b/src/main/java/appeng/client/render/cablebus/CubeBuilder.java index 1f6ce5c8b..c85f1826e 100644 --- a/src/main/java/appeng/client/render/cablebus/CubeBuilder.java +++ b/src/main/java/appeng/client/render/cablebus/CubeBuilder.java @@ -59,6 +59,8 @@ public class CubeBuilder private int color = 0xFFFFFFFF; + private boolean useStandardUV = false; + private boolean renderFullBright; public CubeBuilder( VertexFormat format, List output ) @@ -142,7 +144,9 @@ public class CubeBuilder UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( this.format ); builder.setTexture( texture ); builder.setQuadOrientation( face ); - + builder.setQuadTint( -1 ); + builder.setApplyDiffuseLighting( true ); + UvVector uv = new UvVector(); // The user might have set specific UV coordinates for this face @@ -154,6 +158,10 @@ public class CubeBuilder uv.u2 = texture.getInterpolatedU( customUv.z ); uv.v2 = texture.getInterpolatedV( customUv.w ); } + else if( this.useStandardUV ) + { + uv = this.getStandardUv( face, texture, x1, y1, z1, x2, y2, z2 ); + } else { uv = this.getDefaultUv( face, texture, x1, y1, z1, x2, y2, z2 ); @@ -199,8 +207,7 @@ public class CubeBuilder break; } - int[] vertexData = builder.build().getVertexData(); - this.output.add( new BakedQuad( vertexData, -1, face, texture, true, this.format ) ); + this.output.add( builder.build() ); } private UvVector getDefaultUv( EnumFacing face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2 ) @@ -251,6 +258,51 @@ public class CubeBuilder return uv; } + private UvVector getStandardUv( EnumFacing face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2 ) + { + UvVector uv = new UvVector(); + switch( face ) + { + case DOWN: + uv.u1 = texture.getInterpolatedU( x1 * 16 ); + uv.v1 = texture.getInterpolatedV( 16 - z1 * 16 ); + uv.u2 = texture.getInterpolatedU( x2 * 16 ); + uv.v2 = texture.getInterpolatedV( 16 - z2 * 16 ); + break; + case UP: + uv.u1 = texture.getInterpolatedU( x1 * 16 ); + uv.v1 = texture.getInterpolatedV( z1 * 16 ); + uv.u2 = texture.getInterpolatedU( x2 * 16 ); + uv.v2 = texture.getInterpolatedV( z2 * 16 ); + break; + case NORTH: + uv.u1 = texture.getInterpolatedU( 16 - x1 * 16 ); + uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 ); + uv.u2 = texture.getInterpolatedU( 16 - x2 * 16 ); + uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 ); + break; + case SOUTH: + uv.u1 = texture.getInterpolatedU( x1 * 16 ); + uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 ); + uv.u2 = texture.getInterpolatedU( x2 * 16 ); + uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 ); + break; + case WEST: + uv.u1 = texture.getInterpolatedU( z1 * 16 ); + uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 ); + uv.u2 = texture.getInterpolatedU( z2 * 16 ); + uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 ); + break; + case EAST: + uv.u1 = texture.getInterpolatedU( 16 - z2 * 16 ); + uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 ); + uv.u2 = texture.getInterpolatedU( 16 - z1 * 16 ); + uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 ); + break; + } + return uv; + } + // uv.u1, uv.v1 private void putVertexTL( UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv ) { @@ -484,6 +536,15 @@ public class CubeBuilder this.uvRotations[facing.ordinal()] = (byte) rotation; } + /** + * CubeBuilder uses UV optimized for cables by default. + * This switches to standard UV coordinates. + */ + public void useStandardUV() + { + this.useStandardUV = true; + } + public List getOutput() { return this.output; diff --git a/src/main/java/appeng/client/render/cablebus/FacadeBuilder.java b/src/main/java/appeng/client/render/cablebus/FacadeBuilder.java index 16d67546e..a855f5bb2 100644 --- a/src/main/java/appeng/client/render/cablebus/FacadeBuilder.java +++ b/src/main/java/appeng/client/render/cablebus/FacadeBuilder.java @@ -175,6 +175,7 @@ public class FacadeBuilder // Reset to no color multiplicator builder.setColorRGB( 0xFFFFFF ); + builder.useStandardUV(); // We only render the stilt if we don't intersect with any part directly, and if there's no part on our side if( renderStilt && busBounds == null && layer == BlockRenderLayer.CUTOUT ) @@ -438,22 +439,22 @@ public class FacadeBuilder private static AxisAlignedBB getFacadeBox( EnumFacing side, boolean thinFacades ) { - int thickness = thinFacades ? 1 : 2; + double thickness = ( thinFacades ? 1 : 2 ) / 16.0; switch( side ) { case DOWN: - return new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, ( thickness ) / 16.0, 1.0 ); + return new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, thickness, 1.0 ); case EAST: - return new AxisAlignedBB( ( 16.0 - thickness ) / 16.0, 0.0, 0.0, 1.0, 1.0, 1.0 ); + return new AxisAlignedBB( 1.0 - thickness, 0.0, 0.0, 1.0, 1.0, 1.0 ); case NORTH: - return new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, 1.0, ( thickness ) / 16.0 ); + return new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, 1.0, thickness ); case SOUTH: - return new AxisAlignedBB( 0.0, 0.0, ( 16.0 - thickness ) / 16.0, 1.0, 1.0, 1.0 ); + return new AxisAlignedBB( 0.0, 0.0, 1.0 - thickness, 1.0, 1.0, 1.0 ); case UP: - return new AxisAlignedBB( 0.0, ( 16.0 - thickness ) / 16.0, 0.0, 1.0, 1.0, 1.0 ); + return new AxisAlignedBB( 0.0, 1.0 - thickness, 0.0, 1.0, 1.0, 1.0 ); case WEST: - return new AxisAlignedBB( 0.0, 0.0, 0.0, ( thickness ) / 16.0, 1.0, 1.0 ); + return new AxisAlignedBB( 0.0, 0.0, 0.0, thickness, 1.0, 1.0 ); default: throw new IllegalArgumentException( "Unsupported face: " + side ); }