Skip to content

Commit

Permalink
fix bsp triggering with negative, fix quad appending logic, fix quad …
Browse files Browse the repository at this point in the history
…update logic, fix split case logic to take on-plane vertices into account
  • Loading branch information
douira committed Jan 21, 2025
1 parent 79bf7ed commit a8d8abd
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,11 @@ private SortType sortTypeHeuristic() {
// use the given set of quad count limits to determine if a static topo sort
// should be attempted

var attemptLimitIndex = Mth.clamp(normalCount, 2, STATIC_TOPO_SORT_ATTEMPT_LIMITS.length - 1);
if (this.quads.length <= STATIC_TOPO_SORT_ATTEMPT_LIMITS[attemptLimitIndex]) {
return SortType.STATIC_TOPO;
}
// TODO: make topo sort fail on intersecting geometry when SPLIT_QUADS is enabled
// var attemptLimitIndex = Mth.clamp(normalCount, 2, STATIC_TOPO_SORT_ATTEMPT_LIMITS.length - 1);
// if (this.quads.length <= STATIC_TOPO_SORT_ATTEMPT_LIMITS[attemptLimitIndex]) {
// return SortType.STATIC_TOPO;
// }

return SortType.DYNAMIC;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ public void addModifiedQuadIndex(int index) {
this.add(index);
}

public int addAppendedQuadIndex() {
var index = this.addedQuadCount++;
public void addAppendedQuadIndex(int index) {
this.add(index);
return index;
this.addedQuadCount++;
}

public int getAddedQuadCount() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ void addUnalignedPartitionPlane(Vector3fc planeNormal, float distance) {
int pushQuad(FullTQuad quad) {
this.translucentVertexBuffer.push(quad.getVertices(), DefaultMaterials.TRANSLUCENT);

var index = this.size();
this.add(quad);
this.result.ensureUpdatedQuadIndexes().addAppendedQuadIndex(index);

return this.result.ensureUpdatedQuadIndexes().addAppendedQuadIndex();
return index;
}

int updateQuad(FullTQuad quad, int quadIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ static BSPNode buildFromParts(BSPWorkspace workspace, IntArrayList indexes, int
if (axis == UNALIGNED_AXIS) {
workspace.addUnalignedPartitionPlane(planeNormal, partitionDistance);
} else {
workspace.addAlignedPartitionPlane(axis, partitionDistance);
workspace.addAlignedPartitionPlane(axis, Math.abs(partitionDistance));
}

BSPNode oldInsideNode = null;
Expand All @@ -141,16 +141,10 @@ static BSPNode buildFromParts(BSPWorkspace workspace, IntArrayList indexes, int
}
var onPlaneArr = BSPSortState.compressIndexes(onPlane);

if (axis == UNALIGNED_AXIS) {
return new InnerBinaryPartitionBSPNode(
prepareNodeReuse(workspace, indexes, depth),
partitionDistance, planeNormal,
insideNode, outsideNode, onPlaneArr);
} else {
return new InnerBinaryPartitionBSPNode(
prepareNodeReuse(workspace, indexes, depth),
partitionDistance, axis,
insideNode, outsideNode, onPlaneArr);
}
// always use the correct plane normal here because just specifying the axis causes the constructor to use a wrong and unsigned normal
return new InnerBinaryPartitionBSPNode(
prepareNodeReuse(workspace, indexes, depth),
partitionDistance, planeNormal,
insideNode, outsideNode, onPlaneArr);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ static BSPNode build(BSPWorkspace workspace, IntArrayList indexes, int depth, BS

if (TranslucentGeometryCollector.SPLIT_QUADS) {
// try static topo sorting first because splitting quads is even more expensive
// TODO: re-enable static topo sorting once it fails on intersecting quads
// var multiLeafNode = buildTopoMultiLeafNode(workspace, indexes);
// if (multiLeafNode != null) {
// return multiLeafNode;
Expand Down Expand Up @@ -471,6 +472,7 @@ static private BSPNode handleUnsortableBySplitting(BSPWorkspace workspace, IntAr
representativeIndex = splittingGroup.getInt(0);
}
var representative = (FullTQuad) workspace.get(representativeIndex);
var representativeFacing = representative.getFacing();
int initialSplittingGroupSize = splittingGroup.size();

// split all quads by the splitting group's plane
Expand All @@ -493,48 +495,82 @@ static private BSPNode handleUnsortableBySplitting(BSPWorkspace workspace, IntAr
}

var insideQuad = (FullTQuad) workspace.get(candidateIndex);
var quadFacing = insideQuad.getFacing();

// eliminate quads that lie in the split plane
if (quadFacing == representativeFacing && insideQuad.getAccurateDotProduct() == splitDistance &&
(representativeFacing != ModelQuadFacing.UNASSIGNED ||
insideQuad.getVeryAccurateNormal().equals(representative.getVeryAccurateNormal()))) {
splittingGroup.add(candidateIndex);
continue;
}

var vertices = insideQuad.getVertices();

// calculate inside/outside for each vertex
int vertexInsideMap = 0;
int vertexOnPlaneCount = 0;
int insideMap = 0;
int onPlaneMap = 0;
for (int i = 0; i < 4; i++) {
var vertex = vertices[i];
var dot = splitPlane.dot(vertex.x, vertex.y, vertex.z);
if (dot < splitDistance) {
vertexInsideMap |= 1 << i;
insideMap |= 1 << i;
} else if (dot == splitDistance) {
vertexOnPlaneCount++;
onPlaneMap |= 1 << i;
}
}

// add quads that are nearly coplanar to the splitting group to it
if (vertexOnPlaneCount >= 3) {
var onPlaneCount = Integer.bitCount(onPlaneMap);
var insideCount = Integer.bitCount(insideMap);

// treat quads that are actually or nearly (i.e. bent) coplanar as on the plane
if (onPlaneCount >= 3) {
splittingGroup.add(candidateIndex);
continue;
}

// simply add to inside or outside if not split
if (vertexInsideMap == 0) {
// the quad is outside if all vertices are either outside or on the plane
if (insideMap == 0) {
outside.add(candidateIndex);
continue;
}
if (vertexInsideMap == 0b1111) {

// the quad is inside if all vertices are either inside or on the plane
if ((insideMap | onPlaneMap) == 0b1111) {
inside.add(candidateIndex);
continue;
}

// split with two quads or three quads depending on the orientation
var insideCount = Integer.bitCount(vertexInsideMap);
// after dealing with the other cases, now two vertices being on the plane implies the quad is split exactly along its diagonal
// insideCount is 2, onPlaneMap is 0b0101 or 0b1010
if (onPlaneCount == 2) {
// this case can be treated like even splitting if the two on-plane vertices are declared as each part of one of the sides
if (onPlaneMap == 0b0101) {
insideMap |= 0b0001;
} else {
insideMap |= 0b0010;
}
insideCount = 2;
}

// one vertex being on the plane now implies the quad is split on a vertex and through an edge.
// if there is one vertex inside (and two outside), move the on-plane vertex inside to produce an even split case.
// in the other case nothing needs to be done since for splitting the 0-bits in the insideMap are treated as outside.
else if (onPlaneCount == 1 && insideCount == 1) {
insideMap |= onPlaneMap;
insideCount = 2;
}

// split evenly with two quads or three quads (corner chopped off) depending on the orientation
FullTQuad outsideQuad = FullTQuad.splittingCopy(insideQuad);
if (insideCount == 2) {
splitQuadEven(vertexInsideMap, insideQuad, outsideQuad, splitPlane, splitDistance);
splitQuadEven(insideMap, insideQuad, outsideQuad, splitPlane, splitDistance);
} else if (insideCount == 3) {
var secondInsideQuad = splitQuadOdd(vertexInsideMap, insideCount, insideQuad, outsideQuad, splitPlane, splitDistance);
var secondInsideQuad = splitQuadOdd(insideMap, insideCount, insideQuad, outsideQuad, splitPlane, splitDistance);

// TODO: Implement this
} else {
var secondOutsideQuad = splitQuadOdd(vertexInsideMap, insideCount, insideQuad, outsideQuad, splitPlane, splitDistance);
var secondOutsideQuad = splitQuadOdd(insideMap, insideCount, insideQuad, outsideQuad, splitPlane, splitDistance);

// TODO: Implement this
}
Expand Down

0 comments on commit a8d8abd

Please sign in to comment.