Large Geometry extremely slowdown ray casting performance

When I load large geometry(vertices – 53642, faces 90748), I have fps about 14.
I wrote simple method for split geometry to pieces and fps grows over 30.
(Chrome, GPU Intel HD4600)

This code maybe usable for another users and cases?…

 function splitGeometry(geometry, subBoxSize) {
    geometry = geometry.clone();
    subBoxSize = +subBoxSize || 300;

    var boxes = geometry.faces.map(function(f){
        var a = geometry.vertices[f.a];
        var b = geometry.vertices[f.b];
        var c = geometry.vertices[f.c];
        var triMin = new THREE.Vector3(
            Math.min(a.x, b.x, c.x),
            Math.min(a.y, b.y, c.y),
            Math.min(a.z, b.z, c.z)
        );
        var triMax = new THREE.Vector3(
            Math.max(a.x, b.x, c.x),
            Math.max(a.y, b.y, c.y),
            Math.max(a.z, b.z, c.z)
        );
        return new THREE.Box3(triMin, triMax);
    });
    geometry.computeBoundingBox();
    var currentFaces = [{
        box: new THREE.Box3(geometry.boundingBox.min, geometry.boundingBox.max),
        faceIndexes: geometry.faces.map(function (v, k) { return k; })
    }];
    var boxSize = geometry.boundingBox.max.clone().sub(geometry.boundingBox.min);
    for (var split = true; split;) {
        split = false;
        var mxs = Math.max(boxSize.x, boxSize.y, boxSize.z);
        var coord = mxs === boxSize.x ? 'x' : mxs === boxSize.y ? 'y' : 'z';
        boxSize[coord] /= 2;
        var nextFaces = [];
        for (var k = 0; k < currentFaces.length; k++) {
            var fs = currentFaces[k];
            if (fs.faceIndexes.length > subBoxSize) {
                var box1 = fs.box.clone(), box2 = fs.box.clone();
                var faceIndexes1 = [], faceIndexes2 = [];
                box1.max[coord] -= boxSize[coord];
                box2.min[coord] += boxSize[coord];
                for (var j = 0; j < fs.faceIndexes.length; j++) {
                    var fi = fs.faceIndexes[j];
                    if (boxes[fi].isIntersectionBox(box1)) {
                        faceIndexes1.push(fi);
                    } else {
                        faceIndexes2.push(fi);
                    }
                }
                if (faceIndexes1.length) {
                    nextFaces.push({box: box1, faceIndexes: faceIndexes1});
                }
                if (faceIndexes2.length) {
                    nextFaces.push({box: box2, faceIndexes: faceIndexes2});
                }
                split = true;
            } else {
                nextFaces.push(fs);
            }
        }
        currentFaces = nextFaces;
    }
    return currentFaces.map(function (f) {
        var vi = {};
        var newGeometry = new THREE.Geometry();
        newGeometry.faces = [];
        f.faceIndexes.forEach(function (fi) {
            var face = geometry.faces[fi];
            ['a', 'b', 'c'].forEach(function (comp) {
                var vertex = face[comp];
                if (vi[vertex] === undefined) {
                    vi[vertex] = newGeometry.vertices.push(geometry.vertices[vertex]) - 1;
                }
                face[comp] = vi[face[comp]];
            });
            newGeometry.faceVertexUvs[0].push(geometry.faceVertexUvs[0][fi]);
            newGeometry.faces.push(face);
        });
        newGeometry.computeBoundingSphere();
        return newGeometry;
    });
}

Author: Fantashit

1 thought on “Large Geometry extremely slowdown ray casting performance

  1. @tormozok

    Splitting speed up only ray casting, not rendering.

    That makes sense, as a lots of polygon-level checks are eliminated early in the step of checking intersections of the ray with the bounding volumes of each of the parts. See the raycast method in Mesh here. It first checks against the bounding sphere, then against the bounding box, then if there is an intersection with both, it just loops through all the triangles and checks them one by one.

    You can subclass Mesh for your use case and write a custom raycast method that uses any type of spatial subdivisioning.

Comments are closed.