//----------------------------------------------------------------------- public static void _extrudeShape(ref TriangleBuffer buffer, Shape shape, Vector3 position, Quaternion orientationLeft, Quaternion orientationRight, float scale, float scaleCorrectionLeft, float scaleCorrectionRight, float totalShapeLength, float uTexCoord, bool joinToTheNextSection, Track shapeTextureTrack) { float lineicShapePos = 0.0f; int numSegShape = shape.getSegCount(); // Insert new points for (uint j = 0; j <= numSegShape; ++j) { Vector2 vp2 = shape.getPoint((int)j); Quaternion orientation = (vp2.x > 0) ? orientationRight : orientationLeft; Vector2 vp2normal = shape.getAvgNormal(j); Vector3 vp = new Vector3(); if (vp2.x > 0) { vp = new Vector3(scaleCorrectionRight * vp2.x, vp2.y, 0); } else { vp = new Vector3(scaleCorrectionLeft * vp2.x, vp2.y, 0); } Vector3 normal = new Vector3(vp2normal.x, vp2normal.y, 0); buffer.rebaseOffset(); Vector3 newPoint = position + orientation * (scale * vp); if (j > 0) { lineicShapePos += (vp2 - shape.getPoint((int)j - 1)).Length; } float vTexCoord = 0f; if (shapeTextureTrack != null) { vTexCoord = shapeTextureTrack.getValue(lineicShapePos, lineicShapePos / totalShapeLength, j); } else { vTexCoord = lineicShapePos / totalShapeLength; } buffer.vertex(newPoint, orientation * normal, new Vector2(uTexCoord, vTexCoord)); if (j < numSegShape && joinToTheNextSection) { if (shape.getOutSide() == Side.SIDE_LEFT) { buffer.triangle(numSegShape + 1, numSegShape + 2, 0); buffer.triangle(0, numSegShape + 2, 1); } else { buffer.triangle(numSegShape + 2, numSegShape + 1, 0); buffer.triangle(numSegShape + 2, 0, 1); } } } }
// * // * Builds the mesh into the given TriangleBuffer // * @param buffer The TriangleBuffer on where to append the mesh. // // //ORIGINAL LINE: void addToTriangleBuffer(TriangleBuffer& buffer) const public override void addToTriangleBuffer(ref TriangleBuffer buffer) { buffer.rebaseOffset(); buffer.estimateVertexCount((mNumRings + 1) * (mNumSegments + 1)); buffer.estimateIndexCount(mNumRings * (mNumSegments + 1) * 6); float fDeltaRingAngle = (Math.PI / mNumRings); float fDeltaSegAngle = (Math.TWO_PI / mNumSegments); int offset = 0; // Generate the group of rings for the sphere for (uint ring = 0; ring <= mNumRings; ring++) { float r0 = mRadius * sinf(ring * fDeltaRingAngle); float y0 = mRadius * cosf(ring * fDeltaRingAngle); // Generate the group of segments for the current ring for (uint seg = 0; seg <= mNumSegments; seg++) { float x0 = r0 * sinf(seg * fDeltaSegAngle); float z0 = r0 * cosf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere addPoint(ref buffer, new Vector3(x0, y0, z0), new Vector3(x0, y0, z0).NormalisedCopy, new Vector2((float)seg / (float)mNumSegments, (float)ring / (float)mNumRings)); if (ring != mNumRings) { if (seg != mNumSegments) { // each vertex (except the last) has six indices pointing to it if (ring != mNumRings - 1) { buffer.triangle(offset + (int)mNumSegments + 2, offset, offset + (int)mNumSegments + 1); } if (ring != 0) { buffer.triangle(offset + (int)mNumSegments + 2, offset + 1, offset); } } offset++; } } // end for seg } // end for ring }
//----------------------------------------------------------------------- // //ORIGINAL LINE: void _latheBodyImpl(TriangleBuffer& buffer, const Shape* shapeToExtrude) const private void _latheBodyImpl(ref TriangleBuffer buffer, Shape shapeToExtrude) { if (shapeToExtrude == null) { OGRE_EXCEPT("Ogre::Exception::ERR_INVALID_STATE", "Shape must not be null!", "Procedural::Lathe::_latheBodyImpl(Procedural::TriangleBuffer&, const Procedural::Shape*)"); } int numSegShape = shapeToExtrude.getSegCount(); if (numSegShape < 2) { OGRE_EXCEPT("Ogre::Exception::ERR_INVALID_STATE", "Shape must contain at least two points", "Procedural::Lathe::_latheBodyImpl(Procedural::TriangleBuffer&, const Procedural::Shape*)"); } int offset = 0; //int numSeg = mClosed?mNumSeg+1:mNumSeg; int numSeg = (int)mNumSeg + 1; buffer.rebaseOffset(); buffer.estimateIndexCount((uint)(numSeg * numSegShape * 6)); buffer.estimateVertexCount((uint)((numSegShape + 1) * (numSeg + 1))); Radian angleEnd = new Radian(mAngleEnd); if (mAngleBegin > mAngleEnd) { angleEnd += (Radian)Math.TWO_PI; } for (int i = 0; i < numSeg; i++) { Radian angle = new Radian(); if (mClosed) { angle = i / (float)mNumSeg * Math.TWO_PI; } else { angle = mAngleBegin + i / (float)mNumSeg * (angleEnd - mAngleBegin); } Quaternion q = new Quaternion(); q.FromAngleAxis(angle, Vector3.UNIT_Y); for (int j = 0; j <= numSegShape; j++) { Vector2 v0 = shapeToExtrude.getPoint(j); Vector3 vp = new Vector3(v0.x, v0.y, 0); Vector2 vp2direction = shapeToExtrude.getAvgDirection((uint)j); Vector2 vp2normal = vp2direction.Perpendicular; Vector3 normal = new Vector3(vp2normal.x, vp2normal.y, 0); normal.Normalise(); if (shapeToExtrude.getOutSide() == Side.SIDE_RIGHT) { normal = -normal; } addPoint(ref buffer, q * vp, q * normal, new Vector2(i / (float)mNumSeg, j / (float)numSegShape)); if (j < numSegShape && i < numSeg - 1) { if (shapeToExtrude.getOutSide() == Side.SIDE_RIGHT) { buffer.triangle(offset + numSegShape + 2, offset, offset + numSegShape + 1); buffer.triangle(offset + numSegShape + 2, offset + 1, offset); } else { buffer.triangle(offset + numSegShape + 2, offset + numSegShape + 1, offset); buffer.triangle(offset + numSegShape + 2, offset, offset + 1); } } offset++; } } }
//----------------------------------------------------------------------- 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); } } }
//----------------------------------------------------------------------- public static void _recursiveAddNeighbour(ref TriangleBuffer result, TriangleBuffer source, int triNumber, ref TriLookup lookup, std_set <Segment3D> limits, bool inverted) { if (triNumber == -1) { return; } Utils.log("tri " + (triNumber.ToString())); std_vector <int> ind = source.getIndices(); std_vector <TriangleBuffer.Vertex> vec = source.getVertices(); result.rebaseOffset(); if (inverted) { result.triangle(0, 2, 1); TriangleBuffer.Vertex v = vec[ind[triNumber * 3]]; v.mNormal = -v.mNormal; result.vertex(v); v = vec[ind[triNumber * 3 + 1]]; v.mNormal = -v.mNormal; result.vertex(v); v = vec[ind[triNumber * 3 + 2]]; v.mNormal = -v.mNormal; result.vertex(v); } else { result.triangle(0, 1, 2); result.vertex(vec[ind[triNumber * 3]]); result.vertex(vec[ind[triNumber * 3 + 1]]); result.vertex(vec[ind[triNumber * 3 + 2]]); } //Utils::log("vertex " + StringConverter::toString(vec[ind[triNumber*3]].mPosition)); //Utils::log("vertex " + StringConverter::toString(vec[ind[triNumber*3+1]].mPosition)); //Utils::log("vertex " + StringConverter::toString(vec[ind[triNumber*3+2]].mPosition)); std_pair <Segment3D, List <int> > it = null; int nextTriangle1 = -1; int nextTriangle2 = -1; int nextTriangle3 = -1; int it_find = lookup.find(new Segment3D(vec[ind[triNumber * 3]].mPosition, vec[ind[triNumber * 3 + 1]].mPosition).orderedCopy()); ////if (it != lookup.end() && limits.find(it->first.orderedCopy()) != limits.end()) //// Utils::log("Cross limit1"); //if (it != lookup.end() && limits.find(it->first.orderedCopy()) == limits.end()) { // nextTriangle1 = it->second; // _removeFromTriLookup(nextTriangle1, lookup); //} if (it_find != -1) { it = lookup.get((uint)it_find); if (limits.find(it.first.orderedCopy()) == -1) { nextTriangle1 = it.second[0]; GlobalMembersProceduralBoolean._removeFromTriLookup(nextTriangle1, ref lookup); } } // it = lookup.find(Segment3D(vec[ind[triNumber * 3 + 1]].mPosition, vec[ind[triNumber * 3 + 2]].mPosition).orderedCopy()); it_find = lookup.find(new Segment3D(vec[ind[triNumber * 3 + 1]].mPosition, vec[ind[triNumber * 3 + 2]].mPosition).orderedCopy()); ////if (it != lookup.end() && limits.find(it->first.orderedCopy()) != limits.end()) ////Utils::log("Cross limit2"); //if (it != lookup.end() && limits.find(it->first.orderedCopy()) == limits.end()) { // nextTriangle2 = it->second; // _removeFromTriLookup(nextTriangle2, lookup); //} if (it_find != -1) { it = lookup.get((uint)it_find); if (limits.find(it.first.orderedCopy()) == -1) { nextTriangle2 = it.second[0]; GlobalMembersProceduralBoolean._removeFromTriLookup(nextTriangle2, ref lookup); } } //it = lookup.find(Segment3D(vec[ind[triNumber * 3]].mPosition, vec[ind[triNumber * 3 + 2]].mPosition).orderedCopy()); ////if (it != lookup.end() && limits.find(it->first.orderedCopy()) != limits.end()) //// Utils::log("Cross limit3"); //if (it != lookup.end() && limits.find(it->first.orderedCopy()) == limits.end()) { // nextTriangle3 = it->second; // _removeFromTriLookup(nextTriangle3, lookup); //} it_find = lookup.find(new Segment3D(vec[ind[triNumber * 3]].mPosition, vec[ind[triNumber * 3 + 2]].mPosition).orderedCopy()); if (it_find != -1) { it = lookup.get((uint)it_find); if (limits.find(it.first.orderedCopy()) == -1) { nextTriangle3 = it.second[0]; GlobalMembersProceduralBoolean._removeFromTriLookup(nextTriangle3, ref lookup); } } //Utils::log("add " + StringConverter::toString(nextTriangle1) + " ," + StringConverter::toString(nextTriangle2) + " ,"+StringConverter::toString(nextTriangle3) ); _recursiveAddNeighbour(ref result, source, nextTriangle1, ref lookup, limits, inverted); _recursiveAddNeighbour(ref result, source, nextTriangle2, ref lookup, limits, inverted); _recursiveAddNeighbour(ref result, source, nextTriangle3, ref lookup, limits, inverted); }