This commit is contained in:
mcrcortex
2025-04-04 15:09:42 +10:00
parent 856b5b5b56
commit 9e5e5e654d
3 changed files with 103 additions and 137 deletions

View File

@@ -43,9 +43,9 @@ public class RenderDataFactory45 {
//TODO: emit directly to memory buffer instead of long arrays //TODO: emit directly to memory buffer instead of long arrays
//Each axis gets a max quad count of 2^16 (65536 quads) since that is the max the basic geometry manager can handle //Each axis gets a max quad count of 2^16 (65536 quads) since that is the max the basic geometry manager can handle
private final MemoryBuffer directionalQuadBuffer = new MemoryBuffer(6*(8*(1<<16))); private final MemoryBuffer quadBuffer = new MemoryBuffer(8*(8*(1<<16)));//6 faces + dual direction + translucents
private final long directionalQuadBufferPtr = this.directionalQuadBuffer.address; private final long quadBufferPtr = this.quadBuffer.address;
private final int[] directionalQuadCounters = new int[6];//Maybe change to short? (or long /w raw pointers) private final int[] quadCounters = new int[8];
private int minX; private int minX;
@@ -67,8 +67,6 @@ public class RenderDataFactory45 {
//Note x, z are in top right //Note x, z are in top right
@Override @Override
protected void emitQuad(int x, int z, int length, int width, long data) { protected void emitQuad(int x, int z, int length, int width, long data) {
RenderDataFactory45.this.quadCount++;
if (VERIFY_MESHING) { if (VERIFY_MESHING) {
if (length<1||length>16) { if (length<1||length>16) {
throw new IllegalStateException("length out of bounds: " + length); throw new IllegalStateException("length out of bounds: " + length);
@@ -85,8 +83,10 @@ public class RenderDataFactory45 {
if (x-(length-1)<0 || z-(width-1)<0) { if (x-(length-1)<0 || z-(width-1)<0) {
throw new IllegalStateException("dim out of bounds: " + (x-(length-1))+", " + (z-(width-1))); throw new IllegalStateException("dim out of bounds: " + (x-(length-1))+", " + (z-(width-1)));
} }
} }
RenderDataFactory45.this.quadCount++;
x -= length-1; x -= length-1;
z -= width-1; z -= width-1;
@@ -103,35 +103,44 @@ public class RenderDataFactory45 {
//Lower 26 bits can be auxiliary data since that is where quad position information goes; //Lower 26 bits can be auxiliary data since that is where quad position information goes;
int auxData = (int) (data&((1<<26)-1)); int auxData = (int) (data&((1<<26)-1));
int faceSide = auxData&1; data &= ~((1<<26)-1);
data &= ~(data&((1<<26)-1));
final int axis = this.axis; int axisSide = auxData&1;
int face = (axis<<1)|faceSide; int type = (auxData>>1)&3;//Translucent, double side, directional
int encodedPosition = face;
if (VERIFY_MESHING) {
if (type == 3) {
throw new IllegalStateException();
}
}
//Shift up if is negative axis //Shift up if is negative axis
int auxPos = this.auxiliaryPosition; int auxPos = this.auxiliaryPosition;
auxPos += this.doAuxiliaryFaceOffset?(1-faceSide):0;//Shift auxPos += 1-(this.doAuxiliaryFaceOffset?axisSide:1);//Shift
if (VERIFY_MESHING) { if (VERIFY_MESHING) {
if (auxPos > 31) { if (auxPos > 31) {
throw new IllegalStateException("OOB face: " + auxPos + ", " + faceSide); throw new IllegalStateException("OOB face: " + auxPos + ", " + axisSide);
} }
} }
final int axis = this.axis;
int face = (axis<<1)|axisSide;
int encodedPosition = face;
encodedPosition |= ((width - 1) << 7) | ((length - 1) << 3); encodedPosition |= ((width - 1) << 7) | ((length - 1) << 3);
encodedPosition |= x << (axis==2?16:21); encodedPosition |= x << (axis==2?16:21);
encodedPosition |= z << (axis==1?16:11); encodedPosition |= z << (axis==1?16:11);
encodedPosition |= auxPos << (axis==0?16:(axis==1?11:21)); int shiftAmount = axis==0?16:(axis==1?11:21);
//shiftAmount += ;
encodedPosition |= auxPos << (shiftAmount);
long quad = data | Integer.toUnsignedLong(encodedPosition); long quad = data | Integer.toUnsignedLong(encodedPosition);
int bufferIdx = type+(type==2?face:0);//Translucent, double side, directional
MemoryUtil.memPutLong(RenderDataFactory45.this.directionalQuadBufferPtr + (RenderDataFactory45.this.directionalQuadCounters[face]++)*8L + face*8L*(1<<16), quad); long bufferOffset = (RenderDataFactory45.this.quadCounters[bufferIdx]++)*8L + bufferIdx*8L*(1<<16);
MemoryUtil.memPutLong(RenderDataFactory45.this.quadBufferPtr + bufferOffset, quad);
//Update AABB bounds //Update AABB bounds
@@ -175,7 +184,23 @@ public class RenderDataFactory45 {
this.modelMan = modelManager; this.modelMan = modelManager;
} }
private static long packPartialQuadData(int modelId, long state, long metaData) {
//This uses hardcoded data to shuffle things
long lightAndBiome = (state&((0x1FFL<<47)|(0xFFL<<56)))>>1;
lightAndBiome &= ModelQueries.isBiomeColoured(metaData)?-1:~(0x1FFL<<47);
lightAndBiome &= ModelQueries.isFullyOpaque(metaData)?~(0xFFL<<56):-1;//If its fully opaque it always uses neighbor light?
int type = 0;
{
boolean a = ModelQueries.isTranslucent(metaData);
boolean b = ModelQueries.isDoubleSided(metaData);
type = a|b?0:2;
type |= b?1:0;
}
long quadData = lightAndBiome;
quadData |= Integer.toUnsignedLong(modelId)<<26;
quadData |= type << 1;
return quadData;
}
private int prepareSectionData() { private int prepareSectionData() {
final var sectionData = this.sectionData; final var sectionData = this.sectionData;
@@ -189,7 +214,7 @@ public class RenderDataFactory45 {
int modelId = this.modelMan.getModelId(Mapper.getBlockId(block)); int modelId = this.modelMan.getModelId(Mapper.getBlockId(block));
long modelMetadata = this.modelMan.getModelMetadataFromClientId(modelId); long modelMetadata = this.modelMan.getModelMetadataFromClientId(modelId);
sectionData[i * 2] = modelId | ((long) (Mapper.getLightId(block)) << 16) | (ModelQueries.isBiomeColoured(modelMetadata)?(((long) (Mapper.getBiomeId(block))) << 24):0); sectionData[i * 2] = packPartialQuadData(modelId, block, modelMetadata);
sectionData[i * 2 + 1] = modelMetadata; sectionData[i * 2 + 1] = modelMetadata;
boolean isFullyOpaque = ModelQueries.isFullyOpaque(modelMetadata); boolean isFullyOpaque = ModelQueries.isFullyOpaque(modelMetadata);
@@ -306,7 +331,6 @@ public class RenderDataFactory45 {
this.blockMesher.skip(cSkip); this.blockMesher.skip(cSkip);
cSkip = 0; cSkip = 0;
//TODO: For boarder sections, should NOT EMIT neighbors faces
int faceForwardMsk = msk & current; int faceForwardMsk = msk & current;
int cIdx = -1; int cIdx = -1;
while (msk != 0) { while (msk != 0) {
@@ -331,9 +355,8 @@ public class RenderDataFactory45 {
//Example thing thats just wrong but as example //Example thing thats just wrong but as example
this.blockMesher.putNext(((long) facingForward) |//Facing this.blockMesher.putNext(((long) facingForward) |//Facing
((selfModel & 0xFFFF) << 26) | //ModelId selfModel |
(((nextModel>>16)&0xFF) << 55) |//Lighting (nextModel&(0xFFL<<56))//Apply lighting
((selfModel&(0x1FFL<<24))<<(46-24))//biomeId
); );
} }
} }
@@ -391,9 +414,8 @@ public class RenderDataFactory45 {
//Example thing thats just wrong but as example //Example thing thats just wrong but as example
this.blockMesher.putNext((side == 0 ? 0L : 1L) | this.blockMesher.putNext((side == 0 ? 0L : 1L) |
((A & 0xFFFFL) << 26) | A |
(((long)Mapper.getLightId(neighborId)) << 55) | ((neighborId&(0xFFL<<56))>>1)
((A&(0x1FFL<<24))<<(46-24))
); );
} }
} }
@@ -442,25 +464,24 @@ public class RenderDataFactory45 {
{ {
int idx = index + (pidx * 32); int idx = index + (pidx * 32);
//TODO: swap this out for something not getting the next entry
long A = this.sectionData[idx * 2];
long B = this.sectionData[idx * 2+1]; long B = this.sectionData[idx * 2+1];
if (ModelQueries.isTranslucent(B)) { if (ModelQueries.isTranslucent(B)) {
this.blockMesher.putNext(0); this.blockMesher.putNext(0);
this.seondaryblockMesher.putNext(0); this.seondaryblockMesher.putNext(0);
continue; continue;
} }
long A = this.sectionData[idx * 2];
//Example thing thats just wrong but as example //Example thing thats just wrong but as example
this.blockMesher.putNext((long) (false ? 0L : 1L) | this.blockMesher.putNext((long) (false ? 0L : 1L) |
((A & 0xFFFFL) << 26) | A |
(((0xFFL) & 0xFF) << 55) | (((0xFFL) & 0xFF) << 55)
((A&(0x1FFL<<24))<<(46-24))
); );
this.seondaryblockMesher.putNext((long) (true ? 0L : 1L) | this.seondaryblockMesher.putNext((long) (true ? 0L : 1L) |
((A & 0xFFFFL) << 26) | A |
(((0xFFL) & 0xFF) << 55) | (((0xFFL) & 0xFF) << 55)
((A&(0x1FFL<<24))<<(46-24))
); );
} }
} }
@@ -584,9 +605,8 @@ public class RenderDataFactory45 {
//Example thing thats just wrong but as example //Example thing thats just wrong but as example
mesher.putNext(((long) facingForward) |//Facing mesher.putNext(((long) facingForward) |//Facing
((selfModel & 0xFFFF) << 26) | //ModelId selfModel |
(((nextModel>>16)&0xFF) << 55) |//Lighting (nextModel&(0xFFL<<55))
((selfModel&(0x1FFL<<24))<<(46-24))//biomeId
); );
} }
} }
@@ -644,7 +664,10 @@ public class RenderDataFactory45 {
if (oki) { if (oki) {
ma.skip(skipA); skipA = 0; ma.skip(skipA); skipA = 0;
long A = this.sectionData[(i<<5) * 2]; long A = this.sectionData[(i<<5) * 2];
ma.putNext(0L | ((A&0xFFFF)<<26) | (((long)Mapper.getLightId(neighborId))<<55)|((A&(0x1FFL<<24))<<(46-24))); ma.putNext(0L |
A |
((neighborId&(0xFFL<<56))>>1)
);
} else {skipA++;} } else {skipA++;}
} else {skipA++;} } else {skipA++;}
@@ -660,7 +683,10 @@ public class RenderDataFactory45 {
if (oki) { if (oki) {
mb.skip(skipB); skipB = 0; mb.skip(skipB); skipB = 0;
long A = this.sectionData[(i*32+31) * 2]; long A = this.sectionData[(i*32+31) * 2];
mb.putNext(1L | ((A&0xFFFF)<<26) | (((long)Mapper.getLightId(neighborId))<<55)|((A&(0x1FFL<<24))<<(46-24))); mb.putNext(1L |
A |
((neighborId&(0xFFL<<56))>>1)
);
} else {skipB++;} } else {skipB++;}
} else {skipB++;} } else {skipB++;}
} }
@@ -688,16 +714,6 @@ public class RenderDataFactory45 {
} }
} }
/*
private static long createQuad() {
((long)clientModelId) | (((long) Mapper.getLightId(ModelQueries.faceUsesSelfLighting(metadata, face)?self:facingState))<<16) | ((((long) Mapper.getBiomeId(self))<<24) * (ModelQueries.isBiomeColoured(metadata)?1:0)) | otherFlags
long data = Integer.toUnsignedLong(array[i*3+1]);
data |= ((long) array[i*3+2])<<32;
long encodedQuad = Integer.toUnsignedLong(QuadEncoder.encodePosition(face, otherAxis, quad)) | ((data&0xFFFF)<<26) | (((data>>16)&0xFF)<<55) | (((data>>24)&0x1FF)<<46);
}*/
//section is already acquired and gets released by the parent //section is already acquired and gets released by the parent
public BuiltSection generateMesh(WorldSection section) { public BuiltSection generateMesh(WorldSection section) {
//TODO: FIXME: because of the exceptions that are thrown when aquiring modelId //TODO: FIXME: because of the exceptions that are thrown when aquiring modelId
@@ -729,7 +745,7 @@ public class RenderDataFactory45 {
this.maxY = Integer.MIN_VALUE; this.maxY = Integer.MIN_VALUE;
this.maxZ = Integer.MIN_VALUE; this.maxZ = Integer.MIN_VALUE;
Arrays.fill(this.directionalQuadCounters, (short) 0); Arrays.fill(this.quadCounters, (short) 0);
//Prepare everything //Prepare everything
int neighborMsk = this.prepareSectionData(); int neighborMsk = this.prepareSectionData();
@@ -742,29 +758,25 @@ public class RenderDataFactory45 {
//TODO:NOTE! when doing face culling of translucent blocks, //TODO:NOTE! when doing face culling of translucent blocks,
// if the connecting type of the translucent block is the same AND the face is full, discard it // if the connecting type of the translucent block is the same AND the face is full, discard it
// this stops e.g. multiple layers of glass (and ocean) from having 3000 layers of quads etc // this stops e.g. multiple layers of glass (and ocean) from having 3000 layers of quads etc
if (this.quadCount == 0) { if (this.quadCount == 0) {
return BuiltSection.emptyWithChildren(section.key, section.getNonEmptyChildren()); return BuiltSection.emptyWithChildren(section.key, section.getNonEmptyChildren());
} }
//TODO: FIXME AND OPTIMIZE, get rid of the stupid quad collector bullshit if (this.minX<0 || this.minY<0 || this.minZ<0 || 32<this.maxX || 32<this.maxY || 32<this.maxZ) {
throw new IllegalStateException();
}
int[] offsets = new int[8]; int[] offsets = new int[8];
var buff = new MemoryBuffer(this.quadCount * 8L); var buff = new MemoryBuffer(this.quadCount * 8L);
long ptr = buff.address; long ptr = buff.address;
int coff = 0; int coff = 0;
for (int buffer = 0; buffer < 8; buffer++) {// translucent, double sided quads, 6 faces
for (int face = 0; face < 6; face++) { offsets[buffer] = coff;
offsets[face + 2] = coff; int size = this.quadCounters[buffer];
int size = this.directionalQuadCounters[face]; UnsafeUtil.memcpy(this.quadBufferPtr + (buffer*(8*(1<<16))), ptr + coff*8L, (size* 8L));
UnsafeUtil.memcpy(this.directionalQuadBufferPtr + (face*(8*(1<<16))), ptr + coff*8L, (size* 8L));
coff += size; coff += size;
} }
if (this.minX<0 || this.minY<0 || this.minZ<0 || 32<this.maxX || 32<this.maxY || 32<this.maxZ) {
throw new IllegalStateException();
}
int aabb = 0; int aabb = 0;
aabb |= this.minX; aabb |= this.minX;
aabb |= this.minY<<5; aabb |= this.minY<<5;
@@ -774,68 +786,15 @@ public class RenderDataFactory45 {
aabb |= (this.maxZ-this.minZ-1)<<25; aabb |= (this.maxZ-this.minZ-1)<<25;
return new BuiltSection(section.key, section.getNonEmptyChildren(), aabb, buff, offsets); return new BuiltSection(section.key, section.getNonEmptyChildren(), aabb, buff, offsets);
/*
buff = new MemoryBuffer(bufferSize * 8L);
long ptr = buff.address;
int coff = 0;
//Ordering is: translucent, double sided quads, directional quads
offsets[0] = coff;
int size = this.translucentQuadCollector.size();
LongArrayList arrayList = this.translucentQuadCollector;
for (int i = 0; i < size; i++) {
long data = arrayList.getLong(i);
MemoryUtil.memPutLong(ptr + ((coff++) * 8L), data);
}
offsets[1] = coff;
size = this.doubleSidedQuadCollector.size();
arrayList = this.doubleSidedQuadCollector;
for (int i = 0; i < size; i++) {
long data = arrayList.getLong(i);
MemoryUtil.memPutLong(ptr + ((coff++) * 8L), data);
}
for (int face = 0; face < 6; face++) {
offsets[face + 2] = coff;
final LongArrayList faceArray = this.directionalQuadCollectors[face];
size = faceArray.size();
for (int i = 0; i < size; i++) {
long data = faceArray.getLong(i);
MemoryUtil.memPutLong(ptr + ((coff++) * 8L), data);
}
}
int aabb = 0;
aabb |= this.minX;
aabb |= this.minY<<5;
aabb |= this.minZ<<10;
aabb |= (this.maxX-this.minX)<<15;
aabb |= (this.maxY-this.minY)<<20;
aabb |= (this.maxZ-this.minZ)<<25;
return new BuiltSection(section.key, section.getNonEmptyChildren(), aabb, buff, offsets);
*/
} }
public void free() { public void free() {
this.directionalQuadBuffer.free(); this.quadBuffer.free();
} }
//Returns true if a face was placed //Returns true if a face was placed
private boolean putFluidFaceIfCan(Mesher2D mesher, int face, int opposingFace, long self, long metadata, int selfClientModelId, int selfBlockId, long facingState, long facingMetadata, int facingClientModelId, int a, int b) { private boolean putFluidFaceIfCan(Mesher2D mesher, int face, int opposingFace, long self, long metadata, int selfClientModelId, int selfBlockId, long facingState, long facingMetadata, int facingClientModelId, int a, int b) {
int selfFluidClientId = this.modelMan.getFluidClientStateId(selfClientModelId); int selfFluidClientId = this.modelMan.getFluidClientStateId(selfClientModelId);

View File

@@ -95,19 +95,24 @@ public abstract class ScanMesher2D {
} }
} }
//Note it is illegal for count to cause `this.currentIndex&31` to wrap and continue
public final void skip(int count) { public final void skip(int count) {
/*
if (count == 0) return;
if (this.currentData != 0) {
this.putNext(0); count--;
}
if (count != 0) {
this.emitRanged(((1 << Math.min(count, 31)) - 1) << (this.currentIndex & 31));
}
this.currentIndex += count;
*/
if (count == 0) return; if (count == 0) return;
//TODO: replace with much better method, TODO: check this is right!!
this.putNext(0); this.putNext(0);
if (1<count) { if (1<count) {
this.emitRanged(((1 << (Math.min(count, 32)-1)) - 1) << (this.currentIndex & 31)); this.emitRanged(((1 << (Math.min(count, 32)-1)) - 1) << (this.currentIndex & 31));
this.currentIndex += count - 1; this.currentIndex += count - 1;
} }
/*
for (int i = 0; i < count; i++) {
this.putNext(0);
}*/
} }
public final void reset() { public final void reset() {

View File

@@ -222,16 +222,18 @@ public class WorldConversionFactory {
//Mip L1 //Mip L1
int i = 0; int i = 0;
for (int y = 0; y < 16; y+=2) { int MSK = 0b1110_1110_1110;
for (int z = 0; z < 16; z += 2) { int iMSK1 = (~MSK)+1;
for (int x = 0; x < 16; x += 2) { int q = 0;
data[16*16*16 + i++] = while (true) {
Mipper.mip( data[16*16*16 + i++] = Mipper.mip(
data[G(x, y, z)], data[G(x+1, y, z)], data[G(x, y, z+1)], data[G(x+1, y, z+1)], data[q|G(0,0,0)], data[q|G(1,0,0)], data[q|G(0,0,1)], data[q|G(1,0,1)],
data[G(x, y+1, z)], data[G(x+1, y+1, z)], data[G(x, y+1, z+1)], data[G(x+1, y+1, z+1)], data[q|G(0,1,0)], data[q|G(1,1,0)], data[q|G(0,1,1)], data[q|G(1,1,1)],
mapper); mapper
} );
} if (q == MSK)
break;
q = (q+iMSK1)&MSK;
} }
//Mip L2 //Mip L2