int CreateMarchingCube(Voxel v) { if (v == null) { return(0); } //allows us to track if the mesh is dirty and needs updating //needs to be above the early exit checks, otherwise cells //keep getting marked as dirty v.lastMeshedValue = v.value; //keep the meshing within the volume bounds if (v.xID >= divisions) { return(0); } if (v.yID >= divisions) { return(0); } if (v.zID >= divisions) { return(0); } if (v.xID < 0) { return(0); } if (v.yID < 0) { return(0); } if (v.zID < 0) { return(0); } Voxel v0 = v; //this conditions te input to the polygonize, and make sure all the neighbors have valid entries //if all input voxels are gauranteed to not be edge voxels, this may not be necessary. Voxel v1 = QueryVoxel(v.xID + 1, v.yID, v.zID); if (v1 == null) { voxelBuffer[1].value = initialVoxelValue; voxelBuffer[1].anchor = v.anchor + new Vector3(v.size.x, 0, 0); v1 = voxelBuffer[1]; } Voxel v2 = QueryVoxel(v.xID + 1, v.yID + 1, v.zID); if (v2 == null) { voxelBuffer[2].value = initialVoxelValue; voxelBuffer[2].anchor = v.anchor + new Vector3(v.size.x, v.size.y, 0); v2 = voxelBuffer[2]; } Voxel v3 = QueryVoxel(v.xID, v.yID + 1, v.zID); if (v3 == null) { voxelBuffer[3].value = initialVoxelValue; voxelBuffer[3].anchor = v.anchor + new Vector3(0, v.size.y, 0); v3 = voxelBuffer[3]; } Voxel v4 = QueryVoxel(v.xID, v.yID, v.zID + 1); if (v4 == null) { voxelBuffer[4].value = initialVoxelValue; voxelBuffer[4].anchor = v.anchor + new Vector3(0, 0, v.size.z); v4 = voxelBuffer[4]; } Voxel v5 = QueryVoxel(v.xID + 1, v.yID, v.zID + 1); if (v5 == null) { voxelBuffer[5].value = initialVoxelValue; voxelBuffer[5].anchor = v.anchor + new Vector3(v.size.x, 0, v.size.z); v5 = voxelBuffer[5]; } Voxel v6 = QueryVoxel(v.xID + 1, v.yID + 1, v.zID + 1); if (v6 == null) { voxelBuffer[6].value = initialVoxelValue; voxelBuffer[6].anchor = v.anchor + new Vector3(v.size.x, v.size.y, v.size.z); v6 = voxelBuffer[6]; } Voxel v7 = QueryVoxel(v.xID, v.yID + 1, v.zID + 1); if (v7 == null) { voxelBuffer[7].value = initialVoxelValue; voxelBuffer[7].anchor = v.anchor + new Vector3(0, v.size.y, v.size.z); v7 = voxelBuffer[7]; } int triangleStart = triangles.Count; int createdTriangles = Polygonizer.Process(isolevel, v0.value, v1.value, v2.value, v3.value, v4.value, v5.value, v6.value, v7.value, v0.anchor, v1.anchor, v2.anchor, v3.anchor, v4.anchor, v5.anchor, v6.anchor, v7.anchor, ref vertices, ref triangles); //compute per vertex normal int addedVertCount = 0; while (normals.Count < vertices.Count) { normals.Add(new Vector3(0, 1, 0)); uvs.Add(new Vector2(-1, -1)); addedVertCount++; } for (int i = triangleStart; i < triangles.Count; i += 3) { v.trianglesIndicies.Add(i); //add it to each voxel this impacted? int ia = triangles[i]; int ib = triangles[i + 1]; int ic = triangles[i + 2]; Vector3 a = vertices[ia]; Vector3 b = vertices[ib]; Vector3 c = vertices[ic]; Vector3 n = Vector3.Cross(a - b, b - c).normalized; normals[ia] = n; normals[ib] = n; normals[ic] = n; CalculateUVs(ia, ib, ic); } //adjust per voxel normal return(createdTriangles); }
/// <summary> /// For a given voxel, execute the polygonization algorithm to generate mesh vertices, triangles, normals, and UVs. /// </summary> /// <param name="v">The voxel to mesh.</param> /// <returns>Number of created triangles.</returns> private int Polygonize(Voxel v) { if (v == null) { return(0); } // allows us to track if the mesh is dirty and needs updating // needs to be above the early exit checks, otherwise voxels // keep getting marked as dirty v.lastMeshedValue = v.value; // keep the meshing within the volume bounds if (v.xID >= m_voxelResolution) { return(0); } if (v.yID >= m_voxelResolution) { return(0); } if (v.zID >= m_voxelResolution) { return(0); } if (v.xID < 0) { return(0); } if (v.yID < 0) { return(0); } if (v.zID < 0) { return(0); } Voxel v0 = v; // this conditions te input to the polygonize, and make sure all the neighbors have valid entries // if all input voxels are gauranteed to not be edge voxels, this may not be necessary. // OPIMTIZATION - voxel can store meshing neighbors, rather than query each // skip if they are null Voxel v1 = QueryVoxel(v.xID + 1, v.yID, v.zID); if (v1 == null) { return(0); } Voxel v2 = QueryVoxel(v.xID + 1, v.yID + 1, v.zID); if (v2 == null) { return(0); } Voxel v3 = QueryVoxel(v.xID, v.yID + 1, v.zID); if (v3 == null) { return(0); } Voxel v4 = QueryVoxel(v.xID, v.yID, v.zID + 1); if (v4 == null) { return(0); } Voxel v5 = QueryVoxel(v.xID + 1, v.yID, v.zID + 1); if (v5 == null) { return(0); } Voxel v6 = QueryVoxel(v.xID + 1, v.yID + 1, v.zID + 1); if (v6 == null) { return(0); } Voxel v7 = QueryVoxel(v.xID, v.yID + 1, v.zID + 1); if (v7 == null) { return(0); } int triangleStart = m_triangles.Count; int createdTriangles = Polygonizer.Process(m_meshingIsolevel, v0.value, v1.value, v2.value, v3.value, v4.value, v5.value, v6.value, v7.value, v0.anchor, v1.anchor, v2.anchor, v3.anchor, v4.anchor, v5.anchor, v6.anchor, v7.anchor, ref m_vertices, ref m_triangles); // compute per vertex normal int addedVertCount = 0; while (m_normals.Count < m_vertices.Count) { m_normals.Add(new Vector3(0, 1, 0)); m_uvs.Add(new Vector2(-1, -1)); addedVertCount++; } for (int i = triangleStart; i < m_triangles.Count; i += 3) { v.trianglesIndicies.Add(i); // add it to each voxel this impacted? int ia = m_triangles[i]; int ib = m_triangles[i + 1]; int ic = m_triangles[i + 2]; Vector3 a = m_vertices[ia]; Vector3 b = m_vertices[ib]; Vector3 c = m_vertices[ic]; Vector3 n = Vector3.Cross(a - b, b - c).normalized; m_normals[ia] = n; m_normals[ib] = n; m_normals[ic] = n; CalculateUVs(ia, ib, ic); } // adjust per voxel normal return(createdTriangles); }