Пример #1
0
/*
 *      public static Vector3[,,] CalculateNormals(float[,,] m_voxels) {
 *              //float startTime = Time.realtimeSinceStartup;
 *
 *              //This calculates the normal of each voxel. If you have a 3d array of data
 *              //the normal is the derivitive of the x, y and z axis.
 *              //Normally you need to flip the normal (*-1) but it is not needed in this case.
 *              //If you dont call this function the normals that Unity generates for a mesh are used.
 *              Vector3[,,] m_normals;
 *
 *              int w = m_voxels.GetLength(0);
 *              int h = m_voxels.GetLength(1);
 *              int l = m_voxels.GetLength(2);
 *
 *              m_normals = new Vector3[w,h,l];
 *
 *              for(int x = 2; x < w-2; x++) {
 *                      for(int y = 2; y < h-2; y++) {
 *                              for(int z = 2; z < l-2; z++) {
 *                                      float dx = m_voxels[x+1,y,z] - m_voxels[x-1,y,z];
 *                                      float dy = m_voxels[x,y+1,z] - m_voxels[x,y-1,z];
 *                                      float dz = m_voxels[x,y,z+1] - m_voxels[x,y,z-1];
 *
 *                                      m_normals[x,y,z] = Vector3.Normalize(new Vector3(dx,dy,dz));
 *                              }
 *                      }
 *              }
 *              return m_normals;
 *      }
 */

    //MarchCube performs the Marching Cubes algorithm on a single cube
    static void MarchCube(Vector3 pos, float[] cube, List <Vector3> vertList, List <int> indexList)
    {
        int   i, j, vert, idx;
        int   flagIndex = 0;
        float offset    = 0.0f;

        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 cubes
        for (i = 0; i < 5; i++)
        {
            if (triangleConnectionTable[flagIndex, 3 * i] < 0)
            {
                break;
            }
            idx = vertList.Count;
            int usualIndex = idx;
            for (j = 0; j < 3; j++)
            {
                vert = triangleConnectionTable[flagIndex, 3 * i + j]; // index of the vertex in internal cube coordinates
                //int usualIndex = idx+windingOrder[j]; // index of the vertex in the vertexList, in the usual implementation
                int cullingIndex = 0;
                cullingIndex = vertexTree.AddVertex(edgeVertex[vert], usualIndex);

                if (usualIndex == cullingIndex)                                 // The vertex was NOT already in the tree
                {
                    indexList.Add(usualIndex);
                    vertList.Add(edgeVertex[vert]);
                    usualIndex++;
                }
                else                                                                                    // The vertex was already in the tree, its index is cullingIndex
                {
                    indexList.Add(cullingIndex);
                }
            }
        }
    }