//----------------------------------------------------------------------- /// <summary> /// 查找交集 /// </summary> public void _calcIntersections() { mIntersectionsMap.Clear(); mIntersections.Clear(); //std::map<Ogre::Vector3, PathIntersection, Vector3Comparator> pointSet; std_map <Vector3, std_vector <PathCoordinate> > pointSet = new std_map <Vector3, std_vector <PathCoordinate> >(new Vector3Comparator()); // for (std::vector<Path>::iterator it = mPaths.begin(); it!= mPaths.end(); ++it) uint it_index = 0; foreach (var it in mPaths) { uint it_point_index = 0; //for (std::vector<Ogre::Vector3>::const_iterator it2 = it->getPoints().begin(); it2 != it->getPoints().end(); ++it2) foreach (var it2 in it._getPoints()) { //PathCoordinate pc(it-mPaths.begin(), it2-it->getPoints().begin()); PathCoordinate pc = new PathCoordinate(it_index, it_point_index); //if (pointSet.find(*it2)==pointSet.end()) if (!pointSet.ContainsKey(it2)) { std_vector <PathCoordinate> pi = new std_vector <PathCoordinate>(); pi.Add(pc); //pointSet[it2] = pi; pointSet.Add(it2, pi); } else { pointSet[it2].push_back(pc); } it_point_index++; } it_index++; } //for (std::map<Ogre::Vector3, PathIntersection, Vector3Comparator>::iterator it = pointSet.begin(); it != pointSet.end(); ++it) foreach (var it_ps in pointSet) { if (it_ps.Value.size() > 1) { foreach (var it2 in it_ps.Value) { //mIntersectionsMap[*it2] = it->second; if (mIntersectionsMap.ContainsKey(it2)) { mIntersectionsMap[it2] = it_ps.Value; } else { mIntersectionsMap.Add(it2, it_ps.Value); } } mIntersections.push_back(it_ps.Value); } } // }
//----------------------------------------------------------------------- /// <summary> /// 查找交集 /// </summary> public void _calcIntersections() { mIntersectionsMap.Clear(); mIntersections.Clear(); //std::map<Ogre::Vector3, PathIntersection, Vector3Comparator> pointSet; std_map<Vector3, std_vector<PathCoordinate>> pointSet = new std_map<Vector3, std_vector<PathCoordinate>>(new Vector3Comparator()); // for (std::vector<Path>::iterator it = mPaths.begin(); it!= mPaths.end(); ++it) uint it_index = 0; foreach (var it in mPaths) { uint it_point_index = 0; //for (std::vector<Ogre::Vector3>::const_iterator it2 = it->getPoints().begin(); it2 != it->getPoints().end(); ++it2) foreach (var it2 in it._getPoints()) { //PathCoordinate pc(it-mPaths.begin(), it2-it->getPoints().begin()); PathCoordinate pc = new PathCoordinate(it_index, it_point_index); //if (pointSet.find(*it2)==pointSet.end()) if (!pointSet.ContainsKey(it2)) { std_vector<PathCoordinate> pi = new std_vector<PathCoordinate>(); pi.Add(pc); //pointSet[it2] = pi; pointSet.Add(it2, pi); } else { pointSet[it2].push_back(pc); } it_point_index++; } it_index++; } //for (std::map<Ogre::Vector3, PathIntersection, Vector3Comparator>::iterator it = pointSet.begin(); it != pointSet.end(); ++it) foreach (var it_ps in pointSet) { if (it_ps.Value.size() > 1) { foreach (var it2 in it_ps.Value) { //mIntersectionsMap[*it2] = it->second; if (mIntersectionsMap.ContainsKey(it2)) { mIntersectionsMap[it2] = it_ps.Value; } else { mIntersectionsMap.Add(it2, it_ps.Value); } } mIntersections.push_back(it_ps.Value); } } // }
//-------------------------------------------------------------- public void modify() { if (mInputTriangleBuffer == null) { OGRE_EXCEPT("Exception::ERR_INVALID_STATE", "Input triangle buffer must be set", "__FUNCTION__"); } ; //std.map<Vector3, int, Vector3Comparator> mapExistingVertices = new std.map<Vector3, int, Vector3Comparator>(); std_map <Vector3, int> mapExistingVertices = new std_map <Vector3, int>(new Vector3Comparator()); std_vector <TriangleBuffer.Vertex> vertices = mInputTriangleBuffer.getVertices(); std_vector <int> indices = mInputTriangleBuffer.getIndices(); int newSize = vertices.size(); // for (std::vector<TriangleBuffer::Vertex>::iterator it = vertices.begin(); it!= vertices.end(); ++it) for (int i = 0; i < vertices.Count; i++) { //size_t currentIndex = it - vertices.begin(); TriangleBuffer.Vertex it = vertices[i]; int currentIndex = i; if (currentIndex >= newSize) { break; } //if (mapExistingVertices.find(it.mPosition) == mapExistingVertices.end()) // mapExistingVertices[it.mPosition] = currentIndex; if (mapExistingVertices.find(it.mPosition) == -1) { mapExistingVertices.insert(it.mPosition, currentIndex); } else { int existingIndex = mapExistingVertices[it.mPosition]; --newSize; if (currentIndex == newSize) { //for (std::vector<int>::iterator it2 = indices.begin(); it2 != indices.end(); ++it2) for (int j = 0; j < indices.Count; j++) { int it2 = indices[j]; if (it2 == currentIndex) { //*it2 = existingIndex; indices[j] = existingIndex; } } } else { int lastIndex = newSize; //*it = vertices[lastIndex]; it = vertices[lastIndex]; //for (std::vector<int>::iterator it2 = indices.begin(); it2 != indices.end(); ++it2) for (int j = 0; j < indices.Count; j++) { int it2 = indices[j]; //if (*it2 == currentIndex) if (it2 == currentIndex) { //*it2 = existingIndex; indices[j] = existingIndex; } //else if (*it2 == lastIndex) else if (it2 == lastIndex) { //*it2 = currentIndex; indices[j] = currentIndex; } } } } } }
//-------------------------------------------------------------- public void modify() { if (mInputTriangleBuffer == null) OGRE_EXCEPT("Exception::ERR_INVALID_STATE", "Input triangle buffer must be set", "__FUNCTION__"); ; //std.map<Vector3, int, Vector3Comparator> mapExistingVertices = new std.map<Vector3, int, Vector3Comparator>(); std_map<Vector3, int> mapExistingVertices = new std_map<Vector3, int>(new Vector3Comparator()); std_vector<TriangleBuffer.Vertex> vertices = mInputTriangleBuffer.getVertices(); std_vector<int> indices = mInputTriangleBuffer.getIndices(); int newSize = vertices.size(); // for (std::vector<TriangleBuffer::Vertex>::iterator it = vertices.begin(); it!= vertices.end(); ++it) for (int i = 0; i < vertices.Count; i++) { //size_t currentIndex = it - vertices.begin(); TriangleBuffer.Vertex it = vertices[i]; int currentIndex = i; if (currentIndex >= newSize) break; //if (mapExistingVertices.find(it.mPosition) == mapExistingVertices.end()) // mapExistingVertices[it.mPosition] = currentIndex; if (mapExistingVertices.find(it.mPosition) == -1) { mapExistingVertices.insert(it.mPosition, currentIndex); } else { int existingIndex = mapExistingVertices[it.mPosition]; --newSize; if (currentIndex == newSize) { //for (std::vector<int>::iterator it2 = indices.begin(); it2 != indices.end(); ++it2) for (int j = 0; j < indices.Count; j++) { int it2 = indices[j]; if (it2 == currentIndex) { //*it2 = existingIndex; indices[j] = existingIndex; } } } else { int lastIndex = newSize; //*it = vertices[lastIndex]; it = vertices[lastIndex]; //for (std::vector<int>::iterator it2 = indices.begin(); it2 != indices.end(); ++it2) for (int j = 0; j < indices.Count; j++) { int it2 = indices[j]; //if (*it2 == currentIndex) if (it2 == currentIndex) { //*it2 = existingIndex; indices[j] = existingIndex; } //else if (*it2 == lastIndex) else if (it2 == lastIndex) { //*it2 = currentIndex; indices[j] = currentIndex; } } } } } }
//----------------------------------------------------------------------- //typedef std::vector<PathCoordinate> PathIntersection; public static void _extrudeIntersectionImpl(ref TriangleBuffer buffer, std_vector <MultiPath.PathCoordinate> intersection, MultiPath multiPath, Shape shape, Track shapeTextureTrack) { Vector3 intersectionLocation = multiPath.getPath((int)intersection[0].pathIndex).getPoint((int)intersection[0].pointIndex); Quaternion firstOrientation = Utils._computeQuaternion(multiPath.getPath((int)intersection[0].pathIndex).getDirectionBefore((int)intersection[0].pointIndex)); Vector3 refX = firstOrientation * Vector3.UNIT_X; Vector3 refZ = firstOrientation * Vector3.UNIT_Z; std_vector <Vector2> v2s = new std_vector <Vector2>(); std_vector <MultiPath.PathCoordinate> coords = new std_vector <MultiPath.PathCoordinate>(); std_vector <float> direction = new std_vector <float>(); for (int i = 0; i < intersection.size(); ++i) { Path path = multiPath.getPath((int)intersection[i].pathIndex); int pointIndex = (int)intersection[i].pointIndex; if (pointIndex > 0 || path.isClosed()) { Vector3 vb = path.getDirectionBefore(pointIndex); Vector2 vb2 = new Vector2(vb.DotProduct(refX), vb.DotProduct(refZ)); v2s.push_back(vb2); coords.push_back(intersection[i]); direction.push_back(1); } if (pointIndex < path.getSegCount() || path.isClosed()) { Vector3 va = -path.getDirectionAfter(pointIndex); Vector2 va2 = new Vector2(va.DotProduct(refX), va.DotProduct(refZ)); v2s.push_back(va2); coords.push_back(intersection[i]); direction.push_back(-1); } } std_map <Radian, int> angles = new std_map <Radian, int>(); for (int i = 1; i < v2s.Count; ++i) { //angles[Utils.angleTo(v2s[0], v2s[i])] = i; angles.insert(Utils.angleTo(v2s[0], v2s[i]), i); } std_vector <int> orderedIndices = new std_vector <int>(); orderedIndices.push_back(0); //for (std_map<Radian, int>.Enumerator it = angles.begin(); it != angles.end(); ++it) foreach (var it in angles) { orderedIndices.push_back(it.Value); } for (int i = 0; i < orderedIndices.size(); ++i) { int idx = orderedIndices[i]; int idxBefore = orderedIndices[Utils.modulo(i - 1, orderedIndices.Count)]; int idxAfter = orderedIndices[Utils.modulo(i + 1, orderedIndices.Count)]; Radian angleBefore = (Utils.angleBetween(v2s[idx], v2s[idxBefore]) - (Radian)Math.PI) / 2; Radian angleAfter = ((Radian)Math.PI - Utils.angleBetween(v2s[idx], v2s[idxAfter])) / 2; int pointIndex = (int)((int)coords[idx].pointIndex - direction[idx]); Path path = multiPath.getPath((int)coords[idx].pathIndex); Quaternion qStd = Utils._computeQuaternion(path.getAvgDirection(pointIndex) * direction[idx]); float lineicPos = 0f; float uTexCoord = path.getLengthAtPoint(pointIndex) / path.getTotalLength(); // Shape making the joint with "standard extrusion" _extrudeShape(ref buffer, shape, path.getPoint(pointIndex), qStd, qStd, 1.0f, 1.0f, 1.0f, shape.getTotalLength(), uTexCoord, true, shapeTextureTrack); // Modified shape at the intersection Quaternion q = new Quaternion(); if (direction[idx] > 0f) { q = Utils._computeQuaternion(path.getDirectionBefore((int)coords[idx].pointIndex)); } else { q = Utils._computeQuaternion(-path.getDirectionAfter((int)coords[idx].pointIndex)); } Quaternion qLeft = q * new Quaternion(angleBefore, Vector3.UNIT_Y); Quaternion qRight = q * new Quaternion(angleAfter, Vector3.UNIT_Y); float scaleLeft = 1.0f / Math.Abs(Math.Cos(angleBefore)); float scaleRight = 1.0f / Math.Abs(Math.Cos(angleAfter)); uTexCoord = path.getLengthAtPoint((int)coords[idx].pointIndex) / path.getTotalLength(); _extrudeShape(ref buffer, shape, path.getPoint((int)coords[idx].pointIndex), qLeft, qRight, 1.0f, scaleLeft, scaleRight, shape.getTotalLength(), uTexCoord, false, shapeTextureTrack); } }
// * // * Executes the Constrained Delaunay Triangulation algorithm // * @param output A vector of index where is outputed the resulting triangle indexes // * @param outputVertices A vector of vertices where is outputed the resulting triangle vertices // * @exception Ogre::InvalidStateException Either shape or multishape or segment list must be defined // //void triangulate(ref List<int>& output, ref List<Vector2>& outputVertices) const; public void triangulate(std_vector <int> output, PointList outputVertices) { if (mShapeToTriangulate == null && mMultiShapeToTriangulate == null && mSegmentListToTriangulate == null) { throw new NullReferenceException("Ogre::Exception::ERR_INVALID_STATE," + "Either shape or multishape or segment list must be defined!" + ", Procedural::Triangulator::triangulate(std::vector<int>&, PointList&)"); } //Ogre::Timer mTimer; //Mogre.Timer mTimer = new Timer(); //mTimer.Reset(); DelaunayTriangleBuffer dtb = new std_list <Triangle>(); // Do the Delaunay triangulation std_vector <int> segmentListIndices = new std_vector <int>(); if (mShapeToTriangulate != null) { outputVertices = new std_vector <Vector2>(mShapeToTriangulate.getPoints()); for (int i = 0; i < mShapeToTriangulate.getSegCount(); ++i) { segmentListIndices.push_back(i); segmentListIndices.push_back(mShapeToTriangulate.getBoundedIndex(i + 1)); } } else if (mMultiShapeToTriangulate != null) { outputVertices = new std_vector <Vector2>(mMultiShapeToTriangulate.getPoints()); int index = 0; for (int i = 0; i < mMultiShapeToTriangulate.getShapeCount(); ++i) { Shape shape = mMultiShapeToTriangulate.getShape((uint)i); for (int j = 0; j < shape.getSegCount(); j++) { segmentListIndices.push_back(index + j); segmentListIndices.push_back(index + shape.getBoundedIndex(j + 1)); } index += shape.getSegCount(); } } else if (mSegmentListToTriangulate != null) { //std_map<Vector2, int, Vector2Comparator> backMap; std_map <Vector2, int> backMap = new std_map <Vector2, int>(new Vector2Comparator()); //for (std::vector<Segment2D>::iterator it = mSegmentListToTriangulate->begin(); it!= mSegmentListToTriangulate->end(); it++) foreach (var it in mSegmentListToTriangulate) { if ((it.mA - it.mB).SquaredLength < 1e-6) { continue; } //std::map<Vector2, int, Vector2Comparator>::iterator it2 = backMap.find(it->mA); int it2_pos = backMap.find(it.mA); //if (it2 != backMap.end()) if (it2_pos != -1) { //segmentListIndices.push_back(it2->second); segmentListIndices.push_back(backMap[it.mA]); } else { //backMap[it->mA] = outputVertices.size(); backMap.insert(it.mA, outputVertices.size()); segmentListIndices.push_back(outputVertices.size()); outputVertices.push_back(it.mA); } //it2 = backMap.find(it.mB); it2_pos = backMap.find(it.mB); //if (it2 != backMap.end()) if (it2_pos != -1) { //segmentListIndices.push_back(it2.second); segmentListIndices.push_back(backMap[it.mB]); } else { //backMap[it->mB] = outputVertices.size(); backMap.insert(it.mB, outputVertices.size()); segmentListIndices.push_back(outputVertices.size()); outputVertices.push_back(it.mB); } } if (mManualSuperTriangle != null) { Triangle superTriangle = new Triangle(outputVertices); for (int i = 0; i < 3; i++) { //std::map<Vector2, int, Vector2Comparator>::iterator it = backMap.find(mManualSuperTriangle->mPoints[i]); int it_pos = backMap.find(mManualSuperTriangle.mPoints[i]); //if (it != backMap.end()) if (it_pos != -1) { //segmentListIndices.push_back(it->second); //superTriangle.i[i] = it->second; superTriangle.i[i] = backMap[mManualSuperTriangle.mPoints[i]]; } else { //backMap[mManualSuperTriangle->mPoints[i]] = outputVertices.size(); backMap.insert(mManualSuperTriangle.mPoints[i], outputVertices.size()); //segmentListIndices.push_back(outputVertices.size()); superTriangle.i[i] = outputVertices.size(); outputVertices.push_back(mManualSuperTriangle.mPoints[i]); } } dtb.push_back(superTriangle); } } //Utils::log("Triangulator preparation : " + StringConverter::toString(mTimer.getMicroseconds() / 1000.0f) + " ms"); delaunay(outputVertices, ref dtb); //Utils::log("Triangulator delaunay : " + StringConverter::toString(mTimer.getMicroseconds() / 1000.0f) + " ms"); // Add contraints _addConstraints(ref dtb, outputVertices, segmentListIndices); //Utils::log("Triangulator constraints : " + StringConverter::toString(mTimer.getMicroseconds() / 1000.0f) + " ms"); //Outputs index buffer //for (DelaunayTriangleBuffer::iterator it = dtb.begin(); it!=dtb.end(); ++it) foreach (var it in dtb) { if (!it.isDegenerate()) { output.push_back(it.i[0]); output.push_back(it.i[1]); output.push_back(it.i[2]); } } // Remove super triangle if (mRemoveOutside) { outputVertices.pop_back(); outputVertices.pop_back(); outputVertices.pop_back(); } //Utils::log("Triangulator output : " + StringConverter::toString(mTimer.getMicroseconds() / 1000.0f) + " ms"); }
//----------------------------------------------------------------------- public static void _retriangulate(ref TriangleBuffer newMesh, TriangleBuffer inputMesh, std_vector <Intersect> intersectionList, bool first) { std_vector <TriangleBuffer.Vertex> vec = inputMesh.getVertices(); std_vector <int> ind = inputMesh.getIndices(); // Triangulate // Group intersections by triangle indice std_map <int, std_vector <Segment3D> > meshIntersects = new std_map <int, std_vector <Segment3D> >(); //for (List<Intersect>.Enumerator it = intersectionList.GetEnumerator(); it.MoveNext(); ++it) foreach (var it in intersectionList) { int it2_find; if (first) { it2_find = meshIntersects.find(it.mTri1); } else { it2_find = meshIntersects.find(it.mTri2); } if (it2_find != -1) { std_pair <int, std_vector <Segment3D> > it2 = meshIntersects.get((uint)it2_find); it2.second.push_back(it.mSeg); } else { std_vector <Segment3D> vec2 = new std_vector <Segment3D>(); vec2.push_back(it.mSeg); if (first) { meshIntersects[it.mTri1] = vec2; } else { meshIntersects[it.mTri2] = vec2; } } } // Build a new TriangleBuffer holding non-intersected triangles and retriangulated-intersected triangles //for (List<TriangleBuffer.Vertex>.Enumerator it = vec.GetEnumerator(); it.MoveNext(); ++it) foreach (var it in vec) { newMesh.vertex(it); } //for (int i = 0; i < (int)ind.Count / 3; i++) // if (meshIntersects.find(i) == meshIntersects.end()) // newMesh.triangle(ind[i * 3], ind[i * 3 + 1], ind[i * 3 + 2]); for (int i = 0; i < (int)ind.size() / 3; i++) { if (meshIntersects.find(i) == -1) { newMesh.triangle(ind[i * 3], ind[i * 3 + 1], ind[i * 3 + 2]); } } int numNonIntersected1 = newMesh.getIndices().size(); //for (std.map<int, List<Segment3D> >.Enumerator it = meshIntersects.begin(); it.MoveNext(); ++it) foreach (var it in meshIntersects) { std_vector <Segment3D> segments = it.Value; int triIndex = it.Key; Vector3 v1 = vec[ind[triIndex * 3]].mPosition; Vector3 v2 = vec[ind[triIndex * 3 + 1]].mPosition; Vector3 v3 = vec[ind[triIndex * 3 + 2]].mPosition; Vector3 triNormal = ((v2 - v1).CrossProduct(v3 - v1)).NormalisedCopy; Vector3 xAxis = triNormal.Perpendicular; Vector3 yAxis = triNormal.CrossProduct(xAxis); Vector3 planeOrigin = vec[ind[triIndex * 3]].mPosition; // Project intersection segments onto triangle plane std_vector <Segment2D> segments2 = new std_vector <Segment2D>(); //for (List<Segment3D>.Enumerator it2 = segments.GetEnumerator(); it2.MoveNext(); it2++) // segments2.Add(projectOnAxis(it2.Current, planeOrigin, xAxis, yAxis)); foreach (var it2 in segments) { segments2.push_back(projectOnAxis(it2, planeOrigin, xAxis, yAxis)); } //for (List<Segment2D>.Enumerator it2 = segments2.GetEnumerator(); it2.MoveNext();) int it2_c = segments2.Count; for (int j = it2_c - 1; j >= 0; j--) { Segment2D it2 = segments2[j]; if ((it2.mA - it2.mB).SquaredLength < 1e-5) { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent to the STL vector 'erase' method in C#: //it2 = segments2.erase(it2); segments2.RemoveAt(j); } //else } // Triangulate Triangulator t = new Triangulator(); //Triangle2D[[]] tri = new Triangle2D[ind[triIndex * 3]](projectOnAxis(vec.mPosition, planeOrigin, xAxis, yAxis), projectOnAxis(vec[ind[triIndex * 3 + 1]].mPosition, planeOrigin, xAxis, yAxis), projectOnAxis(vec[ind[triIndex * 3 + 2]].mPosition, planeOrigin, xAxis, yAxis)); Triangle2D tri = new Triangle2D(projectOnAxis(vec[ind[triIndex * 3]].mPosition, planeOrigin, xAxis, yAxis), projectOnAxis(vec[ind[triIndex * 3 + 1]].mPosition, planeOrigin, xAxis, yAxis), projectOnAxis(vec[ind[triIndex * 3 + 2]].mPosition, planeOrigin, xAxis, yAxis)); std_vector <Vector2> outPointList = new std_vector <Vector2>();//PointList outPointList; std_vector <int> outIndice = new std_vector <int>(); t.setManualSuperTriangle(tri).setRemoveOutside(false).setSegmentListToTriangulate(ref segments2).triangulate(outIndice, outPointList); // Deproject and add to triangleBuffer newMesh.rebaseOffset(); //for (List<int>.Enumerator it = outIndice.GetEnumerator(); it.MoveNext(); ++it) // newMesh.index(it.Current); foreach (var oindex in outIndice) { newMesh.index(oindex); } float x1 = tri.mPoints[0].x; float y1 = tri.mPoints[0].y; Vector2 uv1 = vec[ind[triIndex * 3]].mUV; float x2 = tri.mPoints[1].x; float y2 = tri.mPoints[1].y; Vector2 uv2 = vec[ind[triIndex * 3 + 1]].mUV; float x3 = tri.mPoints[2].x; float y3 = tri.mPoints[2].y; Vector2 uv3 = vec[ind[triIndex * 3 + 2]].mUV; float DET = x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 + x3 * y1 - x1 * y3; Vector2 A = ((y2 - y3) * uv1 + (y3 - y1) * uv2 + (y1 - y2) * uv3) / DET; Vector2 B = ((x3 - x2) * uv1 + (x1 - x3) * uv2 + (x2 - x1) * uv3) / DET; Vector2 C = ((x2 * y3 - x3 * y2) * uv1 + (x3 * y1 - x1 * y3) * uv2 + (x1 * y2 - x2 * y1) * uv3) / DET; //for (List<Vector2>.Enumerator it = outPointList.GetEnumerator(); it.MoveNext(); ++it) foreach (var it2 in outPointList) { Vector2 uv = A * it2.x + B * it2.y + C; newMesh.position(deprojectOnAxis(it2, planeOrigin, xAxis, yAxis)); newMesh.normal(triNormal); newMesh.textureCoord(uv); } } }