reformatted all src files (#141)

This commit is contained in:
YoungOnion
2022-09-17 05:08:02 -06:00
committed by GitHub
parent 3328bfcda2
commit 9011273229
1056 changed files with 88127 additions and 110597 deletions
File diff suppressed because it is too large Load Diff
@@ -19,17 +19,11 @@
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import appeng.api.parts.IPartBakedModel;
import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.block.networking.BlockCableBus;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
@@ -44,326 +38,285 @@ import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.common.property.IExtendedBlockState;
import appeng.api.parts.IPartBakedModel;
import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.block.networking.BlockCableBus;
import javax.annotation.Nullable;
import java.util.*;
import java.util.Map.Entry;
public class CableBusBakedModel implements IBakedModel
{
public class CableBusBakedModel implements IBakedModel {
private static final Map<CableBusRenderState, List<BakedQuad>> CABLE_MODEL_CACHE = new HashMap<>();
private static final Map<CableBusRenderState, List<BakedQuad>> CABLE_MODEL_CACHE = new HashMap<>();
private final CableBuilder cableBuilder;
private final CableBuilder cableBuilder;
private final FacadeBuilder facadeBuilder;
private final FacadeBuilder facadeBuilder;
private final Map<ResourceLocation, IBakedModel> partModels;
private final Map<ResourceLocation, IBakedModel> partModels;
private final TextureAtlasSprite particleTexture;
private final TextureAtlasSprite particleTexture;
private final TextureMap textureMap = Minecraft.getMinecraft().getTextureMapBlocks();
private final TextureMap textureMap = Minecraft.getMinecraft().getTextureMapBlocks();
CableBusBakedModel( CableBuilder cableBuilder, FacadeBuilder facadeBuilder, Map<ResourceLocation, IBakedModel> partModels, TextureAtlasSprite particleTexture )
{
this.cableBuilder = cableBuilder;
this.facadeBuilder = facadeBuilder;
this.partModels = partModels;
this.particleTexture = particleTexture;
}
CableBusBakedModel(CableBuilder cableBuilder, FacadeBuilder facadeBuilder, Map<ResourceLocation, IBakedModel> partModels, TextureAtlasSprite particleTexture) {
this.cableBuilder = cableBuilder;
this.facadeBuilder = facadeBuilder;
this.partModels = partModels;
this.particleTexture = particleTexture;
}
@Override
public List<BakedQuad> getQuads( @Nullable IBlockState state, @Nullable EnumFacing side, long rand )
{
CableBusRenderState renderState = getRenderingState( state );
@Override
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {
CableBusRenderState renderState = getRenderingState(state);
if( renderState == null || side != null )
{
return Collections.emptyList();
}
if (renderState == null || side != null) {
return Collections.emptyList();
}
BlockRenderLayer layer = MinecraftForgeClient.getRenderLayer();
BlockRenderLayer layer = MinecraftForgeClient.getRenderLayer();
List<BakedQuad> quads = new ArrayList<>();
List<BakedQuad> quads = new ArrayList<>();
// The core parts of the cable will only be rendered in the CUTOUT layer.
// Facades will add them selves to what ever the block would be rendered with,
// except when transparent facades are enabled, they are forced to TRANSPARENT.
if( layer == BlockRenderLayer.CUTOUT )
{
// The core parts of the cable will only be rendered in the CUTOUT layer.
// Facades will add them selves to what ever the block would be rendered with,
// except when transparent facades are enabled, they are forced to TRANSPARENT.
if (layer == BlockRenderLayer.CUTOUT) {
// First, handle the cable at the center of the cable bus
final List<BakedQuad> cableModel = CABLE_MODEL_CACHE.computeIfAbsent( renderState, k ->
{
final List<BakedQuad> model = new ArrayList<>();
this.addCableQuads( renderState, model );
return model;
} );
quads.addAll( cableModel );
// First, handle the cable at the center of the cable bus
final List<BakedQuad> cableModel = CABLE_MODEL_CACHE.computeIfAbsent(renderState, k ->
{
final List<BakedQuad> model = new ArrayList<>();
this.addCableQuads(renderState, model);
return model;
});
quads.addAll(cableModel);
// Then handle attachments
for( EnumFacing facing : EnumFacing.values() )
{
final IPartModel partModel = renderState.getAttachments().get( facing );
if( partModel == null )
{
continue;
}
// Then handle attachments
for (EnumFacing facing : EnumFacing.values()) {
final IPartModel partModel = renderState.getAttachments().get(facing);
if (partModel == null) {
continue;
}
for( ResourceLocation model : partModel.getModels() )
{
IBakedModel bakedModel = this.partModels.get( model );
for (ResourceLocation model : partModel.getModels()) {
IBakedModel bakedModel = this.partModels.get(model);
if( bakedModel == null )
{
throw new IllegalStateException( "Trying to use an unregistered part model: " + model );
}
if (bakedModel == null) {
throw new IllegalStateException("Trying to use an unregistered part model: " + model);
}
List<BakedQuad> partQuads;
if( bakedModel instanceof IPartBakedModel )
{
partQuads = ( (IPartBakedModel) bakedModel ).getPartQuads( renderState.getPartFlags().get( facing ), rand );
}
else
{
partQuads = bakedModel.getQuads( state, null, rand );
}
List<BakedQuad> partQuads;
if (bakedModel instanceof IPartBakedModel) {
partQuads = ((IPartBakedModel) bakedModel).getPartQuads(renderState.getPartFlags().get(facing), rand);
} else {
partQuads = bakedModel.getQuads(state, null, rand);
}
// Rotate quads accordingly
QuadRotator rotator = new QuadRotator();
partQuads = rotator.rotateQuads( partQuads, facing, EnumFacing.UP );
// Rotate quads accordingly
QuadRotator rotator = new QuadRotator();
partQuads = rotator.rotateQuads(partQuads, facing, EnumFacing.UP);
quads.addAll( partQuads );
}
}
}
this.facadeBuilder.buildFacadeQuads( layer, renderState, rand, quads, this.partModels::get );
quads.addAll(partQuads);
}
}
}
this.facadeBuilder.buildFacadeQuads(layer, renderState, rand, quads, this.partModels::get);
return quads;
}
return quads;
}
// Determines whether a cable is connected to exactly two sides that are opposite each other
private static boolean isStraightLine( AECableType cableType, EnumMap<EnumFacing, AECableType> sides )
{
final Iterator<Entry<EnumFacing, AECableType>> it = sides.entrySet().iterator();
if( !it.hasNext() )
{
return false; // No connections
}
// Determines whether a cable is connected to exactly two sides that are opposite each other
private static boolean isStraightLine(AECableType cableType, EnumMap<EnumFacing, AECableType> sides) {
final Iterator<Entry<EnumFacing, AECableType>> it = sides.entrySet().iterator();
if (!it.hasNext()) {
return false; // No connections
}
final Entry<EnumFacing, AECableType> nextConnection = it.next();
final EnumFacing firstSide = nextConnection.getKey();
final AECableType firstType = nextConnection.getValue();
final Entry<EnumFacing, AECableType> nextConnection = it.next();
final EnumFacing firstSide = nextConnection.getKey();
final AECableType firstType = nextConnection.getValue();
if( !it.hasNext() )
{
return false; // Only a single connection
}
if( firstSide.getOpposite() != it.next().getKey() )
{
return false; // Connected to two sides that are not opposite each other
}
if( it.hasNext() )
{
return false; // Must not have any other connection points
}
if (!it.hasNext()) {
return false; // Only a single connection
}
if (firstSide.getOpposite() != it.next().getKey()) {
return false; // Connected to two sides that are not opposite each other
}
if (it.hasNext()) {
return false; // Must not have any other connection points
}
final AECableType secondType = sides.get( firstSide.getOpposite() );
final AECableType secondType = sides.get(firstSide.getOpposite());
return firstType == secondType && cableType == firstType && cableType == secondType;
}
return firstType == secondType && cableType == firstType && cableType == secondType;
}
private void addCableQuads( CableBusRenderState renderState, List<BakedQuad> quadsOut )
{
AECableType cableType = renderState.getCableType();
if( cableType == AECableType.NONE )
{
return;
}
private void addCableQuads(CableBusRenderState renderState, List<BakedQuad> quadsOut) {
AECableType cableType = renderState.getCableType();
if (cableType == AECableType.NONE) {
return;
}
AEColor cableColor = renderState.getCableColor();
EnumMap<EnumFacing, AECableType> connectionTypes = renderState.getConnectionTypes();
AEColor cableColor = renderState.getCableColor();
EnumMap<EnumFacing, AECableType> connectionTypes = renderState.getConnectionTypes();
// If the connection is straight, no busses are attached, and no covered core has been forced (in case of glass
// cables), then render the cable as a simplified straight line.
boolean noAttachments = !renderState.getAttachments().values().stream().anyMatch( IPartModel::requireCableConnection );
if( noAttachments && isStraightLine( cableType, connectionTypes ) )
{
EnumFacing facing = connectionTypes.keySet().iterator().next();
// If the connection is straight, no busses are attached, and no covered core has been forced (in case of glass
// cables), then render the cable as a simplified straight line.
boolean noAttachments = !renderState.getAttachments().values().stream().anyMatch(IPartModel::requireCableConnection);
if (noAttachments && isStraightLine(cableType, connectionTypes)) {
EnumFacing facing = connectionTypes.keySet().iterator().next();
switch( cableType )
{
case GLASS:
this.cableBuilder.addStraightGlassConnection( facing, cableColor, quadsOut );
break;
case COVERED:
this.cableBuilder.addStraightCoveredConnection( facing, cableColor, quadsOut );
break;
case SMART:
this.cableBuilder.addStraightSmartConnection( facing, cableColor, renderState.getChannelsOnSide().get( facing ), quadsOut );
break;
case DENSE_COVERED:
this.cableBuilder.addStraightDenseCoveredConnection( facing, cableColor, quadsOut );
break;
case DENSE_SMART:
this.cableBuilder.addStraightDenseSmartConnection( facing, cableColor, renderState.getChannelsOnSide().get( facing ), quadsOut );
break;
default:
break;
}
switch (cableType) {
case GLASS:
this.cableBuilder.addStraightGlassConnection(facing, cableColor, quadsOut);
break;
case COVERED:
this.cableBuilder.addStraightCoveredConnection(facing, cableColor, quadsOut);
break;
case SMART:
this.cableBuilder.addStraightSmartConnection(facing, cableColor, renderState.getChannelsOnSide().get(facing), quadsOut);
break;
case DENSE_COVERED:
this.cableBuilder.addStraightDenseCoveredConnection(facing, cableColor, quadsOut);
break;
case DENSE_SMART:
this.cableBuilder.addStraightDenseSmartConnection(facing, cableColor, renderState.getChannelsOnSide().get(facing), quadsOut);
break;
default:
break;
}
return; // Don't render the other form of connection
}
return; // Don't render the other form of connection
}
this.cableBuilder.addCableCore( renderState.getCoreType(), cableColor, quadsOut );
this.cableBuilder.addCableCore(renderState.getCoreType(), cableColor, quadsOut);
// Render all internal connections to attachments
EnumMap<EnumFacing, Integer> attachmentConnections = renderState.getAttachmentConnections();
for( EnumFacing facing : attachmentConnections.keySet() )
{
int distance = attachmentConnections.get( facing );
int channels = renderState.getChannelsOnSide().get( facing );
// Render all internal connections to attachments
EnumMap<EnumFacing, Integer> attachmentConnections = renderState.getAttachmentConnections();
for (EnumFacing facing : attachmentConnections.keySet()) {
int distance = attachmentConnections.get(facing);
int channels = renderState.getChannelsOnSide().get(facing);
switch( cableType )
{
case GLASS:
this.cableBuilder.addConstrainedGlassConnection( facing, cableColor, distance, quadsOut );
break;
case COVERED:
this.cableBuilder.addConstrainedCoveredConnection( facing, cableColor, distance, quadsOut );
break;
case SMART:
this.cableBuilder.addConstrainedSmartConnection( facing, cableColor, distance, channels, quadsOut );
break;
case DENSE_COVERED:
case DENSE_SMART:
// Dense cables do not render connections to parts since none can be attached
break;
default:
break;
}
}
switch (cableType) {
case GLASS:
this.cableBuilder.addConstrainedGlassConnection(facing, cableColor, distance, quadsOut);
break;
case COVERED:
this.cableBuilder.addConstrainedCoveredConnection(facing, cableColor, distance, quadsOut);
break;
case SMART:
this.cableBuilder.addConstrainedSmartConnection(facing, cableColor, distance, channels, quadsOut);
break;
case DENSE_COVERED:
case DENSE_SMART:
// Dense cables do not render connections to parts since none can be attached
break;
default:
break;
}
}
// Render all outgoing connections using the appropriate type
for( final Entry<EnumFacing, AECableType> connection : connectionTypes.entrySet() )
{
final EnumFacing facing = connection.getKey();
final AECableType connectionType = connection.getValue();
final boolean cableBusAdjacent = renderState.getCableBusAdjacent().contains( facing );
final int channels = renderState.getChannelsOnSide().get( facing );
// Render all outgoing connections using the appropriate type
for (final Entry<EnumFacing, AECableType> connection : connectionTypes.entrySet()) {
final EnumFacing facing = connection.getKey();
final AECableType connectionType = connection.getValue();
final boolean cableBusAdjacent = renderState.getCableBusAdjacent().contains(facing);
final int channels = renderState.getChannelsOnSide().get(facing);
switch( cableType )
{
case GLASS:
this.cableBuilder.addGlassConnection( facing, cableColor, connectionType, cableBusAdjacent, quadsOut );
break;
case COVERED:
this.cableBuilder.addCoveredConnection( facing, cableColor, connectionType, cableBusAdjacent, quadsOut );
break;
case SMART:
this.cableBuilder.addSmartConnection( facing, cableColor, connectionType, cableBusAdjacent, channels, quadsOut );
break;
case DENSE_COVERED:
this.cableBuilder.addDenseCoveredConnection( facing, cableColor, connectionType, cableBusAdjacent, quadsOut );
break;
case DENSE_SMART:
this.cableBuilder.addDenseSmartConnection( facing, cableColor, connectionType, cableBusAdjacent, channels, quadsOut );
break;
default:
break;
}
}
}
switch (cableType) {
case GLASS:
this.cableBuilder.addGlassConnection(facing, cableColor, connectionType, cableBusAdjacent, quadsOut);
break;
case COVERED:
this.cableBuilder.addCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent, quadsOut);
break;
case SMART:
this.cableBuilder.addSmartConnection(facing, cableColor, connectionType, cableBusAdjacent, channels, quadsOut);
break;
case DENSE_COVERED:
this.cableBuilder.addDenseCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent, quadsOut);
break;
case DENSE_SMART:
this.cableBuilder.addDenseSmartConnection(facing, cableColor, connectionType, cableBusAdjacent, channels, quadsOut);
break;
default:
break;
}
}
}
/**
* Gets a list of texture sprites appropriate for particles (digging, etc.) given the render state for a cable bus.
*/
public List<TextureAtlasSprite> getParticleTextures( CableBusRenderState renderState )
{
CableCoreType coreType = CableCoreType.fromCableType( renderState.getCableType() );
AEColor cableColor = renderState.getCableColor();
/**
* Gets a list of texture sprites appropriate for particles (digging, etc.) given the render state for a cable bus.
*/
public List<TextureAtlasSprite> getParticleTextures(CableBusRenderState renderState) {
CableCoreType coreType = CableCoreType.fromCableType(renderState.getCableType());
AEColor cableColor = renderState.getCableColor();
List<TextureAtlasSprite> result = new ArrayList<>();
List<TextureAtlasSprite> result = new ArrayList<>();
if( coreType != null )
{
result.add( this.cableBuilder.getCoreTexture( coreType, cableColor ) );
}
if (coreType != null) {
result.add(this.cableBuilder.getCoreTexture(coreType, cableColor));
}
// If no core is present, just use the first part that comes into play
for( EnumFacing side : renderState.getAttachments().keySet() )
{
IPartModel partModel = renderState.getAttachments().get( side );
// If no core is present, just use the first part that comes into play
for (EnumFacing side : renderState.getAttachments().keySet()) {
IPartModel partModel = renderState.getAttachments().get(side);
for( ResourceLocation model : partModel.getModels() )
{
IBakedModel bakedModel = this.partModels.get( model );
for (ResourceLocation model : partModel.getModels()) {
IBakedModel bakedModel = this.partModels.get(model);
if( bakedModel == null )
{
throw new IllegalStateException( "Trying to use an unregistered part model: " + model );
}
if (bakedModel == null) {
throw new IllegalStateException("Trying to use an unregistered part model: " + model);
}
TextureAtlasSprite particleTexture = bakedModel.getParticleTexture();
TextureAtlasSprite particleTexture = bakedModel.getParticleTexture();
// If a part sub-model has no particle texture (indicated by it being the missing texture),
// don't add it, so we don't get ugly missing texture break particles.
if( this.textureMap.getMissingSprite() != particleTexture )
{
result.add( particleTexture );
}
}
}
// If a part sub-model has no particle texture (indicated by it being the missing texture),
// don't add it, so we don't get ugly missing texture break particles.
if (this.textureMap.getMissingSprite() != particleTexture) {
result.add(particleTexture);
}
}
}
return result;
}
return result;
}
private static CableBusRenderState getRenderingState( IBlockState state )
{
if( state == null || !( state instanceof IExtendedBlockState ) )
{
return null;
}
private static CableBusRenderState getRenderingState(IBlockState state) {
if (state == null || !(state instanceof IExtendedBlockState)) {
return null;
}
IExtendedBlockState extendedBlockState = (IExtendedBlockState) state;
return extendedBlockState.getValue( BlockCableBus.RENDER_STATE_PROPERTY );
}
IExtendedBlockState extendedBlockState = (IExtendedBlockState) state;
return extendedBlockState.getValue(BlockCableBus.RENDER_STATE_PROPERTY);
}
@Override
public boolean isAmbientOcclusion()
{
return true;
}
@Override
public boolean isAmbientOcclusion() {
return true;
}
@Override
public boolean isGui3d()
{
return false;
}
@Override
public boolean isGui3d() {
return false;
}
@Override
public boolean isBuiltInRenderer()
{
return false;
}
@Override
public boolean isBuiltInRenderer() {
return false;
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.particleTexture;
}
@Override
public TextureAtlasSprite getParticleTexture() {
return this.particleTexture;
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return ItemCameraTransforms.DEFAULT;
}
@Override
public ItemCameraTransforms getItemCameraTransforms() {
return ItemCameraTransforms.DEFAULT;
}
@Override
public ItemOverrideList getOverrides()
{
return ItemOverrideList.NONE;
}
@Override
public ItemOverrideList getOverrides() {
return ItemOverrideList.NONE;
}
}
@@ -19,13 +19,11 @@
package appeng.client.render.cablebus;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import appeng.api.util.AEColor;
import appeng.core.AELog;
import appeng.core.features.registries.PartModels;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
@@ -35,84 +33,72 @@ import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.TRSRTransformation;
import appeng.api.util.AEColor;
import appeng.core.AELog;
import appeng.core.features.registries.PartModels;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
/**
* The built-in model for the cable bus block.
*/
public class CableBusModel implements IModel
{
public class CableBusModel implements IModel {
private final PartModels partModels;
private final PartModels partModels;
public CableBusModel( PartModels partModels )
{
this.partModels = partModels;
}
public CableBusModel(PartModels partModels) {
this.partModels = partModels;
}
@Override
public Collection<ResourceLocation> getDependencies()
{
this.partModels.setInitialized( true );
return this.partModels.getModels();
}
@Override
public Collection<ResourceLocation> getDependencies() {
this.partModels.setInitialized(true);
return this.partModels.getModels();
}
@Override
public Collection<ResourceLocation> getTextures()
{
return ImmutableList.<ResourceLocation>builder()
.addAll( CableBuilder.getTextures() )
.build();
}
@Override
public Collection<ResourceLocation> getTextures() {
return ImmutableList.<ResourceLocation>builder()
.addAll(CableBuilder.getTextures())
.build();
}
@Override
public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
Map<ResourceLocation, IBakedModel> partModels = this.loadPartModels( state, format, bakedTextureGetter );
@Override
public IBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {
Map<ResourceLocation, IBakedModel> partModels = this.loadPartModels(state, format, bakedTextureGetter);
CableBuilder cableBuilder = new CableBuilder( format, bakedTextureGetter );
FacadeBuilder facadeBuilder = new FacadeBuilder();
CableBuilder cableBuilder = new CableBuilder(format, bakedTextureGetter);
FacadeBuilder facadeBuilder = new FacadeBuilder();
// This should normally not be used, but we *have* to provide a particle texture or otherwise damage models will
// crash
TextureAtlasSprite particleTexture = cableBuilder.getCoreTexture( CableCoreType.GLASS, AEColor.TRANSPARENT );
// This should normally not be used, but we *have* to provide a particle texture or otherwise damage models will
// crash
TextureAtlasSprite particleTexture = cableBuilder.getCoreTexture(CableCoreType.GLASS, AEColor.TRANSPARENT);
return new CableBusBakedModel( cableBuilder, facadeBuilder, partModels, particleTexture );
}
return new CableBusBakedModel(cableBuilder, facadeBuilder, partModels, particleTexture);
}
private Map<ResourceLocation, IBakedModel> loadPartModels( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
ImmutableMap.Builder<ResourceLocation, IBakedModel> result = ImmutableMap.builder();
private Map<ResourceLocation, IBakedModel> loadPartModels(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {
ImmutableMap.Builder<ResourceLocation, IBakedModel> result = ImmutableMap.builder();
for( ResourceLocation location : this.partModels.getModels() )
{
IModel model = this.tryLoadPartModel( location );
IBakedModel bakedModel = model.bake( state, format, bakedTextureGetter );
result.put( location, bakedModel );
}
for (ResourceLocation location : this.partModels.getModels()) {
IModel model = this.tryLoadPartModel(location);
IBakedModel bakedModel = model.bake(state, format, bakedTextureGetter);
result.put(location, bakedModel);
}
return result.build();
}
return result.build();
}
private IModel tryLoadPartModel( ResourceLocation location )
{
try
{
return ModelLoaderRegistry.getModel( location );
}
catch( Exception e )
{
AELog.error( e, "Unable to load part model " + location );
return ModelLoaderRegistry.getMissingModel();
}
}
private IModel tryLoadPartModel(ResourceLocation location) {
try {
return ModelLoaderRegistry.getModel(location);
} catch (Exception e) {
AELog.error(e, "Unable to load part model " + location);
return ModelLoaderRegistry.getMissingModel();
}
}
@Override
public IModelState getDefaultState()
{
return TRSRTransformation.identity();
}
@Override
public IModelState getDefaultState() {
return TRSRTransformation.identity();
}
}
@@ -19,212 +19,180 @@
package appeng.client.render.cablebus;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import java.lang.ref.WeakReference;
import java.util.*;
/**
* This class captures the entire rendering state needed for a cable bus and transports it to the rendering thread
* for processing.
*/
public class CableBusRenderState
{
public class CableBusRenderState {
// The cable type used for rendering the outgoing connections to other blocks and attached parts
private AECableType cableType = AECableType.NONE;
// The cable type used for rendering the outgoing connections to other blocks and attached parts
private AECableType cableType = AECableType.NONE;
// The type to use for rendering the core of the cable.
private CableCoreType coreType;
// The type to use for rendering the core of the cable.
private CableCoreType coreType;
private AEColor cableColor = AEColor.TRANSPARENT;
private AEColor cableColor = AEColor.TRANSPARENT;
// Describes the outgoing connections of this cable bus to other blocks, and how they should be rendered
private EnumMap<EnumFacing, AECableType> connectionTypes = new EnumMap<>( EnumFacing.class );
// Describes the outgoing connections of this cable bus to other blocks, and how they should be rendered
private EnumMap<EnumFacing, AECableType> connectionTypes = new EnumMap<>(EnumFacing.class);
// Indicate on which sides signified by connectionTypes above, there is another cable bus. If a side is connected,
// but it is absent from this
// set, then it means that there is a Grid host, but not a cable bus on that side (i.e. an interface, a controller,
// etc.)
private EnumSet<EnumFacing> cableBusAdjacent = EnumSet.noneOf( EnumFacing.class );
// Indicate on which sides signified by connectionTypes above, there is another cable bus. If a side is connected,
// but it is absent from this
// set, then it means that there is a Grid host, but not a cable bus on that side (i.e. an interface, a controller,
// etc.)
private EnumSet<EnumFacing> cableBusAdjacent = EnumSet.noneOf(EnumFacing.class);
// Specifies the number of channels used for the connection to a given side. Only contains entries if
// connections contains a corresponding entry.
private EnumMap<EnumFacing, Integer> channelsOnSide = new EnumMap<>( EnumFacing.class );
// Specifies the number of channels used for the connection to a given side. Only contains entries if
// connections contains a corresponding entry.
private EnumMap<EnumFacing, Integer> channelsOnSide = new EnumMap<>(EnumFacing.class);
private EnumMap<EnumFacing, IPartModel> attachments = new EnumMap<>( EnumFacing.class );
private final EnumMap<EnumFacing, IPartModel> attachments = new EnumMap<>(EnumFacing.class);
// For each attachment, this contains the distance from the edge until which a cable connection should be drawn
private EnumMap<EnumFacing, Integer> attachmentConnections = new EnumMap<>( EnumFacing.class );
// For each attachment, this contains the distance from the edge until which a cable connection should be drawn
private final EnumMap<EnumFacing, Integer> attachmentConnections = new EnumMap<>(EnumFacing.class);
// Contains the facade to use for each side that has a facade attached
private EnumMap<EnumFacing, FacadeRenderState> facades = new EnumMap<>( EnumFacing.class );
// Contains the facade to use for each side that has a facade attached
private final EnumMap<EnumFacing, FacadeRenderState> facades = new EnumMap<>(EnumFacing.class);
// Used for Facades.
private WeakReference<IBlockAccess> world;
private BlockPos pos;
// Used for Facades.
private WeakReference<IBlockAccess> world;
private BlockPos pos;
// Contains the bounding boxes of all parts on the cable bus to allow facades to cut out holes for the parts. This
// list is only populated if there are
// facades on this cable bus
private List<AxisAlignedBB> boundingBoxes = new ArrayList<>();
// Contains the bounding boxes of all parts on the cable bus to allow facades to cut out holes for the parts. This
// list is only populated if there are
// facades on this cable bus
private final List<AxisAlignedBB> boundingBoxes = new ArrayList<>();
private EnumMap<EnumFacing, Long> partFlags = new EnumMap<>( EnumFacing.class );
private final EnumMap<EnumFacing, Long> partFlags = new EnumMap<>(EnumFacing.class);
public CableCoreType getCoreType()
{
return this.coreType;
}
public CableCoreType getCoreType() {
return this.coreType;
}
public void setCoreType( CableCoreType coreType )
{
this.coreType = coreType;
}
public void setCoreType(CableCoreType coreType) {
this.coreType = coreType;
}
public AECableType getCableType()
{
return this.cableType;
}
public AECableType getCableType() {
return this.cableType;
}
public void setCableType( AECableType cableType )
{
this.cableType = cableType;
}
public void setCableType(AECableType cableType) {
this.cableType = cableType;
}
public AEColor getCableColor()
{
return this.cableColor;
}
public AEColor getCableColor() {
return this.cableColor;
}
public void setCableColor( AEColor cableColor )
{
this.cableColor = cableColor;
}
public void setCableColor(AEColor cableColor) {
this.cableColor = cableColor;
}
public EnumMap<EnumFacing, Integer> getChannelsOnSide()
{
return this.channelsOnSide;
}
public EnumMap<EnumFacing, Integer> getChannelsOnSide() {
return this.channelsOnSide;
}
public EnumMap<EnumFacing, AECableType> getConnectionTypes()
{
return this.connectionTypes;
}
public EnumMap<EnumFacing, AECableType> getConnectionTypes() {
return this.connectionTypes;
}
public void setConnectionTypes( EnumMap<EnumFacing, AECableType> connectionTypes )
{
this.connectionTypes = connectionTypes;
}
public void setConnectionTypes(EnumMap<EnumFacing, AECableType> connectionTypes) {
this.connectionTypes = connectionTypes;
}
public void setChannelsOnSide( EnumMap<EnumFacing, Integer> channelsOnSide )
{
this.channelsOnSide = channelsOnSide;
}
public void setChannelsOnSide(EnumMap<EnumFacing, Integer> channelsOnSide) {
this.channelsOnSide = channelsOnSide;
}
public EnumSet<EnumFacing> getCableBusAdjacent()
{
return this.cableBusAdjacent;
}
public EnumSet<EnumFacing> getCableBusAdjacent() {
return this.cableBusAdjacent;
}
public void setCableBusAdjacent( EnumSet<EnumFacing> cableBusAdjacent )
{
this.cableBusAdjacent = cableBusAdjacent;
}
public void setCableBusAdjacent(EnumSet<EnumFacing> cableBusAdjacent) {
this.cableBusAdjacent = cableBusAdjacent;
}
public EnumMap<EnumFacing, IPartModel> getAttachments()
{
return this.attachments;
}
public EnumMap<EnumFacing, IPartModel> getAttachments() {
return this.attachments;
}
public EnumMap<EnumFacing, Integer> getAttachmentConnections()
{
return this.attachmentConnections;
}
public EnumMap<EnumFacing, Integer> getAttachmentConnections() {
return this.attachmentConnections;
}
public EnumMap<EnumFacing, FacadeRenderState> getFacades()
{
return this.facades;
}
public EnumMap<EnumFacing, FacadeRenderState> getFacades() {
return this.facades;
}
public IBlockAccess getWorld()
{
return this.world.get();
}
public IBlockAccess getWorld() {
return this.world.get();
}
public void setWorld( IBlockAccess world )
{
this.world = new WeakReference<>( world );
}
public void setWorld(IBlockAccess world) {
this.world = new WeakReference<>(world);
}
public BlockPos getPos()
{
return this.pos;
}
public BlockPos getPos() {
return this.pos;
}
public void setPos( BlockPos pos )
{
this.pos = pos;
}
public void setPos(BlockPos pos) {
this.pos = pos;
}
public List<AxisAlignedBB> getBoundingBoxes()
{
return this.boundingBoxes;
}
public List<AxisAlignedBB> getBoundingBoxes() {
return this.boundingBoxes;
}
public EnumMap<EnumFacing, Long> getPartFlags()
{
return this.partFlags;
}
public EnumMap<EnumFacing, Long> getPartFlags() {
return this.partFlags;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ( ( this.attachmentConnections == null ) ? 0 : this.attachmentConnections.hashCode() );
result = prime * result + ( ( this.cableBusAdjacent == null ) ? 0 : this.cableBusAdjacent.hashCode() );
result = prime * result + ( ( this.cableColor == null ) ? 0 : this.cableColor.hashCode() );
result = prime * result + ( ( this.cableType == null ) ? 0 : this.cableType.hashCode() );
result = prime * result + ( ( this.channelsOnSide == null ) ? 0 : this.channelsOnSide.hashCode() );
result = prime * result + ( ( this.connectionTypes == null ) ? 0 : this.connectionTypes.hashCode() );
result = prime * result + ( ( this.coreType == null ) ? 0 : this.coreType.hashCode() );
result = prime * result + ( ( this.partFlags == null ) ? 0 : this.partFlags.hashCode() );
return result;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.attachmentConnections == null) ? 0 : this.attachmentConnections.hashCode());
result = prime * result + ((this.cableBusAdjacent == null) ? 0 : this.cableBusAdjacent.hashCode());
result = prime * result + ((this.cableColor == null) ? 0 : this.cableColor.hashCode());
result = prime * result + ((this.cableType == null) ? 0 : this.cableType.hashCode());
result = prime * result + ((this.channelsOnSide == null) ? 0 : this.channelsOnSide.hashCode());
result = prime * result + ((this.connectionTypes == null) ? 0 : this.connectionTypes.hashCode());
result = prime * result + ((this.coreType == null) ? 0 : this.coreType.hashCode());
result = prime * result + ((this.partFlags == null) ? 0 : this.partFlags.hashCode());
return result;
}
@Override
public boolean equals( Object obj )
{
if( this == obj )
{
return true;
}
if( obj == null )
{
return false;
}
if( this.getClass() != obj.getClass() )
{
return false;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final CableBusRenderState other = (CableBusRenderState) obj;
final CableBusRenderState other = (CableBusRenderState) obj;
return this.cableColor == other.cableColor && this.cableType == other.cableType && this.coreType == other.coreType && Objects
.equals( this.attachmentConnections, other.attachmentConnections ) && Objects.equals( this.cableBusAdjacent, other.cableBusAdjacent ) && Objects
.equals( this.channelsOnSide, other.channelsOnSide ) && Objects.equals( this.connectionTypes, other.connectionTypes ) && Objects
.equals( this.partFlags, other.partFlags );
}
return this.cableColor == other.cableColor && this.cableType == other.cableType && this.coreType == other.coreType && Objects
.equals(this.attachmentConnections, other.attachmentConnections) && Objects.equals(this.cableBusAdjacent, other.cableBusAdjacent) && Objects
.equals(this.channelsOnSide, other.channelsOnSide) && Objects.equals(this.connectionTypes, other.connectionTypes) && Objects
.equals(this.partFlags, other.partFlags);
}
}
@@ -19,16 +19,14 @@
package appeng.client.render.cablebus;
import java.util.EnumMap;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import net.minecraft.util.ResourceLocation;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.core.AppEng;
import com.google.common.collect.ImmutableMap;
import net.minecraft.util.ResourceLocation;
import java.util.EnumMap;
import java.util.Map;
/**
@@ -38,49 +36,44 @@ import appeng.core.AppEng;
* - Covered (also used by the Smart Cable)
* - Dense
*/
public enum CableCoreType
{
GLASS( "parts/cable/core/glass" ), COVERED( "parts/cable/core/covered" ), DENSE( "parts/cable/core/dense_smart" );
public enum CableCoreType {
GLASS("parts/cable/core/glass"), COVERED("parts/cable/core/covered"), DENSE("parts/cable/core/dense_smart");
private static final Map<AECableType, CableCoreType> cableMapping = generateCableMapping();
private static final Map<AECableType, CableCoreType> cableMapping = generateCableMapping();
/**
* Creates the mapping that assigns a cable core type to an AE cable type.
*/
private static Map<AECableType, CableCoreType> generateCableMapping()
{
/**
* Creates the mapping that assigns a cable core type to an AE cable type.
*/
private static Map<AECableType, CableCoreType> generateCableMapping() {
Map<AECableType, CableCoreType> result = new EnumMap<>( AECableType.class );
Map<AECableType, CableCoreType> result = new EnumMap<>(AECableType.class);
result.put( AECableType.GLASS, CableCoreType.GLASS );
result.put( AECableType.COVERED, CableCoreType.COVERED );
result.put( AECableType.SMART, CableCoreType.COVERED );
result.put( AECableType.DENSE_COVERED, CableCoreType.DENSE );
result.put( AECableType.DENSE_SMART, CableCoreType.DENSE );
result.put(AECableType.GLASS, CableCoreType.GLASS);
result.put(AECableType.COVERED, CableCoreType.COVERED);
result.put(AECableType.SMART, CableCoreType.COVERED);
result.put(AECableType.DENSE_COVERED, CableCoreType.DENSE);
result.put(AECableType.DENSE_SMART, CableCoreType.DENSE);
return ImmutableMap.copyOf( result );
}
return ImmutableMap.copyOf(result);
}
private final String textureFolder;
private final String textureFolder;
CableCoreType( String textureFolder )
{
this.textureFolder = textureFolder;
}
CableCoreType(String textureFolder) {
this.textureFolder = textureFolder;
}
/**
* @return The type of core that should be rendered when the given cable isn't straight and needs to have a core to
* attach connections to.
* Is null for the NULL cable.
*/
public static CableCoreType fromCableType( AECableType cableType )
{
return cableMapping.get( cableType );
}
/**
* @return The type of core that should be rendered when the given cable isn't straight and needs to have a core to
* attach connections to.
* Is null for the NULL cable.
*/
public static CableCoreType fromCableType(AECableType cableType) {
return cableMapping.get(cableType);
}
public ResourceLocation getTexture( AEColor color )
{
return new ResourceLocation( AppEng.MOD_ID, this.textureFolder + "/" + color.name().toLowerCase() );
}
public ResourceLocation getTexture(AEColor color) {
return new ResourceLocation(AppEng.MOD_ID, this.textureFolder + "/" + color.name().toLowerCase());
}
}
@@ -19,15 +19,8 @@
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import javax.vecmath.Vector4f;
import appeng.client.render.VertexFormats;
import com.google.common.base.Preconditions;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
@@ -36,517 +29,468 @@ import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
import appeng.client.render.VertexFormats;
import javax.vecmath.Vector4f;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
/**
* Builds the quads for a cube.
*/
public class CubeBuilder
{
public class CubeBuilder {
private VertexFormat format;
private VertexFormat format;
private final List<BakedQuad> output;
private final List<BakedQuad> output;
private final EnumMap<EnumFacing, TextureAtlasSprite> textures = new EnumMap<>( EnumFacing.class );
private final EnumMap<EnumFacing, TextureAtlasSprite> textures = new EnumMap<>(EnumFacing.class);
private EnumSet<EnumFacing> drawFaces = EnumSet.allOf( EnumFacing.class );
private EnumSet<EnumFacing> drawFaces = EnumSet.allOf(EnumFacing.class);
private final EnumMap<EnumFacing, Vector4f> customUv = new EnumMap<>( EnumFacing.class );
private final EnumMap<EnumFacing, Vector4f> customUv = new EnumMap<>(EnumFacing.class);
private byte[] uvRotations = new byte[EnumFacing.values().length];
private final byte[] uvRotations = new byte[EnumFacing.values().length];
private int color = 0xFFFFFFFF;
private int color = 0xFFFFFFFF;
private boolean useStandardUV = false;
private boolean useStandardUV = false;
private boolean renderFullBright;
private boolean renderFullBright;
public CubeBuilder( VertexFormat format, List<BakedQuad> output )
{
this.output = output;
this.format = format;
}
public CubeBuilder(VertexFormat format, List<BakedQuad> output) {
this.output = output;
this.format = format;
}
public CubeBuilder( VertexFormat format )
{
this( format, new ArrayList<>( 6 ) );
}
public CubeBuilder(VertexFormat format) {
this(format, new ArrayList<>(6));
}
public void addCube( float x1, float y1, float z1, float x2, float y2, float z2 )
{
x1 /= 16.0f;
y1 /= 16.0f;
z1 /= 16.0f;
x2 /= 16.0f;
y2 /= 16.0f;
z2 /= 16.0f;
public void addCube(float x1, float y1, float z1, float x2, float y2, float z2) {
x1 /= 16.0f;
y1 /= 16.0f;
z1 /= 16.0f;
x2 /= 16.0f;
y2 /= 16.0f;
z2 /= 16.0f;
// If brightness is forced to specific values, extend the vertex format to contain the multi-texturing lightmap
// offset
VertexFormat savedFormat = null;
if( this.renderFullBright )
{
savedFormat = this.format;
this.format = VertexFormats.getFormatWithLightMap( this.format );
}
// If brightness is forced to specific values, extend the vertex format to contain the multi-texturing lightmap
// offset
VertexFormat savedFormat = null;
if (this.renderFullBright) {
savedFormat = this.format;
this.format = VertexFormats.getFormatWithLightMap(this.format);
}
for( EnumFacing face : this.drawFaces )
{
this.putFace( face, x1, y1, z1, x2, y2, z2 );
}
for (EnumFacing face : this.drawFaces) {
this.putFace(face, x1, y1, z1, x2, y2, z2);
}
// Restore old format
if( savedFormat != null )
{
this.format = savedFormat;
}
}
// Restore old format
if (savedFormat != null) {
this.format = savedFormat;
}
}
public void addQuad( EnumFacing face, float x1, float y1, float z1, float x2, float y2, float z2 )
{
// If brightness is forced to specific values, extend the vertex format to contain the multi-texturing lightmap
// offset
VertexFormat savedFormat = null;
if( this.renderFullBright )
{
savedFormat = this.format;
this.format = new VertexFormat( savedFormat );
if( !this.format.getElements().contains( DefaultVertexFormats.TEX_2S ) )
{
this.format.addElement( DefaultVertexFormats.TEX_2S );
}
}
public void addQuad(EnumFacing face, float x1, float y1, float z1, float x2, float y2, float z2) {
// If brightness is forced to specific values, extend the vertex format to contain the multi-texturing lightmap
// offset
VertexFormat savedFormat = null;
if (this.renderFullBright) {
savedFormat = this.format;
this.format = new VertexFormat(savedFormat);
if (!this.format.getElements().contains(DefaultVertexFormats.TEX_2S)) {
this.format.addElement(DefaultVertexFormats.TEX_2S);
}
}
this.putFace( face, x1, y1, z1, x2, y2, z2 );
this.putFace(face, x1, y1, z1, x2, y2, z2);
// Restore old format
if( savedFormat != null )
{
this.format = savedFormat;
}
}
// Restore old format
if (savedFormat != null) {
this.format = savedFormat;
}
}
private static final class UvVector
{
float u1;
float u2;
float v1;
float v2;
}
private static final class UvVector {
float u1;
float u2;
float v1;
float v2;
}
private void putFace( EnumFacing face, float x1, float y1, float z1, float x2, float y2, float z2 )
{
private void putFace(EnumFacing face, float x1, float y1, float z1, float x2, float y2, float z2) {
TextureAtlasSprite texture = this.textures.get( face );
TextureAtlasSprite texture = this.textures.get(face);
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( this.format );
builder.setTexture( texture );
builder.setQuadOrientation( face );
builder.setQuadTint( -1 );
builder.setApplyDiffuseLighting( true );
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(this.format);
builder.setTexture(texture);
builder.setQuadOrientation(face);
builder.setQuadTint(-1);
builder.setApplyDiffuseLighting(true);
UvVector uv = new UvVector();
UvVector uv = new UvVector();
// The user might have set specific UV coordinates for this face
Vector4f customUv = this.customUv.get( face );
if( customUv != null )
{
uv.u1 = texture.getInterpolatedU( customUv.x );
uv.v1 = texture.getInterpolatedV( customUv.y );
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 );
}
// The user might have set specific UV coordinates for this face
Vector4f customUv = this.customUv.get(face);
if (customUv != null) {
uv.u1 = texture.getInterpolatedU(customUv.x);
uv.v1 = texture.getInterpolatedV(customUv.y);
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);
}
switch( face )
{
case DOWN:
this.putVertexTR( builder, face, x2, y1, z1, uv );
this.putVertexBR( builder, face, x2, y1, z2, uv );
this.putVertexBL( builder, face, x1, y1, z2, uv );
this.putVertexTL( builder, face, x1, y1, z1, uv );
break;
case UP:
this.putVertexTL( builder, face, x1, y2, z1, uv );
this.putVertexBL( builder, face, x1, y2, z2, uv );
this.putVertexBR( builder, face, x2, y2, z2, uv );
this.putVertexTR( builder, face, x2, y2, z1, uv );
break;
case NORTH:
this.putVertexBR( builder, face, x2, y2, z1, uv );
this.putVertexTR( builder, face, x2, y1, z1, uv );
this.putVertexTL( builder, face, x1, y1, z1, uv );
this.putVertexBL( builder, face, x1, y2, z1, uv );
break;
case SOUTH:
this.putVertexBL( builder, face, x1, y2, z2, uv );
this.putVertexTL( builder, face, x1, y1, z2, uv );
this.putVertexTR( builder, face, x2, y1, z2, uv );
this.putVertexBR( builder, face, x2, y2, z2, uv );
break;
case WEST:
this.putVertexTL( builder, face, x1, y1, z1, uv );
this.putVertexTR( builder, face, x1, y1, z2, uv );
this.putVertexBR( builder, face, x1, y2, z2, uv );
this.putVertexBL( builder, face, x1, y2, z1, uv );
break;
case EAST:
this.putVertexBR( builder, face, x2, y2, z1, uv );
this.putVertexBL( builder, face, x2, y2, z2, uv );
this.putVertexTL( builder, face, x2, y1, z2, uv );
this.putVertexTR( builder, face, x2, y1, z1, uv );
break;
}
switch (face) {
case DOWN:
this.putVertexTR(builder, face, x2, y1, z1, uv);
this.putVertexBR(builder, face, x2, y1, z2, uv);
this.putVertexBL(builder, face, x1, y1, z2, uv);
this.putVertexTL(builder, face, x1, y1, z1, uv);
break;
case UP:
this.putVertexTL(builder, face, x1, y2, z1, uv);
this.putVertexBL(builder, face, x1, y2, z2, uv);
this.putVertexBR(builder, face, x2, y2, z2, uv);
this.putVertexTR(builder, face, x2, y2, z1, uv);
break;
case NORTH:
this.putVertexBR(builder, face, x2, y2, z1, uv);
this.putVertexTR(builder, face, x2, y1, z1, uv);
this.putVertexTL(builder, face, x1, y1, z1, uv);
this.putVertexBL(builder, face, x1, y2, z1, uv);
break;
case SOUTH:
this.putVertexBL(builder, face, x1, y2, z2, uv);
this.putVertexTL(builder, face, x1, y1, z2, uv);
this.putVertexTR(builder, face, x2, y1, z2, uv);
this.putVertexBR(builder, face, x2, y2, z2, uv);
break;
case WEST:
this.putVertexTL(builder, face, x1, y1, z1, uv);
this.putVertexTR(builder, face, x1, y1, z2, uv);
this.putVertexBR(builder, face, x1, y2, z2, uv);
this.putVertexBL(builder, face, x1, y2, z1, uv);
break;
case EAST:
this.putVertexBR(builder, face, x2, y2, z1, uv);
this.putVertexBL(builder, face, x2, y2, z2, uv);
this.putVertexTL(builder, face, x2, y1, z2, uv);
this.putVertexTR(builder, face, x2, y1, z1, uv);
break;
}
this.output.add( builder.build() );
}
this.output.add(builder.build());
}
private UvVector getDefaultUv( EnumFacing face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2 )
{
private UvVector getDefaultUv(EnumFacing face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2) {
UvVector uv = new UvVector();
UvVector uv = new UvVector();
switch( face )
{
case DOWN:
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 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( x1 * 16 );
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
uv.u2 = texture.getInterpolatedU( 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( z2 * 16 );
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
uv.u2 = texture.getInterpolatedU( z1 * 16 );
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
break;
}
switch (face) {
case DOWN:
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 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(x1 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(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(z2 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(z1 * 16);
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
break;
}
return uv;
}
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;
}
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 )
{
float u, v;
// uv.u1, uv.v1
private void putVertexTL(UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv) {
float u, v;
switch( this.uvRotations[face.ordinal()] )
{
default:
case 0:
u = uv.u1;
v = uv.v1;
break;
case 1: // 90° clockwise
u = uv.u1;
v = uv.v2;
break;
case 2: // 180° clockwise
u = uv.u2;
v = uv.v2;
break;
case 3: // 270° clockwise
u = uv.u2;
v = uv.v1;
break;
}
switch (this.uvRotations[face.ordinal()]) {
default:
case 0:
u = uv.u1;
v = uv.v1;
break;
case 1: // 90° clockwise
u = uv.u1;
v = uv.v2;
break;
case 2: // 180° clockwise
u = uv.u2;
v = uv.v2;
break;
case 3: // 270° clockwise
u = uv.u2;
v = uv.v1;
break;
}
this.putVertex( builder, face, x, y, z, u, v );
}
this.putVertex(builder, face, x, y, z, u, v);
}
// uv.u2, uv.v1
private void putVertexTR( UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv )
{
float u, v;
// uv.u2, uv.v1
private void putVertexTR(UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv) {
float u, v;
switch( this.uvRotations[face.ordinal()] )
{
default:
case 0:
u = uv.u2;
v = uv.v1;
break;
case 1: // 90° clockwise
u = uv.u1;
v = uv.v1;
break;
case 2: // 180° clockwise
u = uv.u1;
v = uv.v2;
break;
case 3: // 270° clockwise
u = uv.u2;
v = uv.v2;
break;
}
this.putVertex( builder, face, x, y, z, u, v );
}
switch (this.uvRotations[face.ordinal()]) {
default:
case 0:
u = uv.u2;
v = uv.v1;
break;
case 1: // 90° clockwise
u = uv.u1;
v = uv.v1;
break;
case 2: // 180° clockwise
u = uv.u1;
v = uv.v2;
break;
case 3: // 270° clockwise
u = uv.u2;
v = uv.v2;
break;
}
this.putVertex(builder, face, x, y, z, u, v);
}
// uv.u2, uv.v2
private void putVertexBR( UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv )
{
// uv.u2, uv.v2
private void putVertexBR(UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv) {
float u;
float v;
float u;
float v;
switch( this.uvRotations[face.ordinal()] )
{
default:
case 0:
u = uv.u2;
v = uv.v2;
break;
case 1: // 90° clockwise
u = uv.u2;
v = uv.v1;
break;
case 2: // 180° clockwise
u = uv.u1;
v = uv.v1;
break;
case 3: // 270° clockwise
u = uv.u1;
v = uv.v2;
break;
}
switch (this.uvRotations[face.ordinal()]) {
default:
case 0:
u = uv.u2;
v = uv.v2;
break;
case 1: // 90° clockwise
u = uv.u2;
v = uv.v1;
break;
case 2: // 180° clockwise
u = uv.u1;
v = uv.v1;
break;
case 3: // 270° clockwise
u = uv.u1;
v = uv.v2;
break;
}
this.putVertex( builder, face, x, y, z, u, v );
}
this.putVertex(builder, face, x, y, z, u, v);
}
// uv.u1, uv.v2
private void putVertexBL( UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv )
{
// uv.u1, uv.v2
private void putVertexBL(UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv) {
float u;
float v;
float u;
float v;
switch( this.uvRotations[face.ordinal()] )
{
default:
case 0:
u = uv.u1;
v = uv.v2;
break;
case 1: // 90° clockwise
u = uv.u2;
v = uv.v2;
break;
case 2: // 180° clockwise
u = uv.u2;
v = uv.v1;
break;
case 3: // 270° clockwise
u = uv.u1;
v = uv.v1;
break;
}
switch (this.uvRotations[face.ordinal()]) {
default:
case 0:
u = uv.u1;
v = uv.v2;
break;
case 1: // 90° clockwise
u = uv.u2;
v = uv.v2;
break;
case 2: // 180° clockwise
u = uv.u2;
v = uv.v1;
break;
case 3: // 270° clockwise
u = uv.u1;
v = uv.v1;
break;
}
this.putVertex( builder, face, x, y, z, u, v );
}
this.putVertex(builder, face, x, y, z, u, v);
}
private void putVertex( UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, float u, float v )
{
VertexFormat format = builder.getVertexFormat();
private void putVertex(UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, float u, float v) {
VertexFormat format = builder.getVertexFormat();
for( int i = 0; i < format.getElementCount(); i++ )
{
VertexFormatElement e = format.getElement( i );
switch( e.getUsage() )
{
case POSITION:
builder.put( i, x, y, z );
break;
case NORMAL:
builder.put( i, face.getFrontOffsetX(), face.getFrontOffsetY(), face.getFrontOffsetZ() );
break;
case COLOR:
// Color format is RGBA
float r = ( this.color >> 16 & 0xFF ) / 255f;
float g = ( this.color >> 8 & 0xFF ) / 255f;
float b = ( this.color & 0xFF ) / 255f;
float a = ( this.color >> 24 & 0xFF ) / 255f;
builder.put( i, r, g, b, a );
break;
case UV:
if( e.getIndex() == 0 )
{
builder.put( i, u, v );
}
else
{
// Force Brightness to 15, this is for full bright mode
// this vertex element will only be present in that case
final float lightMapU = (float) ( 15 * 0x20 ) / 0xFFFF;
final float lightMapV = (float) ( 15 * 0x20 ) / 0xFFFF;
builder.put( i, lightMapU, lightMapV );
}
break;
default:
builder.put( i );
break;
}
}
}
for (int i = 0; i < format.getElementCount(); i++) {
VertexFormatElement e = format.getElement(i);
switch (e.getUsage()) {
case POSITION:
builder.put(i, x, y, z);
break;
case NORMAL:
builder.put(i, face.getFrontOffsetX(), face.getFrontOffsetY(), face.getFrontOffsetZ());
break;
case COLOR:
// Color format is RGBA
float r = (this.color >> 16 & 0xFF) / 255f;
float g = (this.color >> 8 & 0xFF) / 255f;
float b = (this.color & 0xFF) / 255f;
float a = (this.color >> 24 & 0xFF) / 255f;
builder.put(i, r, g, b, a);
break;
case UV:
if (e.getIndex() == 0) {
builder.put(i, u, v);
} else {
// Force Brightness to 15, this is for full bright mode
// this vertex element will only be present in that case
final float lightMapU = (float) (15 * 0x20) / 0xFFFF;
final float lightMapV = (float) (15 * 0x20) / 0xFFFF;
builder.put(i, lightMapU, lightMapV);
}
break;
default:
builder.put(i);
break;
}
}
}
public void setTexture( TextureAtlasSprite texture )
{
for( EnumFacing face : EnumFacing.values() )
{
this.textures.put( face, texture );
}
}
public void setTexture(TextureAtlasSprite texture) {
for (EnumFacing face : EnumFacing.values()) {
this.textures.put(face, texture);
}
}
public void setTextures( TextureAtlasSprite up, TextureAtlasSprite down, TextureAtlasSprite north, TextureAtlasSprite south, TextureAtlasSprite east, TextureAtlasSprite west )
{
this.textures.put( EnumFacing.UP, up );
this.textures.put( EnumFacing.DOWN, down );
this.textures.put( EnumFacing.NORTH, north );
this.textures.put( EnumFacing.SOUTH, south );
this.textures.put( EnumFacing.EAST, east );
this.textures.put( EnumFacing.WEST, west );
}
public void setTextures(TextureAtlasSprite up, TextureAtlasSprite down, TextureAtlasSprite north, TextureAtlasSprite south, TextureAtlasSprite east, TextureAtlasSprite west) {
this.textures.put(EnumFacing.UP, up);
this.textures.put(EnumFacing.DOWN, down);
this.textures.put(EnumFacing.NORTH, north);
this.textures.put(EnumFacing.SOUTH, south);
this.textures.put(EnumFacing.EAST, east);
this.textures.put(EnumFacing.WEST, west);
}
public void setTexture( EnumFacing facing, TextureAtlasSprite sprite )
{
this.textures.put( facing, sprite );
}
public void setTexture(EnumFacing facing, TextureAtlasSprite sprite) {
this.textures.put(facing, sprite);
}
public void setDrawFaces( EnumSet<EnumFacing> drawFaces )
{
this.drawFaces = drawFaces;
}
public void setDrawFaces(EnumSet<EnumFacing> drawFaces) {
this.drawFaces = drawFaces;
}
public void setColor( int color )
{
this.color = color;
}
public void setColor(int color) {
this.color = color;
}
/**
* Sets the vertex color for future vertices to the given RGB value, and forces the alpha component to 255.
*/
public void setColorRGB( int color )
{
this.setColor( color | 0xFF000000 );
}
/**
* Sets the vertex color for future vertices to the given RGB value, and forces the alpha component to 255.
*/
public void setColorRGB(int color) {
this.setColor(color | 0xFF000000);
}
public void setColorRGB( float r, float g, float b )
{
this.setColorRGB( (int) ( r * 255 ) << 16 | (int) ( g * 255 ) << 8 | (int) ( b * 255 ) );
}
public void setColorRGB(float r, float g, float b) {
this.setColorRGB((int) (r * 255) << 16 | (int) (g * 255) << 8 | (int) (b * 255));
}
public void setRenderFullBright( boolean renderFullBright )
{
this.renderFullBright = renderFullBright;
}
public void setRenderFullBright(boolean renderFullBright) {
this.renderFullBright = renderFullBright;
}
public void setCustomUv( EnumFacing facing, float u1, float v1, float u2, float v2 )
{
this.customUv.put( facing, new Vector4f( u1, v1, u2, v2 ) );
}
public void setCustomUv(EnumFacing facing, float u1, float v1, float u2, float v2) {
this.customUv.put(facing, new Vector4f(u1, v1, u2, v2));
}
public void setUvRotation( EnumFacing facing, int rotation )
{
if( rotation == 2 )
{
rotation = 3;
}
else if( rotation == 3 )
{
rotation = 2;
}
Preconditions.checkArgument( rotation >= 0 && rotation <= 3, "rotation" );
this.uvRotations[facing.ordinal()] = (byte) rotation;
}
public void setUvRotation(EnumFacing facing, int rotation) {
if (rotation == 2) {
rotation = 3;
} else if (rotation == 3) {
rotation = 2;
}
Preconditions.checkArgument(rotation >= 0 && rotation <= 3, "rotation");
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;
}
/**
* CubeBuilder uses UV optimized for cables by default.
* This switches to standard UV coordinates.
*/
public void useStandardUV() {
this.useStandardUV = true;
}
public List<BakedQuad> getOutput()
{
return this.output;
}
public List<BakedQuad> getOutput() {
return this.output;
}
}
@@ -19,8 +19,6 @@
package appeng.client.render.cablebus;
import javax.annotation.Nullable;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
@@ -29,6 +27,8 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.WorldType;
import net.minecraft.world.biome.Biome;
import javax.annotation.Nullable;
/**
* This is used to retrieve the ExtendedState of a block for facade rendering.
@@ -36,80 +36,66 @@ import net.minecraft.world.biome.Biome;
*
* @author covers1624
*/
public class FacadeBlockAccess implements IBlockAccess
{
public class FacadeBlockAccess implements IBlockAccess {
private final IBlockAccess world;
private final BlockPos pos;
private final EnumFacing side;
private final IBlockState state;
private final IBlockAccess world;
private final BlockPos pos;
private final EnumFacing side;
private final IBlockState state;
public FacadeBlockAccess( IBlockAccess world, BlockPos pos, EnumFacing side, IBlockState state )
{
this.world = world;
this.pos = pos;
this.side = side;
this.state = state;
}
public FacadeBlockAccess(IBlockAccess world, BlockPos pos, EnumFacing side, IBlockState state) {
this.world = world;
this.pos = pos;
this.side = side;
this.state = state;
}
@Nullable
@Override
public TileEntity getTileEntity( BlockPos pos )
{
return this.world.getTileEntity( pos );
}
@Nullable
@Override
public TileEntity getTileEntity(BlockPos pos) {
return this.world.getTileEntity(pos);
}
@Override
public int getCombinedLight( BlockPos pos, int lightValue )
{
return this.world.getCombinedLight( pos, lightValue );
}
@Override
public int getCombinedLight(BlockPos pos, int lightValue) {
return this.world.getCombinedLight(pos, lightValue);
}
@Override
public IBlockState getBlockState( BlockPos pos )
{
if( this.pos == pos )
{
return this.state;
}
return this.world.getBlockState( pos );
}
@Override
public IBlockState getBlockState(BlockPos pos) {
if (this.pos == pos) {
return this.state;
}
return this.world.getBlockState(pos);
}
@Override
public boolean isAirBlock( BlockPos pos )
{
IBlockState state = this.getBlockState( pos );
return state.getBlock().isAir( state, this.world, pos );
}
@Override
public boolean isAirBlock(BlockPos pos) {
IBlockState state = this.getBlockState(pos);
return state.getBlock().isAir(state, this.world, pos);
}
@Override
public Biome getBiome( BlockPos pos )
{
return this.world.getBiome( pos );
}
@Override
public Biome getBiome(BlockPos pos) {
return this.world.getBiome(pos);
}
@Override
public int getStrongPower( BlockPos pos, EnumFacing direction )
{
return this.world.getStrongPower( pos, direction );
}
@Override
public int getStrongPower(BlockPos pos, EnumFacing direction) {
return this.world.getStrongPower(pos, direction);
}
@Override
public WorldType getWorldType()
{
return this.world.getWorldType();
}
@Override
public WorldType getWorldType() {
return this.world.getWorldType();
}
@Override
public boolean isSideSolid( BlockPos pos, EnumFacing side, boolean _default )
{
if( pos.getX() < -30000000 || pos.getZ() < -30000000 || pos.getX() >= 30000000 || pos.getZ() >= 30000000 )
{
return _default;
}
else
{
return this.getBlockState( pos ).isSideSolid( this, pos, side );
}
}
@Override
public boolean isSideSolid(BlockPos pos, EnumFacing side, boolean _default) {
if (pos.getX() < -30000000 || pos.getZ() < -30000000 || pos.getX() >= 30000000 || pos.getZ() >= 30000000) {
return _default;
} else {
return this.getBlockState(pos).isSideSolid(this, pos, side);
}
}
}
@@ -19,16 +19,13 @@
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nullable;
import appeng.api.AEApi;
import appeng.api.util.AEAxisAlignedBB;
import appeng.parts.misc.PartCableAnchor;
import appeng.thirdparty.codechicken.lib.model.CachedFormat;
import appeng.thirdparty.codechicken.lib.model.Quad;
import appeng.thirdparty.codechicken.lib.model.pipeline.BakedPipeline;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.*;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockRendererDispatcher;
@@ -45,18 +42,10 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.client.ForgeHooksClient;
import appeng.api.AEApi;
import appeng.api.util.AEAxisAlignedBB;
import appeng.parts.misc.PartCableAnchor;
import appeng.thirdparty.codechicken.lib.model.CachedFormat;
import appeng.thirdparty.codechicken.lib.model.Quad;
import appeng.thirdparty.codechicken.lib.model.pipeline.BakedPipeline;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadAlphaOverride;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadClamper;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadCornerKicker;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadFaceStripper;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadReInterpolator;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadTinter;
import javax.annotation.Nullable;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
/**
@@ -64,428 +53,375 @@ import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadTinter;
*
* @author covers1624
*/
public class FacadeBuilder
{
public class FacadeBuilder {
public static final double THICK_THICKNESS = 2D / 16D;
public static final double THIN_THICKNESS = 1D / 16D;
public static final double THICK_THICKNESS = 2D / 16D;
public static final double THIN_THICKNESS = 1D / 16D;
public static final AxisAlignedBB[] THICK_FACADE_BOXES = new AxisAlignedBB[] {
new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, THICK_THICKNESS, 1.0 ),
new AxisAlignedBB( 0.0, 1.0 - THICK_THICKNESS, 0.0, 1.0, 1.0, 1.0 ),
new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, 1.0, THICK_THICKNESS ),
new AxisAlignedBB( 0.0, 0.0, 1.0 - THICK_THICKNESS, 1.0, 1.0, 1.0 ),
new AxisAlignedBB( 0.0, 0.0, 0.0, THICK_THICKNESS, 1.0, 1.0 ),
new AxisAlignedBB( 1.0 - THICK_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0 )
};
public static final AxisAlignedBB[] THICK_FACADE_BOXES = new AxisAlignedBB[]{
new AxisAlignedBB(0.0, 0.0, 0.0, 1.0, THICK_THICKNESS, 1.0),
new AxisAlignedBB(0.0, 1.0 - THICK_THICKNESS, 0.0, 1.0, 1.0, 1.0),
new AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 1.0, THICK_THICKNESS),
new AxisAlignedBB(0.0, 0.0, 1.0 - THICK_THICKNESS, 1.0, 1.0, 1.0),
new AxisAlignedBB(0.0, 0.0, 0.0, THICK_THICKNESS, 1.0, 1.0),
new AxisAlignedBB(1.0 - THICK_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0)
};
public static final AxisAlignedBB[] THIN_FACADE_BOXES = new AxisAlignedBB[] {
new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, THIN_THICKNESS, 1.0 ),
new AxisAlignedBB( 0.0, 1.0 - THIN_THICKNESS, 0.0, 1.0, 1.0, 1.0 ),
new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, 1.0, THIN_THICKNESS ),
new AxisAlignedBB( 0.0, 0.0, 1.0 - THIN_THICKNESS, 1.0, 1.0, 1.0 ),
new AxisAlignedBB( 0.0, 0.0, 0.0, THIN_THICKNESS, 1.0, 1.0 ),
new AxisAlignedBB( 1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0 )
};
public static final AxisAlignedBB[] THIN_FACADE_BOXES = new AxisAlignedBB[]{
new AxisAlignedBB(0.0, 0.0, 0.0, 1.0, THIN_THICKNESS, 1.0),
new AxisAlignedBB(0.0, 1.0 - THIN_THICKNESS, 0.0, 1.0, 1.0, 1.0),
new AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 1.0, THIN_THICKNESS),
new AxisAlignedBB(0.0, 0.0, 1.0 - THIN_THICKNESS, 1.0, 1.0, 1.0),
new AxisAlignedBB(0.0, 0.0, 0.0, THIN_THICKNESS, 1.0, 1.0),
new AxisAlignedBB(1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0)
};
private ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial( () -> BakedPipeline.builder()
// Clamper is responsible for clamping the vertex to the bounds specified.
.addElement( "clamper", QuadClamper.FACTORY )
// Strips faces if they match a mask.
.addElement( "face_stripper", QuadFaceStripper.FACTORY )
// Kicks the edge inner corners in, solves Z fighting
.addElement( "corner_kicker", QuadCornerKicker.FACTORY )
// Re-Interpolates the UV's for the quad.
.addElement( "interp", QuadReInterpolator.FACTORY )
// Tints the quad if we need it to. Disabled by default.
.addElement( "tinter", QuadTinter.FACTORY, false )
// Overrides the quad's alpha if we are forcing transparent facades.
.addElement( "transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride( 0x4C / 255F ) )
.build()//
);
private ThreadLocal<Quad> collectors = ThreadLocal.withInitial( Quad::new );
private final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> BakedPipeline.builder()
// Clamper is responsible for clamping the vertex to the bounds specified.
.addElement("clamper", QuadClamper.FACTORY)
// Strips faces if they match a mask.
.addElement("face_stripper", QuadFaceStripper.FACTORY)
// Kicks the edge inner corners in, solves Z fighting
.addElement("corner_kicker", QuadCornerKicker.FACTORY)
// Re-Interpolates the UV's for the quad.
.addElement("interp", QuadReInterpolator.FACTORY)
// Tints the quad if we need it to. Disabled by default.
.addElement("tinter", QuadTinter.FACTORY, false)
// Overrides the quad's alpha if we are forcing transparent facades.
.addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F))
.build()//
);
private final ThreadLocal<Quad> collectors = ThreadLocal.withInitial(Quad::new);
public void buildFacadeQuads( BlockRenderLayer layer, CableBusRenderState renderState, long rand, List<BakedQuad> quads, Function<ResourceLocation, IBakedModel> modelLookup )
{
BakedPipeline pipeline = this.pipelines.get();
Quad collectorQuad = this.collectors.get();
boolean transparent = AEApi.instance().partHelper().getCableRenderMode().transparentFacades;
Map<EnumFacing, FacadeRenderState> facadeStates = renderState.getFacades();
List<AxisAlignedBB> partBoxes = renderState.getBoundingBoxes();
Set<EnumFacing> sidesWithParts = renderState.getAttachments().keySet();
IBlockAccess parentWorld = renderState.getWorld();
BlockPos pos = renderState.getPos();
BlockColors blockColors = Minecraft.getMinecraft().getBlockColors();
boolean thinFacades = isUseThinFacades( partBoxes );
public void buildFacadeQuads(BlockRenderLayer layer, CableBusRenderState renderState, long rand, List<BakedQuad> quads, Function<ResourceLocation, IBakedModel> modelLookup) {
BakedPipeline pipeline = this.pipelines.get();
Quad collectorQuad = this.collectors.get();
boolean transparent = AEApi.instance().partHelper().getCableRenderMode().transparentFacades;
Map<EnumFacing, FacadeRenderState> facadeStates = renderState.getFacades();
List<AxisAlignedBB> partBoxes = renderState.getBoundingBoxes();
Set<EnumFacing> sidesWithParts = renderState.getAttachments().keySet();
IBlockAccess parentWorld = renderState.getWorld();
BlockPos pos = renderState.getPos();
BlockColors blockColors = Minecraft.getMinecraft().getBlockColors();
boolean thinFacades = isUseThinFacades(partBoxes);
for( Entry<EnumFacing, FacadeRenderState> entry : facadeStates.entrySet() )
{
EnumFacing side = entry.getKey();
int sideIndex = side.ordinal();
FacadeRenderState facadeRenderState = entry.getValue();
boolean renderStilt = !sidesWithParts.contains( side );
if( layer == BlockRenderLayer.CUTOUT && renderStilt )
{
for( ResourceLocation part : PartCableAnchor.FACADE_MODELS.getModels() )
{
IBakedModel partModel = modelLookup.apply( part );
QuadRotator rotator = new QuadRotator();
quads.addAll( rotator.rotateQuads( gatherQuads( partModel, null, rand ), side, EnumFacing.UP ) );
}
}
// If we are forcing transparency and this isn't the Translucent layer.
if( transparent && layer != BlockRenderLayer.TRANSLUCENT )
{
continue;
}
for (Entry<EnumFacing, FacadeRenderState> entry : facadeStates.entrySet()) {
EnumFacing side = entry.getKey();
int sideIndex = side.ordinal();
FacadeRenderState facadeRenderState = entry.getValue();
boolean renderStilt = !sidesWithParts.contains(side);
if (layer == BlockRenderLayer.CUTOUT && renderStilt) {
for (ResourceLocation part : PartCableAnchor.FACADE_MODELS.getModels()) {
IBakedModel partModel = modelLookup.apply(part);
QuadRotator rotator = new QuadRotator();
quads.addAll(rotator.rotateQuads(gatherQuads(partModel, null, rand), side, EnumFacing.UP));
}
}
// If we are forcing transparency and this isn't the Translucent layer.
if (transparent && layer != BlockRenderLayer.TRANSLUCENT) {
continue;
}
IBlockState blockState = facadeRenderState.getSourceBlock();
// If we aren't forcing transparency let the block decide if it should render.
if( !transparent && layer != null )
{
if( !blockState.getBlock().canRenderInLayer( blockState, layer ) )
{
continue;
}
}
IBlockState blockState = facadeRenderState.getSourceBlock();
// If we aren't forcing transparency let the block decide if it should render.
if (!transparent && layer != null) {
if (!blockState.getBlock().canRenderInLayer(blockState, layer)) {
continue;
}
}
AxisAlignedBB fullBounds = thinFacades ? THIN_FACADE_BOXES[sideIndex] : THICK_FACADE_BOXES[sideIndex];
AxisAlignedBB facadeBox = fullBounds;
// If we are a transparent facade, we need to modify out BB.
if( facadeRenderState.isTransparent() )
{
double offset = thinFacades ? THIN_THICKNESS : THICK_THICKNESS;
AEAxisAlignedBB tmpBB = null;
for( EnumFacing face : EnumFacing.VALUES )
{
// Only faces that aren't on our axis
if( face.getAxis() != side.getAxis() )
{
FacadeRenderState otherState = facadeStates.get( face );
if( otherState != null && !otherState.isTransparent() )
{
if( tmpBB == null )
{
tmpBB = AEAxisAlignedBB.fromBounds( facadeBox );
}
switch( face )
{
case DOWN:
tmpBB.minY += offset;
break;
case UP:
tmpBB.maxY -= offset;
break;
case NORTH:
tmpBB.minZ += offset;
break;
case SOUTH:
tmpBB.maxZ -= offset;
break;
case WEST:
tmpBB.minX += offset;
break;
case EAST:
tmpBB.maxX -= offset;
break;
default:
throw new RuntimeException( "Switch falloff. " + String.valueOf( face ) );
}
}
}
}
if( tmpBB != null )
{
facadeBox = tmpBB.getBoundingBox();
}
}
AxisAlignedBB fullBounds = thinFacades ? THIN_FACADE_BOXES[sideIndex] : THICK_FACADE_BOXES[sideIndex];
AxisAlignedBB facadeBox = fullBounds;
// If we are a transparent facade, we need to modify out BB.
if (facadeRenderState.isTransparent()) {
double offset = thinFacades ? THIN_THICKNESS : THICK_THICKNESS;
AEAxisAlignedBB tmpBB = null;
for (EnumFacing face : EnumFacing.VALUES) {
// Only faces that aren't on our axis
if (face.getAxis() != side.getAxis()) {
FacadeRenderState otherState = facadeStates.get(face);
if (otherState != null && !otherState.isTransparent()) {
if (tmpBB == null) {
tmpBB = AEAxisAlignedBB.fromBounds(facadeBox);
}
switch (face) {
case DOWN:
tmpBB.minY += offset;
break;
case UP:
tmpBB.maxY -= offset;
break;
case NORTH:
tmpBB.minZ += offset;
break;
case SOUTH:
tmpBB.maxZ -= offset;
break;
case WEST:
tmpBB.minX += offset;
break;
case EAST:
tmpBB.maxX -= offset;
break;
default:
throw new RuntimeException("Switch falloff. " + face);
}
}
}
}
if (tmpBB != null) {
facadeBox = tmpBB.getBoundingBox();
}
}
AEAxisAlignedBB cutOutBox = getCutOutBox( facadeBox, partBoxes );
List<AxisAlignedBB> holeStrips = getBoxes( facadeBox, cutOutBox, side.getAxis() );
IBlockAccess facadeAccess = new FacadeBlockAccess( parentWorld, pos, side, blockState );
AEAxisAlignedBB cutOutBox = getCutOutBox(facadeBox, partBoxes);
List<AxisAlignedBB> holeStrips = getBoxes(facadeBox, cutOutBox, side.getAxis());
IBlockAccess facadeAccess = new FacadeBlockAccess(parentWorld, pos, side, blockState);
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
try
{
blockState = blockState.getActualState( facadeAccess, pos );
}
catch( Exception ignored )
{
}
IBakedModel model = dispatcher.getModelForState( blockState );
try
{
blockState = blockState.getBlock().getExtendedState( blockState, facadeAccess, pos );
}
catch( Exception ignored )
{
}
try {
blockState = blockState.getActualState(facadeAccess, pos);
} catch (Exception ignored) {
}
IBakedModel model = dispatcher.getModelForState(blockState);
try {
blockState = blockState.getBlock().getExtendedState(blockState, facadeAccess, pos);
} catch (Exception ignored) {
}
List<BakedQuad> modelQuads = new ArrayList<>();
// If we are forcing transparent facades, fake the render layer, and grab all quads.
if( transparent || layer == null )
{
for( BlockRenderLayer forcedLayer : BlockRenderLayer.values() )
{
// Check if the block renders on the layer we want to force.
if( blockState.getBlock().canRenderInLayer( blockState, forcedLayer ) )
{
// Force the layer and gather quads.
ForgeHooksClient.setRenderLayer( forcedLayer );
modelQuads.addAll( gatherQuads( model, blockState, rand ) );
}
}
List<BakedQuad> modelQuads = new ArrayList<>();
// If we are forcing transparent facades, fake the render layer, and grab all quads.
if (transparent || layer == null) {
for (BlockRenderLayer forcedLayer : BlockRenderLayer.values()) {
// Check if the block renders on the layer we want to force.
if (blockState.getBlock().canRenderInLayer(blockState, forcedLayer)) {
// Force the layer and gather quads.
ForgeHooksClient.setRenderLayer(forcedLayer);
modelQuads.addAll(gatherQuads(model, blockState, rand));
}
}
// Reset.
ForgeHooksClient.setRenderLayer( layer );
}
else
{
modelQuads.addAll( gatherQuads( model, blockState, rand ) );
}
// Reset.
ForgeHooksClient.setRenderLayer(layer);
} else {
modelQuads.addAll(gatherQuads(model, blockState, rand));
}
// No quads.. Cool, next!
if( modelQuads.isEmpty() )
{
continue;
}
// No quads.. Cool, next!
if (modelQuads.isEmpty()) {
continue;
}
// Grab out pipeline elements.
QuadClamper clamper = pipeline.getElement( "clamper", QuadClamper.class );
QuadFaceStripper edgeStripper = pipeline.getElement( "face_stripper", QuadFaceStripper.class );
QuadTinter tinter = pipeline.getElement( "tinter", QuadTinter.class );
QuadCornerKicker kicker = pipeline.getElement( "corner_kicker", QuadCornerKicker.class );
// Grab out pipeline elements.
QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
QuadFaceStripper edgeStripper = pipeline.getElement("face_stripper", QuadFaceStripper.class);
QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
QuadCornerKicker kicker = pipeline.getElement("corner_kicker", QuadCornerKicker.class);
// Set global element states.
// Set global element states.
// calculate the side mask.
int facadeMask = 0;
for( Entry<EnumFacing, FacadeRenderState> ent : facadeStates.entrySet() )
{
EnumFacing s = ent.getKey();
if( s.getAxis() != side.getAxis() )
{
FacadeRenderState otherState = ent.getValue();
if( !otherState.isTransparent() )
{
facadeMask |= 1 << s.ordinal();
}
}
}
// Setup the edge stripper.
edgeStripper.setBounds( fullBounds );
edgeStripper.setMask( facadeMask );
// calculate the side mask.
int facadeMask = 0;
for (Entry<EnumFacing, FacadeRenderState> ent : facadeStates.entrySet()) {
EnumFacing s = ent.getKey();
if (s.getAxis() != side.getAxis()) {
FacadeRenderState otherState = ent.getValue();
if (!otherState.isTransparent()) {
facadeMask |= 1 << s.ordinal();
}
}
}
// Setup the edge stripper.
edgeStripper.setBounds(fullBounds);
edgeStripper.setMask(facadeMask);
// Setup the kicker.
kicker.setSide( sideIndex );
kicker.setFacadeMask( facadeMask );
kicker.setBox( fullBounds );
kicker.setThickness( thinFacades ? THIN_THICKNESS : THICK_THICKNESS );
// Setup the kicker.
kicker.setSide(sideIndex);
kicker.setFacadeMask(facadeMask);
kicker.setBox(fullBounds);
kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
for( BakedQuad quad : modelQuads )
{
// lookup the format in CachedFormat.
CachedFormat format = CachedFormat.lookup( quad.getFormat() );
// If this quad has a tint index, setup the tinter.
if( quad.hasTintIndex() )
{
tinter.setTint( blockColors.colorMultiplier( blockState, facadeAccess, pos, quad.getTintIndex() ) );
}
for( AxisAlignedBB box : holeStrips )
{
// setup the clamper for this box
clamper.setClampBounds( box );
// Reset the pipeline, clears all enabled/disabled states.
pipeline.reset( format );
// Reset out collector.
collectorQuad.reset( format );
// Enable / disable the optional elements
pipeline.setElementState( "tinter", quad.hasTintIndex() );
pipeline.setElementState( "transparent", transparent );
// Prepare the pipeline for a quad.
pipeline.prepare( collectorQuad );
for (BakedQuad quad : modelQuads) {
// lookup the format in CachedFormat.
CachedFormat format = CachedFormat.lookup(quad.getFormat());
// If this quad has a tint index, setup the tinter.
if (quad.hasTintIndex()) {
tinter.setTint(blockColors.colorMultiplier(blockState, facadeAccess, pos, quad.getTintIndex()));
}
for (AxisAlignedBB box : holeStrips) {
// setup the clamper for this box
clamper.setClampBounds(box);
// Reset the pipeline, clears all enabled/disabled states.
pipeline.reset(format);
// Reset out collector.
collectorQuad.reset(format);
// Enable / disable the optional elements
pipeline.setElementState("tinter", quad.hasTintIndex());
pipeline.setElementState("transparent", transparent);
// Prepare the pipeline for a quad.
pipeline.prepare(collectorQuad);
// Pipe our quad into the pipeline.
quad.pipe( pipeline );
// Check if the collector got any data.
if( collectorQuad.full )
{
// Add the result.
quads.add( collectorQuad.bake() );
}
}
}
}
}
// Pipe our quad into the pipeline.
quad.pipe(pipeline);
// Check if the collector got any data.
if (collectorQuad.full) {
// Add the result.
quads.add(collectorQuad.bake());
}
}
}
}
}
/**
* This is slow, so should be cached.
*
* @return The model.
*/
public List<BakedQuad> buildFacadeItemQuads( ItemStack textureItem, EnumFacing side )
{
List<BakedQuad> facadeQuads = new ArrayList<>();
IBakedModel model = Minecraft.getMinecraft().getRenderItem().getItemModelWithOverrides( textureItem, null, null );
List<BakedQuad> modelQuads = gatherQuads( model, null, 0 );
/**
* This is slow, so should be cached.
*
* @return The model.
*/
public List<BakedQuad> buildFacadeItemQuads(ItemStack textureItem, EnumFacing side) {
List<BakedQuad> facadeQuads = new ArrayList<>();
IBakedModel model = Minecraft.getMinecraft().getRenderItem().getItemModelWithOverrides(textureItem, null, null);
List<BakedQuad> modelQuads = gatherQuads(model, null, 0);
BakedPipeline pipeline = this.pipelines.get();
Quad collectorQuad = this.collectors.get();
BakedPipeline pipeline = this.pipelines.get();
Quad collectorQuad = this.collectors.get();
// Grab pipeline elements.
QuadClamper clamper = pipeline.getElement( "clamper", QuadClamper.class );
QuadTinter tinter = pipeline.getElement( "tinter", QuadTinter.class );
// Grab pipeline elements.
QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
for( BakedQuad quad : modelQuads )
{
// Lookup the CachedFormat for this quads format.
CachedFormat format = CachedFormat.lookup( quad.getFormat() );
// Reset the pipeline.
pipeline.reset( format );
// Reset the collector.
collectorQuad.reset( format );
// If we have a tint index, setup the tinter and enable it.
if( quad.hasTintIndex() )
{
tinter.setTint( Minecraft.getMinecraft().getItemColors().colorMultiplier( textureItem, quad.getTintIndex() ) );
pipeline.enableElement( "tinter" );
}
// Disable elements we don't need for items.
pipeline.disableElement( "face_stripper" );
pipeline.disableElement( "corner_kicker" );
// Setup the clamper
clamper.setClampBounds( THICK_FACADE_BOXES[side.ordinal()] );
// Prepare the pipeline.
pipeline.prepare( collectorQuad );
// Pipe our quad into the pipeline.
quad.pipe( pipeline );
// Check the collector for data and add the quad if there was.
if( collectorQuad.full )
{
facadeQuads.add( collectorQuad.bakeUnpacked() );
}
}
return facadeQuads;
}
for (BakedQuad quad : modelQuads) {
// Lookup the CachedFormat for this quads format.
CachedFormat format = CachedFormat.lookup(quad.getFormat());
// Reset the pipeline.
pipeline.reset(format);
// Reset the collector.
collectorQuad.reset(format);
// If we have a tint index, setup the tinter and enable it.
if (quad.hasTintIndex()) {
tinter.setTint(Minecraft.getMinecraft().getItemColors().colorMultiplier(textureItem, quad.getTintIndex()));
pipeline.enableElement("tinter");
}
// Disable elements we don't need for items.
pipeline.disableElement("face_stripper");
pipeline.disableElement("corner_kicker");
// Setup the clamper
clamper.setClampBounds(THICK_FACADE_BOXES[side.ordinal()]);
// Prepare the pipeline.
pipeline.prepare(collectorQuad);
// Pipe our quad into the pipeline.
quad.pipe(pipeline);
// Check the collector for data and add the quad if there was.
if (collectorQuad.full) {
facadeQuads.add(collectorQuad.bakeUnpacked());
}
}
return facadeQuads;
}
// Helper to gather all quads from a model into a list.
private static List<BakedQuad> gatherQuads( IBakedModel model, IBlockState state, long rand )
{
List<BakedQuad> modelQuads = new ArrayList<>();
for( EnumFacing face : EnumFacing.VALUES )
{
modelQuads.addAll( model.getQuads( state, face, rand ) );
}
modelQuads.addAll( model.getQuads( state, null, rand ) );
return modelQuads;
}
// Helper to gather all quads from a model into a list.
private static List<BakedQuad> gatherQuads(IBakedModel model, IBlockState state, long rand) {
List<BakedQuad> modelQuads = new ArrayList<>();
for (EnumFacing face : EnumFacing.VALUES) {
modelQuads.addAll(model.getQuads(state, face, rand));
}
modelQuads.addAll(model.getQuads(state, null, rand));
return modelQuads;
}
/**
* Given the actual facade bounding box, and the bounding boxes of all parts, determine the biggest union of AABB
* that intersect with the facade's bounding
* box. This AABB will need to be "cut out" when the facade is rendered.
*/
@Nullable
private static AEAxisAlignedBB getCutOutBox( AxisAlignedBB facadeBox, List<AxisAlignedBB> partBoxes )
{
AEAxisAlignedBB b = null;
for( AxisAlignedBB bb : partBoxes )
{
if( bb.intersects( facadeBox ) )
{
if( b == null )
{
b = AEAxisAlignedBB.fromBounds( bb );
}
else
{
b.maxX = Math.max( b.maxX, bb.maxX );
b.maxY = Math.max( b.maxY, bb.maxY );
b.maxZ = Math.max( b.maxZ, bb.maxZ );
b.minX = Math.min( b.minX, bb.minX );
b.minY = Math.min( b.minY, bb.minY );
b.minZ = Math.min( b.minZ, bb.minZ );
}
}
}
return b;
}
/**
* Given the actual facade bounding box, and the bounding boxes of all parts, determine the biggest union of AABB
* that intersect with the facade's bounding
* box. This AABB will need to be "cut out" when the facade is rendered.
*/
@Nullable
private static AEAxisAlignedBB getCutOutBox(AxisAlignedBB facadeBox, List<AxisAlignedBB> partBoxes) {
AEAxisAlignedBB b = null;
for (AxisAlignedBB bb : partBoxes) {
if (bb.intersects(facadeBox)) {
if (b == null) {
b = AEAxisAlignedBB.fromBounds(bb);
} else {
b.maxX = Math.max(b.maxX, bb.maxX);
b.maxY = Math.max(b.maxY, bb.maxY);
b.maxZ = Math.max(b.maxZ, bb.maxZ);
b.minX = Math.min(b.minX, bb.minX);
b.minY = Math.min(b.minY, bb.minY);
b.minZ = Math.min(b.minZ, bb.minZ);
}
}
}
return b;
}
/**
* Generates the box segments around the specified hole. If the specified hole is null, a Singleton of the Facade
* box is returned.
*
* @param fb The Facade's box.
* @param hole The hole to 'cut'.
* @param axis The axis the facade is on.
*
* @return The box segments.
*/
private static List<AxisAlignedBB> getBoxes( AxisAlignedBB fb, AEAxisAlignedBB hole, Axis axis )
{
if( hole == null )
{
return Collections.singletonList( fb );
}
List<AxisAlignedBB> boxes = new ArrayList<>();
switch( axis )
{
case Y:
boxes.add( new AxisAlignedBB( fb.minX, fb.minY, fb.minZ, hole.minX, fb.maxY, fb.maxZ ) );
boxes.add( new AxisAlignedBB( hole.maxX, fb.minY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ ) );
/**
* Generates the box segments around the specified hole. If the specified hole is null, a Singleton of the Facade
* box is returned.
*
* @param fb The Facade's box.
* @param hole The hole to 'cut'.
* @param axis The axis the facade is on.
* @return The box segments.
*/
private static List<AxisAlignedBB> getBoxes(AxisAlignedBB fb, AEAxisAlignedBB hole, Axis axis) {
if (hole == null) {
return Collections.singletonList(fb);
}
List<AxisAlignedBB> boxes = new ArrayList<>();
switch (axis) {
case Y:
boxes.add(new AxisAlignedBB(fb.minX, fb.minY, fb.minZ, hole.minX, fb.maxY, fb.maxZ));
boxes.add(new AxisAlignedBB(hole.maxX, fb.minY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ));
boxes.add( new AxisAlignedBB( hole.minX, fb.minY, fb.minZ, hole.maxX, fb.maxY, hole.minZ ) );
boxes.add( new AxisAlignedBB( hole.minX, fb.minY, hole.maxZ, hole.maxX, fb.maxY, fb.maxZ ) );
boxes.add(new AxisAlignedBB(hole.minX, fb.minY, fb.minZ, hole.maxX, fb.maxY, hole.minZ));
boxes.add(new AxisAlignedBB(hole.minX, fb.minY, hole.maxZ, hole.maxX, fb.maxY, fb.maxZ));
break;
case Z:
boxes.add( new AxisAlignedBB( fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ ) );
boxes.add( new AxisAlignedBB( fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ ) );
break;
case Z:
boxes.add(new AxisAlignedBB(fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ));
boxes.add(new AxisAlignedBB(fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ));
boxes.add( new AxisAlignedBB( fb.minX, hole.minY, fb.minZ, hole.minX, hole.maxY, fb.maxZ ) );
boxes.add( new AxisAlignedBB( hole.maxX, hole.minY, fb.minZ, fb.maxX, hole.maxY, fb.maxZ ) );
boxes.add(new AxisAlignedBB(fb.minX, hole.minY, fb.minZ, hole.minX, hole.maxY, fb.maxZ));
boxes.add(new AxisAlignedBB(hole.maxX, hole.minY, fb.minZ, fb.maxX, hole.maxY, fb.maxZ));
break;
case X:
boxes.add( new AxisAlignedBB( fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ ) );
boxes.add( new AxisAlignedBB( fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ ) );
break;
case X:
boxes.add(new AxisAlignedBB(fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ));
boxes.add(new AxisAlignedBB(fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ));
boxes.add( new AxisAlignedBB( fb.minX, hole.minY, fb.minZ, fb.maxX, hole.maxY, hole.minZ ) );
boxes.add( new AxisAlignedBB( fb.minX, hole.minY, hole.maxZ, fb.maxX, hole.maxY, fb.maxZ ) );
break;
default:
// should never happen.
throw new RuntimeException( "switch falloff. " + String.valueOf( axis ) );
}
boxes.add(new AxisAlignedBB(fb.minX, hole.minY, fb.minZ, fb.maxX, hole.maxY, hole.minZ));
boxes.add(new AxisAlignedBB(fb.minX, hole.minY, hole.maxZ, fb.maxX, hole.maxY, fb.maxZ));
break;
default:
// should never happen.
throw new RuntimeException("switch falloff. " + axis);
}
return boxes;
}
return boxes;
}
/**
* Determines if any of the part's bounding boxes intersects with the outside 2 voxel wide layer. If so, we should
* use thinner facades (1 voxel deep).
*/
private static boolean isUseThinFacades( List<AxisAlignedBB> partBoxes )
{
final double min = 2.0 / 16.0;
final double max = 14.0 / 16.0;
/**
* Determines if any of the part's bounding boxes intersects with the outside 2 voxel wide layer. If so, we should
* use thinner facades (1 voxel deep).
*/
private static boolean isUseThinFacades(List<AxisAlignedBB> partBoxes) {
final double min = 2.0 / 16.0;
final double max = 14.0 / 16.0;
for( AxisAlignedBB bb : partBoxes )
{
int o = 0;
o += bb.maxX > max ? 1 : 0;
o += bb.maxY > max ? 1 : 0;
o += bb.maxZ > max ? 1 : 0;
o += bb.minX < min ? 1 : 0;
o += bb.minY < min ? 1 : 0;
o += bb.minZ < min ? 1 : 0;
for (AxisAlignedBB bb : partBoxes) {
int o = 0;
o += bb.maxX > max ? 1 : 0;
o += bb.maxY > max ? 1 : 0;
o += bb.maxZ > max ? 1 : 0;
o += bb.minX < min ? 1 : 0;
o += bb.minY < min ? 1 : 0;
o += bb.minZ < min ? 1 : 0;
if( o >= 2 )
{
return true;
}
}
return false;
}
if (o >= 2) {
return true;
}
}
return false;
}
}
@@ -1,4 +1,3 @@
package appeng.client.render.cablebus;
@@ -8,27 +7,23 @@ import net.minecraft.block.state.IBlockState;
/**
* Captures the state required to render a facade properly.
*/
public class FacadeRenderState
{
public class FacadeRenderState {
// The block state to use for rendering this facade
private final IBlockState sourceBlock;
// The block state to use for rendering this facade
private final IBlockState sourceBlock;
private final boolean transparent;
private final boolean transparent;
public FacadeRenderState( IBlockState sourceBlock, boolean transparent )
{
this.sourceBlock = sourceBlock;
this.transparent = transparent;
}
public FacadeRenderState(IBlockState sourceBlock, boolean transparent) {
this.sourceBlock = sourceBlock;
this.transparent = transparent;
}
public IBlockState getSourceBlock()
{
return this.sourceBlock;
}
public IBlockState getSourceBlock() {
return this.sourceBlock;
}
public boolean isTransparent()
{
return this.transparent;
}
public boolean isTransparent() {
return this.transparent;
}
}
@@ -1,14 +1,11 @@
package appeng.client.render.cablebus;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import appeng.api.parts.IPartBakedModel;
import appeng.api.util.AEColor;
import appeng.util.Platform;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
@@ -17,126 +14,106 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.EnumFacing;
import appeng.api.parts.IPartBakedModel;
import appeng.api.util.AEColor;
import appeng.util.Platform;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class P2PTunnelFrequencyBakedModel implements IBakedModel, IPartBakedModel
{
private final VertexFormat format;
private final TextureAtlasSprite texture;
public class P2PTunnelFrequencyBakedModel implements IBakedModel, IPartBakedModel {
private final VertexFormat format;
private final TextureAtlasSprite texture;
private final static Cache<Long, List<BakedQuad>> modelCache = CacheBuilder.newBuilder().maximumSize( 100 ).build();
private final static Cache<Long, List<BakedQuad>> modelCache = CacheBuilder.newBuilder().maximumSize(100).build();
private static final int[][] QUAD_OFFSETS = new int[][] {
{ 4, 10, 2 },
{ 10, 10, 2 },
{ 4, 4, 2 },
{ 10, 4, 2 }
};
private static final int[][] QUAD_OFFSETS = new int[][]{
{4, 10, 2},
{10, 10, 2},
{4, 4, 2},
{10, 4, 2}
};
public P2PTunnelFrequencyBakedModel( final VertexFormat format, final TextureAtlasSprite texture )
{
this.format = format;
this.texture = texture;
}
public P2PTunnelFrequencyBakedModel(final VertexFormat format, final TextureAtlasSprite texture) {
this.format = format;
this.texture = texture;
}
@Override
public List<BakedQuad> getPartQuads( Long partFlags, long rand )
{
try
{
return modelCache.get( partFlags, () ->
{
short frequency = 0;
boolean active = false;
if( partFlags != null )
{
frequency = (short) ( partFlags.longValue() & 0xffffL );
active = ( partFlags.longValue() & 0x10000L ) != 0;
}
return this.getQuadsForFrequency( frequency, active );
} );
}
catch( ExecutionException e )
{
return Collections.emptyList();
}
}
@Override
public List<BakedQuad> getPartQuads(Long partFlags, long rand) {
try {
return modelCache.get(partFlags, () ->
{
short frequency = 0;
boolean active = false;
if (partFlags != null) {
frequency = (short) (partFlags.longValue() & 0xffffL);
active = (partFlags.longValue() & 0x10000L) != 0;
}
return this.getQuadsForFrequency(frequency, active);
});
} catch (ExecutionException e) {
return Collections.emptyList();
}
}
@Override
public List<BakedQuad> getQuads( IBlockState state, EnumFacing side, long rand )
{
if( side != null )
{
return Collections.emptyList();
}
return this.getPartQuads( null, rand );
}
@Override
public List<BakedQuad> getQuads(IBlockState state, EnumFacing side, long rand) {
if (side != null) {
return Collections.emptyList();
}
return this.getPartQuads(null, rand);
}
private List<BakedQuad> getQuadsForFrequency( final short frequency, final boolean active )
{
final AEColor[] colors = Platform.p2p().toColors( frequency );
final CubeBuilder cb = new CubeBuilder( this.format );
private List<BakedQuad> getQuadsForFrequency(final short frequency, final boolean active) {
final AEColor[] colors = Platform.p2p().toColors(frequency);
final CubeBuilder cb = new CubeBuilder(this.format);
cb.setTexture( this.texture );
cb.useStandardUV();
cb.setRenderFullBright( active );
cb.setTexture(this.texture);
cb.useStandardUV();
cb.setRenderFullBright(active);
for( int i = 0; i < 4; ++i )
{
final int[] offs = QUAD_OFFSETS[i];
for( int j = 0; j < 4; ++j )
{
final AEColor c = colors[j];
if( active )
{
cb.setColorRGB( c.dye.getColorValue() );
}
else
{
final float cv[] = c.dye.getColorComponentValues();
cb.setColorRGB( cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f );
}
for (int i = 0; i < 4; ++i) {
final int[] offs = QUAD_OFFSETS[i];
for (int j = 0; j < 4; ++j) {
final AEColor c = colors[j];
if (active) {
cb.setColorRGB(c.dye.getColorValue());
} else {
final float[] cv = c.dye.getColorComponentValues();
cb.setColorRGB(cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f);
}
final int startx = j % 2;
final int starty = 1 - j / 2;
final int startx = j % 2;
final int starty = 1 - j / 2;
cb.addCube( offs[0] + startx, offs[1] + starty, offs[2], offs[0] + startx + 1, offs[1] + starty + 1, offs[2] + 1 );
}
cb.addCube(offs[0] + startx, offs[1] + starty, offs[2], offs[0] + startx + 1, offs[1] + starty + 1, offs[2] + 1);
}
}
return cb.getOutput();
}
}
return cb.getOutput();
}
@Override
public boolean isAmbientOcclusion()
{
return false;
}
@Override
public boolean isAmbientOcclusion() {
return false;
}
@Override
public boolean isGui3d()
{
return false;
}
@Override
public boolean isGui3d() {
return false;
}
@Override
public boolean isBuiltInRenderer()
{
return true;
}
@Override
public boolean isBuiltInRenderer() {
return true;
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.texture;
}
@Override
public TextureAtlasSprite getParticleTexture() {
return this.texture;
}
@Override
public ItemOverrideList getOverrides()
{
return ItemOverrideList.NONE;
}
@Override
public ItemOverrideList getOverrides() {
return ItemOverrideList.NONE;
}
}
@@ -1,11 +1,7 @@
package appeng.client.render.cablebus;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Function;
import appeng.core.AppEng;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
@@ -13,31 +9,27 @@ import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.common.model.IModelState;
import appeng.core.AppEng;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Function;
public class P2PTunnelFrequencyModel implements IModel
{
private static final ResourceLocation TEXTURE = new ResourceLocation( AppEng.MOD_ID, "parts/p2p_tunnel_frequency" );
public class P2PTunnelFrequencyModel implements IModel {
private static final ResourceLocation TEXTURE = new ResourceLocation(AppEng.MOD_ID, "parts/p2p_tunnel_frequency");
@Override
public Collection<ResourceLocation> getTextures()
{
return Collections.singletonList( TEXTURE );
}
@Override
public Collection<ResourceLocation> getTextures() {
return Collections.singletonList(TEXTURE);
}
@Override
public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
try
{
final TextureAtlasSprite texture = bakedTextureGetter.apply( TEXTURE );
return new P2PTunnelFrequencyBakedModel( format, texture );
}
catch( Exception e )
{
throw new RuntimeException( e );
}
}
@Override
public IBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {
try {
final TextureAtlasSprite texture = bakedTextureGetter.apply(TEXTURE);
return new P2PTunnelFrequencyBakedModel(format, texture);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@@ -19,171 +19,144 @@
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.List;
import javax.vecmath.Matrix4f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import appeng.client.render.FacingToRotation;
import appeng.core.AELog;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.EnumFacing;
import appeng.client.render.FacingToRotation;
import appeng.core.AELog;
import javax.vecmath.Matrix4f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import java.util.ArrayList;
import java.util.List;
/**
* Assuming a default-orientation of forward=NORTH and up=UP, this class rotates a given list of quads to the desired
* facing
*/
public class QuadRotator
{
public class QuadRotator {
public List<BakedQuad> rotateQuads( List<BakedQuad> quads, EnumFacing newForward, EnumFacing newUp )
{
if( newForward == EnumFacing.NORTH && newUp == EnumFacing.UP )
{
return quads; // This is the default orientation
}
public List<BakedQuad> rotateQuads(List<BakedQuad> quads, EnumFacing newForward, EnumFacing newUp) {
if (newForward == EnumFacing.NORTH && newUp == EnumFacing.UP) {
return quads; // This is the default orientation
}
List<BakedQuad> result = new ArrayList<>( quads.size() );
List<BakedQuad> result = new ArrayList<>(quads.size());
for( BakedQuad quad : quads )
{
result.add( this.rotateQuad( quad, newForward, newUp ) );
}
for (BakedQuad quad : quads) {
result.add(this.rotateQuad(quad, newForward, newUp));
}
return result;
}
return result;
}
private BakedQuad rotateQuad( BakedQuad quad, EnumFacing forward, EnumFacing up )
{
// Sanitize forward/up
if( forward.getAxis() == up.getAxis() )
{
if( up.getAxis() == EnumFacing.Axis.Y )
{
up = EnumFacing.NORTH;
}
else
{
up = EnumFacing.UP;
}
}
private BakedQuad rotateQuad(BakedQuad quad, EnumFacing forward, EnumFacing up) {
// Sanitize forward/up
if (forward.getAxis() == up.getAxis()) {
if (up.getAxis() == EnumFacing.Axis.Y) {
up = EnumFacing.NORTH;
} else {
up = EnumFacing.UP;
}
}
FacingToRotation rotation = FacingToRotation.get( forward, up );
Matrix4f mat = rotation.getMat();
FacingToRotation rotation = FacingToRotation.get(forward, up);
Matrix4f mat = rotation.getMat();
// Clone the vertex data used by the quad
int[] newData = quad.getVertexData().clone();
// Clone the vertex data used by the quad
int[] newData = quad.getVertexData().clone();
// Figure out where the position is in the array
VertexFormat format = quad.getFormat();
int posIdx = this.findPositionOffset( format ) / 4;
int stride = format.getNextOffset() / 4;
int normalIdx = format.getNormalOffset();
VertexFormatElement.EnumType normalType = null;
// Figure out the type of the normals
if( normalIdx != -1 )
{
for( int i = 0; i < format.getElements().size(); i++ )
{
VertexFormatElement element = format.getElement( i );
if( element.getUsage() == VertexFormatElement.EnumUsage.NORMAL )
{
normalType = element.getType();
}
}
}
// Figure out where the position is in the array
VertexFormat format = quad.getFormat();
int posIdx = this.findPositionOffset(format) / 4;
int stride = format.getNextOffset() / 4;
int normalIdx = format.getNormalOffset();
VertexFormatElement.EnumType normalType = null;
// Figure out the type of the normals
if (normalIdx != -1) {
for (int i = 0; i < format.getElements().size(); i++) {
VertexFormatElement element = format.getElement(i);
if (element.getUsage() == VertexFormatElement.EnumUsage.NORMAL) {
normalType = element.getType();
}
}
}
for( int i = 0; i < 4; i++ )
{
Point3f pos = new Point3f( Float.intBitsToFloat( newData[i * stride + posIdx] ) - 0.5f, Float
.intBitsToFloat( newData[i * stride + posIdx + 1] ) - 0.5f, Float.intBitsToFloat( newData[i * stride + posIdx + 2] ) - 0.5f );
for (int i = 0; i < 4; i++) {
Point3f pos = new Point3f(Float.intBitsToFloat(newData[i * stride + posIdx]) - 0.5f, Float
.intBitsToFloat(newData[i * stride + posIdx + 1]) - 0.5f, Float.intBitsToFloat(newData[i * stride + posIdx + 2]) - 0.5f);
// Rotate stuff around
mat.transform( pos );
// Rotate stuff around
mat.transform(pos);
// Write back
newData[i * stride + posIdx] = Float.floatToIntBits( pos.getX() + 0.5f );
newData[i * stride + posIdx + 1] = Float.floatToIntBits( pos.getY() + 0.5f );
newData[i * stride + posIdx + 2] = Float.floatToIntBits( pos.getZ() + 0.5f );
// Write back
newData[i * stride + posIdx] = Float.floatToIntBits(pos.getX() + 0.5f);
newData[i * stride + posIdx + 1] = Float.floatToIntBits(pos.getY() + 0.5f);
newData[i * stride + posIdx + 2] = Float.floatToIntBits(pos.getZ() + 0.5f);
// Transform the normal if one is present
if( normalIdx != -1 )
{
if( normalType == VertexFormatElement.EnumType.FLOAT )
{
Vector3f normal = new Vector3f( Float.intBitsToFloat( newData[i * stride + normalIdx] ), Float
.intBitsToFloat( newData[i * stride + normalIdx + 1] ), Float.intBitsToFloat( newData[i * stride + normalIdx + 2] ) );
// Transform the normal if one is present
if (normalIdx != -1) {
if (normalType == VertexFormatElement.EnumType.FLOAT) {
Vector3f normal = new Vector3f(Float.intBitsToFloat(newData[i * stride + normalIdx]), Float
.intBitsToFloat(newData[i * stride + normalIdx + 1]), Float.intBitsToFloat(newData[i * stride + normalIdx + 2]));
// Rotate stuff around
mat.transform( normal );
// Rotate stuff around
mat.transform(normal);
// Write back
newData[i * stride + normalIdx] = Float.floatToIntBits( normal.getX() );
newData[i * stride + normalIdx + 1] = Float.floatToIntBits( normal.getY() );
newData[i * stride + normalIdx + 2] = Float.floatToIntBits( normal.getZ() );
}
else if( normalType == VertexFormatElement.EnumType.BYTE )
{
int idx = i * stride * 4 + normalIdx;
Vector3f normal = new Vector3f( getByte( newData, idx ) / 127.0f, getByte( newData, idx + 1 ) / 127.0f, getByte( newData,
idx + 2 ) / 127.0f );
// Write back
newData[i * stride + normalIdx] = Float.floatToIntBits(normal.getX());
newData[i * stride + normalIdx + 1] = Float.floatToIntBits(normal.getY());
newData[i * stride + normalIdx + 2] = Float.floatToIntBits(normal.getZ());
} else if (normalType == VertexFormatElement.EnumType.BYTE) {
int idx = i * stride * 4 + normalIdx;
Vector3f normal = new Vector3f(getByte(newData, idx) / 127.0f, getByte(newData, idx + 1) / 127.0f, getByte(newData,
idx + 2) / 127.0f);
// Rotate stuff around
mat.transform( normal );
// Rotate stuff around
mat.transform(normal);
// Write back
setByte( newData, idx, (int) ( normal.getX() * 127 ) );
setByte( newData, idx + 1, (int) ( normal.getY() * 127 ) );
setByte( newData, idx + 2, (int) ( normal.getZ() * 127 ) );
}
else
{
AELog.warn( "Unsupported normal format: {}", normalType );
}
}
}
// Write back
setByte(newData, idx, (int) (normal.getX() * 127));
setByte(newData, idx + 1, (int) (normal.getY() * 127));
setByte(newData, idx + 2, (int) (normal.getZ() * 127));
} else {
AELog.warn("Unsupported normal format: {}", normalType);
}
}
}
EnumFacing newFace = rotation.rotate( quad.getFace() );
return new BakedQuad( newData, quad.getTintIndex(), newFace, quad.getSprite(), quad.shouldApplyDiffuseLighting(), quad.getFormat() );
}
EnumFacing newFace = rotation.rotate(quad.getFace());
return new BakedQuad(newData, quad.getTintIndex(), newFace, quad.getSprite(), quad.shouldApplyDiffuseLighting(), quad.getFormat());
}
private static int getByte( int[] data, int offset )
{
int idx = offset / 4;
int subOffset = offset % 4;
return (byte) ( data[idx] >> ( subOffset * 8 ) );
}
private static int getByte(int[] data, int offset) {
int idx = offset / 4;
int subOffset = offset % 4;
return (byte) (data[idx] >> (subOffset * 8));
}
private static void setByte( int[] data, int offset, int value )
{
int idx = offset / 4;
int subOffset = offset % 4;
int mask = 0xFF << ( subOffset * 8 );
data[idx] = data[idx] & ( ~mask ) | ( ( value & 0xFF ) << ( subOffset * 8 ) );
}
private static void setByte(int[] data, int offset, int value) {
int idx = offset / 4;
int subOffset = offset % 4;
int mask = 0xFF << (subOffset * 8);
data[idx] = data[idx] & (~mask) | ((value & 0xFF) << (subOffset * 8));
}
private int findPositionOffset( VertexFormat format )
{
List<VertexFormatElement> elements = format.getElements();
for( int i = 0; i < elements.size(); i++ )
{
VertexFormatElement e = elements.get( i );
if( e.isPositionElement() )
{
if( e.getType() != VertexFormatElement.EnumType.FLOAT )
{
throw new IllegalArgumentException( "Only floating point positions are supported" );
}
return i;
}
}
private int findPositionOffset(VertexFormat format) {
List<VertexFormatElement> elements = format.getElements();
for (int i = 0; i < elements.size(); i++) {
VertexFormatElement e = elements.get(i);
if (e.isPositionElement()) {
if (e.getType() != VertexFormatElement.EnumType.FLOAT) {
throw new IllegalArgumentException("Only floating point positions are supported");
}
return i;
}
}
throw new IllegalArgumentException( "Vertex format " + format + " has no position attribute!" );
}
throw new IllegalArgumentException("Vertex format " + format + " has no position attribute!");
}
}
@@ -19,73 +19,58 @@
package appeng.client.render.cablebus;
import java.util.Arrays;
import java.util.function.Function;
import appeng.core.AppEng;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
import appeng.core.AppEng;
import java.util.Arrays;
import java.util.function.Function;
/**
* Manages the channel textures for smart cables.
*/
public class SmartCableTextures
{
public class SmartCableTextures {
public static final ResourceLocation[] SMART_CHANNELS_TEXTURES = { new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_00" ),
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_01" ), new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_02" ),
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_03" ), new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_04" ),
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_10" ), new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_11" ),
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_12" ), new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_13" ),
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_14" )
};
public static final ResourceLocation[] SMART_CHANNELS_TEXTURES = {new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_00"),
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_01"), new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_02"),
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_03"), new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_04"),
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_10"), new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_11"),
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_12"), new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_13"),
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_14")
};
// Textures used to display channels on smart cables. There's two sets of 5 textures each, and
// one of each set are composed together to get even/odd colored channels
private final TextureAtlasSprite[] textures;
// Textures used to display channels on smart cables. There's two sets of 5 textures each, and
// one of each set are composed together to get even/odd colored channels
private final TextureAtlasSprite[] textures;
public SmartCableTextures( Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
this.textures = Arrays.stream( SMART_CHANNELS_TEXTURES ).map( bakedTextureGetter::apply ).toArray( TextureAtlasSprite[]::new );
}
public SmartCableTextures(Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {
this.textures = Arrays.stream(SMART_CHANNELS_TEXTURES).map(bakedTextureGetter::apply).toArray(TextureAtlasSprite[]::new);
}
/**
* The odd variant is used for displaying channels 1-4 as in use.
*/
public TextureAtlasSprite getOddTextureForChannels( int channels )
{
if( channels < 0 )
{
return this.textures[0];
}
else if( channels <= 4 )
{
return this.textures[channels];
}
else
{
return this.textures[4];
}
}
/**
* The odd variant is used for displaying channels 1-4 as in use.
*/
public TextureAtlasSprite getOddTextureForChannels(int channels) {
if (channels < 0) {
return this.textures[0];
} else if (channels <= 4) {
return this.textures[channels];
} else {
return this.textures[4];
}
}
/**
* The odd variant is used for displaying channels 5-8 as in use.
*/
public TextureAtlasSprite getEvenTextureForChannels( int channels )
{
if( channels < 5 )
{
return this.textures[5];
}
else if( channels <= 8 )
{
return this.textures[1 + channels];
}
else
{
return this.textures[9];
}
}
/**
* The odd variant is used for displaying channels 5-8 as in use.
*/
public TextureAtlasSprite getEvenTextureForChannels(int channels) {
if (channels < 5) {
return this.textures[5];
} else if (channels <= 8) {
return this.textures[1 + channels];
} else {
return this.textures[9];
}
}
}