private Vector3 toVoxelSpace(Vector3 worldSpace, ThreadSafeVoxelisation.GridSize size, float scale) { float side = size.side; Vector3 mid = new Vector3(size.x * 0.5f, size.y * 0.5f, size.z * 0.5f); return(new Vector3(worldSpace.x * size.x * scale, worldSpace.y * size.y * scale, worldSpace.z * size.z * scale) + mid); }
private Vector3 toWorldSpace(Vector3 voxelSpace) { ThreadSafeVoxelisation.GridSize gridSize = grid.GetSize(); float x = (voxelSpace.x - (gridSize.x * 0.5f)) * gridSize.side / 2; float y = (voxelSpace.y - (gridSize.y * 0.5f)) * gridSize.side / 2; float z = (voxelSpace.z - (gridSize.z * 0.5f)) * gridSize.side / 2; return(new Vector3(x, y, z)); }
private void findHitVoxel(Vector3 hitPoint) { ThreadSafeVoxelisation.GridSize gridSize = aabcGrid.GetSize(); Vector3 center = aabcGrid.GetCenter(); Vector3 difference = hitPoint - center; short xOff, yOff, zOff; xOff = (short)(difference.x / gridSize.side); yOff = (short)(difference.y / gridSize.side); zOff = (short)(difference.z / gridSize.side); hit.x = (short)(gridSize.x / 2 + xOff); hit.y = (short)(gridSize.y / 2 + yOff); hit.z = (short)(gridSize.z / 2 + zOff); }
public Dictionary <short, MeshInfo> Split(MeshInfo mesh, KDTree tree, List <Vector3> voxels, short[,,] colourings, ThreadSafeVoxelisation.GridSize size) { Dictionary <short, Dictionary <string, int> > meshFoundIndices = new Dictionary <short, Dictionary <string, int> >(); Dictionary <short, List <Vector3> > meshVertices = new Dictionary <short, List <Vector3> >(); Dictionary <short, List <int> > meshIndices = new Dictionary <short, List <int> >(); Dictionary <short, List <Vector3> > meshEdges = new Dictionary <short, List <Vector3> >(); int[] tris = mesh.index; Vector3[] verts = mesh.verts; for (int i = 0; i < tris.Length; i += 3) { Vector3 v1 = verts[tris[i]]; Vector3 v2 = verts[tris[i + 1]]; Vector3 v3 = verts[tris[i + 2]]; short c1 = nearestColour(toVoxelSpace(v1, size, 0.5f), tree, voxels, colourings); short c2 = nearestColour(toVoxelSpace(v2, size, 0.5f), tree, voxels, colourings); short c3 = nearestColour(toVoxelSpace(v3, size, 0.5f), tree, voxels, colourings); if (c1 == c2 && c1 == c3) { Dictionary <string, int> foundIndices; if (!(meshFoundIndices.TryGetValue(c1, out foundIndices))) { foundIndices = new Dictionary <string, int>(); meshFoundIndices.Add(c1, foundIndices); } List <Vector3> vertices; if (!(meshVertices.TryGetValue(c1, out vertices))) { vertices = new List <Vector3>(); meshVertices.Add(c1, vertices); } List <int> indices; if (!(meshIndices.TryGetValue(c1, out indices))) { indices = new List <int>(); meshIndices.Add(c1, indices); } StoreVertex(v1, foundIndices, indices, vertices); StoreVertex(v2, foundIndices, indices, vertices); StoreVertex(v3, foundIndices, indices, vertices); } else { if (c1 == c2) { List <Vector3> edges; if (!(meshEdges.TryGetValue(c1, out edges))) { edges = new List <Vector3>(); meshEdges.Add(c1, edges); } edges.Add(v1); edges.Add(v2); edges.Add(new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity)); } if (c1 == c3) { List <Vector3> edges; if (!(meshEdges.TryGetValue(c1, out edges))) { edges = new List <Vector3>(); meshEdges.Add(c1, edges); } edges.Add(v1); edges.Add(new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity)); edges.Add(v3); } if (c2 == c3) { List <Vector3> edges; if (!(meshEdges.TryGetValue(c2, out edges))) { edges = new List <Vector3>(); meshEdges.Add(c2, edges); } edges.Add(new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity)); edges.Add(v2); edges.Add(v3); } } } Dictionary <short, MeshInfo> output = new Dictionary <short, MeshInfo>(); foreach (short s in meshFoundIndices.Keys) { List <Vector3> vertices; meshVertices.TryGetValue(s, out vertices); List <int> indices; meshIndices.TryGetValue(s, out indices); List <Vector3> edges; meshEdges.TryGetValue(s, out edges); Fragment c = new Fragment(s); c.vertices.AddRange(edges); output.Add(s, new MeshInfo(vertices.ToArray(), indices.ToArray(), c)); } return(output); }
public void SetSize(GridSize dimension) { SetSize((short)dimension.x, (short)dimension.y, (short)dimension.z, dimension.side); }
//MarchTetrahedron performs the Marching Tetrahedrons algorithm on a single tetrahedron static void MarchTetrahedron(Vector3[] tetrahedronPosition, float[] tetrahedronValue, List <Vector3> vertList, List <int> indexList, ThreadSafeVoxelisation.Voxelization.AABCGrid grid, Dictionary <string, int> indices, KDTree surface, List <Vector3> parentVerts) { ThreadSafeVoxelisation.GridSize gridSize = grid.GetSize(); int i, j, vert, vert0, vert1, idx; int flagIndex = 0, edgeFlags; float offset, invOffset; bool boundary = false; Vector3[] edgeVertex = new Vector3[6]; //Find which vertices are inside of the surface and which are outside for (i = 0; i < 4; i++) { if (tetrahedronValue[i] == -999f) { boundary = true; } if (tetrahedronValue[i] <= target) { flagIndex |= 1 << i; } } //Find which edges are intersected by the surface edgeFlags = tetrahedronEdgeFlags[flagIndex]; //If the tetrahedron is entirely inside or outside of the surface, then there will be no intersections if (edgeFlags == 0) { return; } //Find the point of intersection of the surface with each edge for (i = 0; i < 6; i++) { //if there is an intersection on this edge if ((edgeFlags & (1 << i)) != 0) { vert0 = tetrahedronEdgeConnection[i, 0]; vert1 = tetrahedronEdgeConnection[i, 1]; offset = GetOffset(tetrahedronValue[vert0], tetrahedronValue[vert1]); invOffset = 1.0f - offset; edgeVertex[i].x = ((invOffset * tetrahedronPosition[vert0].x + offset * tetrahedronPosition[vert1].x) - (gridSize.x * 0.5f)) * gridSize.side / 2.1f; edgeVertex[i].y = ((invOffset * tetrahedronPosition[vert0].y + offset * tetrahedronPosition[vert1].y) - (gridSize.y * 0.5f)) * gridSize.side / 2.1f; edgeVertex[i].z = ((invOffset * tetrahedronPosition[vert0].z + offset * tetrahedronPosition[vert1].z) - (gridSize.z * 0.5f)) * gridSize.side / 2.1f; } } Vector3[] oEdgeVertex = new Vector3[6]; if (boundary) { for (int c = 0; c < edgeVertex.Length; c++) { oEdgeVertex[c] = edgeVertex[c]; int index = surface.FindNearest(edgeVertex[c]); edgeVertex[c] = parentVerts[index]; } } else { for (int c = 0; c < edgeVertex.Length; c++) { oEdgeVertex[c] = edgeVertex[c]; Vector3 random = Random.insideUnitSphere; random *= 1f / 4f; random.x = (random.x) * gridSize.side / 2.1f; random.y = (random.y) * gridSize.side / 2.1f; random.z = (random.z) * gridSize.side / 2.1f; edgeVertex[c] = edgeVertex[c] + random; } } //Save the triangles that were found. There can be up to 2 per tetrahedron for (i = 0; i < 2; i++) { if (tetrahedronTriangles[flagIndex, 3 * i] < 0) { break; } for (j = 0; j < 3; j++) { idx = vertList.Count; vert = tetrahedronTriangles[flagIndex, 3 * i + windingOrder[j]]; Vector3 vertex = edgeVertex[vert]; string points = oEdgeVertex[vert].x + "," + oEdgeVertex[vert].y + "," + oEdgeVertex[vert].z; int index = -1; bool found = indices.TryGetValue(points, out index); if (found) { indexList.Add(index); } else { indexList.Add(idx); vertList.Add(edgeVertex[vert]); indices.Add(points, idx); } } } }
//MarchCube performs the Marching Cubes algorithm on a single cube static void MarchCube(Vector3 pos, float[] cube, List <Vector3> vertList, List <int> indexList, ThreadSafeVoxelisation.Voxelization.AABCGrid grid, Dictionary <string, int> indices, KDTree surface, List <Vector3> parentVerts) { int i, j, vert, idx; int flagIndex = 0; float offset = 0.0f; ThreadSafeVoxelisation.GridSize gridSize = grid.GetSize(); Vector3[] edgeVertex = new Vector3[12]; //Find which vertices are inside of the surface and which are outside for (i = 0; i < 8; i++) { if (cube[i] <= target) { flagIndex |= 1 << i; } } //Find which edges are intersected by the surface int edgeFlags = cubeEdgeFlags[flagIndex]; //If the cube is entirely inside or outside of the surface, then there will be no intersections if (edgeFlags == 0) { return; } //Find the point of intersection of the surface with each edge for (i = 0; i < 12; i++) { //if there is an intersection on this edge if ((edgeFlags & (1 << i)) != 0) { offset = GetOffset(cube[edgeConnection[i, 0]], cube[edgeConnection[i, 1]]); edgeVertex[i].x = pos.x + (vertexOffset[edgeConnection[i, 0], 0] + offset * edgeDirection[i, 0]); edgeVertex[i].y = pos.y + (vertexOffset[edgeConnection[i, 0], 1] + offset * edgeDirection[i, 1]); edgeVertex[i].z = pos.z + (vertexOffset[edgeConnection[i, 0], 2] + offset * edgeDirection[i, 2]); } } //Save the triangles that were found. There can be up to five per cube /*for (i = 0; i < 5; i++) { * if (triangleConnectionTable[flagIndex, 3 * i] < 0) break; * * for (j = 0; j < 3; j++) { * idx = vertList.Count; * vert = triangleConnectionTable[flagIndex, 3 * i + windingOrder[j]]; * * Vector3 vertex = edgeVertex[vert]; * string points = vertex.x + "" + vertex.y + "" + vertex.z; * int index = -1; * * bool found = indices.TryGetValue(points, out index); * * if (found) { * indexList.Add(index); * } else { * indexList.Add(idx); * vertList.Add(edgeVertex[vert]); * indices.Add(points, idx); * } * } * * }*/ for (i = 0; i < 5; i++) { if (triangleConnectionTable[flagIndex, 3 * i] < 0) { break; } idx = vertList.Count; for (j = 0; j < 3; j++) { vert = triangleConnectionTable[flagIndex, 3 * i + j]; indexList.Add(idx + windingOrder[j]); vertList.Add(edgeVertex[vert]); } } }