pick 97420a31d The big reformat of 2020

This commit is contained in:
yueh
2020-06-16 21:41:28 +02:00
parent 5304b3febe
commit 5225ea426b
2252 changed files with 95466 additions and 118582 deletions
@@ -18,7 +18,6 @@
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -35,8 +34,8 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.color.BlockColors;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
@@ -64,420 +63,374 @@ import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadFaceStr
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadReInterpolator;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadTinter;
/**
* The FacadeBuilder builds for facades..
*
* @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 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 );
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( RenderType layer, CableBusRenderState renderState, Random 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<Direction, FacadeRenderState> facadeStates = renderState.getFacades();
List<AxisAlignedBB> partBoxes = renderState.getBoundingBoxes();
Set<Direction> sidesWithParts = renderState.getAttachments().keySet();
ILightReader parentWorld = renderState.getWorld();
BlockPos pos = renderState.getPos();
BlockColors blockColors = Minecraft.getInstance().getBlockColors();
boolean thinFacades = isUseThinFacades( partBoxes );
public void buildFacadeQuads(RenderType layer, CableBusRenderState renderState, Random 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<Direction, FacadeRenderState> facadeStates = renderState.getFacades();
List<AxisAlignedBB> partBoxes = renderState.getBoundingBoxes();
Set<Direction> sidesWithParts = renderState.getAttachments().keySet();
ILightReader parentWorld = renderState.getWorld();
BlockPos pos = renderState.getPos();
BlockColors blockColors = Minecraft.getInstance().getBlockColors();
boolean thinFacades = isUseThinFacades(partBoxes);
for( Entry<Direction, FacadeRenderState> entry : facadeStates.entrySet() )
{
Direction side = entry.getKey();
int sideIndex = side.ordinal();
FacadeRenderState facadeRenderState = entry.getValue();
boolean renderStilt = !sidesWithParts.contains( side );
if( layer == RenderType.getCutout() && 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, EmptyModelData.INSTANCE ), side, Direction.UP ) );
}
}
// If we are forcing transparency and this isn't the Translucent layer.
if( transparent && layer != RenderType.getTranslucent() )
{
continue;
}
for (Entry<Direction, FacadeRenderState> entry : facadeStates.entrySet()) {
Direction side = entry.getKey();
int sideIndex = side.ordinal();
FacadeRenderState facadeRenderState = entry.getValue();
boolean renderStilt = !sidesWithParts.contains(side);
if (layer == RenderType.getCutout() && 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, EmptyModelData.INSTANCE), side,
Direction.UP));
}
}
// If we are forcing transparency and this isn't the Translucent layer.
if (transparent && layer != RenderType.getTranslucent()) {
continue;
}
BlockState blockState = facadeRenderState.getSourceBlock();
// If we aren't forcing transparency let the block decide if it should render.
if( !transparent && layer != null )
{
if( !RenderTypeLookup.canRenderInLayer( blockState, layer ) )
{
continue;
}
}
BlockState blockState = facadeRenderState.getSourceBlock();
// If we aren't forcing transparency let the block decide if it should render.
if (!transparent && layer != null) {
if (!RenderTypeLookup.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( Direction face : Direction.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 (Direction face : Direction.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();
}
}
AEAxisAlignedBB cutOutBox = getCutOutBox( facadeBox, partBoxes );
List<AxisAlignedBB> holeStrips = getBoxes( facadeBox, cutOutBox, side.getAxis() );
ILightReader facadeAccess = new FacadeBlockAccess( parentWorld, pos, side, blockState );
AEAxisAlignedBB cutOutBox = getCutOutBox(facadeBox, partBoxes);
List<AxisAlignedBB> holeStrips = getBoxes(facadeBox, cutOutBox, side.getAxis());
ILightReader facadeAccess = new FacadeBlockAccess(parentWorld, pos, side, blockState);
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
IBakedModel model = dispatcher.getModelForState( blockState );
IModelData modelData = model.getModelData( facadeAccess, pos, blockState, EmptyModelData.INSTANCE );
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
IBakedModel model = dispatcher.getModelForState(blockState);
IModelData modelData = model.getModelData(facadeAccess, pos, blockState, EmptyModelData.INSTANCE);
List<BakedQuad> modelQuads = new ArrayList<>();
// If we are forcing transparent facades, fake the render layer, and grab all quads.
if( transparent || layer == null )
{
for( RenderType forcedLayer : RenderType.getBlockRenderTypes() )
{
// Check if the block renders on the layer we want to force.
if( RenderTypeLookup.canRenderInLayer( blockState, forcedLayer ) )
{
// Force the layer and gather quads.
ForgeHooksClient.setRenderLayer( forcedLayer );
modelQuads.addAll( gatherQuads( model, blockState, rand, modelData) );
}
}
List<BakedQuad> modelQuads = new ArrayList<>();
// If we are forcing transparent facades, fake the render layer, and grab all
// quads.
if (transparent || layer == null) {
for (RenderType forcedLayer : RenderType.getBlockRenderTypes()) {
// Check if the block renders on the layer we want to force.
if (RenderTypeLookup.canRenderInLayer(blockState, forcedLayer)) {
// Force the layer and gather quads.
ForgeHooksClient.setRenderLayer(forcedLayer);
modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
}
}
// Reset.
ForgeHooksClient.setRenderLayer( layer );
}
else
{
modelQuads.addAll( gatherQuads( model, blockState, rand, modelData ) );
}
// Reset.
ForgeHooksClient.setRenderLayer(layer);
} else {
modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
}
// 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<Direction, FacadeRenderState> ent : facadeStates.entrySet() )
{
Direction 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<Direction, FacadeRenderState> ent : facadeStates.entrySet()) {
Direction 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( DefaultVertexFormats.BLOCK );
// If this quad has a tint index, setup the tinter.
if( quad.hasTintIndex() )
{
tinter.setTint( blockColors.getColor( 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(DefaultVertexFormats.BLOCK);
// If this quad has a tint index, setup the tinter.
if (quad.hasTintIndex()) {
tinter.setTint(blockColors.getColor(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, Direction side )
{
List<BakedQuad> facadeQuads = new ArrayList<>();
IBakedModel model = Minecraft.getInstance().getItemRenderer().getItemModelWithOverrides( textureItem, null, null );
List<BakedQuad> modelQuads = gatherQuads( model, null, new Random(), EmptyModelData.INSTANCE );
/**
* This is slow, so should be cached.
*
* @return The model.
*/
public List<BakedQuad> buildFacadeItemQuads(ItemStack textureItem, Direction side) {
List<BakedQuad> facadeQuads = new ArrayList<>();
IBakedModel model = Minecraft.getInstance().getItemRenderer().getItemModelWithOverrides(textureItem, null,
null);
List<BakedQuad> modelQuads = gatherQuads(model, null, new Random(), EmptyModelData.INSTANCE);
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( DefaultVertexFormats.BLOCK );
// 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.getInstance().getItemColors().getColor( 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.bake() );
}
}
return facadeQuads;
}
for (BakedQuad quad : modelQuads) {
// Lookup the CachedFormat for this quads format.
CachedFormat format = CachedFormat.lookup(DefaultVertexFormats.BLOCK);
// 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.getInstance().getItemColors().getColor(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.bake());
}
}
return facadeQuads;
}
// Helper to gather all quads from a model into a list.
private static List<BakedQuad> gatherQuads( IBakedModel model, BlockState state, Random rand, IModelData data )
{
List<BakedQuad> modelQuads = new ArrayList<>();
for( Direction face : Direction.values() )
{
modelQuads.addAll( model.getQuads( state, face, rand, data) );
}
modelQuads.addAll( model.getQuads( state, null, rand, data ) );
return modelQuads;
}
// Helper to gather all quads from a model into a list.
private static List<BakedQuad> gatherQuads(IBakedModel model, BlockState state, Random rand, IModelData data) {
List<BakedQuad> modelQuads = new ArrayList<>();
for (Direction face : Direction.values()) {
modelQuads.addAll(model.getQuads(state, face, rand, data));
}
modelQuads.addAll(model.getQuads(state, null, rand, data));
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. " + String.valueOf(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;
}
}