QBVHAccel::QBVHAccel(const unsigned int vCount, const unsigned int triangleCount, const Triangle *p, const Point *v, u_int mp, u_int fst, u_int sf) : Accellerator(vCount, triangleCount, p,v),fullSweepThreshold(fst), skipFactor(sf), maxPrimsPerLeaf(mp) { initialized = false; maxDepth = 0; int nPrims = triangleCount; vertices = v; triangles = p; // Temporary data for building u_int *primsIndexes = new u_int[nPrims + 3]; // For the case where // the last quad would begin at the last primitive // (or the second or third last primitive) // The number of nodes depends on the number of primitives, // and is bounded by 2 * nPrims - 1. // Even if there will normally have at least 4 primitives per leaf, // it is not always the case => continue to use the normal bounds. nNodes = 0; maxNodes = 1; for (u_int layer = ((nPrims + maxPrimsPerLeaf - 1) / maxPrimsPerLeaf + 3) / 4; layer != 1; layer = (layer + 3) / 4) maxNodes += layer; nodes = AllocAligned<QBVHNode>(maxNodes); for (u_int i = 0; i < maxNodes; ++i) nodes[i] = QBVHNode(); // The arrays that will contain // - the bounding boxes for all triangles // - the centroids for all triangles BBox *primsBboxes = new BBox[nPrims]; Point *primsCentroids = new Point[nPrims]; // The bouding volume of all the centroids BBox centroidsBbox; // Fill each base array for (u_int i = 0; i < triangleCount; ++i) { // This array will be reorganized during construction. primsIndexes[i] = i; // Compute the bounding box for the triangle primsBboxes[i] = triangles[i].WorldBound(v); primsBboxes[i].Expand(RAY_EPSILON); primsCentroids[i] = (primsBboxes[i].pMin + primsBboxes[i].pMax) * .5f; // Update the global bounding boxes worldBound = Union(worldBound, primsBboxes[i]); centroidsBbox = Union(centroidsBbox, primsCentroids[i]); } // Arbitrarily take the last primitive for the last 3 primsIndexes[nPrims] = nPrims - 1; primsIndexes[nPrims + 1] = nPrims - 1; primsIndexes[nPrims + 2] = nPrims - 1; // Recursively build the tree //LR_LOG(context, "Building QBVH, primitives: " << nPrims << ", initial nodes: " << maxNodes); nQuads = 0; BuildTree(0, nPrims, primsIndexes, primsBboxes, primsCentroids,worldBound, centroidsBbox, -1, 0, 0); prims = AllocAligned<QuadTriangle>(nQuads); nQuads = 0; PreSwizzle(0, primsIndexes); //LR_LOG(context, "QBVH completed with " << nNodes << "/" << maxNodes << " nodes"); //LR_LOG(context, "Total QBVH memory usage: " << nNodes * sizeof(QBVHNode) / 1024 << "Kbytes"); //LR_LOG(context, "Total QBVH QuadTriangle count: " << nQuads); // Release temporary memory delete[] primsBboxes; delete[] primsCentroids; delete[] primsIndexes; }
void QBVHAccel::Init(const Mesh *m) { assert (!initialized); mesh = m; const unsigned int totalTriangleCount = mesh->GetTotalTriangleCount(); // Temporary data for building u_int *primsIndexes = new u_int[totalTriangleCount + 3]; // For the case where // the last quad would begin at the last primitive // (or the second or third last primitive) // The number of nodes depends on the number of primitives, // and is bounded by 2 * nPrims - 1. // Even if there will normally have at least 4 primitives per leaf, // it is not always the case => continue to use the normal bounds. nNodes = 0; maxNodes = 1; for (u_int layer = ((totalTriangleCount + maxPrimsPerLeaf - 1) / maxPrimsPerLeaf + 3) / 4; layer != 1; layer = (layer + 3) / 4) maxNodes += layer; nodes = AllocAligned<QBVHNode> (maxNodes); for (u_int i = 0; i < maxNodes; ++i) nodes[i] = QBVHNode(); // The arrays that will contain // - the bounding boxes for all triangles // - the centroids for all triangles BBox *primsBboxes = new BBox[totalTriangleCount]; Point *primsCentroids = new Point[totalTriangleCount]; // The bouding volume of all the centroids BBox centroidsBbox; const Point *verts = mesh->GetVertices(); const Triangle *triangles = mesh->GetTriangles(); // Fill each base array for (u_int i = 0; i < totalTriangleCount; ++i) { // This array will be reorganized during construction. primsIndexes[i] = i; // Compute the bounding box for the triangle primsBboxes[i] = triangles[i].WorldBound(verts); primsBboxes[i].Expand(RAY_EPSILON); primsCentroids[i] = (primsBboxes[i].pMin + primsBboxes[i].pMax) * .5f; // Update the global bounding boxes worldBound = Union(worldBound, primsBboxes[i]); centroidsBbox = Union(centroidsBbox, primsCentroids[i]); } // Arbitrarily take the last primitive for the last 3 primsIndexes[totalTriangleCount] = totalTriangleCount - 1; primsIndexes[totalTriangleCount + 1] = totalTriangleCount - 1; primsIndexes[totalTriangleCount + 2] = totalTriangleCount - 1; // Recursively build the tree LR_LOG( "Building QBVH, primitives: " << totalTriangleCount << ", initial nodes: " << maxNodes); nQuads = 0; BuildTree(0, totalTriangleCount, primsIndexes, primsBboxes, primsCentroids, worldBound, centroidsBbox, -1, 0, 0); prims = AllocAligned<QuadTriangle> (nQuads); nQuads = 0; PreSwizzle(0, primsIndexes); LR_LOG( "QBVH completed with " << nNodes << "/" << maxNodes << " nodes"); LR_LOG( "Total QBVH memory usage: " << nNodes * sizeof(QBVHNode) / 1024 << "Kbytes"); LR_LOG( "Total QBVH QuadTriangle count: " << nQuads); LR_LOG( "Max. QBVH Depth: " << maxDepth); // Release temporary memory delete[] primsBboxes; delete[] primsCentroids; delete[] primsIndexes; initialized = true; }