slightly faster raycasts

This commit is contained in:
RandomityGuy 2024-06-19 12:17:11 +05:30
parent 82ceb35251
commit 6f0b5857e4
11 changed files with 38 additions and 22 deletions

View file

@ -6,7 +6,7 @@ import h3d.col.Bounds;
interface IBVHObject { interface IBVHObject {
var boundingBox:Bounds; var boundingBox:Bounds;
var key:Int; var key:Int;
function rayCast(rayOrigin:Vector, rayDirection:Vector, results:Array<octree.IOctreeObject.RayIntersectionData>):Void; function rayCast(rayOrigin:Vector, rayDirection:Vector, results:Array<octree.IOctreeObject.RayIntersectionData>, bestT:Float):Float;
} }
@:generic @:generic
@ -463,7 +463,7 @@ class BVHTree<T:IBVHObject> {
return res; return res;
} }
public function rayCast(origin:Vector, direction:Vector) { public function rayCast(origin:Vector, direction:Vector, bestT:Float) {
var res = []; var res = [];
if (this.root == null) if (this.root == null)
return res; return res;
@ -476,7 +476,7 @@ class BVHTree<T:IBVHObject> {
var currentnode = this.nodes[current]; var currentnode = this.nodes[current];
if (currentnode.collideRay(ray)) { if (currentnode.collideRay(ray)) {
if (currentnode.isLeaf) { if (currentnode.isLeaf) {
currentnode.object.rayCast(origin, direction, res); bestT = currentnode.object.rayCast(origin, direction, res, bestT);
} else { } else {
if (currentnode.child1 != -1) if (currentnode.child1 != -1)
q.push(currentnode.child1); q.push(currentnode.child1);

View file

@ -48,8 +48,9 @@ class BoxCollisionEntity extends CollisionEntity implements IBVHObject {
} }
} }
public override function rayCast(rayOrigin:Vector, rayDirection:Vector, results:Array<octree.IOctreeObject.RayIntersectionData>) { public override function rayCast(rayOrigin:Vector, rayDirection:Vector, results:Array<octree.IOctreeObject.RayIntersectionData>, bestT:Float) {
// TEMP cause bruh // TEMP cause bruh
return Math.POSITIVE_INFINITY;
} }
public override function sphereIntersection(collisionEntity:SphereCollisionEntity, timeState:TimeState) { public override function sphereIntersection(collisionEntity:SphereCollisionEntity, timeState:TimeState) {

View file

@ -141,7 +141,7 @@ class CollisionEntity implements IOctreeObject implements IBVHObject {
} }
} }
public function rayCast(rayOrigin:Vector, rayDirection:Vector, results:Array<RayIntersectionData>) { public function rayCast(rayOrigin:Vector, rayDirection:Vector, results:Array<RayIntersectionData>, bestT:Float) {
var invMatrix = invTransform; var invMatrix = invTransform;
var invTPos = invMatrix.clone(); var invTPos = invMatrix.clone();
invTPos.transpose(); invTPos.transpose();
@ -159,13 +159,17 @@ class CollisionEntity implements IOctreeObject implements IBVHObject {
// } // }
// return intersections; // iData; // return intersections; // iData;
// } else { // } else {
var intersections = grid.rayCast(rStart, rDir); // this.bvh.rayCast(rStart, rDir); var intersections = grid.rayCast(rStart, rDir, bestT); // this.bvh.rayCast(rStart, rDir);
for (i in intersections) { for (i in intersections) {
i.point.transform(transform); i.point.transform(transform);
i.normal.transform3x3(invTPos); i.normal.transform3x3(invTPos);
i.normal.normalize(); i.normal.normalize();
results.push(i); if (i.t < bestT) {
bestT = i.t;
results.push(i);
}
} }
return bestT;
// } // }
} }

View file

@ -139,7 +139,7 @@ class CollisionSurface implements IOctreeObject implements IBVHObject {
normals.push(z); normals.push(z);
} }
public function rayCast(rayOrigin:Vector, rayDirection:Vector, intersections:Array<RayIntersectionData>) { public function rayCast(rayOrigin:Vector, rayDirection:Vector, intersections:Array<RayIntersectionData>, bestT:Float) {
var i = 0; var i = 0;
while (i < indices.length) { while (i < indices.length) {
var p1 = getPoint(indices[i]); var p1 = getPoint(indices[i]);
@ -152,10 +152,19 @@ class CollisionSurface implements IOctreeObject implements IBVHObject {
var ip = rayOrigin.add(rayDirection.multiply(t)); var ip = rayOrigin.add(rayDirection.multiply(t));
ip.w = 1; ip.w = 1;
if (t >= 0 && Collision.PointInTriangle(ip, p1, p2, p3)) { if (t >= 0 && Collision.PointInTriangle(ip, p1, p2, p3)) {
intersections.push({point: ip, normal: n, object: cast this}); if (t < bestT) {
bestT = t;
intersections.push({
point: ip,
normal: n,
object: cast this,
t: t
});
}
} }
i += 3; i += 3;
} }
return bestT;
} }
public function support(direction:Vector, transform:Matrix) { public function support(direction:Vector, transform:Matrix) {

View file

@ -139,12 +139,12 @@ class CollisionWorld {
var results = []; var results = [];
for (obj in objs) { for (obj in objs) {
var oo = cast(obj, CollisionEntity); var oo = cast(obj, CollisionEntity);
oo.rayCast(rayStart, rayDirection, results); oo.rayCast(rayStart, rayDirection, results, rayLength);
} }
for (obj in dynObjs) { for (obj in dynObjs) {
var oo = cast(obj, CollisionEntity); var oo = cast(obj, CollisionEntity);
oo.rayCast(rayStart, rayDirection, results); oo.rayCast(rayStart, rayDirection, results, rayLength);
} }
// results = results.concat(this.staticWorld.rayCast(rayStart, rayDirection)); // results = results.concat(this.staticWorld.rayCast(rayStart, rayDirection));
return results; return results;

View file

@ -9,7 +9,7 @@ class Grid {
public var cellSize:Vector; // The dimensions of one cell public var cellSize:Vector; // The dimensions of one cell
static var CELL_SIZE = 16; static var CELL_SIZE = 24;
public var CELL_DIV = new Vector(CELL_SIZE, CELL_SIZE); // split the bounds into cells of dimensions 1/16th of the corresponding dimensions of the bounds public var CELL_DIV = new Vector(CELL_SIZE, CELL_SIZE); // split the bounds into cells of dimensions 1/16th of the corresponding dimensions of the bounds
@ -124,7 +124,7 @@ class Grid {
return elegantPair(elegantPair(x, y), z); return elegantPair(elegantPair(x, y), z);
} }
public function rayCast(origin:Vector, direction:Vector) { public function rayCast(origin:Vector, direction:Vector, bestT:Float) {
var cell = origin.sub(this.bounds.getMin().toVector()); var cell = origin.sub(this.bounds.getMin().toVector());
cell.x /= this.cellSize.x; cell.x /= this.cellSize.x;
cell.y /= this.cellSize.y; cell.y /= this.cellSize.y;
@ -175,7 +175,7 @@ class Grid {
if (surf.key == searchKey) if (surf.key == searchKey)
continue; continue;
surf.key = searchKey; surf.key = searchKey;
surf.rayCast(origin, direction, results); bestT = surf.rayCast(origin, direction, results, bestT);
} }
if (tmax.x < tmax.y) { if (tmax.x < tmax.y) {
X = X + stepX; X = X + stepX;

View file

@ -69,8 +69,9 @@ class SphereCollisionEntity extends CollisionEntity {
} }
} }
public override function rayCast(rayOrigin:Vector, rayDirection:Vector, results:Array<octree.IOctreeObject.RayIntersectionData>) { public override function rayCast(rayOrigin:Vector, rayDirection:Vector, results:Array<octree.IOctreeObject.RayIntersectionData>, bestT:Float) {
// TEMP cause bruh // TEMP cause bruh
return Math.POSITIVE_INFINITY;
} }
public override function sphereIntersection(collisionEntity:SphereCollisionEntity, timeState:TimeState) { public override function sphereIntersection(collisionEntity:SphereCollisionEntity, timeState:TimeState) {

View file

@ -49,7 +49,7 @@ class GemSpawnPoint implements IOctreeObject {
this.priority = priority; this.priority = priority;
} }
public function rayCast(rayOrigin:Vector, rayDirection:Vector, resultSet:Array<RayIntersectionData>) { public function rayCast(rayOrigin:Vector, rayDirection:Vector, resultSet:Array<RayIntersectionData>, bestT:Float):Float {
throw new haxe.exceptions.NotImplementedException(); // Not applicable throw new haxe.exceptions.NotImplementedException(); // Not applicable
} }
} }

View file

@ -9,9 +9,10 @@ class RayIntersectionData {
var point:Vector; var point:Vector;
var normal:Vector; var normal:Vector;
var object:IOctreeObject; var object:IOctreeObject;
var t:Float;
} }
interface IOctreeObject extends IOctreeElement { interface IOctreeObject extends IOctreeElement {
var boundingBox:Bounds; var boundingBox:Bounds;
function rayCast(rayOrigin:Vector, rayDirection:Vector, resultSet:Array<RayIntersectionData>):Void; function rayCast(rayOrigin:Vector, rayDirection:Vector, resultSet:Array<RayIntersectionData>, bestT:Float):Float;
} }

View file

@ -153,9 +153,9 @@ class Octree {
} }
/** Returns a list of all objects that intersect with the given ray, sorted by distance. */ /** Returns a list of all objects that intersect with the given ray, sorted by distance. */
public function raycast(rayOrigin:Vector, rayDirection:Vector) { public function raycast(rayOrigin:Vector, rayDirection:Vector, bestT:Float) {
var intersections:Array<OctreeIntersection> = []; var intersections:Array<OctreeIntersection> = [];
this.root.raycast(rayOrigin, rayDirection, intersections); this.root.raycast(rayOrigin, rayDirection, intersections, bestT);
intersections.sort((a, b) -> (a.distance == b.distance) ? 0 : (a.distance > b.distance ? 1 : -1)); intersections.sort((a, b) -> (a.distance == b.distance) ? 0 : (a.distance > b.distance ? 1 : -1));
return intersections; return intersections;
} }

View file

@ -192,7 +192,7 @@ class OctreeNode implements IOctreeElement {
return maxmin; return maxmin;
} }
public function raycast(rayOrigin:Vector, rayDirection:Vector, intersections:Array<OctreeIntersection>) { public function raycast(rayOrigin:Vector, rayDirection:Vector, intersections:Array<OctreeIntersection>, bestT:Float) {
var ray = Ray.fromValues(rayOrigin.x, rayOrigin.y, rayOrigin.z, rayDirection.x, rayDirection.y, rayDirection.z); var ray = Ray.fromValues(rayOrigin.x, rayOrigin.y, rayOrigin.z, rayDirection.x, rayDirection.y, rayDirection.z);
// Construct the loose bounding box of this node (2x in size, with the regular bounding box in the center) // Construct the loose bounding box of this node (2x in size, with the regular bounding box in the center)
@ -201,7 +201,7 @@ class OctreeNode implements IOctreeElement {
for (obj in this.objects) { for (obj in this.objects) {
var iSecs = []; var iSecs = [];
obj.rayCast(rayOrigin, rayDirection, iSecs); obj.rayCast(rayOrigin, rayDirection, iSecs, bestT);
for (intersection in iSecs) { for (intersection in iSecs) {
var intersectionData = new OctreeIntersection(); var intersectionData = new OctreeIntersection();
intersectionData.distance = rayOrigin.distance(intersection.point); intersectionData.distance = rayOrigin.distance(intersection.point);
@ -215,7 +215,7 @@ class OctreeNode implements IOctreeElement {
if (this.octants != null) { if (this.octants != null) {
for (i in 0...8) { for (i in 0...8) {
var octant = this.octants[i]; var octant = this.octants[i];
octant.raycast(rayOrigin, rayDirection, intersections); octant.raycast(rayOrigin, rayDirection, intersections, bestT);
} }
} }
} }