Browse Source

Added culling test to the occlusion test, so that negative projections don't pass.

David Piuva 3 years ago
parent
commit
7266ba13be
1 changed files with 24 additions and 7 deletions
  1. 24 7
      Source/DFPSR/api/modelAPI.cpp

+ 24 - 7
Source/DFPSR/api/modelAPI.cpp

@@ -467,13 +467,30 @@ public:
 			}
 		}
 	}
-	// Occlusion test for whole model bounds
-	//   Because outerBound gives negative regions when outside of the picture, it can also be used as a rough culling test
+	// Occlusion test for whole model bounds.
+	// Returns false if the convex hull of the corners has a chance to be seen from the camera.
 	bool isHullOccluded(ProjectedPoint* outputHullCorners, const FVector3D* inputHullCorners, int cornerCount, const Transform3D &modelToWorldTransform, const Camera &camera) {
+		FVector3D cameraPoints[cornerCount];
 		for (int p = 0; p < cornerCount; p++) {
-			FVector3D worldPoint = modelToWorldTransform.transformPoint(inputHullCorners[p]);
-			FVector3D cameraPoint = camera.worldToCamera(worldPoint);
-			outputHullCorners[p] = camera.cameraToScreen(cameraPoint);
+			cameraPoints[p] = camera.worldToCamera(modelToWorldTransform.transformPoint(inputHullCorners[p]));
+			outputHullCorners[p] = camera.cameraToScreen(cameraPoints[p]);
+		}
+		// Culling test to see if all points are outside of the same plane of the view frustum.
+		for (int s = 0; s < camera.cullFrustum.getPlaneCount(); s++) {
+			bool allOutside = true; // True until prooven false.
+			FPlane3D plane = camera.cullFrustum.getPlane(s);
+			for (int p = 0; p < cornerCount; p++) {
+				if (plane.inside(cameraPoints[p])) {
+					// One point was inside of this plane, so it can not guarantee that all interpolated points between the corners are outside.
+					allOutside = false;
+					break;
+				}
+			}
+			// If all points are outside of the same plane in the view frustum...
+			if (allOutside) {
+				// ...then we know that all interpolated points in between are also outside of this plane.
+				return true; // Occluded due to failing culling test.
+			}
 		}
 		IRect pixelBound = getPixelBoundFromProjection(outputHullCorners, cornerCount);
 		float closestDistance = std::numeric_limits<float>::infinity();
@@ -485,11 +502,11 @@ public:
 		for (int cellY = outerBound.top(); cellY < outerBound.bottom(); cellY++) {
 			for (int cellX = outerBound.left(); cellX < outerBound.right(); cellX++) {
 				if (closestDistance < image_readPixel_clamp(this->depthGrid, cellX, cellY)) {
-					return false;
+					return false; // Visible because one cell had a more distant maximum depth.
 				}
 			}
 		}
-		return true;
+		return true; // Occluded, because none of the cells had a more distant depth.
 	}
 	// Checks if the box from minimum to maximum in object space is fully occluded when seen by the camera
 	// Must be the same camera as when occluders filled the grid with occlusion depth