//-------------------------------------------------------------- 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); } }
//-------------------------------------------------------------- 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; } } } } } }
// * // * 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"); }