Mostly finish non-opaque model support
This commit is contained in:
@@ -179,7 +179,6 @@ public class RenderDataFactory45 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private final Mesher blockMesher = new Mesher();
|
private final Mesher blockMesher = new Mesher();
|
||||||
private final Mesher seondaryblockMesher = new Mesher();//Used for dual non-opaque geometry
|
private final Mesher seondaryblockMesher = new Mesher();//Used for dual non-opaque geometry
|
||||||
|
|
||||||
@@ -214,6 +213,7 @@ public class RenderDataFactory45 {
|
|||||||
|
|
||||||
private int prepareSectionData() {
|
private int prepareSectionData() {
|
||||||
final var sectionData = this.sectionData;
|
final var sectionData = this.sectionData;
|
||||||
|
final var rawModelIds = this.modelMan._unsafeRawAccess();
|
||||||
int opaque = 0;
|
int opaque = 0;
|
||||||
int notEmpty = 0;
|
int notEmpty = 0;
|
||||||
int pureFluid = 0;
|
int pureFluid = 0;
|
||||||
@@ -226,7 +226,10 @@ public class RenderDataFactory45 {
|
|||||||
sectionData[i * 2] = (block&(0xFFL<<56))>>1;
|
sectionData[i * 2] = (block&(0xFFL<<56))>>1;
|
||||||
sectionData[i * 2 + 1] = 0;
|
sectionData[i * 2 + 1] = 0;
|
||||||
} else {
|
} else {
|
||||||
int modelId = this.modelMan.getModelId(Mapper.getBlockId(block));
|
int modelId = rawModelIds[Mapper.getBlockId(block)];
|
||||||
|
if (modelId == -1) {//Failed, so just return error
|
||||||
|
return Mapper.getBlockId(block)|(1<<31);
|
||||||
|
}
|
||||||
long modelMetadata = this.modelMan.getModelMetadataFromClientId(modelId);
|
long modelMetadata = this.modelMan.getModelMetadataFromClientId(modelId);
|
||||||
|
|
||||||
sectionData[i * 2] = packPartialQuadData(modelId, block, modelMetadata);
|
sectionData[i * 2] = packPartialQuadData(modelId, block, modelMetadata);
|
||||||
@@ -239,8 +242,6 @@ public class RenderDataFactory45 {
|
|||||||
partialFluid |= ModelQueries.containsFluid(modelMetadata) ? msk : 0;
|
partialFluid |= ModelQueries.containsFluid(modelMetadata) ? msk : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: here also do bitmask of what neighboring sections are needed to compute (may be getting rid of this in future)
|
|
||||||
|
|
||||||
//Do increment here
|
//Do increment here
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
@@ -332,7 +333,24 @@ public class RenderDataFactory45 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: add neighbor face culling
|
private static boolean shouldMeshNonOpaqueBlockFace(int face, long quad, long meta, long neighborQuad, long neighborMeta) {
|
||||||
|
if (((quad^neighborQuad)&(0xFFFFL<<26))==0) return false;//This is a hack, if the neigbor and this are the same, dont mesh the face
|
||||||
|
if (!ModelQueries.faceExists(meta, face)) return false;//Dont mesh if no face
|
||||||
|
//if (ModelQueries.faceCanBeOccluded(meta, face)) //TODO: maybe enable this
|
||||||
|
if (ModelQueries.faceOccludes(neighborMeta, face^1)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void meshNonOpaqueFace(int face, long quad, long meta, long neighborQuad, long neighborMeta, Mesher mesher) {
|
||||||
|
if (shouldMeshNonOpaqueBlockFace(face, quad, meta, neighborQuad, neighborMeta)) {
|
||||||
|
mesher.putNext((long) (face&1) |
|
||||||
|
quad |
|
||||||
|
((ModelQueries.faceUsesSelfLighting(meta, face)?quad:neighborQuad) & (0xFFL << 55)));
|
||||||
|
} else {
|
||||||
|
mesher.skip(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void generateYZOpaqueInnerGeometry(int axis) {
|
private void generateYZOpaqueInnerGeometry(int axis) {
|
||||||
for (int layer = 0; layer < 31; layer++) {
|
for (int layer = 0; layer < 31; layer++) {
|
||||||
this.blockMesher.auxiliaryPosition = layer;
|
this.blockMesher.auxiliaryPosition = layer;
|
||||||
@@ -668,35 +686,8 @@ public class RenderDataFactory45 {
|
|||||||
long A = this.sectionData[idx * 2];
|
long A = this.sectionData[idx * 2];
|
||||||
long B = this.sectionData[idx * 2+1];
|
long B = this.sectionData[idx * 2+1];
|
||||||
|
|
||||||
long nA = this.sectionData[(idx+skipAmount)*2];
|
meshNonOpaqueFace((axis<<1)|0, A, B, this.sectionData[(idx-skipAmount)*2], this.sectionData[(idx-skipAmount)*2+1], this.seondaryblockMesher);//-
|
||||||
long nB = this.sectionData[(idx+skipAmount)*2 + 1];
|
meshNonOpaqueFace((axis<<1)|1, A, B, this.sectionData[(idx+skipAmount)*2], this.sectionData[(idx+skipAmount)*2+1], this.blockMesher);//+
|
||||||
|
|
||||||
//TODO: filtering
|
|
||||||
if (ModelQueries.faceExists(B, (axis<<1)|0) && (nA&(0xFFFFL<<26)) != (A&(0xFFFFL<<26))&& (!ModelQueries.faceOccludes(nB, (axis<<1)|0))) {
|
|
||||||
//ModelQueries.faceCanBeOccluded(B, (axis<<1)|(1))&&
|
|
||||||
|
|
||||||
//Example thing thats just wrong but as example
|
|
||||||
this.blockMesher.putNext((long) (false ? 0L : 1L) |
|
|
||||||
A |
|
|
||||||
((ModelQueries.faceUsesSelfLighting(B, (axis<<1)|1)?A:nA) & (0xFFL << 55))//(((0xFFL) & 0xFF) << 55)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.blockMesher.skip(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
nA = this.sectionData[(idx-skipAmount)*2];
|
|
||||||
nB = this.sectionData[(idx-skipAmount)*2 + 1];
|
|
||||||
if (ModelQueries.faceExists(B, (axis<<1)|1) && (nA&(0xFFFFL<<26)) != (A&(0xFFFFL<<26)) && (!ModelQueries.faceOccludes(nB, (axis<<1)|1))) {
|
|
||||||
//ModelQueries.faceCanBeOccluded(B, (axis<<1)|(0))&&
|
|
||||||
|
|
||||||
this.seondaryblockMesher.putNext((long) (true ? 0L : 1L) |
|
|
||||||
A |
|
|
||||||
((ModelQueries.faceUsesSelfLighting(B, (axis<<1)|0)?A:nA) & (0xFFL << 55))//(((0xFFL) & 0xFF) << 55)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.seondaryblockMesher.skip(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.blockMesher.endRow();
|
this.blockMesher.endRow();
|
||||||
@@ -822,6 +813,7 @@ public class RenderDataFactory45 {
|
|||||||
|
|
||||||
|
|
||||||
private final Mesher[] xAxisMeshers = new Mesher[32];
|
private final Mesher[] xAxisMeshers = new Mesher[32];
|
||||||
|
private final Mesher[] secondaryXAxisMeshers = new Mesher[32];
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
var mesher = new Mesher();
|
var mesher = new Mesher();
|
||||||
@@ -829,6 +821,15 @@ public class RenderDataFactory45 {
|
|||||||
mesher.axis = 2;//X axis
|
mesher.axis = 2;//X axis
|
||||||
this.xAxisMeshers[i] = mesher;
|
this.xAxisMeshers[i] = mesher;
|
||||||
}
|
}
|
||||||
|
if (CHECK_NEIGHBOR_FACE_OCCLUSION) {
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
var mesher = new Mesher();
|
||||||
|
mesher.auxiliaryPosition = i;
|
||||||
|
mesher.axis = 2;//X axis
|
||||||
|
mesher.doAuxiliaryFaceOffset = false;
|
||||||
|
this.secondaryXAxisMeshers[i] = mesher;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final long X_I_MSK = 0x4210842108421L;
|
private static final long X_I_MSK = 0x4210842108421L;
|
||||||
@@ -1318,7 +1319,191 @@ public class RenderDataFactory45 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateXNonOpaqueInnerGeometry() {
|
private void generateXNonOpaqueInnerGeometry() {
|
||||||
|
for (int y = 0; y < 32; y++) {
|
||||||
|
long sumA = 0;
|
||||||
|
long sumB = 0;
|
||||||
|
long sumC = 0;
|
||||||
|
int partialHasCount = -1;
|
||||||
|
int msk = 0;
|
||||||
|
for (int z = 0; z < 32; z++) {
|
||||||
|
msk = this.nonOpaqueMasks[y*32+z]&(~0x80000001);//Dont mesh the outer layer
|
||||||
|
|
||||||
|
//Always increment cause can do funny trick (i.e. -1 on skip amount)
|
||||||
|
sumA += X_I_MSK;
|
||||||
|
sumB += X_I_MSK;
|
||||||
|
sumC += X_I_MSK;
|
||||||
|
|
||||||
|
partialHasCount &= ~msk;
|
||||||
|
|
||||||
|
if (z == 30 && partialHasCount != 0) {//Hackfix for incremental count overflow issue
|
||||||
|
int cmsk = partialHasCount;
|
||||||
|
while (cmsk!=0) {
|
||||||
|
int index = Integer.numberOfTrailingZeros(cmsk);
|
||||||
|
cmsk &= ~Integer.lowestOneBit(cmsk);
|
||||||
|
|
||||||
|
this.xAxisMeshers[index].skip(31);
|
||||||
|
this.secondaryXAxisMeshers[index].skip(31);
|
||||||
|
}
|
||||||
|
//Clear the sum
|
||||||
|
sumA &= ~(Long.expand(Integer.toUnsignedLong(partialHasCount), X_I_MSK)*0x1F);
|
||||||
|
sumB &= ~(Long.expand(Integer.toUnsignedLong(partialHasCount)>>11, X_I_MSK)*0x1F);
|
||||||
|
sumC &= ~(Long.expand(Integer.toUnsignedLong(partialHasCount)>>22, X_I_MSK)*0x1F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msk == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iter = msk;
|
||||||
|
while (iter!=0) {
|
||||||
|
int index = Integer.numberOfTrailingZeros(iter);
|
||||||
|
iter &= ~Integer.lowestOneBit(iter);
|
||||||
|
|
||||||
|
|
||||||
|
int skipCount;//Compute the skip count
|
||||||
|
{//TODO: Branch-less
|
||||||
|
//Compute skip and clear
|
||||||
|
if (index<11) {
|
||||||
|
skipCount = (int) (sumA>>(index*5));
|
||||||
|
sumA &= ~(0x1FL<<(index*5));
|
||||||
|
} else if (index<22) {
|
||||||
|
skipCount = (int) (sumB>>((index-11)*5));
|
||||||
|
sumB &= ~(0x1FL<<((index-11)*5));
|
||||||
|
} else {
|
||||||
|
skipCount = (int) (sumC>>((index-22)*5));
|
||||||
|
sumC &= ~(0x1FL<<((index-22)*5));
|
||||||
|
}
|
||||||
|
skipCount &= 0x1F;
|
||||||
|
skipCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mesherA = this.xAxisMeshers[index];
|
||||||
|
var mesherB = this.secondaryXAxisMeshers[index];
|
||||||
|
if (skipCount != 0) {
|
||||||
|
mesherA.skip(skipCount);
|
||||||
|
mesherB.skip(skipCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int idx = index + (z * 32) + (y * 32 * 32);
|
||||||
|
|
||||||
|
long A = this.sectionData[idx*2];
|
||||||
|
long Am = this.sectionData[idx*2+1];
|
||||||
|
|
||||||
|
//Check and generate the mesh for both + and - faces
|
||||||
|
meshNonOpaqueFace(2<<1, A, Am, this.sectionData[(idx-1)*2], this.sectionData[(idx-1)*2+1], mesherB);//-
|
||||||
|
meshNonOpaqueFace((2<<1)|1, A, Am, this.sectionData[(idx+1)*2], this.sectionData[(idx+1)*2+1], mesherA);//+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Need to skip the remaining entries in the skip array
|
||||||
|
{
|
||||||
|
msk = ~msk;//Invert the mask as we only need to set stuff that isnt 0
|
||||||
|
while (msk!=0) {
|
||||||
|
int index = Integer.numberOfTrailingZeros(msk);
|
||||||
|
msk &= ~Integer.lowestOneBit(msk);
|
||||||
|
int skipCount;
|
||||||
|
if (index < 11) {
|
||||||
|
skipCount = (int) (sumA>>(index*5));
|
||||||
|
} else if (index<22) {
|
||||||
|
skipCount = (int) (sumB>>((index-11)*5));
|
||||||
|
} else {
|
||||||
|
skipCount = (int) (sumC>>((index-22)*5));
|
||||||
|
}
|
||||||
|
skipCount &= 0x1F;
|
||||||
|
|
||||||
|
if (skipCount != 0) {
|
||||||
|
this.xAxisMeshers[index].skip(skipCount);
|
||||||
|
this.secondaryXAxisMeshers[index].skip(skipCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static void dualMeshNonOpaqueOuterX(int side, long quad, long meta, int neighborAId, int neighborLight, long neighborAMeta, long neighborBQuad, long neighborBMeta, Mesher ma, Mesher mb) {
|
||||||
|
//side == 0 if is on 0 side and 1 if on 31 side
|
||||||
|
|
||||||
|
//TODO: Check (neighborAId!=0) && works oki
|
||||||
|
if ((neighborAId==0 && ModelQueries.faceExists(meta, ((2<<1)|0)^side))||(neighborAId!=0&&shouldMeshNonOpaqueBlockFace(((2<<1)|0)^side, quad, meta, ((long)neighborAId)<<26, neighborAMeta))) {
|
||||||
|
ma.putNext(((long)side)|
|
||||||
|
quad |
|
||||||
|
(ModelQueries.faceUsesSelfLighting(meta, ((2<<1)|0)^side)?quad:(((long)neighborLight)<<55))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ma.skip(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldMeshNonOpaqueBlockFace(((2<<1)|1)^side, quad, meta, neighborBQuad, neighborBMeta)) {
|
||||||
|
mb.putNext(((long)(side^1))|
|
||||||
|
quad |
|
||||||
|
((ModelQueries.faceUsesSelfLighting(meta, ((2<<1)|1)^side)?quad:neighborBQuad)&(0xFFL<<55))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
mb.skip(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateXNonOpaqueOuterGeometry() {
|
||||||
|
var npx = this.xAxisMeshers[0]; npx.finish();
|
||||||
|
var nnx = this.secondaryXAxisMeshers[0]; nnx.finish();
|
||||||
|
var ppx = this.xAxisMeshers[31]; ppx.finish();
|
||||||
|
var pnx = this.secondaryXAxisMeshers[31]; pnx.finish();
|
||||||
|
|
||||||
|
for (int y = 0; y < 32; y++) {
|
||||||
|
int skipA = 0;
|
||||||
|
int skipB = 0;
|
||||||
|
for (int z = 0; z < 32; z++) {
|
||||||
|
int i = y*32+z;
|
||||||
|
int msk = this.nonOpaqueMasks[i];
|
||||||
|
if ((msk & 1) != 0) {//-x
|
||||||
|
long neighborId = this.neighboringFaces[i];
|
||||||
|
|
||||||
|
int sidx = (i<<5) * 2;
|
||||||
|
long A = this.sectionData[sidx];
|
||||||
|
long Am = this.sectionData[sidx + 1];
|
||||||
|
|
||||||
|
int modelId = 0;
|
||||||
|
long nM = 0;
|
||||||
|
if (Mapper.getBlockId(neighborId) != 0) {//Not air
|
||||||
|
modelId = this.modelMan.getModelId(Mapper.getBlockId(neighborId));
|
||||||
|
nM = this.modelMan.getModelMetadataFromClientId(modelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
nnx.skip(skipA);
|
||||||
|
npx.skip(skipA); skipA = 0;
|
||||||
|
|
||||||
|
dualMeshNonOpaqueOuterX(0, A, Am, modelId, Mapper.getLightId(neighborId), nM, this.sectionData[sidx+2], this.sectionData[sidx+3], nnx, npx);
|
||||||
|
} else {skipA++;}
|
||||||
|
|
||||||
|
if ((msk & (1<<31)) != 0) {//+x
|
||||||
|
long neighborId = this.neighboringFaces[i+32*32];
|
||||||
|
|
||||||
|
int sidx = (i*32+31) * 2;
|
||||||
|
long A = this.sectionData[sidx];
|
||||||
|
long Am = this.sectionData[sidx + 1];
|
||||||
|
|
||||||
|
int modelId = 0;
|
||||||
|
long nM = 0;
|
||||||
|
if (Mapper.getBlockId(neighborId) != 0) {//Not air
|
||||||
|
modelId = this.modelMan.getModelId(Mapper.getBlockId(neighborId));
|
||||||
|
nM = this.modelMan.getModelMetadataFromClientId(modelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
pnx.skip(skipB);
|
||||||
|
ppx.skip(skipB); skipB = 0;
|
||||||
|
|
||||||
|
dualMeshNonOpaqueOuterX(1, A, Am, modelId, Mapper.getLightId(neighborId), nM, this.sectionData[sidx-2], this.sectionData[sidx-1], ppx, pnx);
|
||||||
|
} else {skipB++;}
|
||||||
|
}
|
||||||
|
nnx.skip(skipA);
|
||||||
|
npx.skip(skipA);
|
||||||
|
pnx.skip(skipB);
|
||||||
|
ppx.skip(skipB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateXFaces() {
|
private void generateXFaces() {
|
||||||
@@ -1335,6 +1520,17 @@ public class RenderDataFactory45 {
|
|||||||
for (var mesher : this.xAxisMeshers) {
|
for (var mesher : this.xAxisMeshers) {
|
||||||
mesher.finish();
|
mesher.finish();
|
||||||
}
|
}
|
||||||
|
if (CHECK_NEIGHBOR_FACE_OCCLUSION) {
|
||||||
|
this.generateXNonOpaqueInnerGeometry();
|
||||||
|
this.generateXNonOpaqueOuterGeometry();
|
||||||
|
|
||||||
|
for (var mesher : this.xAxisMeshers) {
|
||||||
|
mesher.finish();
|
||||||
|
}
|
||||||
|
for (var mesher : this.secondaryXAxisMeshers) {
|
||||||
|
mesher.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//section is already acquired and gets released by the parent
|
//section is already acquired and gets released by the parent
|
||||||
@@ -1359,6 +1555,12 @@ public class RenderDataFactory45 {
|
|||||||
mesher.reset();
|
mesher.reset();
|
||||||
mesher.doAuxiliaryFaceOffset = true;
|
mesher.doAuxiliaryFaceOffset = true;
|
||||||
}
|
}
|
||||||
|
if (CHECK_NEIGHBOR_FACE_OCCLUSION) {
|
||||||
|
for (var mesher : this.secondaryXAxisMeshers) {
|
||||||
|
mesher.reset();
|
||||||
|
mesher.doAuxiliaryFaceOffset = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.minX = Integer.MAX_VALUE;
|
this.minX = Integer.MAX_VALUE;
|
||||||
@@ -1375,6 +1577,9 @@ public class RenderDataFactory45 {
|
|||||||
|
|
||||||
//Prepare everything
|
//Prepare everything
|
||||||
int neighborMsk = this.prepareSectionData();
|
int neighborMsk = this.prepareSectionData();
|
||||||
|
if (neighborMsk>>31!=0) {//We failed to get everything so throw exception
|
||||||
|
throw new IdNotYetComputedException(neighborMsk&(~(1<<31)), true);
|
||||||
|
}
|
||||||
this.acquireNeighborData(section, neighborMsk);
|
this.acquireNeighborData(section, neighborMsk);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user