// * // * Determines whether the outside as defined by user equals "real" outside // //----------------------------------------------------------------------- // //ORIGINAL LINE: bool isOutsideRealOutside() const public bool isOutsideRealOutside() { float x = float.MinValue;//std.numeric_limits<float>.min(); int index = 0; int shapeIndex = 0; for (int j = 0; j < mShapes.size(); j++) { Shape s = mShapes[j]; std_vector <Vector2> points = s.getPointsReference(); for (int i = 0; i < points.Count; i++) { if (x < points[i].x) { x = points[i].x; index = i; shapeIndex = j; } } } Radian alpha1 = Utils.angleTo(Vector2.UNIT_Y, mShapes[shapeIndex].getDirectionAfter((uint)index)); Radian alpha2 = Utils.angleTo(Vector2.UNIT_Y, -mShapes[shapeIndex].getDirectionBefore((uint)index)); Side shapeSide; if (alpha1 < alpha2) { shapeSide = Side.SIDE_RIGHT; } else { shapeSide = Side.SIDE_LEFT; } return(shapeSide == mShapes[shapeIndex].getOutSide()); }
//----------------------------------------------------------------------- public static void _buildTriLookup(ref TriLookup lookup, TriangleBuffer newMesh) { std_vector <TriangleBuffer.Vertex> nvec = newMesh.getVertices(); std_vector <int> nind = newMesh.getIndices(); for (int i = 0; i < (int)nind.Count / 3; i++) { lookup.insert(new Segment3D(nvec[nind[i * 3]].mPosition, nvec[nind[i * 3 + 1]].mPosition).orderedCopy(), i); lookup.insert(new KeyValuePair <Segment3D, int>(new Segment3D(nvec[nind[i * 3]].mPosition, nvec[nind[i * 3 + 2]].mPosition).orderedCopy(), i)); lookup.insert(new KeyValuePair <Segment3D, int>(new Segment3D(nvec[nind[i * 3 + 1]].mPosition, nvec[nind[i * 3 + 2]].mPosition).orderedCopy(), i)); } }
/// Builds an aggregated list of all points contained in all shapes //----------------------------------------------------------------------- // //ORIGINAL LINE: List<Vector2> getPoints() const public std_vector <Vector2> getPoints() { std_vector <Vector2> result = new std_vector <Vector2>(); for (int i = 0; i < mShapes.Count; i++) { Vector2[] points = mShapes[i].getPoints(); // //result.insert(result.end(), points.GetEnumerator(), points.end()); result.AddRange(points); } return(result); }
//----------------------------------------------------------------------- // //ORIGINAL LINE: MultiShape _booleanOperation(const Shape& STLAllocator<U, AllocPolicy>, BooleanOperationType opType) const private MultiShape _booleanOperation(Shape other, BooleanOperationType opType) { if (!mClosed || mPoints.size() < 2) OGRE_EXCEPT("Ogre::Exception::ERR_INVALID_STATE", "Current shapes must be closed and has to contain at least 2 points!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)"); if (!other.mClosed || other.mPoints.size() < 2) OGRE_EXCEPT("Ogre::Exception::ERR_INVALIDPARAMS", "Other shapes must be closed and has to contain at least 2 points!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)"); ; // Compute the intersection between the 2 shapes std_vector<IntersectionInShape> intersections = new std_vector<IntersectionInShape>(); _findAllIntersections(other, ref intersections); // Build the resulting shape if (intersections.empty()) { if (isPointInside(other.getPoint(0))) { // Shape B is completely inside shape A if (opType == BooleanOperationType.BOT_UNION) { MultiShape ms = new MultiShape(); ms.addShape(this); return ms; } else if (opType == BooleanOperationType.BOT_INTERSECTION) { MultiShape ms = new MultiShape(); ms.addShape(other); return ms; } else if (opType == BooleanOperationType.BOT_DIFFERENCE) { MultiShape ms = new MultiShape(); ms.addShape(this); ms.addShape(other); ms.getShape(1).switchSide(); return ms; } } else if (other.isPointInside(getPoint(0))) { // Shape A is completely inside shape B if (opType == BooleanOperationType.BOT_UNION) { MultiShape ms = new MultiShape(); ms.addShape(other); return ms; } else if (opType == BooleanOperationType.BOT_INTERSECTION) { MultiShape ms = new MultiShape(); ms.addShape(this); return ms; } else if (opType == BooleanOperationType.BOT_DIFFERENCE) { MultiShape ms = new MultiShape(); ms.addShape(this); ms.addShape(other); ms.getShape(0).switchSide(); return ms; } } else { if (opType == BooleanOperationType.BOT_UNION) { MultiShape ms = new MultiShape(); ms.addShape(this); ms.addShape(other); return ms; } else if (opType == BooleanOperationType.BOT_INTERSECTION) return new MultiShape(); //empty result else if (opType == BooleanOperationType.BOT_DIFFERENCE) return new MultiShape(); //empty result } } MultiShape outputMultiShape = new MultiShape(); Shape[] inputShapes = new Shape[2]; inputShapes[0] = this; inputShapes[1] = other; while (!intersections.empty()) { Shape outputShape = new Shape(); byte shapeSelector = 0; // 0 : first shape, 1 : second shape Vector2 currentPosition = intersections[0].position;//intersections.GetEnumerator().position; IntersectionInShape firstIntersection = intersections[0];//*intersections.GetEnumerator(); uint currentSegment = firstIntersection.index[shapeSelector]; //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent to the STL vector 'erase' method in C#: //intersections.erase(intersections.GetEnumerator());//ÒƳý intersections.erase(firstIntersection, true); outputShape.addPoint(currentPosition); sbyte isIncreasing = 0; // +1 if increasing, -1 if decreasing, 0 if undefined if (!_findWhereToGo(inputShapes, opType, firstIntersection, ref shapeSelector, ref isIncreasing, ref currentSegment)) { // That intersection is located on a place where the resulting shape won't go => discard continue; } while (true) { // find the closest intersection on the same segment, in the correct direction //List<IntersectionInShape>.Enumerator found_next_intersection = intersections.end(); IntersectionInShape found_next_intersection = intersections[intersections.Count - 1]; int found_next_intersection_pos = -1; float distanceToNextIntersection = float.MaxValue;// std.numeric_limits<Real>.max(); uint nextPoint = currentSegment + (uint)(isIncreasing == 1 ? 1 : 0); bool nextPointIsOnIntersection = false; //for (List<IntersectionInShape>.Enumerator it = intersections.GetEnumerator(); it.MoveNext(); ++it) for (int i = 0; i < intersections.Count; i++) { IntersectionInShape it = intersections[i]; if (currentSegment == it.index[shapeSelector]) { if (((it.position - currentPosition).DotProduct(it.position - inputShapes[shapeSelector].getPoint((int)nextPoint)) < 0f) || (it.onVertex[shapeSelector] && nextPoint == it.index[shapeSelector])) { // found an intersection between the current one and the next segment point float d = (it.position - currentPosition).Length; if (d < distanceToNextIntersection) { // check if we have the nearest intersection found_next_intersection = it; found_next_intersection_pos = i; distanceToNextIntersection = d; } } } if (nextPoint == it.index[shapeSelector] && it.onVertex[shapeSelector]) nextPointIsOnIntersection = true; } // stop condition if (currentSegment == firstIntersection.index[shapeSelector]) { // we found ourselves on the same segment as the first intersection and no other if ((firstIntersection.position - currentPosition).DotProduct(firstIntersection.position - inputShapes[shapeSelector].getPoint((int)nextPoint)) < 0f) { float d = (firstIntersection.position - currentPosition).Length; if (d > 0.0f && d < distanceToNextIntersection) { outputShape.close(); break; } } } // We actually found the next intersection => change direction and add current intersection to the list //if (found_next_intersection.MoveNext()) //if (intersections.Count > 1) { if (found_next_intersection_pos != -1) { //IntersectionInShape currentIntersection = found_next_intersection.Current; IntersectionInShape currentIntersection = found_next_intersection; intersections.erase(found_next_intersection, true); //IntersectionInShape currentIntersection = intersections[intersections.Count - 1]; outputShape.addPoint(currentIntersection.position); bool result = _findWhereToGo(inputShapes, opType, currentIntersection, ref shapeSelector, ref isIncreasing, ref currentSegment); if (result == null) { OGRE_EXCEPT("Ogre::Exception::ERR_INTERNAL_ERROR", "We should not be here!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)"); ; } } else { // no intersection found for the moment => just continue on the current segment if (!nextPointIsOnIntersection) { if (isIncreasing == 1) currentPosition = inputShapes[shapeSelector].getPoint((int)currentSegment + 1); else currentPosition = inputShapes[shapeSelector].getPoint((int)currentSegment); outputShape.addPoint(currentPosition); } currentSegment = (uint)Utils.modulo((int)currentSegment + isIncreasing, inputShapes[shapeSelector].getSegCount()); } } outputMultiShape.addShape(outputShape); } return outputMultiShape; }
public Shape addPointRel(std_vector<Vector2> pointList) { if (mPoints.Count == 0) { mPoints.AddRange(pointList.ToArray()); } else { Vector2 refVector = mPoints[mPoints.size() - 1]; foreach (var it in pointList) { addPoint(it + refVector); } } return this; }
//----------------------------------------------------------------------- // //ORIGINAL LINE: void _findAllIntersections(const Shape& STLAllocator<U, AllocPolicy>, List<IntersectionInShape>& intersections) const private void _findAllIntersections(Shape other, ref std_vector<IntersectionInShape> intersections) { for (ushort i = 0; i < getSegCount(); i++) { Segment2D seg1 = new Segment2D(getPoint(i), getPoint(i + 1)); for (ushort j = 0; j < other.getSegCount(); j++) { Segment2D seg2 = new Segment2D(other.getPoint(j), other.getPoint(j + 1)); Vector2 intersect = new Vector2(); if (seg1.findIntersect(seg2, ref intersect)) { IntersectionInShape inter = new IntersectionInShape(i, j, intersect); // check if intersection is "borderline" : too near to a vertex if ((seg1.mA - intersect).SquaredLength < 1e-8) { inter.onVertex[0] = true; } if ((seg1.mB - intersect).SquaredLength < 1e-8) { inter.onVertex[0] = true; inter.index[0]++; } if ((seg2.mA - intersect).SquaredLength < 1e-8) { inter.onVertex[1] = true; } if ((seg2.mB - intersect).SquaredLength < 1e-8) { inter.onVertex[1] = true; inter.index[1]++; } intersections.push_back(inter); } } } }
// //ORIGINAL LINE: List<std::pair<uint, uint> > getNoIntersectionParts(uint pathIndex) const /// <summary> /// 获取非交集 /// </summary> /// <param name="pathIndex"></param> /// <returns></returns> public std_vector<std_pair<uint, uint>> getNoIntersectionParts(uint pathIndex) { Path path = mPaths[(int)pathIndex]; std_vector<std_pair<uint, uint>> result = new std_vector<std_pair<uint, uint>>(); std_vector<int> intersections = new std_vector<int>(); //for (std.map<PathCoordinate, List<PathCoordinate>>.Enumerator it = mIntersectionsMap.begin(); it != mIntersectionsMap.end(); ++it) { foreach (var it in mIntersectionsMap) { if (it.Key.pathIndex == pathIndex) { intersections.push_back((int)it.Key.pointIndex); } } //std.sort(intersections.GetEnumerator(), intersections.end()); intersections.Sort((x, y) => { return x - y;//正序排序(重写int比较器,|x|>|y|返回正数,|x|=|y|返回0,|x|<|y|返回负数) }); //Array.Sort(intersections.ToArray()); int begin = 0; //for (std::vector<int>::iterator it = intersections.begin(); it!= intersections.end(); ++it) //{ // if (*it-1>begin) // result.push_back(std::pair<unsigned int, unsigned int>(begin, *it-1)); // begin = *it+1; //} //if (path.getSegCount() > begin) // result.push_back(std::pair<unsigned int, unsigned int>(begin, path.getSegCount())); //for (List<int>.Enumerator it = intersections.GetEnumerator(); it.MoveNext(); ++it) foreach (var it in intersections) { if (it - 1 > begin) result.push_back(new std_pair<uint, uint>((uint)begin, (uint)it - 1)); begin = it + 1; } if (path.getSegCount() > begin) result.push_back(new std_pair<uint, uint>((uint)begin, (uint)path.getSegCount())); return result; }
//----------------------------------------------------------------------- /// <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 buildFromSegmentSoup(std_vector<Segment3D> segList, ref std_vector<Path> @out) { //typedef std::multimap<Vector3, Vector3, Vector3Comparator> Vec3MultiMap; //Vec3MultiMap segs; std_multimap<Vector3,Vector3>segs=new std_multimap<Vector3,Vector3>(new Vector3Comparator()); // for (std::vector<Segment3D>::const_iterator it = segList.begin(); it != segList.end(); ++it) foreach(var it in segList) { //segs.insert(std::pair<Vector3, Vector3 > (it->mA, it->mB)); //segs.insert(std::pair<Vector3, Vector3 > (it->mB, it->mA)); segs.insert(it.mA,it.mB); segs.insert(it.mB,it.mA); } while (!segs.empty()) { Vector3 headFirst = segs.get(0).first;//segs.begin()->first; Vector3 headSecond = segs.get(0).second[0];//segs.begin()->second; Path p=new Path(); p.addPoint(headFirst).addPoint(headSecond); //Vec3MultiMap::iterator firstSeg = segs.begin(); int firstSeg_pos=segs.begin(); Vector3 firstSeg=segs.get(0).first; //std::pair<Vec3MultiMap::iterator, Vec3MultiMap::iterator> correspondants2 = segs.equal_range(headSecond); std_pair<std_pair<Vector3,List<Vector3>>,std_pair<Vector3,List<Vector3>>> correspondants2 = segs.equal_range(headSecond); //for (Vec3MultiMap::iterator it = correspondants2.first; it != correspondants2.second;) for(int i=correspondants2.first.second.Count-1;i>=0;i--) { // Vec3MultiMap::iterator removeIt = it++; Vector3 removeIt=correspondants2.first.second[i]; //if ((removeIt->second - firstSeg->first).squaredLength() < 1e-8) if((removeIt-firstSeg).SquaredLength<1e-8) segs.erase(removeIt); } segs.erase(firstSeg); bool foundSomething = true; while (!segs.empty() && foundSomething) { foundSomething = false; //Vec3MultiMap::iterator next = segs.find(headSecond); int next_pos = segs.find(headSecond); //if (next != segs.end()) if(next_pos!=-1) { std_pair<Vector3,List<Vector3>>next=segs.get((uint)next_pos); foundSomething = true; headSecond = next.second[0]; p.addPoint(headSecond); //std::pair<Vec3MultiMap::iterator, Vec3MultiMap::iterator> correspondants = segs.equal_range(headSecond); std_pair<std_pair<Vector3,List<Vector3>>,std_pair<Vector3,List<Vector3>>>correspondants = segs.equal_range(headSecond); //for (Vec3MultiMap::iterator it = correspondants.first; it != correspondants.second;) for (int i = correspondants.first.second.Count - 1; i >= 0;i-- ) { //Vec3MultiMap::iterator removeIt = it++; Vector3 removeIt = correspondants.first.second[i]; //if ((removeIt->second - next->first).squaredLength() < 1e-8) if ((removeIt - next.first).SquaredLength < 1e-8) segs.erase(removeIt); } //segs.erase(next); segs.erase(next.first); } //Vec3MultiMap::iterator previous = segs.find(headFirst); int previous_pos=segs.find(headFirst); //if (previous != segs.end()) if(previous_pos!=-1) { std_pair<Vector3, List<Vector3>> previous = segs.get((uint)previous_pos); foundSomething = true; //p.insertPoint(0, previous.second); p.insertPoint(0, previous.second[0]);//??? headFirst = previous.second[0]; //std::pair<Vec3MultiMap::iterator, Vec3MultiMap::iterator> correspondants = segs.equal_range(headFirst); std_pair<std_pair<Vector3,List<Vector3>>,std_pair<Vector3,List<Vector3>>>correspondants = segs.equal_range(headFirst); //for (Vec3MultiMap::iterator it = correspondants.first; it != correspondants.second;) for(int i=correspondants.first.second.Count-1;i>=0;i--) { //Vec3MultiMap::iterator removeIt = it++; Vector3 removeIt=correspondants.first.second[i]; //if ((removeIt->second - previous->first).squaredLength() < 1e-8) if((removeIt-previous.first).SquaredLength<1e-8) segs.erase(removeIt); } //segs.erase(previous); segs.erase(previous.first); } } if ((p.getPoint(0)-p.getPoint(p.getSegCount() + 1)).SquaredLength < 1e-6) { p.getPointsReference().pop_back(); p.close(); } @out.push_back(p); } }
//std_vector<std::string> split(const std::string& str, const std::string& delimiters, bool removeEmpty = true); std_vector<string> split(string str, string delimiters, bool removeEmpty) { std_vector<string> tokens = new std_vector<string>(); //std::string::size_type delimPos = 0, tokenPos = 0, pos = 0; //int delimPos = 0, tokenPos = 0, pos = 0; //if (str.empty()) return tokens; if (string.IsNullOrEmpty(str)) return tokens; string[] strsplits = str.Split(delimiters.ToCharArray()); foreach (var v in strsplits) { if (removeEmpty) { if (!string.IsNullOrEmpty(v)) { tokens.push_back(v); } } else { tokens.push_back(v); } } //while (true) //{ // delimPos = str.find_first_of(delimiters, pos); // tokenPos = str.find_first_not_of(delimiters, pos); // if (std::string::npos != delimPos) // { // if (std::string::npos != tokenPos) // { // if (tokenPos < delimPos) // tokens.push_back(str.substr(pos,delimPos-pos)); // else // { // if (!removeEmpty) tokens.push_back(""); // } // } // else // { // if (!removeEmpty) tokens.push_back(""); // } // pos = delimPos+1; // } // else // { // if (std::string::npos != tokenPos) // tokens.push_back(str.substr(pos)); // else // { // if (!removeEmpty) tokens.push_back(""); // } // break; // } //} return tokens; }
// SvgLoaderPath(std::vector<std::string> p, unsigned int ns); public SvgLoaderPath(std_vector<string> p, uint ns) { parts = p; mNumSeg = ns; px = 0.0f; py = 0.0f; index = 0; char lastCmd = (char)0; while (index < p.Count) { try { char newCmd = parts[index][0]; bool next = true; if (lastCmd != newCmd && newCmd != '.' && newCmd != '-' && (newCmd < '0' || newCmd > '9') && curve.size() > 3 && ((lastCmd == 'c' || lastCmd == 'C') && (newCmd == 's' || newCmd == 'S') || (lastCmd == 'q' || lastCmd == 'Q') && (newCmd == 't' || newCmd == 'T'))) { // finish curve finishCurve(lastCmd); } switch (newCmd) { case 'l': parseLineTo(true, next); break; case 'L': parseLineTo(false, next); break; case 'm': parseMoveTo(true, next); newCmd = 'l'; break; case 'M': parseMoveTo(false, next); newCmd = 'L'; break; case 'h': parseHLineTo(true, next); break; case 'H': parseHLineTo(false, next); break; case 'v': parseVLineTo(true, next); break; case 'V': parseVLineTo(false, next); break; case 'c': curve.push_back(point); parseCurveCTo(true, next); break; case 'C': curve.push_back(point); parseCurveCTo(false, next); break; case 's': parseCurveSTo(true, next); break; case 'S': parseCurveSTo(false, next); break; case 'q': curve.push_back(point); parseCurveQTo(true, next); break; case 'Q': curve.push_back(point); parseCurveQTo(false, next); break; case 't': parseCurveTTo(true, next); break; case 'T': parseCurveTTo(false, next); break; case 'a': parseArcTo(true, next); break; case 'A': parseArcTo(false, next); break; case 'z': case 'Z': shape.close(); index++; break; default: newCmd = lastCmd; next = false; switch (lastCmd) { case 'l': parseLineTo(true, next); break; case 'L': parseLineTo(false, next); break; case 'm': parseMoveTo(true, next); break; case 'M': parseMoveTo(false, next); break; case 'h': parseHLineTo(true, next); break; case 'H': parseHLineTo(false, next); break; case 'v': parseVLineTo(true, next); break; case 'V': parseVLineTo(false, next); break; case 'c': parseCurveCTo(true, next); break; case 'C': parseCurveCTo(false, next); break; case 's': parseCurveSTo(true, next); break; case 'S': parseCurveSTo(false, next); break; case 'q': parseCurveQTo(true, next); break; case 'Q': parseCurveQTo(false, next); break; case 't': parseCurveTTo(true, next); break; case 'T': parseCurveTTo(false, next); break; case 'a': parseArcTo(true, next); break; case 'A': parseArcTo(false, next); break; default: break; } break; } lastCmd = newCmd; } catch { } } if (curve.size() > 0) finishCurve(lastCmd); }
//-------------------------------------------------------------- public void modify() { if (mInputTriangleBuffer == null) OGRE_EXCEPT("Exception::ERR_INVALID_STATE", "Input triangle buffer must be set", "__FUNCTION__"); ; std_vector<TriangleBuffer.Vertex> newVertices = new std_vector<TriangleBuffer.Vertex>(); std_vector<TriangleBuffer.Vertex> originVertices = mInputTriangleBuffer.getVertices(); std_vector<int> originIndices = mInputTriangleBuffer.getIndices(); for (int i = 0; i < originIndices.size(); i += 3) { newVertices.push_back(originVertices[originIndices[i]]); newVertices.push_back(originVertices[originIndices[i + 1]]); newVertices.push_back(originVertices[originIndices[i + 2]]); } mInputTriangleBuffer.getVertices().clear(); mInputTriangleBuffer.getVertices().reserve(newVertices.size()); //for (List<TriangleBuffer.Vertex>.Enumerator it = newVertices.GetEnumerator(); it.MoveNext(); ++it) // mInputTriangleBuffer.getVertices().push_back(it.Current); foreach (var it in newVertices) { mInputTriangleBuffer.getVertices().push_back(it); } mInputTriangleBuffer.getIndices().clear(); mInputTriangleBuffer.getIndices().reserve(newVertices.size()); for (int i = 0; i < newVertices.size(); i++) mInputTriangleBuffer.getIndices().push_back(i); }
//-------------------------------------------------------------- public void modify() { if (mInputTriangleBuffer == null) OGRE_EXCEPT("Exception::ERR_INVALID_STATE", "Input triangle buffer must be set", "__FUNCTION__"); ; if (mComputeMode == NormalComputeMode.NCM_TRIANGLE) { if (mMustWeldUnweldFirst) new UnweldVerticesModifier().setInputTriangleBuffer(mInputTriangleBuffer).modify(); std_vector<int> indices = mInputTriangleBuffer.getIndices(); std_vector<TriangleBuffer.Vertex> vertices = mInputTriangleBuffer.getVertices(); for (int i = 0; i < indices.size(); i += 3) { Vector3 v1 = vertices[indices[i]].mPosition; Vector3 v2 = vertices[indices[i + 1]].mPosition; Vector3 v3 = vertices[indices[i + 2]].mPosition; Vector3 n = (v2 - v1).CrossProduct(v3 - v1).NormalisedCopy; // //ORIGINAL LINE: vertices[indices[i]].mNormal = n; vertices[indices[i]].mNormal = (n); // //ORIGINAL LINE: vertices[indices[i+1]].mNormal = n; vertices[indices[i + 1]].mNormal = (n); // //ORIGINAL LINE: vertices[indices[i+2]].mNormal = n; vertices[indices[i + 2]].mNormal = (n); } } else { if (mMustWeldUnweldFirst) new WeldVerticesModifier().setInputTriangleBuffer(mInputTriangleBuffer).modify(); std_vector<int> indices = mInputTriangleBuffer.getIndices(); std_vector<TriangleBuffer.Vertex> vertices = mInputTriangleBuffer.getVertices(); std_vector<std_vector<Vector3>> tmpNormals = new std_vector<std_vector<Vector3>>(); tmpNormals.resize(vertices.size()); for (int i = 0; i < indices.size(); i += 3) { Vector3 v1 = vertices[indices[i]].mPosition; Vector3 v2 = vertices[indices[i + 1]].mPosition; Vector3 v3 = vertices[indices[i + 2]].mPosition; Vector3 n = (v2 - v1).CrossProduct(v3 - v1); tmpNormals[indices[i]].push_back(n); tmpNormals[indices[i + 1]].push_back(n); tmpNormals[indices[i + 2]].push_back(n); } for (int i = 0; i < vertices.size(); i++) { Vector3 n = (Vector3.ZERO); for (int j = 0; j < tmpNormals[i].size(); j++) n += tmpNormals[i][j]; vertices[i].mNormal = n.NormalisedCopy; } } }