public List <Vect3> ConvertFaceToLocal(Face face, Component component) { List <Vect3> facePositions = new List <Vect3> { component.GetCoordinate(face.vertexIndices[0]), component.GetCoordinate(face.vertexIndices[1]), component.GetCoordinate(face.vertexIndices[2]) }; return(ConvertToLocalCoordinates(facePositions)); }
/* * Fills internal volume of voxels by finding points in the voxel grid captured * by a mesh. Relies on the original meshes to perform odd/even polygon capture calculation. * * https://en.wikipedia.org/wiki/Point_in_polygon */ public void FillInternalVolume(Component component) { OrientedBBox componentOBB = componentOBBs[component.index]; List <Vect3> points = new List <Vect3>(); foreach (var vertex in component.vertices) { points.Add(vertex.coordinate); } VoxelSpan componentVoxelSpan = new VoxelSpan(points, this, BorderOffset); for (int x = componentVoxelSpan.minX; x < componentVoxelSpan.maxX; x++) { for (int z = componentVoxelSpan.minZ; z < componentVoxelSpan.maxZ; z++) { for (int y = componentVoxelSpan.minY; y < componentVoxelSpan.maxY; y++) { if (!coordinateGrid[x][y][z] && coordinateGrid[x][Math.Max(0, y - 1)][z]) { Vect3 globalPos = voxelStartCoordinate + orientedBbox.localX * x * resolution + orientedBbox.localY * y * resolution + orientedBbox.localZ * z * resolution; if (!componentOBB.ContainsGlobalCoordinate(globalPos, OrientedBBoxExpansionFactor)) { continue; } int intersects = 0; foreach (Face face in component.faces) { Vect3 triA = component.GetCoordinate(face.vertexIndices[0]); Vect3 triB = component.GetCoordinate(face.vertexIndices[1]); Vect3 triC = component.GetCoordinate(face.vertexIndices[2]); // if (intersect_triangle(globalPos, Vect3.Up, triA, triB, triC)) if (rayIntersectsTriangle(globalPos, Vect3.Up, triA, triB, triC)) { intersects++; } } if ((intersects % 2) != 0) { int rise = 0; while (!coordinateGrid[x][y + rise][z]) { coordinateGrid[x][y + rise][z] = true; rise++; } } else if (intersects == 0) { // If there is no intersecting surface above whatsoever, this column cannot // contain points that are inside a polygon. break; } } } } } }
/* * Finds and removes redundant points in a circular list of vertices that describe an exterior ring of a mesh. * * Examines the list three elements at a time. If the vector formed by the first and second element has the same * direction as the the vector formed by the second and third element, the second element is redundant and removed. */ private static void RemoveRedundantPoints(ref LinkedList <int> floorSideVertices, Component component) { Vect3 firstPoint; Vect3 secondPoint; Vect3 thirdPoint; Vect3 firstToSecond;; Vect3 secondToThird; //Handle midlist cases var current = floorSideVertices.First.Next; while (current != floorSideVertices.Last) { if (current == floorSideVertices.First) { current = current.Next; continue; } firstPoint = component.GetCoordinate(current.Previous.Value); secondPoint = component.GetCoordinate(current.Value); thirdPoint = component.GetCoordinate(current.Next.Value); firstToSecond = secondPoint - firstPoint; secondToThird = thirdPoint - secondPoint; if (firstToSecond.AngleTo(secondToThird) < AngleEqualityTolerance) { current = current.Previous; floorSideVertices.Remove(current.Next); } else { current = current.Next; } } //Noncircular list data structure for circular list // Compare secondToLast->Last->First, if same, remove last, repeat check firstPoint = component.GetVertex(floorSideVertices.Last.Previous.Value).coordinate; secondPoint = component.GetVertex(floorSideVertices.Last.Value).coordinate; thirdPoint = component.GetVertex(floorSideVertices.First.Value).coordinate; firstToSecond = secondPoint - firstPoint; secondToThird = thirdPoint - secondPoint; while (firstToSecond.AngleTo(secondToThird) < AngleEqualityTolerance) { floorSideVertices.RemoveLast(); firstPoint = component.GetVertex(floorSideVertices.Last.Previous.Value).coordinate; secondPoint = component.GetVertex(floorSideVertices.Last.Value).coordinate; thirdPoint = component.GetVertex(floorSideVertices.First.Value).coordinate; firstToSecond = secondPoint - firstPoint; secondToThird = thirdPoint - secondPoint; } // Compare Last->->First->SecondAfterFirst, if same, remove first, repeat check firstPoint = component.GetVertex(floorSideVertices.Last.Value).coordinate; secondPoint = component.GetVertex(floorSideVertices.First.Value).coordinate; thirdPoint = component.GetVertex(floorSideVertices.First.Next.Value).coordinate; firstToSecond = secondPoint - firstPoint; secondToThird = thirdPoint - secondPoint; while (firstToSecond.AngleTo(secondToThird) < AngleEqualityTolerance) { floorSideVertices.RemoveFirst(); firstPoint = component.GetVertex(floorSideVertices.Last.Value).coordinate; secondPoint = component.GetVertex(floorSideVertices.First.Value).coordinate; thirdPoint = component.GetVertex(floorSideVertices.First.Next.Value).coordinate; firstToSecond = secondPoint - firstPoint; secondToThird = thirdPoint - secondPoint; } }