void ConvexClipper<Real>::Convert (ConvexPolyhedron<Real>& polyhedron) { // Get visible vertices. int numVertices = (int)mVertices.size(); std::vector<Vector3<Real> > points; int* vMap = new1<int>(numVertices); memset(vMap, 0xFF, numVertices*sizeof(int)); for (int v = 0; v < numVertices; ++v) { const Vertex& vertex = mVertices[v]; if (vertex.Visible) { vMap[v] = (int)points.size(); points.push_back(vertex.Point); } } std::vector<int> indices; std::vector<Plane3<Real> > planes; GetTriangles(indices, planes); // Reorder the indices. for (int c = 0; c < (int)indices.size(); ++c) { int oldC = indices[c]; assertion(0 <= oldC && oldC < numVertices, "Index out of range.\n"); int newC = vMap[oldC]; assertion(0 <= newC && newC < (int)points.size(), "Index out of range.\n"); indices[c] = newC; } delete1(vMap); polyhedron.Create(points, indices, planes); }
//---------------------------------------------------------------------------- void ConvexPolyhedron::CreateEggShape (const Vector3& rkCenter, Real fX0, Real fX1, Real fY0, Real fY1, Real fZ0, Real fZ1, int iMaxSteps, ConvexPolyhedron& rkEgg) { assert( fX0 > 0.0f && fX1 > 0.0f ); assert( fY0 > 0.0f && fY1 > 0.0f ); assert( fZ0 > 0.0f && fZ1 > 0.0f ); assert( iMaxSteps >= 0 ); // Start with an octahedron whose 6 vertices are (-x0,0,0), (x1,0,0), // (0,-y0,0), (0,y1,0), (0,0,-z0), (0,0,z1). The center point will be // added later. vector<Vector3> akPoint(6); akPoint[0] = Vector3(-fX0,0.0f,0.0f); akPoint[1] = Vector3(fX1,0.0f,0.0f); akPoint[2] = Vector3(0.0f,-fY0,0.0f); akPoint[3] = Vector3(0.0f,fY1,0.0f); akPoint[4] = Vector3(0.0f,0.0f,-fZ0); akPoint[5] = Vector3(0.0f,0.0f,fZ1); vector<int> aiConnect(24); aiConnect[ 0] = 1; aiConnect[ 1] = 3; aiConnect[ 2] = 5; aiConnect[ 3] = 3; aiConnect[ 4] = 0; aiConnect[ 5] = 5; aiConnect[ 6] = 0; aiConnect[ 7] = 2; aiConnect[ 8] = 5; aiConnect[ 9] = 2; aiConnect[10] = 1; aiConnect[11] = 5; aiConnect[12] = 3; aiConnect[13] = 1; aiConnect[14] = 4; aiConnect[15] = 0; aiConnect[16] = 3; aiConnect[17] = 4; aiConnect[18] = 2; aiConnect[19] = 0; aiConnect[20] = 4; aiConnect[21] = 1; aiConnect[22] = 2; aiConnect[23] = 4; rkEgg.InitialELabel() = 0; rkEgg.Create(akPoint,aiConnect); // Subdivide the triangles. The midpoints of the edges are computed. // The triangle is replaced by four sub triangles using the original 3 // vertices and the 3 new edge midpoints. int i; for (int iStep = 1; iStep <= iMaxSteps; iStep++) { int iVQuantity = rkEgg.GetVQuantity(); int iEQuantity = rkEgg.GetEQuantity(); int iTQuantity = rkEgg.GetTQuantity(); // compute lifted edge midpoints for (i = 0; i < iEQuantity; i++) { // get edge const MTEdge& rkE = rkEgg.GetEdge(i); int iV0 = rkEgg.GetVLabel(rkE.GetVertex(0)); int iV1 = rkEgg.GetVLabel(rkE.GetVertex(1)); // compute "lifted" centroid to points Vector3 kCen = rkEgg.Point(iV0)+rkEgg.Point(iV1); Real fXR = (kCen.x > 0.0f ? kCen.x/fX1 : kCen.x/fX0); Real fYR = (kCen.y > 0.0f ? kCen.y/fY1 : kCen.y/fY0); Real fZR = (kCen.z > 0.0f ? kCen.z/fZ1 : kCen.z/fZ0); kCen *= Math::InvSqrt(fXR*fXR+fYR*fYR+fZR*fZR); // Add the point to the array. Store the point index in the edge // label for support in adding new triangles. rkEgg.ELabel(i) = iVQuantity++; rkEgg.AddPoint(kCen); } // Add the new triangles and remove the old triangle. The removal // in slot i will cause the last added triangle to be moved to that // slot. This side effect will not interfere with the iteration // and removal of the triangles. for (i = 0; i < iTQuantity; i++) { const MTTriangle& rkT = rkEgg.GetTriangle(i); int iV0 = rkEgg.GetVLabel(rkT.GetVertex(0)); int iV1 = rkEgg.GetVLabel(rkT.GetVertex(1)); int iV2 = rkEgg.GetVLabel(rkT.GetVertex(2)); int iV01 = rkEgg.GetELabel(rkT.GetEdge(0)); int iV12 = rkEgg.GetELabel(rkT.GetEdge(1)); int iV20 = rkEgg.GetELabel(rkT.GetEdge(2)); rkEgg.Insert(iV0,iV01,iV20); rkEgg.Insert(iV01,iV1,iV12); rkEgg.Insert(iV20,iV12,iV2); rkEgg.Insert(iV01,iV12,iV20); rkEgg.Remove(iV0,iV1,iV2); } } // add center for (i = 0; i < (int)rkEgg.m_akPoint.size(); i++) rkEgg.m_akPoint[i] += rkCenter; rkEgg.UpdatePlanes(); }