public void Build(Mesh mesh) { if (mesh == null || !mesh.isReadable) { return; } if (nodes != null) { nodes.Clear(); } nodes = new List <KDopNode>(); BuildTriangles(mesh); KDopNode rootNode = new KDopNode(); nodes.Add(rootNode); rootNode.SplitTriangleList(0, triangles.Count, this); nodes[0] = rootNode; }
public KDopBounds SplitTriangleList(int startIndex, int numTriangles, KDopTree kDopTree) { if (numTriangles > 4) { isLeaf = false; int BestPlane = -1; float BestMean = 0.0f; float BestVariance = 0.0f; for (int nPlane = 0; nPlane < KDopTree.NUM_PLANES; nPlane++) { float Mean = 0.0f; float Variance = 0.0f; for (int nTriangle = startIndex; nTriangle < startIndex + numTriangles; nTriangle++) { Mean += kDopTree.triangles[nTriangle].GetCentroid()[nPlane]; } Mean /= (float)numTriangles; for (int nTriangle = startIndex; nTriangle < startIndex + numTriangles; nTriangle++) { float Dot = kDopTree.triangles[nTriangle].GetCentroid()[nPlane]; Variance += (Dot - Mean) * (Dot - Mean); } Variance /= (float)numTriangles; if (Variance >= BestVariance) { BestPlane = nPlane; BestVariance = Variance; BestMean = Mean; } } int Left = startIndex - 1; int Right = startIndex + numTriangles; while (Left < Right) { float Dot; do { Dot = kDopTree.triangles[++Left].GetCentroid()[BestPlane]; }while (Dot < BestMean && Left < Right); do { Dot = kDopTree.triangles[--Right].GetCentroid()[BestPlane]; }while (Dot >= BestMean && Right > 0 && Left < Right); if (Left < Right) { KDopTriangle Temp = kDopTree.triangles[Left]; kDopTree.triangles[Left] = kDopTree.triangles[Right]; kDopTree.triangles[Right] = Temp; } } if (Left == startIndex + numTriangles || Right == startIndex) { Left = startIndex + (numTriangles / 2); } KDopNode leftNode = new KDopNode(); int leftNodeIndex = kDopTree.nodes.Count; kDopTree.nodes.Add(leftNode); data.leftNode = leftNodeIndex; KDopNode rightNode = new KDopNode(); int rightNodeIndex = kDopTree.nodes.Count; kDopTree.nodes.Add(rightNode); data.rightNode = rightNodeIndex; KDopBounds leftBoundingVolume = leftNode.SplitTriangleList(startIndex, Left - startIndex, kDopTree); KDopBounds rightBoundingVolume = rightNode.SplitTriangleList(Left, startIndex + numTriangles - Left, kDopTree); boundingVolumes.Encapsulate(leftBoundingVolume); boundingVolumes.Encapsulate(rightBoundingVolume); kDopTree.nodes[leftNodeIndex] = leftNode; kDopTree.nodes[rightNodeIndex] = rightNode; } else { isLeaf = true; data.startIndex = startIndex; data.numTriangles = numTriangles; for (int triIndex = data.startIndex; triIndex < data.startIndex + numTriangles; ++triIndex) { KDopTriangle tri = kDopTree.triangles[triIndex]; boundingVolumes.Encapsulate(tri.v0); boundingVolumes.Encapsulate(tri.v1); boundingVolumes.Encapsulate(tri.v2); } } return(boundingVolumes); }