Refactor Quad, BlockPos, and QuadProvider API

Also optimize static models
This commit is contained in:
ah-OOG-ah committed 2024-02-29 21:17:46 -05:00
1 parent da8f700068
commit 346a305f1d
49 files changed
+701 -525

No files matched your search

+4
View File
@@ -2,6 +2,10 @@ plugins {
id("com.gtnewhorizons.gtnhconvention")
}
minecraft {
extraRunJvmArguments.add("-Dangelica.enableTestBlocks=true")
}
tasks.test {
useJUnitPlatform()
testLogging {
@@ -0,0 +1,49 @@
package com.gtnewhorizons.angelica.api;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import net.minecraft.util.MathHelper;
import net.minecraftforge.common.util.ForgeDirection;
import java.math.RoundingMode;
import static com.google.common.math.IntMath.log2;
public interface BlockPos {
int SIZE_BITS_X = 1 + log2(MathHelper.roundUpToPowerOfTwo(30000000), RoundingMode.UNNECESSARY);
int SIZE_BITS_Z = SIZE_BITS_X;
int SIZE_BITS_Y = 64 - SIZE_BITS_X - SIZE_BITS_Z;
long BITS_X = (1L << SIZE_BITS_X) - 1L;
long BITS_Y = (1L << SIZE_BITS_Y) - 1L;
long BITS_Z = (1L << SIZE_BITS_Z) - 1L;
int BIT_SHIFT_Z = SIZE_BITS_Y;
int BIT_SHIFT_X = SIZE_BITS_Y + SIZE_BITS_Z;
int getX();
int getY();
int getZ();
BlockPosImpl offset(ForgeDirection d);
BlockPosImpl down();
BlockPosImpl up();
long asLong();
static long asLong(int x, int y, int z) {
long l = 0L;
l |= ((long) x & BITS_X) << BIT_SHIFT_X;
l |= ((long) y & BITS_Y) << 0;
l |= ((long) z & BITS_Z) << BIT_SHIFT_Z;
return l;
}
public static int unpackLongX(long packedPos) {
return (int)(packedPos << 64 - BIT_SHIFT_X - SIZE_BITS_X >> 64 - SIZE_BITS_X);
}
public static int unpackLongY(long packedPos) {
return (int)(packedPos << 64 - SIZE_BITS_Y >> 64 - SIZE_BITS_Y);
}
public static int unpackLongZ(long packedPos) {
return (int)(packedPos << 64 - BIT_SHIFT_Z - SIZE_BITS_Z >> 64 - SIZE_BITS_Z);
}
}
@@ -0,0 +1,8 @@
package com.gtnewhorizons.angelica.api;
public interface MutableBlockPos extends BlockPos {
MutableBlockPos set(int x, int y, int z);
MutableBlockPos set(long packedPos);
}
@@ -1,14 +1,12 @@
package com.gtnewhorizons.angelica.api;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
import net.minecraft.block.Block;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
public interface QuadProvider {
@@ -23,9 +21,23 @@ public interface QuadProvider {
*/
default int getColor(IBlockAccess world, BlockPos pos, Block block, int meta, Random random) {
final int cin = block.colorMultiplier(world, pos.x, pos.y, pos.z);
final int cin = block.colorMultiplier(world, pos.getX(), pos.getY(), pos.getZ());
return (0xFF << 24) | ((cin & B_MASK) << 16) | (cin & G_MASK) | ((cin & R_MASK) >>> 16);
}
List<Quad> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, ObjectPooler<Quad> quadPool);
/**
* If you need to allocate new quads, set this to true. If true, the quads returned by {@link #getQuads} are
* recycled, and you should not keep a reference to them. Example: stone can return a static list every time, but a
* modded block which adds or removes quads based on location would need dynamic quads.
*/
default boolean isDynamic() {
return false;
}
/**
* Provide quads to render. If you need new quads, they should be obtained with the passed supplier and
* {@link #isDynamic} overridden to return true. If so, all quads in the list are recycled and references to them
* should not be kept.
*/
List<QuadView> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, Supplier<QuadView> quadPool);
}
@@ -0,0 +1,22 @@
package com.gtnewhorizons.angelica.api;
import me.jellysquid.mods.sodium.client.model.quad.ModelQuadViewMutable;
import me.jellysquid.mods.sodium.client.render.pipeline.BlockRenderer;
import net.minecraftforge.common.util.ForgeDirection;
import javax.annotation.Nullable;
public interface QuadView extends ModelQuadViewMutable {
boolean isShade();
boolean isDeleted();
ForgeDirection getFace();
void copyFrom(QuadView src);
void setRaw(int[] data, boolean shade, @Nullable ForgeDirection face, int colorIndex, int flags);
int[] getRawVertexes();
/**
* Present for compatibility with the Tesselator, not recommended for general use.
*/
void setState(int[] rawBuffer, int offset, BlockRenderer.Flags flags, int drawMode, float offsetX, float offsetY, float offsetZ);
}
@@ -1,8 +1,9 @@
package com.gtnewhorizons.angelica.client.renderer;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import com.gtnewhorizons.angelica.compat.mojang.VertexFormat;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import me.jellysquid.mods.sodium.client.model.quad.Quad;
import com.gtnewhorizons.angelica.glsm.stacks.Vector3dStack;
import com.gtnewhorizons.angelica.mixins.interfaces.ITessellatorInstance;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
@@ -39,15 +40,15 @@ public class CapturingTessellator extends Tessellator implements ITessellatorIns
private static final MethodHandle sRawBufferSize;
private static final MethodHandle gRawBufferSize;
private final BlockRenderer.Flags FLAGS = new BlockRenderer.Flags(true, true, true, true);
private final ObjectPooler<Quad> quadBuf = new ObjectPooler<>(Quad::new);
private final List<Quad> collectedQuads = new ObjectArrayList<>();
private final ObjectPooler<QuadView> quadBuf = new ObjectPooler<>(Quad::new);
private final List<QuadView> collectedQuads = new ObjectArrayList<>();
// Any offset we need to the Tesselator's offset!
private final BlockPos offset = new BlockPos();
private final BlockPosImpl offset = new BlockPosImpl();
private final Vector3dStack storedTranslation = new Vector3dStack();
public void setOffset(BlockPos pos) {
public void setOffset(BlockPosImpl pos) {
this.offset.set(pos);
}
public void resetOffset() {
@@ -93,10 +94,10 @@ public class CapturingTessellator extends Tessellator implements ITessellatorIns
for(int quadI = 0; quadI < this.vertexCount / verticesPerPrimitive; quadI++) {
final Quad quad = quadBuf.getInstance();
final QuadView quad = quadBuf.getInstance();
quad.setState(this.rawBuffer, quadI * (verticesPerPrimitive * 8), FLAGS, this.drawMode, -offset.x, -offset.y, -offset.z);
if(quad.deleted) {
if(quad.isDeleted()) {
quadBuf.releaseInstance(quad);
} else {
this.collectedQuads.add(quad);
@@ -115,7 +116,7 @@ public class CapturingTessellator extends Tessellator implements ITessellatorIns
}
public List<Quad> getQuads() {
public List<QuadView> getQuads() {
return collectedQuads;
}
@@ -127,7 +128,7 @@ public class CapturingTessellator extends Tessellator implements ITessellatorIns
this.collectedQuads.clear();
}
public static ByteBuffer quadsToBuffer(List<Quad> quads, VertexFormat format) {
public static ByteBuffer quadsToBuffer(List<QuadView> quads, VertexFormat format) {
if(!format.canWriteQuads()) {
throw new IllegalStateException("Vertex format has no quad writer: " + format);
}
@@ -1,12 +1,11 @@
package com.gtnewhorizons.angelica.common;
import com.gtnewhorizons.angelica.api.BlockPos;
import com.gtnewhorizons.angelica.api.QuadProvider;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.models.json.JsonModel;
import com.gtnewhorizons.angelica.models.json.Loader;
import com.gtnewhorizons.angelica.models.json.Variant;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
import it.unimi.dsi.fastutil.objects.ObjectImmutableList;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
@@ -19,6 +18,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
public class BlockTest extends Block implements QuadProvider {
@@ -48,7 +48,7 @@ public class BlockTest extends Block implements QuadProvider {
false
),
};
private static final List<Quad> EMPTY = ObjectImmutableList.of();
private static final List<QuadView> EMPTY = ObjectImmutableList.of();
private static final JsonModel[] model = new JsonModel[4];
public BlockTest() {
@@ -78,7 +78,7 @@ public class BlockTest extends Block implements QuadProvider {
}
@Override
public List<Quad> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, ObjectPooler<Quad> quadPool) {
public List<QuadView> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, Supplier<QuadView> quadPool) {
if (meta < 2 || meta > 5) meta = 2;
@@ -1,102 +0,0 @@
package com.gtnewhorizons.angelica.compat.mojang;
import net.minecraft.util.MathHelper;
import net.minecraft.world.ChunkPosition;
import net.minecraftforge.common.util.ForgeDirection;
import org.joml.Vector3i;
import java.math.RoundingMode;
import static com.google.common.math.IntMath.log2;
// Should we keep this?
public class BlockPos extends Vector3i {
private static final int SIZE_BITS_X = 1 + log2(MathHelper.roundUpToPowerOfTwo(30000000), RoundingMode.UNNECESSARY);
private static final int SIZE_BITS_Z = SIZE_BITS_X;
private static final int SIZE_BITS_Y = 64 - SIZE_BITS_X - SIZE_BITS_Z;
private static final long BITS_X = (1L << SIZE_BITS_X) - 1L;
private static final long BITS_Y = (1L << SIZE_BITS_Y) - 1L;
private static final long BITS_Z = (1L << SIZE_BITS_Z) - 1L;
private static final int BIT_SHIFT_Z = SIZE_BITS_Y;
private static final int BIT_SHIFT_X = SIZE_BITS_Y + SIZE_BITS_Z;
public BlockPos() {
super();
}
public BlockPos(int x, int y, int z) {
super(x, y, z);
}
public BlockPos(ChunkPosition chunkPosition) {
super(chunkPosition.chunkPosX, chunkPosition.chunkPosY, chunkPosition.chunkPosZ);
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public int getZ() {
return this.z;
}
public BlockPos set(int x, int y, int z) {
super.set(x, y, z);
return this;
}
/**
* This method does NOT mutate the BlockPos
*/
public BlockPos offset(ForgeDirection d) {
return new BlockPos(this.x + d.offsetX, this.y + d.offsetY, this.z + d.offsetZ);
}
/**
* This method does NOT mutate the BlockPos
*/
public BlockPos down() {
return offset(ForgeDirection.DOWN);
}
/**
* This method does NOT mutate the BlockPos
*/
public BlockPos up() {
return offset(ForgeDirection.UP);
}
public long asLong() {
return asLong(this.x, this.y, this.z);
}
public static long asLong(int x, int y, int z) {
long l = 0L;
l |= ((long)x & BITS_X) << BIT_SHIFT_X;
l |= ((long)y & BITS_Y) << 0;
l |= ((long)z & BITS_Z) << BIT_SHIFT_Z;
return l;
}
public BlockPos set(long packedPos) {
return set(unpackLongX(packedPos), unpackLongY(packedPos), unpackLongZ(packedPos));
}
public static int unpackLongX(long packedPos) {
return (int)(packedPos << 64 - BIT_SHIFT_X - SIZE_BITS_X >> 64 - SIZE_BITS_X);
}
public static int unpackLongY(long packedPos) {
return (int)(packedPos << 64 - SIZE_BITS_Y >> 64 - SIZE_BITS_Y);
}
public static int unpackLongZ(long packedPos) {
return (int)(packedPos << 64 - BIT_SHIFT_Z - SIZE_BITS_Z >> 64 - SIZE_BITS_Z);
}
public static class Mutable extends BlockPos {
}
}
@@ -0,0 +1,70 @@
package com.gtnewhorizons.angelica.compat.mojang;
import com.gtnewhorizons.angelica.api.BlockPos;
import com.gtnewhorizons.angelica.api.MutableBlockPos;
import net.minecraft.world.ChunkPosition;
import net.minecraftforge.common.util.ForgeDirection;
import org.joml.Vector3i;
import static com.gtnewhorizons.angelica.api.BlockPos.unpackLongX;
import static com.gtnewhorizons.angelica.api.BlockPos.unpackLongY;
import static com.gtnewhorizons.angelica.api.BlockPos.unpackLongZ;
// Should we keep this?
public class BlockPosImpl extends Vector3i implements MutableBlockPos {
public BlockPosImpl() {
super();
}
public BlockPosImpl(int x, int y, int z) {
super(x, y, z);
}
public BlockPosImpl(ChunkPosition chunkPosition) {
super(chunkPosition.chunkPosX, chunkPosition.chunkPosY, chunkPosition.chunkPosZ);
}
@Override
public int getX() {
return this.x;
}
@Override
public int getY() {
return this.y;
}
@Override
public int getZ() {
return this.z;
}
@Override
public BlockPosImpl offset(ForgeDirection d) {
return new BlockPosImpl(this.x + d.offsetX, this.y + d.offsetY, this.z + d.offsetZ);
}
@Override
public BlockPosImpl down() {
return offset(ForgeDirection.DOWN);
}
@Override
public BlockPosImpl up() {
return offset(ForgeDirection.UP);
}
@Override
public long asLong() {
return BlockPos.asLong(this.x, this.y, this.z);
}
@Override
public BlockPosImpl set(int x, int y, int z) {
super.set(x, y, z);
return this;
}
@Override
public BlockPosImpl set(long packedPos) {
return set(unpackLongX(packedPos), unpackLongY(packedPos), unpackLongZ(packedPos));
}
}
@@ -13,7 +13,7 @@ import org.joml.Vector4f;
@Getter
public class Camera {
final Vector3d pos = new Vector3d();
final BlockPos.Mutable blockPos = new BlockPos.Mutable();
final BlockPosImpl blockPos = new BlockPosImpl();
float pitch;
float yaw;
EntityLivingBase entity;
@@ -36,12 +36,12 @@ public class ChunkOcclusionDataBuilder {
}
private int openCount = 4096;
public void markClosed(BlockPos pos) {
public void markClosed(BlockPosImpl pos) {
this.closed.set(pack(pos), true);
--this.openCount;
}
private static int pack(BlockPos pos) {
private static int pack(BlockPosImpl pos) {
return pack(pos.getX() & 15, pos.getY() & 15, pos.getZ() & 15);
}
@@ -12,7 +12,7 @@ public class ChunkPos {
this.z = z;
}
public ChunkPos(BlockPos pos) {
public ChunkPos(BlockPosImpl pos) {
this.x = pos.getX() >> 4;
this.z = pos.getZ() >> 4;
}
@@ -19,7 +19,7 @@ public class ChunkSectionPos extends Vector3i {
return new ChunkSectionPos(x, y, z);
}
public static ChunkSectionPos from(BlockPos pos) {
public static ChunkSectionPos from(BlockPosImpl pos) {
return new ChunkSectionPos(getSectionCoord(pos.getX()), getSectionCoord(pos.getY()), getSectionCoord(pos.getZ()));
}
@@ -1,8 +1,8 @@
package com.gtnewhorizons.angelica.compat.mojang;
import com.google.common.collect.ImmutableList;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.compat.nd.IWriteQuads;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import lombok.Getter;
@@ -79,7 +79,7 @@ public class VertexFormat {
return quadWriter != null;
}
public void writeQuad(Quad quad, ByteBuffer byteBuffer) {
public void writeQuad(QuadView quad, ByteBuffer byteBuffer) {
if(quadWriter == null) {
throw new IllegalStateException("No quad writer set");
}
@@ -1,7 +1,9 @@
package com.gtnewhorizons.angelica.compat.nd;
import com.gtnewhorizons.angelica.api.QuadView;
import java.nio.ByteBuffer;
public interface IWriteQuads {
void writeQuad(Quad quad, ByteBuffer buf);
void writeQuad(QuadView quad, ByteBuffer buf);
}
@@ -1,218 +0,0 @@
package com.gtnewhorizons.angelica.compat.nd;
import lombok.Getter;
import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView;
import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing;
import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFlags;
import me.jellysquid.mods.sodium.client.render.pipeline.BlockRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraftforge.common.util.ForgeDirection;
import org.joml.Vector3f;
import org.lwjgl.opengl.GL11;
import javax.annotation.Nullable;
import java.util.Locale;
public class Quad implements ModelQuadView {
// Adapted from Neodymium
private final static int DEFAULT_BRIGHTNESS = 15 << 20 | 15 << 4;
private final static int DEFAULT_COLOR = 0xFFFFFFFF;
public float[] xs = new float[4];
public float[] ys = new float[4];
public float[] zs = new float[4];
public float[] us = new float[4];
public float[] vs = new float[4];
public int[] cs = new int[4];
public int[] ns = new int[4];
public int[] bs = new int[4];
public boolean deleted;
private final Vector3f vectorA = new Vector3f(), vectorB = new Vector3f(), vectorC = new Vector3f();
@Getter
private boolean shade;
private int cachedFlags;
@Getter
private ForgeDirection face;
private int colorIndex = -1;
public int[] getColors() {
return this.cs;
}
/** Returns the face, forced to take one of 6 directions to mirror the behavior of baked quads in 1.16.5. */
@Override
public ForgeDirection getLightFace() {
return this.face != ForgeDirection.UNKNOWN ? this.face : ForgeDirection.UP;
}
@Override
public float getX(int idx) {
return xs[idx];
}
@Override
public float getY(int idx) {
return ys[idx];
}
@Override
public float getZ(int idx) {
return zs[idx];
}
@Override
public int getColor(int idx) {
return cs[idx];
}
@Override
public float getTexU(int idx) {
return us[idx];
}
@Override
public float getTexV(int idx) {
return vs[idx];
}
@Override
public int getFlags() {
return this.cachedFlags;
}
@Override
public int getLight(int idx) {
return bs[idx];
}
@Override
public int getNormal(int idx) {
return ns[idx];
}
@Override
public int getColorIndex() {
return colorIndex;
}
@Override
public TextureAtlasSprite rubidium$getSprite() {
return null;
}
public void copyFrom(Quad quad) {
System.arraycopy(quad.xs, 0, this.xs, 0, 4);
System.arraycopy(quad.ys, 0, this.ys, 0, 4);
System.arraycopy(quad.zs, 0, this.zs, 0, 4);
System.arraycopy(quad.us, 0, this.us, 0, 4);
System.arraycopy(quad.vs, 0, this.vs, 0, 4);
System.arraycopy(quad.cs, 0, this.cs, 0, 4);
System.arraycopy(quad.ns, 0, this.ns, 0, 4);
System.arraycopy(quad.bs, 0, this.bs, 0, 4);
this.deleted = quad.deleted;
this.shade = quad.shade;
this.cachedFlags = quad.cachedFlags;
this.face = quad.face;
this.colorIndex = quad.colorIndex;
}
public void setRaw(int[] data, boolean shade, @Nullable ForgeDirection face, int colorIndex, int flags) {
int i = 0;
for(int vi = 0; vi < 4; vi++) {
xs[vi] = Float.intBitsToFloat(data[i + 0]);
ys[vi] = Float.intBitsToFloat(data[i + 1]);
zs[vi] = Float.intBitsToFloat(data[i + 2]);
us[vi] = Float.intBitsToFloat(data[i + 3]);
vs[vi] = Float.intBitsToFloat(data[i + 4]);
cs[vi] = data[i + 5];
ns[vi] = data[i + 6];
bs[vi] = data[i + 7];
i += 8;
}
this.shade = shade;
this.deleted = false;
this.face = face;
this.colorIndex = colorIndex;
this.cachedFlags = flags;
}
private void read(int[] rawBuffer, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, BlockRenderer.Flags flags) {
final int vertices = drawMode == GL11.GL_TRIANGLES ? 3 : 4;
int i = offset;
for(int vi = 0; vi < vertices; vi++) {
xs[vi] = Float.intBitsToFloat(rawBuffer[i + 0]) + offsetX;
ys[vi] = Float.intBitsToFloat(rawBuffer[i + 1]) + offsetY;
zs[vi] = Float.intBitsToFloat(rawBuffer[i + 2]) + offsetZ;
us[vi] = Float.intBitsToFloat(rawBuffer[i + 3]);
vs[vi] = Float.intBitsToFloat(rawBuffer[i + 4]);
cs[vi] = flags.hasColor ? rawBuffer[i + 5] : DEFAULT_COLOR;
ns[vi] = flags.hasNormals ? rawBuffer[i + 6] : 0;
bs[vi] = flags.hasBrightness ? rawBuffer[i + 7] : DEFAULT_BRIGHTNESS;
i += 8;
}
// sus
this.shade = flags.hasBrightness;
if(vertices == 3) {
// Quadrangulate!
xs[3] = xs[2];
ys[3] = ys[2];
zs[3] = zs[2];
us[3] = us[2];
vs[3] = vs[2];
bs[3] = bs[2];
cs[3] = cs[2];
ns[3] = ns[2];
}
}
public void setState(int[] rawBuffer, int offset, BlockRenderer.Flags flags, int drawMode, float offsetX, float offsetY, float offsetZ) {
deleted = false;
read(rawBuffer, offset, offsetX, offsetY, offsetZ, drawMode, flags);
if(xs[0] == xs[1] && xs[1] == xs[2] && xs[2] == xs[3] && ys[0] == ys[1] && ys[1] == ys[2] && ys[2] == ys[3]) {
// ignore empty quads (e.g. alpha pass of EnderIO item conduits)
deleted = true;
return;
}
vectorA.set(xs[1] - xs[0], ys[1] - ys[0], zs[1] - zs[0]);
vectorB.set(xs[2] - xs[1], ys[2] - ys[1], zs[2] - zs[1]);
vectorA.cross(vectorB, vectorC);
this.face = ModelQuadFacing.toDirection(ModelQuadFacing.fromVector(vectorC));
this.cachedFlags = ModelQuadFlags.getQuadFlags(this);
}
public static boolean isValid(Quad q) {
return q != null && !q.deleted;
}
@Override
public String toString() {
return String.format(Locale.ENGLISH, "%s[(%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f)]", deleted ? "XXX " : "", xs[0], ys[0], zs[0], xs[1], ys[1], zs[1], xs[2], ys[2], zs[2], xs[3], ys[3], zs[3]);
}
}
@@ -1,7 +1,7 @@
package com.gtnewhorizons.angelica.compat.nd.writers;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.compat.nd.IWriteQuads;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import java.nio.ByteBuffer;
@@ -17,7 +17,7 @@ public class ItemVBOQuadWriter implements IWriteQuads {
this.direct = direct;
}
@Override
public void writeQuad(Quad quad, ByteBuffer buf) {
public void writeQuad(QuadView quad, ByteBuffer buf) {
if(direct) {
writeQuadDirect(quad, buf);
} else {
@@ -25,11 +25,11 @@ public class ItemVBOQuadWriter implements IWriteQuads {
}
}
protected void writeQuadDirect(Quad quad, ByteBuffer buf) {
protected void writeQuadDirect(QuadView quad, ByteBuffer buf) {
throw new UnsupportedOperationException("Direct mode not supported yet");
}
protected void writeQuadIndirect(Quad quad, ByteBuffer buf) {
protected void writeQuadIndirect(QuadView quad, ByteBuffer buf) {
for(int idx = 0; idx < 4; ++idx) {
// Position
buf.putFloat(quad.getX(idx));
@@ -1,7 +1,7 @@
package com.gtnewhorizons.angelica.compat.nd.writers;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.compat.nd.IWriteQuads;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import java.nio.ByteBuffer;
@@ -17,7 +17,7 @@ public class PositionColorTextureQuadWriter implements IWriteQuads {
this.direct = direct;
}
@Override
public void writeQuad(Quad quad, ByteBuffer buf) {
public void writeQuad(QuadView quad, ByteBuffer buf) {
if(direct) {
writeQuadDirect(quad, buf);
} else {
@@ -25,11 +25,11 @@ public class PositionColorTextureQuadWriter implements IWriteQuads {
}
}
protected void writeQuadDirect(Quad quad, ByteBuffer buf) {
protected void writeQuadDirect(QuadView quad, ByteBuffer buf) {
throw new UnsupportedOperationException("Direct mode not supported yet");
}
protected void writeQuadIndirect(Quad quad, ByteBuffer buf) {
protected void writeQuadIndirect(QuadView quad, ByteBuffer buf) {
for(int idx = 0; idx < 4; ++idx) {
// Position
buf.putFloat(quad.getX(idx));
@@ -1,7 +1,7 @@
package com.gtnewhorizons.angelica.compat.nd.writers;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.compat.nd.IWriteQuads;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import java.nio.ByteBuffer;
@@ -17,7 +17,7 @@ public class PositionQuadWriter implements IWriteQuads {
this.direct = direct;
}
@Override
public void writeQuad(Quad quad, ByteBuffer buf) {
public void writeQuad(QuadView quad, ByteBuffer buf) {
if(direct) {
writeQuadDirect(quad, buf);
} else {
@@ -25,11 +25,11 @@ public class PositionQuadWriter implements IWriteQuads {
}
}
protected void writeQuadDirect(Quad quad, ByteBuffer buf) {
protected void writeQuadDirect(QuadView quad, ByteBuffer buf) {
throw new UnsupportedOperationException("Direct mode not supported yet");
}
protected void writeQuadIndirect(Quad quad, ByteBuffer buf) {
protected void writeQuadIndirect(QuadView quad, ByteBuffer buf) {
for(int idx = 0; idx < 4; ++idx) {
// Position
buf.putFloat(quad.getX(idx));
@@ -1,7 +1,7 @@
package com.gtnewhorizons.angelica.compat.nd.writers;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.compat.nd.IWriteQuads;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import java.nio.ByteBuffer;
@@ -17,7 +17,7 @@ public class PositionTextureColorQuadWriter implements IWriteQuads {
this.direct = direct;
}
@Override
public void writeQuad(Quad quad, ByteBuffer buf) {
public void writeQuad(QuadView quad, ByteBuffer buf) {
if(direct) {
writeQuadDirect(quad, buf);
} else {
@@ -25,11 +25,11 @@ public class PositionTextureColorQuadWriter implements IWriteQuads {
}
}
protected void writeQuadDirect(Quad quad, ByteBuffer buf) {
protected void writeQuadDirect(QuadView quad, ByteBuffer buf) {
throw new UnsupportedOperationException("Direct mode not supported yet");
}
protected void writeQuadIndirect(Quad quad, ByteBuffer buf) {
protected void writeQuadIndirect(QuadView quad, ByteBuffer buf) {
for(int idx = 0; idx < 4; ++idx) {
// Position
buf.putFloat(quad.getX(idx));
@@ -1,7 +1,7 @@
package com.gtnewhorizons.angelica.compat.nd.writers;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.compat.nd.IWriteQuads;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import java.nio.ByteBuffer;
@@ -17,7 +17,7 @@ public class PositionTextureQuadWriter implements IWriteQuads {
this.direct = direct;
}
@Override
public void writeQuad(Quad quad, ByteBuffer buf) {
public void writeQuad(QuadView quad, ByteBuffer buf) {
if(direct) {
writeQuadDirect(quad, buf);
} else {
@@ -25,11 +25,11 @@ public class PositionTextureQuadWriter implements IWriteQuads {
}
}
protected void writeQuadDirect(Quad quad, ByteBuffer buf) {
protected void writeQuadDirect(QuadView quad, ByteBuffer buf) {
throw new UnsupportedOperationException("Direct mode not supported yet");
}
protected void writeQuadIndirect(Quad quad, ByteBuffer buf) {
protected void writeQuadIndirect(QuadView quad, ByteBuffer buf) {
for(int idx = 0; idx < 4; ++idx) {
// Position
buf.putFloat(quad.getX(idx));
@@ -1,16 +1,15 @@
package com.gtnewhorizons.angelica.glsm;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.client.renderer.CapturingTessellator;
import com.gtnewhorizons.angelica.compat.mojang.VertexBuffer;
import com.gtnewhorizons.angelica.compat.mojang.VertexFormat;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import net.minecraft.client.renderer.Tessellator;
import org.lwjgl.opengl.GL11;
import java.nio.ByteBuffer;
import java.util.List;
import org.lwjgl.opengl.GL11;
@SuppressWarnings("unused")
public class TessellatorManager {
private static final ThreadLocal<CapturingTessellator> capturingTessellator = ThreadLocal.withInitial(CapturingTessellator::new);
@@ -51,7 +50,7 @@ public class TessellatorManager {
* Stop the CapturingTessellator and return the pooled quads. The quads are valid until clearQuads() is
* called on the CapturingTesselator, which must be done before starting capturing again.
*/
public static List<Quad> stopCapturingToPooledQuads() {
public static List<QuadView> stopCapturingToPooledQuads() {
if(!currentlyCapturing.get()) throw new IllegalStateException("Tried to stop capturing when not capturing!");
currentlyCapturing.set(false);
final CapturingTessellator tess = capturingTessellator.get();
@@ -59,7 +58,7 @@ public class TessellatorManager {
// Be sure we got all the quads
if(tess.isDrawing) tess.draw();
final List<Quad> quads = tess.getQuads();
final List<QuadView> quads = tess.getQuads();
tess.discard();
tess.restoreTranslation();
@@ -1,25 +1,28 @@
package com.gtnewhorizons.angelica.mixins.early.angelica.models;
import com.gtnewhorizons.angelica.api.BlockPos;
import com.gtnewhorizons.angelica.api.QuadProvider;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
import com.gtnewhorizons.angelica.api.QuadView;
import it.unimi.dsi.fastutil.objects.ObjectImmutableList;
import net.minecraft.block.Block;
import net.minecraft.block.BlockAir;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
@Mixin(BlockAir.class)
public abstract class MixinBlockAir implements QuadProvider {
private static List<Quad> quads = ObjectImmutableList.of();
@Unique
private static final List<QuadView> angelica$EMPTY = ObjectImmutableList.of();
public List<Quad> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, ObjectPooler<Quad> quadPool) {
return quads;
@Override
public List<QuadView> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, Supplier<QuadView> quadPool) {
return angelica$EMPTY;
}
}
@@ -1,9 +1,8 @@
package com.gtnewhorizons.angelica.mixins.early.angelica.models;
import com.gtnewhorizons.angelica.api.BlockPos;
import com.gtnewhorizons.angelica.api.QuadProvider;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
import com.gtnewhorizons.angelica.api.QuadView;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLeaves;
import net.minecraft.block.material.Material;
@@ -13,13 +12,20 @@ import org.spongepowered.asm.mixin.Mixin;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
import static com.gtnewhorizons.angelica.models.CubeModel.INSTANCE;
@Mixin(BlockLeaves.class)
public abstract class MixinBlockLeaves extends Block implements QuadProvider {
public List<Quad> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, ObjectPooler<Quad> quadPool) {
@Override
public boolean isDynamic() {
return true;
}
@Override
public List<QuadView> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, Supplier<QuadView> quadPool) {
return INSTANCE.get().getQuads(world, pos, block, meta, dir, random, color, quadPool);
}
@@ -1,10 +1,9 @@
package com.gtnewhorizons.angelica.mixins.early.angelica.models;
import com.gtnewhorizons.angelica.api.BlockPos;
import com.gtnewhorizons.angelica.api.QuadProvider;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.models.VanillaModels;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
import net.minecraft.block.Block;
import net.minecraft.block.BlockStone;
import net.minecraft.world.IBlockAccess;
@@ -13,12 +12,13 @@ import org.spongepowered.asm.mixin.Mixin;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
@Mixin(BlockStone.class)
public abstract class MixinBlockStone implements QuadProvider {
// TODO: Use modern model API
public List<Quad> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, ObjectPooler<Quad> quadPool) {
@Override
public List<QuadView> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, Supplier<QuadView> quadPool) {
return VanillaModels.stoneModel.getQuads(world, pos, block, meta, dir, random, color, quadPool);
}
}
@@ -1,10 +1,9 @@
package com.gtnewhorizons.angelica.mixins.early.angelica.models;
import com.gtnewhorizons.angelica.api.BlockPos;
import com.gtnewhorizons.angelica.api.QuadProvider;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.models.CubeModel;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
import net.minecraft.block.Block;
import net.minecraft.block.BlockWorkbench;
import net.minecraft.world.IBlockAccess;
@@ -13,12 +12,13 @@ import org.spongepowered.asm.mixin.Mixin;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
@Mixin(BlockWorkbench.class)
public class MixinBlockWorkbench implements QuadProvider {
// TODO: Use modern model API
public List<Quad> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, ObjectPooler<Quad> quadPool) {
@Override
public List<QuadView> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, Supplier<QuadView> quadPool) {
return CubeModel.INSTANCE.get().getQuads(world, pos, block, meta, dir, random, color, quadPool);
}
}
@@ -1,9 +1,8 @@
package com.gtnewhorizons.angelica.models;
import com.gtnewhorizons.angelica.api.BlockPos;
import com.gtnewhorizons.angelica.api.QuadProvider;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
import com.gtnewhorizons.angelica.api.QuadView;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectImmutableList;
import net.minecraft.block.Block;
@@ -13,6 +12,7 @@ import net.minecraftforge.common.util.ForgeDirection;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
public class CubeModel implements QuadProvider {
@@ -23,8 +23,8 @@ public class CubeModel implements QuadProvider {
public static final ThreadLocal<CubeModel> INSTANCE = ThreadLocal.withInitial(CubeModel::new);
private final NdQuadBuilder builder = new NdQuadBuilder();
private static final List<Quad> EMPTY = ObjectImmutableList.of();
private final List<Quad> ONE = new ObjectArrayList<>(1);
private static final List<QuadView> EMPTY = ObjectImmutableList.of();
private final List<QuadView> ONE = new ObjectArrayList<>(1);
public CubeModel() {
@@ -32,7 +32,12 @@ public class CubeModel implements QuadProvider {
}
@Override
public List<Quad> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, ObjectPooler<Quad> quadPool) {
public boolean isDynamic() {
return true;
}
@Override
public List<QuadView> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, Supplier<QuadView> quadPool) {
if (dir == ForgeDirection.UNKNOWN)
return EMPTY;
@@ -43,7 +48,7 @@ public class CubeModel implements QuadProvider {
this.builder.color(color, color, color, color);
ONE.set(0, this.builder.build(quadPool.getInstance()));
ONE.set(0, this.builder.build(quadPool.get()));
return ONE;
}
}
@@ -1,7 +1,7 @@
package com.gtnewhorizons.angelica.models;
import com.gtnewhorizons.angelica.compat.mojang.Axis;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import me.jellysquid.mods.sodium.client.model.quad.Quad;
import net.minecraftforge.common.util.ForgeDirection;
import org.joml.Vector3f;
@@ -1,6 +1,7 @@
package com.gtnewhorizons.angelica.models;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import com.gtnewhorizons.angelica.api.QuadView;
import me.jellysquid.mods.sodium.client.model.quad.Quad;
import lombok.Getter;
import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView;
import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFlags;
@@ -16,18 +17,6 @@ import java.util.Arrays;
public class NdQuadBuilder implements ModelQuadView {
// x, y, z, u, v, color, normal, lightmap
public static final int INTS_PER_VERTEX = 8;
public static final int QUAD_STRIDE = INTS_PER_VERTEX * 4;
public static final int X_INDEX = 0;
public static final int Y_INDEX = 1;
public static final int Z_INDEX = 2;
public static final int U_INDEX = 3;
public static final int V_INDEX = 4;
public static final int COLOR_INDEX = 5;
public static final int NORMAL_INDEX = 6;
public static final int LIGHTMAP_INDEX = 7;
/**
* Causes texture to appear with no rotation.
* Pass in bakeFlags parameter to {@link #spriteBake(IIcon, int)}.
@@ -99,7 +88,7 @@ public class NdQuadBuilder implements ModelQuadView {
private ForgeDirection lightFace = ForgeDirection.UP;
// It's called a header, but because I'm lazy it's at the end
// The header is an int with flags -------- -------- -------- -GGGNNNN, then an int for the normal
private final int[] data = new int[QUAD_STRIDE];
private final int[] data = new int[Quad.QUAD_STRIDE];
private int geometryFlags = 0;
private boolean isGeometryInvalid = true;
private int tag = 0;
@@ -111,7 +100,7 @@ public class NdQuadBuilder implements ModelQuadView {
/**
* Dumps to {@param out} and returns it.
*/
public Quad build(Quad out) {
public QuadView build(QuadView out) {
// FRAPI does this late, but we need to do it before baking to Nd quads
this.computeGeometry();
@@ -137,7 +126,7 @@ public class NdQuadBuilder implements ModelQuadView {
* Set vertex color in ARGB format (0xAARRGGBB).
*/
public void color(int vertexIndex, int color) {
data[vertexIndex * INTS_PER_VERTEX + COLOR_INDEX] = color;
data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.COLOR_INDEX] = color;
}
/**
@@ -247,18 +236,18 @@ public class NdQuadBuilder implements ModelQuadView {
*/
public void pos(int vertexIndex, float x, float y, float z) {
data[vertexIndex * INTS_PER_VERTEX + X_INDEX] = Float.floatToRawIntBits(x);
data[vertexIndex * INTS_PER_VERTEX + Y_INDEX] = Float.floatToRawIntBits(y);
data[vertexIndex * INTS_PER_VERTEX + Z_INDEX] = Float.floatToRawIntBits(z);
data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.X_INDEX] = Float.floatToRawIntBits(x);
data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.Y_INDEX] = Float.floatToRawIntBits(y);
data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.Z_INDEX] = Float.floatToRawIntBits(z);
isGeometryInvalid = true;
}
public Vector3f pos(int vertexIndex) {
return new Vector3f(
Float.intBitsToFloat(data[vertexIndex * INTS_PER_VERTEX + X_INDEX]),
Float.intBitsToFloat(data[vertexIndex * INTS_PER_VERTEX + Y_INDEX]),
Float.intBitsToFloat(data[vertexIndex * INTS_PER_VERTEX + Z_INDEX])
Float.intBitsToFloat(data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.X_INDEX]),
Float.intBitsToFloat(data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.Y_INDEX]),
Float.intBitsToFloat(data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.Z_INDEX])
);
}
@@ -266,7 +255,7 @@ public class NdQuadBuilder implements ModelQuadView {
* Convenience: access x, y, z by index 0-2.
*/
float posByIndex(int vertexIndex, int coordinateIndex) {
return Float.intBitsToFloat(data[vertexIndex * INTS_PER_VERTEX + X_INDEX + coordinateIndex]);
return Float.intBitsToFloat(data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.X_INDEX + coordinateIndex]);
}
/**
@@ -365,48 +354,48 @@ public class NdQuadBuilder implements ModelQuadView {
*/
public void uv(int vertexIndex, float u, float v) {
data[vertexIndex * INTS_PER_VERTEX + U_INDEX] = Float.floatToRawIntBits(u);
data[vertexIndex * INTS_PER_VERTEX + V_INDEX] = Float.floatToRawIntBits(v);
data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.U_INDEX] = Float.floatToRawIntBits(u);
data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.V_INDEX] = Float.floatToRawIntBits(v);
}
@Override
public float getX(int vertexIndex) {
return Float.intBitsToFloat(data[vertexIndex * INTS_PER_VERTEX + X_INDEX]);
return Float.intBitsToFloat(data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.X_INDEX]);
}
@Override
public float getY(int vertexIndex) {
return Float.intBitsToFloat(data[vertexIndex * INTS_PER_VERTEX + Y_INDEX]);
return Float.intBitsToFloat(data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.Y_INDEX]);
}
@Override
public float getZ(int vertexIndex) {
return Float.intBitsToFloat(data[vertexIndex * INTS_PER_VERTEX + Z_INDEX]);
return Float.intBitsToFloat(data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.Z_INDEX]);
}
@Override
public float getTexU(int vertexIndex) {
return Float.intBitsToFloat(data[vertexIndex * INTS_PER_VERTEX + U_INDEX]);
return Float.intBitsToFloat(data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.U_INDEX]);
}
@Override
public float getTexV(int vertexIndex) {
return Float.intBitsToFloat(data[vertexIndex * INTS_PER_VERTEX + V_INDEX]);
return Float.intBitsToFloat(data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.V_INDEX]);
}
@Override
public int getColor(int vertexIndex) {
return this.data[vertexIndex * INTS_PER_VERTEX + COLOR_INDEX];
return this.data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.COLOR_INDEX];
}
@Override
public int getNormal(int vertexIndex) {
return this.data[vertexIndex * INTS_PER_VERTEX + NORMAL_INDEX];
return this.data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.NORMAL_INDEX];
}
@Override
public int getLight(int vertexIndex) {
return this.data[vertexIndex * INTS_PER_VERTEX + LIGHTMAP_INDEX];
return this.data[vertexIndex * Quad.INTS_PER_VERTEX + Quad.LIGHTMAP_INDEX];
}
@Override
@@ -6,13 +6,13 @@ import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.gtnewhorizons.angelica.api.BlockPos;
import com.gtnewhorizons.angelica.api.QuadProvider;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.compat.mojang.Axis;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import me.jellysquid.mods.sodium.client.model.quad.Quad;
import com.gtnewhorizons.angelica.models.NdQuadBuilder;
import com.gtnewhorizons.angelica.utils.DirUtil;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
import it.unimi.dsi.fastutil.Function;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
@@ -32,6 +32,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Supplier;
import static com.gtnewhorizons.angelica.utils.JsonUtil.*;
import static me.jellysquid.mods.sodium.common.util.DirectionUtil.ALL_DIRECTIONS;
@@ -47,9 +48,9 @@ public class JsonModel implements QuadProvider {
private final Map<ModelDisplay.Position, ModelDisplay> display;
private final Map<String, String> textures;
private List<ModelElement> elements;
private List<Quad> allQuadStore = new ObjectArrayList<>();
private final Map<ForgeDirection, List<Quad>> sidedQuadStore = new Object2ObjectOpenHashMap<>();
private static final List<Quad> EMPTY = ObjectImmutableList.of();
private List<QuadView> allQuadStore = new ObjectArrayList<>();
private final Map<ForgeDirection, List<QuadView>> sidedQuadStore = new Object2ObjectOpenHashMap<>();
private static final List<QuadView> EMPTY = ObjectImmutableList.of();
JsonModel(@Nullable ResourceLocation parentId, boolean useAO, Map<ModelDisplay.Position, ModelDisplay> display, Map<String, String> textures, List<ModelElement> elements) {
this.parentId = parentId;
@@ -136,7 +137,7 @@ public class JsonModel implements QuadProvider {
builder.mat.setAO(this.useAO);
// Bake and add it
final Quad q = builder.build(new Quad());
final QuadView q = builder.build(new Quad());
this.allQuadStore.add(q);
this.sidedQuadStore.computeIfAbsent(f.getCullFace(),
o -> new ObjectArrayList<>()).add(q);
@@ -147,7 +148,7 @@ public class JsonModel implements QuadProvider {
this.allQuadStore = new ObjectImmutableList<>(this.allQuadStore);
for (ForgeDirection f : ALL_DIRECTIONS) {
List<Quad> l = this.sidedQuadStore.computeIfAbsent(f, o -> EMPTY);
List<QuadView> l = this.sidedQuadStore.computeIfAbsent(f, o -> EMPTY);
if (!l.isEmpty())
this.sidedQuadStore.put(f, new ObjectImmutableList<>(l));
}
@@ -158,19 +159,9 @@ public class JsonModel implements QuadProvider {
}
@Override
public List<Quad> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, ObjectPooler<Quad> quadPool) {
public List<QuadView> getQuads(IBlockAccess world, BlockPos pos, Block block, int meta, ForgeDirection dir, Random random, int color, Supplier<QuadView> quadPool) {
final List<Quad> src = this.sidedQuadStore.getOrDefault(dir, EMPTY);
final List<Quad> ret = new ObjectArrayList<>(src.size());
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < src.size(); ++i) {
final Quad q = quadPool.getInstance();
q.copyFrom(src.get(i));
ret.add(q);
}
return ret;
return this.sidedQuadStore.getOrDefault(dir, EMPTY);
}
public void resolveParents(Function<ResourceLocation, JsonModel> modelLoader) {
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.model.light;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import net.minecraft.util.MathHelper;
import net.minecraft.entity.Entity;
import net.minecraft.world.EnumSkyBlock;
@@ -46,7 +46,7 @@ public class EntityLighter {
double sl = 0;
double bl = 0;
BlockPos.Mutable pos = new BlockPos.Mutable();
BlockPosImpl pos = new BlockPosImpl();
// Iterate over every block in the sampling volume
for (int bX = bMinX; bX < bMaxX; bX++) {
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.model.light;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import me.jellysquid.mods.sodium.client.model.light.data.QuadLightData;
import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView;
import net.minecraftforge.common.util.ForgeDirection;
@@ -18,5 +18,5 @@ public interface LightPipeline {
* @param face The pre-computed facing vector of the quad
* @param shade True if the block is shaded by ambient occlusion
*/
void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, ForgeDirection cullFace, ForgeDirection face, boolean shade);
void calculate(ModelQuadView quad, BlockPosImpl pos, QuadLightData out, ForgeDirection cullFace, ForgeDirection face, boolean shade);
}
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.model.light.cache;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.api.BlockPos;
import it.unimi.dsi.fastutil.longs.Long2LongLinkedOpenHashMap;
import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess;
import me.jellysquid.mods.sodium.client.world.WorldSlice;
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.model.light.data;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import me.jellysquid.mods.sodium.client.util.StateUtil;
import me.jellysquid.mods.sodium.client.world.WorldSlice;
import net.minecraft.block.Block;
@@ -22,7 +22,7 @@ import net.minecraftforge.common.util.ForgeDirection;
* You can use the various static pack/unpack methods to extract these values in a usable format.
*/
public abstract class LightDataAccess {
private final BlockPos.Mutable pos = new BlockPos.Mutable();
private final BlockPosImpl pos = new BlockPosImpl();
protected WorldSlice world;
public long get(int x, int y, int z, ForgeDirection d1, ForgeDirection d2) {
@@ -33,11 +33,11 @@ public abstract class LightDataAccess {
return this.get(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ);
}
public long get(BlockPos pos, ForgeDirection dir) {
public long get(BlockPosImpl pos, ForgeDirection dir) {
return this.get(pos.x, pos.y, pos.z, dir);
}
public long get(BlockPos pos) {
public long get(BlockPosImpl pos) {
return this.get(pos.x, pos.y, pos.getZ());
}
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.model.light.flat;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import me.jellysquid.mods.sodium.client.model.light.LightPipeline;
import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess;
@@ -27,7 +27,7 @@ public class FlatLightPipeline implements LightPipeline {
}
@Override
public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, ForgeDirection cullFace, ForgeDirection face, boolean shade) {
public void calculate(ModelQuadView quad, BlockPosImpl pos, QuadLightData out, ForgeDirection cullFace, ForgeDirection face, boolean shade) {
int lightmap;
// To match vanilla behavior, use the cull face if it exists/is available
@@ -57,7 +57,7 @@ public class FlatLightPipeline implements LightPipeline {
* behind tinted glass. {@link LightDataAccess} cannot efficiently store lightmaps computed with
* inconsistent values so this method exists to mirror vanilla behavior as closely as possible.
*/
private int getOffsetLightmap(BlockPos pos, ForgeDirection face) {
private int getOffsetLightmap(BlockPosImpl pos, ForgeDirection face) {
int lightmap = LightDataAccess.unpackLM(this.lightCache.get(pos, face));
// If the block light is not 15 (max)...
if ((lightmap & 0xF0) != 0xF0) {
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.model.light.smooth;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess;
import net.minecraftforge.common.util.ForgeDirection;
@@ -18,7 +18,7 @@ class AoFaceData {
private int flags;
public void initLightData(LightDataAccess cache, BlockPos pos, ForgeDirection direction, boolean offset) {
public void initLightData(LightDataAccess cache, BlockPosImpl pos, ForgeDirection direction, boolean offset) {
final int x = pos.x;
final int y = pos.y;
final int z = pos.z;
@@ -1,7 +1,7 @@
package me.jellysquid.mods.sodium.client.model.light.smooth;
import com.google.common.math.DoubleMath;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import me.jellysquid.mods.sodium.client.model.light.LightPipeline;
import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess;
@@ -69,7 +69,7 @@ public class SmoothLightPipeline implements LightPipeline {
}
@Override
public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, ForgeDirection cullFace, ForgeDirection face, boolean shade) {
public void calculate(ModelQuadView quad, BlockPosImpl pos, QuadLightData out, ForgeDirection cullFace, ForgeDirection face, boolean shade) {
this.updateCachedData(pos.asLong());
int flags = quad.getFlags();
@@ -101,7 +101,7 @@ public class SmoothLightPipeline implements LightPipeline {
* have two contributing sides.
* Flags: IS_ALIGNED, !IS_PARTIAL
*/
private void applyAlignedFullFace(AoNeighborInfo neighborInfo, BlockPos pos, ForgeDirection dir, QuadLightData out) {
private void applyAlignedFullFace(AoNeighborInfo neighborInfo, BlockPosImpl pos, ForgeDirection dir, QuadLightData out) {
AoFaceData faceData = this.getCachedFaceData(pos, dir, true);
neighborInfo.mapCorners(faceData.lm, faceData.ao, out.lm, out.br);
}
@@ -110,7 +110,7 @@ public class SmoothLightPipeline implements LightPipeline {
* Calculates the light data for a grid-aligned quad that does not cover the entire block volume's face.
* Flags: IS_ALIGNED, IS_PARTIAL
*/
private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, ForgeDirection dir, QuadLightData out) {
private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPosImpl pos, ForgeDirection dir, QuadLightData out) {
for (int i = 0; i < 4; i++) {
// Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting
float cx = clamp(quad.getX(i));
@@ -124,13 +124,13 @@ public class SmoothLightPipeline implements LightPipeline {
}
/**
* This method is the same as {@link #applyNonParallelFace(AoNeighborInfo, ModelQuadView, BlockPos, ForgeDirection,
* This method is the same as {@link #applyNonParallelFace(AoNeighborInfo, ModelQuadView, BlockPosImpl, ForgeDirection,
* QuadLightData)} but with the check for a depth of approximately 0 removed. If the quad is parallel but not
* aligned, all of its vertices will have the same depth and this depth must be approximately greater than 0,
* meaning the check for 0 will always return false.
* Flags: !IS_ALIGNED, IS_PARALLEL
*/
private void applyParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, ForgeDirection dir, QuadLightData out) {
private void applyParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPosImpl pos, ForgeDirection dir, QuadLightData out) {
for (int i = 0; i < 4; i++) {
// Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting
float cx = clamp(quad.getX(i));
@@ -157,7 +157,7 @@ public class SmoothLightPipeline implements LightPipeline {
/**
* Flags: !IS_ALIGNED, !IS_PARALLEL
*/
private void applyNonParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, ForgeDirection dir, QuadLightData out) {
private void applyNonParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPosImpl pos, ForgeDirection dir, QuadLightData out) {
for (int i = 0; i < 4; i++) {
// Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting
float cx = clamp(quad.getX(i));
@@ -182,7 +182,7 @@ public class SmoothLightPipeline implements LightPipeline {
}
}
private void applyAlignedPartialFaceVertex(BlockPos pos, ForgeDirection dir, float[] w, int i, QuadLightData out, boolean offset) {
private void applyAlignedPartialFaceVertex(BlockPosImpl pos, ForgeDirection dir, float[] w, int i, QuadLightData out, boolean offset) {
AoFaceData faceData = this.getCachedFaceData(pos, dir, offset);
if (!faceData.hasUnpackedLightData()) {
@@ -197,7 +197,7 @@ public class SmoothLightPipeline implements LightPipeline {
out.lm[i] = getLightMapCoord(sl, bl);
}
private void applyInsetPartialFaceVertex(BlockPos pos, ForgeDirection dir, float n1d, float n2d, float[] w, int i, QuadLightData out) {
private void applyInsetPartialFaceVertex(BlockPosImpl pos, ForgeDirection dir, float n1d, float n2d, float[] w, int i, QuadLightData out) {
AoFaceData n1 = this.getCachedFaceData(pos, dir, false);
if (!n1.hasUnpackedLightData()) {
@@ -235,7 +235,7 @@ public class SmoothLightPipeline implements LightPipeline {
/**
* Returns the cached data for a given facing or calculates it if it hasn't been cached.
*/
private AoFaceData getCachedFaceData(BlockPos pos, ForgeDirection face, boolean offset) {
private AoFaceData getCachedFaceData(BlockPosImpl pos, ForgeDirection face, boolean offset) {
AoFaceData data = this.cachedFaceData[offset ? face.ordinal() : face.ordinal() + 6];
if (!data.hasLightData()) {
@@ -0,0 +1,335 @@
package me.jellysquid.mods.sodium.client.model.quad;
import com.gtnewhorizons.angelica.api.QuadView;
import lombok.Getter;
import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing;
import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFlags;
import me.jellysquid.mods.sodium.client.render.pipeline.BlockRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraftforge.common.util.ForgeDirection;
import org.joml.Vector3f;
import org.lwjgl.opengl.GL11;
import javax.annotation.Nullable;
import java.util.Locale;
/**
* Roughly equivalent to 16.5's BakedQuadView and BakedQuadMixin
*/
public class Quad implements QuadView {
// Adapted from Neodymium
public static final int INTS_PER_VERTEX = 8;
public static final int QUAD_STRIDE = INTS_PER_VERTEX * 4;
public static final int X_INDEX = 0;
public static final int Y_INDEX = 1;
public static final int Z_INDEX = 2;
public static final int U_INDEX = 3;
public static final int V_INDEX = 4;
public static final int COLOR_INDEX = 5;
public static final int NORMAL_INDEX = 6;
public static final int LIGHTMAP_INDEX = 7;
private final static int DEFAULT_LIGHTMAP = 15 << 20 | 15 << 4;
private final static int DEFAULT_COLOR = 0xFFFFFFFF;
private final int[] data = new int[QUAD_STRIDE];
@Getter
private boolean deleted;
private final Vector3f vectorA = new Vector3f(), vectorB = new Vector3f(), vectorC = new Vector3f();
@Getter
private boolean shade;
private int cachedFlags;
@Getter
private ForgeDirection face;
private int colorIndex = -1;
private TextureAtlasSprite sprite = null;
/** Returns the face, forced to take one of 6 directions to mirror the behavior of baked quads in 1.16.5. */
@Override
public ForgeDirection getLightFace() {
return this.face != ForgeDirection.UNKNOWN ? this.face : ForgeDirection.UP;
}
@Override
public float getX(int idx) {
return Float.intBitsToFloat(this.data[idx * INTS_PER_VERTEX + X_INDEX]);
}
@Override
public float getY(int idx) {
return Float.intBitsToFloat(this.data[idx * INTS_PER_VERTEX + Y_INDEX]);
}
@Override
public float getZ(int idx) {
return Float.intBitsToFloat(this.data[idx * INTS_PER_VERTEX + Z_INDEX]);
}
@Override
public float getTexU(int idx) {
return Float.intBitsToFloat(this.data[idx * INTS_PER_VERTEX + U_INDEX]);
}
@Override
public float getTexV(int idx) {
return Float.intBitsToFloat(this.data[idx * INTS_PER_VERTEX + V_INDEX]);
}
@Override
public int getColor(int idx) {
return this.data[idx * INTS_PER_VERTEX + COLOR_INDEX];
}
@Override
public int getLight(int idx) {
return this.data[idx * INTS_PER_VERTEX + LIGHTMAP_INDEX];
}
@Override
public int getNormal(int idx) {
return this.data[idx * INTS_PER_VERTEX + NORMAL_INDEX];
}
@Override
public int getFlags() {
return this.cachedFlags;
}
@Override
public int getColorIndex() {
return this.colorIndex;
}
@Override
public TextureAtlasSprite rubidium$getSprite() {
return this.sprite;
}
@Override
public void setX(int idx, float x) {
this.data[idx * INTS_PER_VERTEX + X_INDEX] = Float.floatToRawIntBits(x);
}
@Override
public void setY(int idx, float y) {
this.data[idx * INTS_PER_VERTEX + Y_INDEX] = Float.floatToRawIntBits(y);
}
@Override
public void setZ(int idx, float z) {
this.data[idx * INTS_PER_VERTEX + Z_INDEX] = Float.floatToRawIntBits(z);
}
@Override
public void setTexU(int idx, float u) {
this.data[idx * INTS_PER_VERTEX + U_INDEX] = Float.floatToRawIntBits(u);
}
@Override
public void setTexV(int idx, float v) {
this.data[idx * INTS_PER_VERTEX + V_INDEX] = Float.floatToRawIntBits(v);
}
@Override
public void setColor(int idx, int c) {
this.data[idx * INTS_PER_VERTEX + COLOR_INDEX] = c;
}
@Override
public void setLight(int idx, int l) {
this.data[idx * INTS_PER_VERTEX + LIGHTMAP_INDEX] = l;
}
@Override
public void setNormal(int idx, int n) {
this.data[idx * INTS_PER_VERTEX + NORMAL_INDEX] = n;
}
@Override
public void setFlags(int flags) {
this.cachedFlags = flags;
}
@Override
public void setColorIndex(int i) {
this.colorIndex = i;
}
@Override
public void setSprite(TextureAtlasSprite sprite) {
this.sprite = sprite;
}
@Override
public int[] getRawVertexes() {
return this.data;
}
/**
* Convenience: access x, y, z by index 0-2.
*/
private float posByIndex(int vertexIndex, int coordinateIndex) {
return Float.intBitsToFloat(this.data[vertexIndex * INTS_PER_VERTEX + coordinateIndex]);
}
/**
* Convenience: access x, y, z by index 0-2.
*/
private void setPosByIndex(int vertexIndex, int coordinateIndex, float val) {
this.data[vertexIndex * INTS_PER_VERTEX + coordinateIndex] = Float.floatToRawIntBits(val);
}
/**
* Offset all xs, ys, or zs by index 0-2.
*/
private void offsetPos(int idx, float offset) {
this.setPosByIndex(0, idx, this.posByIndex(0, idx) + offset);
this.setPosByIndex(1, idx, this.posByIndex(1, idx) + offset);
this.setPosByIndex(2, idx, this.posByIndex(2, idx) + offset);
this.setPosByIndex(3, idx, this.posByIndex(3, idx) + offset);
}
private void clearColors() {
this.setColor(0, DEFAULT_COLOR);
this.setColor(1, DEFAULT_COLOR);
this.setColor(2, DEFAULT_COLOR);
this.setColor(3, DEFAULT_COLOR);
}
private void clearNormals() {
this.setNormal(0, 0);
this.setNormal(1, 0);
this.setNormal(2, 0);
this.setNormal(3, 0);
}
private void clearLight() {
this.setLight(0, DEFAULT_LIGHTMAP);
this.setLight(1, DEFAULT_LIGHTMAP);
this.setLight(2, DEFAULT_LIGHTMAP);
this.setLight(3, DEFAULT_LIGHTMAP);
}
private boolean isEmpty() {
return this.getX(0) == this.getX(1)
&& this.getX(1) == this.getX(2)
&& this.getX(2) == this.getX(3)
&& this.getY(0) == this.getY(1)
&& this.getY(1) == this.getY(2)
&& this.getY(2) == this.getY(3);
}
private void calcNormal() {
this.vectorA.set(
this.getX(1) - this.getX(0),
this.getY(1) - this.getY(0),
this.getZ(1) - this.getZ(0)
);
this.vectorB.set(
this.getX(2) - this.getX(1),
this.getY(2) - this.getY(1),
this.getZ(2) - this.getZ(1)
);
this.vectorA.cross(this.vectorB, this.vectorC);
}
@Override
public void copyFrom(QuadView quad) {
System.arraycopy(quad.getRawVertexes(), 0, this.data, 0, QUAD_STRIDE);
this.deleted = quad.isDeleted();
this.shade = quad.isShade();
this.face = quad.getFace();
this.colorIndex = quad.getColorIndex();
this.cachedFlags = quad.getFlags();
this.sprite = quad.rubidium$getSprite();
}
/**
* Unlike setState, setRaw assumes your quad is valid and does not compute normals, clear color/normal/lightmap
* values, or quadrangulate. Basically the same as copyFrom but without an input quad.
*/
public void setRaw(int[] data, boolean shade, @Nullable ForgeDirection face, int colorIndex, int flags) {
System.arraycopy(data, 0, this.data, 0, QUAD_STRIDE);
this.deleted = false;
this.shade = shade;
this.face = face;
this.colorIndex = colorIndex;
this.cachedFlags = flags;
}
private void read(int[] rawBuffer, int offset, float offsetX, float offsetY, float offsetZ, int drawMode, BlockRenderer.Flags flags) {
System.arraycopy(rawBuffer, offset, this.data, 0, QUAD_STRIDE);
if (offsetX != 0) this.offsetPos(0, offsetX);
if (offsetY != 0) this.offsetPos(1, offsetY);
if (offsetZ != 0) this.offsetPos(2, offsetZ);
if (!flags.hasColor) this.clearColors();
if (!flags.hasNormals) this.clearNormals();
if (!flags.hasBrightness) this.clearLight();
// sus
this.shade = flags.hasBrightness;
if (drawMode == GL11.GL_TRIANGLES) {
// Quadrangulate!
this.setX(3, this.getX(2));
this.setY(3, this.getY(2));
this.setZ(3, this.getZ(2));
this.setTexU(3, this.getTexU(2));
this.setTexV(3, this.getTexV(2));
this.setLight(3, this.getLight(2));
this.setColor(3, this.getColor(2));
this.setNormal(3, this.getNormal(2));
}
}
@Override
public void setState(int[] rawBuffer, int offset, BlockRenderer.Flags flags, int drawMode, float offsetX, float offsetY, float offsetZ) {
this.deleted = false;
read(rawBuffer, offset, offsetX, offsetY, offsetZ, drawMode, flags);
if (this.isEmpty()) {
// ignore empty quads (e.g. alpha pass of EnderIO item conduits)
this.deleted = true;
return;
}
this.calcNormal();
this.face = ModelQuadFacing.toDirection(ModelQuadFacing.fromVector(this.vectorC));
this.cachedFlags = ModelQuadFlags.getQuadFlags(this);
}
@Override
public String toString() {
return String.format(
Locale.ENGLISH,
"%s[(%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f), (%.1f, %.1f, %.1f)]",
this.deleted ? "XXX " : "",
this.getX(0),
this.getY(0),
this.getZ(0),
this.getX(1),
this.getY(1),
this.getZ(1),
this.getX(2),
this.getY(2),
this.getZ(2),
this.getX(3),
this.getY(3),
this.getZ(3)
);
}
}
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.render.chunk;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import com.gtnewhorizons.angelica.compat.mojang.ChunkSectionPos;
import com.gtnewhorizons.angelica.utils.AnimationsRenderUtils;
import lombok.Getter;
@@ -265,8 +265,8 @@ public class ChunkRenderContainer<T extends ChunkGraphicsState> {
return this.getOriginZ() + 8.0D;
}
public BlockPos getRenderOrigin() {
return new BlockPos(this.getRenderX(), this.getRenderY(), this.getRenderZ());
public BlockPosImpl getRenderOrigin() {
return new BlockPosImpl(this.getRenderX(), this.getRenderY(), this.getRenderZ());
}
public void setGraphicsState(BlockRenderPass pass, T state) {
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.render.chunk.cull.graph;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import com.gtnewhorizons.angelica.compat.mojang.Camera;
import com.gtnewhorizons.angelica.compat.mojang.ChunkOcclusionData;
import com.gtnewhorizons.angelica.compat.mojang.ChunkSectionPos;
@@ -77,7 +77,7 @@ public class ChunkGraphCuller implements ChunkCuller {
this.visible.clear();
BlockPos origin = camera.getBlockPos();
BlockPosImpl origin = camera.getBlockPos();
int chunkX = origin.getX() >> 4;
int chunkY = origin.getY() >> 4;
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.render.chunk.cull.graph;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import com.gtnewhorizons.angelica.compat.mojang.ChunkOcclusionData;
import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData;
import me.jellysquid.mods.sodium.client.util.math.FrustumExtended;
@@ -146,7 +146,7 @@ public class ChunkGraphNode {
* @return The squared distance from the center of this chunk in the world to the center of the block position
* given by {@param pos}
*/
public double getSquaredDistance(BlockPos pos) {
public double getSquaredDistance(BlockPosImpl pos) {
return this.getSquaredDistance(pos.x + 0.5D, pos.y + 0.5D, pos.z + 0.5D);
}
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.render.chunk.tasks;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import com.gtnewhorizons.angelica.compat.mojang.ChunkOcclusionDataBuilder;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.mixins.interfaces.ITexturesCache;
@@ -48,7 +48,7 @@ import java.util.concurrent.ExecutionException;
public class ChunkRenderRebuildTask<T extends ChunkGraphicsState> extends ChunkRenderBuildTask<T> {
private final ChunkRenderContainer<T> render;
private final BlockPos offset;
private final BlockPosImpl offset;
private final ChunkRenderContext context;
@@ -56,7 +56,7 @@ public class ChunkRenderRebuildTask<T extends ChunkGraphicsState> extends ChunkR
private final boolean translucencySorting;
public ChunkRenderRebuildTask(ChunkRenderContainer<T> render, ChunkRenderContext context, BlockPos offset) {
public ChunkRenderRebuildTask(ChunkRenderContainer<T> render, ChunkRenderContext context, BlockPosImpl offset) {
this.render = render;
this.offset = offset;
this.context = context;
@@ -121,8 +121,8 @@ public class ChunkRenderRebuildTask<T extends ChunkGraphicsState> extends ChunkR
final int baseY = this.render.getOriginY();
final int baseZ = this.render.getOriginZ();
final BlockPos pos = new BlockPos();
final BlockPos renderOffset = this.offset;
final BlockPosImpl pos = new BlockPosImpl();
final BlockPosImpl renderOffset = this.offset;
final LongArrayFIFOQueue mainThreadBlocks = new LongArrayFIFOQueue();
boolean hasMainThreadBlocks = false;
@@ -240,11 +240,11 @@ public class ChunkRenderRebuildTask<T extends ChunkGraphicsState> extends ChunkR
*/
private void performMainBuild(ChunkRenderCacheLocal cache, ChunkBuildBuffers buffers, CancellationSource cancellationSource, ChunkRenderBounds.Builder bounds, ChunkRenderData.Builder renderData, LongArrayFIFOQueue mainThreadBlocks) {
final WorldSlice slice = cache.getWorldSlice();
final BlockPos pos = new BlockPos();
final BlockPosImpl pos = new BlockPosImpl();
final int baseX = this.render.getOriginX();
final int baseY = this.render.getOriginY();
final int baseZ = this.render.getOriginZ();
final BlockPos renderOffset = this.offset;
final BlockPosImpl renderOffset = this.offset;
final RenderBlocks rb = new RenderBlocks(slice.getWorld());
while(!mainThreadBlocks.isEmpty()) {
final long longPos = mainThreadBlocks.dequeueLong();
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.render.chunk.tasks;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import me.jellysquid.mods.sodium.client.gl.buffer.VertexData;
import me.jellysquid.mods.sodium.client.gl.util.BufferSlice;
import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing;
@@ -32,10 +32,10 @@ public class ChunkRenderTranslucencySortTask<T extends ChunkGraphicsState> exten
private static final BlockRenderPass[] NO_PASSES = new BlockRenderPass[0];
private final ChunkRenderContainer<T> render;
private final BlockPos offset;
private final BlockPosImpl offset;
private final Vector3d camera;
public ChunkRenderTranslucencySortTask(ChunkRenderContainer<T> render, BlockPos offset, Vector3d camera) {
public ChunkRenderTranslucencySortTask(ChunkRenderContainer<T> render, BlockPosImpl offset, Vector3d camera) {
this.render = render;
this.offset = offset;
this.camera = camera;
@@ -1,10 +1,10 @@
package me.jellysquid.mods.sodium.client.render.entity;
import net.minecraft.entity.Entity;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
public interface EntityLightSampler<T extends Entity> {
int bridge$getBlockLight(T entity, BlockPos pos);
int bridge$getBlockLight(T entity, BlockPosImpl pos);
int bridge$getSkyLight(T entity, BlockPos pos);
int bridge$getSkyLight(T entity, BlockPosImpl pos);
}
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.render.occlusion;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import it.unimi.dsi.fastutil.objects.Object2ByteLinkedOpenHashMap;
import net.minecraft.block.Block;
import net.minecraft.world.IBlockAccess;
@@ -11,7 +11,7 @@ public class BlockOcclusionCache {
private final Object2ByteLinkedOpenHashMap<CachedOcclusionShapeTest> map;
private final CachedOcclusionShapeTest cachedTest = new CachedOcclusionShapeTest();
private final BlockPos cpos = new BlockPos();
private final BlockPosImpl cpos = new BlockPosImpl();
public BlockOcclusionCache() {
this.map = new Object2ByteLinkedOpenHashMap<>(2048, 0.5F);
@@ -26,11 +26,11 @@ public class BlockOcclusionCache {
* @param facing The facing direction of the side to check
* @return True if the block side facing {@param dir} is not occluded, otherwise false
*/
public boolean shouldDrawSide(Block block, int meta, IBlockAccess view, BlockPos pos, ForgeDirection facing) {
public boolean shouldDrawSide(Block block, int meta, IBlockAccess view, BlockPosImpl pos, ForgeDirection facing) {
if (facing == ForgeDirection.UNKNOWN)
return true;
BlockPos adjPos = this.cpos;
BlockPosImpl adjPos = this.cpos;
adjPos.set(pos.getX() + facing.offsetX, pos.getY() + facing.offsetY, pos.getZ() + facing.offsetZ);
Block adjState = view.getBlock(adjPos.x, adjPos.y, adjPos.z);
@@ -1,9 +1,10 @@
package me.jellysquid.mods.sodium.client.render.pipeline;
import com.gtnewhorizons.angelica.api.QuadProvider;
import com.gtnewhorizons.angelica.api.QuadView;
import com.gtnewhorizons.angelica.client.renderer.CapturingTessellator;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.nd.Quad;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import me.jellysquid.mods.sodium.client.model.quad.Quad;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.glsm.TessellatorManager;
import com.gtnewhorizons.angelica.utils.ObjectPooler;
@@ -43,7 +44,7 @@ public class BlockRenderer {
private final LightPipelineProvider lighters;
private final BlockOcclusionCache occlusionCache;
private final ObjectPooler<Quad> quadPool = new ObjectPooler<>(Quad::new);
private final ObjectPooler<QuadView> quadPool = new ObjectPooler<>(Quad::new);
// TODO: Use modern model API, and store them here
@@ -54,7 +55,7 @@ public class BlockRenderer {
this.occlusionCache = new BlockOcclusionCache();
}
public boolean renderModel(IBlockAccess world, RenderBlocks renderBlocks, Block block, int meta, BlockPos pos, ChunkModelBuffers buffers, boolean cull, long seed) {
public boolean renderModel(IBlockAccess world, RenderBlocks renderBlocks, Block block, int meta, BlockPosImpl pos, ChunkModelBuffers buffers, boolean cull, long seed) {
final LightMode mode = this.getLightingMode(block);
final LightPipeline lighter = this.lighters.getLighter(mode);
@@ -69,18 +70,18 @@ public class BlockRenderer {
for (ForgeDirection dir : ForgeDirection.values()) {
this.random.setSeed(seed);
List<Quad> quads = null;
List<QuadView> quads;
if (!cull || this.occlusionCache.shouldDrawSide(block, meta, world, pos, dir)) {
quads = qBlock.getQuads(world, pos, block, meta, dir, random, color, this.quadPool);
quads = qBlock.getQuads(world, pos, block, meta, dir, random, color, this.quadPool::getInstance);
if (quads.isEmpty()) continue;
this.renderQuadList(pos, lighter, buffers, quads, ModelQuadFacing.fromDirection(dir), true);
rendered = true;
}
if (quads != null)
for (Quad q : quads) this.quadPool.releaseInstance(q);
if (qBlock.isDynamic())
for (QuadView q : quads) this.quadPool.releaseInstance(q);
}
}
} else {
@@ -92,7 +93,7 @@ public class BlockRenderer {
tess.setOffset(pos);
renderBlocks.renderBlockByRenderType(block, pos.x, pos.y, pos.z);
final List<Quad> quads = TessellatorManager.stopCapturingToPooledQuads();
final List<QuadView> quads = TessellatorManager.stopCapturingToPooledQuads();
tess.resetOffset();
for (ModelQuadFacing facing : ModelQuadFacing.VALUES) {
@@ -109,7 +110,7 @@ public class BlockRenderer {
return rendered;
}
private void renderQuadList(BlockPos pos, LightPipeline lighter, ChunkModelBuffers buffers, List<Quad> quads, ModelQuadFacing facing, boolean useSodiumLight) {
private void renderQuadList(BlockPosImpl pos, LightPipeline lighter, ChunkModelBuffers buffers, List<QuadView> quads, ModelQuadFacing facing, boolean useSodiumLight) {
final ForgeDirection cullFace = ModelQuadFacing.toDirection(facing);
final ModelVertexSink sink = buffers.getSink(facing);
@@ -120,7 +121,7 @@ public class BlockRenderer {
// This is a very hot allocation, iterate over it manually
// noinspection ForLoopReplaceableByForEach
for (int i = 0, quadsSize = quads.size(); i < quadsSize; i++) {
final Quad quad = quads.get(i);
final QuadView quad = quads.get(i);
// If we aren't using sodium light (i.e. it's the CapturingTesselator)
// manually filter quads by side
@@ -138,7 +139,7 @@ public class BlockRenderer {
sink.flush();
}
private void renderQuad(ModelVertexSink sink, Quad quad, QuadLightData light, ChunkRenderData.Builder renderData, boolean useSodiumLight) {
private void renderQuad(ModelVertexSink sink, QuadView quad, QuadLightData light, ChunkRenderData.Builder renderData, boolean useSodiumLight) {
final ModelQuadOrientation order = (useSodiumLight || this.useSeparateAo) ? ModelQuadOrientation.orient(light.br) : ModelQuadOrientation.NORMAL;
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.client.render.pipeline;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import me.jellysquid.mods.sodium.client.model.light.LightMode;
import me.jellysquid.mods.sodium.client.model.light.LightPipeline;
@@ -38,7 +38,7 @@ public class FluidRenderer {
private static final float EPSILON = 0.001f;
private final LightPipelineProvider lpp;
private final BlockPos.Mutable scratchPos = new BlockPos.Mutable();
private final BlockPosImpl scratchPos = new BlockPosImpl();
private final ModelQuadViewMutable quad = new ModelQuad();
@@ -69,7 +69,7 @@ public class FluidRenderer {
}
private boolean isSideExposed(IBlockAccess world, int x, int y, int z, ForgeDirection dir, float height) {
BlockPos pos = this.scratchPos.set(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ);
BlockPosImpl pos = this.scratchPos.set(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ);
Block block = world.getBlock(pos.x, pos.y, pos.z);
if (block.getMaterial().isOpaque()) {
@@ -87,7 +87,7 @@ public class FluidRenderer {
return true;
}
public boolean render(IBlockAccess world, WorldSlice slice, Block block, BlockPos pos, ChunkModelBuffers buffers) {
public boolean render(IBlockAccess world, WorldSlice slice, Block block, BlockPosImpl pos, ChunkModelBuffers buffers) {
this.useSeparateAo = AngelicaConfig.enableIris && BlockRenderingSettings.INSTANCE.shouldUseSeparateAo();
int posX = pos.x;
@@ -349,7 +349,7 @@ public class FluidRenderer {
return rendered;
}
private void calculateQuadColors(ModelQuadView quad, BlockPos pos, LightPipeline lighter, ForgeDirection dir, float brightness, boolean colorized, WorldSlice slice) {
private void calculateQuadColors(ModelQuadView quad, BlockPosImpl pos, LightPipeline lighter, ForgeDirection dir, float brightness, boolean colorized, WorldSlice slice) {
QuadLightData light = this.quadLightData;
lighter.calculate(quad, pos, light, null, dir, false);
@@ -437,7 +437,7 @@ public class FluidRenderer {
return 1.0F;
}
BlockPos pos = this.scratchPos.set(x2, y, z2);
BlockPosImpl pos = this.scratchPos.set(x2, y, z2);
block = world.getBlock(pos.x, pos.y, pos.z);
int meta = world.getBlockMetadata(pos.x, pos.y, pos.z);
@@ -3,7 +3,6 @@ package me.jellysquid.mods.sodium.client.world.cloned;
import com.falsepattern.endlessids.mixin.helpers.ChunkBiomeHook;
import com.gtnewhorizons.angelica.compat.ExtendedBlockStorageExt;
import com.gtnewhorizons.angelica.compat.ModStatus;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.ChunkSectionPos;
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
@@ -1,6 +1,6 @@
package me.jellysquid.mods.sodium.common.util;
import com.gtnewhorizons.angelica.compat.mojang.BlockPos;
import com.gtnewhorizons.angelica.compat.mojang.BlockPosImpl;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.material.Material;
@@ -70,7 +70,7 @@ public class WorldUtil {
* Returns true if any block in a 3x3x3 cube is not the same fluid and not an opaque full cube.
* Equivalent to FluidState::method_15756 in modern.
*/
public static boolean method_15756(IBlockAccess world, BlockPos pos, Fluid fluid) {
public static boolean method_15756(IBlockAccess world, BlockPosImpl pos, Fluid fluid) {
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j) {
Block block = world.getBlock(pos.x, pos.y, pos.z);
@@ -126,7 +126,7 @@ public class WorldUtil {
/**
* Equivalent to method_15749 in 1.16.5
*/
public static boolean method_15749(IBlockAccess world, Fluid thiz, BlockPos pos, ForgeDirection dir) {
public static boolean method_15749(IBlockAccess world, Fluid thiz, BlockPosImpl pos, ForgeDirection dir) {
Block b = world.getBlock(pos.x, pos.y, pos.z);
Fluid f = getFluid(b);
if (f == thiz) {