internal void PolygonizeCell(Vector3i offsetPos, Vector3i pos, ref Mesh mesh, int lod) { offsetPos += pos * lod; sbyte[] density = new sbyte[8]; for (int i = 0; i < density.Length; i++) { density [i] = volume [offsetPos + Tables.CornerIndex [i] * lod]; } byte caseCode = (byte)((density [0] >> 7 & 0x01) | (density [1] >> 6 & 0x02) | (density [2] >> 5 & 0x04) | (density [3] >> 4 & 0x08) | (density [4] >> 3 & 0x10) | (density [5] >> 2 & 0x20) | (density [6] >> 1 & 0x40) | (density [7] & 0x80)); if ((caseCode ^ ((density [7] >> 7) & 0xFF)) != 0) { byte regCellClass = Tables.RegularCellClass [caseCode]; ushort[] vertexLocations = Tables.RegularVertexData [caseCode]; Tables.RegularCell c = Tables.RegularCellData [regCellClass]; long triangleCount = c.GetTriangleCount(); byte[] indexOffset = c.Indizes(); //index offsets for current cell //array with real indizes for current cell for (int i = 0; i < c.GetVertexCount(); i++) { byte edge = (byte)(vertexLocations [i] & 0xFF); byte v0 = (byte)((edge >> 4) & 0x0F); //First Corner Index byte v1 = (byte)(edge & 0x0F); //Second Corner Index sbyte d0 = density [v0]; sbyte d1 = density [v1]; int t = (d1 << 8) / (d1 - d0); int u = 0x0100 - t; Vector3 P0 = (offsetPos + Tables.CornerIndex [v0] * lod).ToVector3(); Vector3 P1 = (offsetPos + Tables.CornerIndex [v1] * lod).ToVector3(); Vector3 Q = (t * P0 + u * P1) / 256f; vertices.Add(Q); mappedIndizes [i] = (ushort)(vertices.Count - 1); } for (int t = 0; t < c.GetTriangleCount(); t++) { for (int i = 0; i < 3; i++) { triangles.Add(mappedIndizes [indexOffset [t * 3 + i]]); } } } }
internal void PolygonizeCell(Vector3i offsetPos, Vector3i pos, ref Mesh mesh, int lod) { Debug.Assert(lod >= 1, "Level of Detail must be greater than 1"); offsetPos += pos * lod; byte directionMask = (byte)((pos.X > 0 ? 1 : 0) | ((pos.Z > 0 ? 1 : 0) << 1) | ((pos.Y > 0 ? 1 : 0) << 2)); sbyte[] density = new sbyte[8]; for (int i = 0; i < density.Length; i++) { density[i] = volume[offsetPos + Tables.CornerIndex[i] * lod]; } byte caseCode = getCaseCode(density); if ((caseCode ^ ((density[7] >> 7) & 0xFF)) == 0) //for this cases there is no triangulation { return; } Vector3f[] cornerNormals = new Vector3f[8]; for (int i = 0; i < 8; i++) { var p = offsetPos + Tables.CornerIndex[i] * lod; float nx = (volume[p + Vector3i.UnitX] - volume[p - Vector3i.UnitX]) * 0.5f; float ny = (volume[p + Vector3i.UnitY] - volume[p - Vector3i.UnitY]) * 0.5f; float nz = (volume[p + Vector3i.UnitZ] - volume[p - Vector3i.UnitZ]) * 0.5f; //cornerNormals[i] = new Vector3f(nx, ny, nz); cornerNormals[i].X = nx; cornerNormals[i].Y = ny; cornerNormals[i].Z = nz; cornerNormals[i].Normalize(); } byte regularCellClass = Tables.RegularCellClass[caseCode]; ushort[] vertexLocations = Tables.RegularVertexData[caseCode]; Tables.RegularCell c = Tables.RegularCellData[regularCellClass]; long vertexCount = c.GetVertexCount(); long triangleCount = c.GetTriangleCount(); byte[] indexOffset = c.Indizes(); //index offsets for current cell ushort[] mappedIndizes = new ushort[indexOffset.Length]; //array with real indizes for current cell for (int i = 0; i < vertexCount; i++) { byte edge = (byte)(vertexLocations[i] >> 8); byte reuseIndex = (byte)(edge & 0xF); //Vertex id which should be created or reused 1,2 or 3 byte rDir = (byte)(edge >> 4); //the direction to go to reach a previous cell for reusing byte v1 = (byte)((vertexLocations[i]) & 0x0F); //Second Corner Index byte v0 = (byte)((vertexLocations[i] >> 4) & 0x0F); //First Corner Index sbyte d0 = density[v0]; sbyte d1 = density[v1]; //Vector3f n0 = cornerNormals[v0]; //Vector3f n1 = cornerNormals[v1]; Debug.Assert(v1 > v0); int t = (d1 << 8) / (d1 - d0); int u = 0x0100 - t; float t0 = t / 256f; float t1 = u / 256f; int index = -1; if (UseCache && v1 != 7 && (rDir & directionMask) == rDir) { Debug.Assert(reuseIndex != 0); ReuseCell cell = cache.GetReusedIndex(pos, rDir); index = cell.Verts[reuseIndex]; } if (index == -1) { Vector3f normal = cornerNormals[v0] * t0 + cornerNormals[v1] * t1; GenerateVertex(ref offsetPos, ref pos, mesh, lod, t, ref v0, ref v1, ref d0, ref d1, normal); index = mesh.LatestAddedVertIndex(); } if ((rDir & 8) != 0) { cache.SetReusableIndex(pos, reuseIndex, mesh.LatestAddedVertIndex()); } mappedIndizes[i] = (ushort)index; } for (int t = 0; t < triangleCount; t++) { for (int i = 0; i < 3; i++) { mesh.AddIndex(mappedIndizes[c.Indizes()[t * 3 + i]]); } } }
private static void PolygonizeCell(Vector3i pos, sbyte[] density, MeshBuilder mesh, int lod) { byte directionMask = (byte)((pos.x > 0 ? 1 : 0) | ((pos.z > 0 ? 1 : 0) << 1) | ((pos.y > 0 ? 1 : 0) << 2)); byte caseCode = GetCaseCode(density); if ((caseCode ^ ((density[7] >> 7) & 0xFF)) == 0) //for this cases there is no triangulation { return; } byte regularCellClass = Tables.RegularCellClass[caseCode]; ushort[] vertexLocations = Tables.RegularVertexData[caseCode]; Tables.RegularCell c = Tables.RegularCellData[regularCellClass]; long vertexCount = c.GetVertexCount(); long triangleCount = c.GetTriangleCount(); byte[] indexOffset = c.GetIndices(); // index offsets for current cell int[] mappedIndices = new int[indexOffset.Length]; for (int i = 0; i < vertexCount; ++i) { byte edge = (byte)(vertexLocations[i] >> 8); byte reuseIndex = (byte)(edge & 0xF); // vertex id which should be created or reused 1,2 or 3 byte rDir = (byte)(edge >> 4); // the direction to go to reach a previous cell for reusing byte v0 = (byte)((vertexLocations[i] >> 4) & 0x0F); // first corner index byte v1 = (byte)((vertexLocations[i]) & 0x0F); // second corner index sbyte d0 = density[v0]; sbyte d1 = density[v1]; Debug.Assert(v1 > v0); int t = (d1 << 8) / (d1 - d0); int u = 0x0100 - t; float t0 = t / 256f; float t1 = u / 256f; int index = -1; // todo: try the caching stuff later if (index == -1) { Vector3 p0 = new Vector3( pos.x + Tables.vertexOffset[v0, 0], pos.y + Tables.vertexOffset[v0, 1], pos.z + Tables.vertexOffset[v0, 2]); Vector3 p1 = new Vector3( pos.x + Tables.vertexOffset[v1, 0], pos.y + Tables.vertexOffset[v1, 1], pos.z + Tables.vertexOffset[v1, 2]); mesh.AddVertex(InterpolateVoxelVector(t, p0, p1)); } mappedIndices[i] = index; } }