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]]);
                }
            }
        }
Beispiel #3
0
    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;
        }
    }