static void kdSerialize(u::vector<unsigned char> &buffer, const T *data, size_t size) { const unsigned char *const beg = (const unsigned char *const)data; const unsigned char *const end = ((const unsigned char *const)data) + size; buffer.insert(buffer.end(), beg, end); }
kdNode::kdNode(kdTree *tree, const u::vector<int> &tris, size_t recursionDepth) : m_front(nullptr) , m_back(nullptr) , m_sphereRadius(0.0f) { const size_t triangleCount = tris.size(); if (recursionDepth > tree->m_depth) tree->m_depth = recursionDepth; if (recursionDepth > kdTree::kMaxRecursionDepth) return; tree->m_nodeCount++; if (!calculateSphere(tree, tris)) { u::Log::err("[world] => level geometry is too large: collision detection and rendering may not work"); return; } u::vector<int> fx, fy, fz; // front u::vector<int> bx, by, bz; // back u::vector<int> sx, sy, sz; // split u::vector<int> *const frontList[3] = { &fx, &fy, &fz }; u::vector<int> *const backList[3] = { &bx, &by, &bz }; u::vector<int> *const splitList[3] = { &sx, &sy, &sz }; m::plane plane[3]; float ratio[3]; size_t best = recursionDepth % 3; // find a plane which gives a good balanced node for (size_t i = 0; i < 3; i++) { split(tree, tris, m::axis(i), *frontList[i], *backList[i], *splitList[i], plane[i]); const size_t fsize = (*frontList[i]).size(); const size_t bsize = (*backList[i]).size(); if (fsize > bsize) ratio[i] = (float)bsize / (float)fsize; else ratio[i] = (float)fsize / (float)bsize; } float bestRatio = 0.0f; for (size_t i = 0; i < 3; i++) { if (ratio[i] > bestRatio) { best = i; bestRatio = ratio[i]; } } m_splitPlane = plane[best]; // when there isn't many triangles left, create a leaf. In doing so we can // continue to create further subdivisions. if (frontList[best]->size() == 0 || backList[best]->size() == 0 || triangleCount <= kdTree::kMaxTrianglesPerLeaf) { // create subspace with `triangleCount` polygons m_triangles.insert(m_triangles.begin(), tris.begin(), tris.end()); tree->m_leafCount++; return; } // insert the split triangles on both sides of the plane. frontList[best]->insert(frontList[best]->end(), splitList[best]->begin(), splitList[best]->end()); backList[best]->insert(backList[best]->end(), splitList[best]->begin(), splitList[best]->end()); // recurse m_front = new kdNode(tree, *frontList[best], recursionDepth + 1); m_back = new kdNode(tree, *backList[best], recursionDepth + 1); }