public override void Process(NPVoxModel model, NPVoxMeshData tempdata, Vector3[] inNormals, ref Vector3[] outNormals)
 {
     for (int t = 0; t < tempdata.numVertices; t++)
     {
         outNormals[tempdata.vertexIndexOffsetBegin + t] = inNormals[tempdata.vertexIndexOffsetBegin + t].normalized;
     }
 }
 public void ComputeLocalOffset(NPVoxMeshData tempdata, out Vector3 result)
 {
     result = Vector3.zero;
     if (tempdata.hasBack)
     {
         result += NPVoxCoord.BACK.ToVector3();
     }
     if (tempdata.hasLeft)
     {
         result += NPVoxCoord.LEFT.ToVector3();
     }
     if (tempdata.hasDown)
     {
         result += NPVoxCoord.DOWN.ToVector3();
     }
     if (tempdata.hasForward)
     {
         result += NPVoxCoord.FORWARD.ToVector3();
     }
     if (tempdata.hasRight)
     {
         result += NPVoxCoord.RIGHT.ToVector3();
     }
     if (tempdata.hasUp)
     {
         result += NPVoxCoord.UP.ToVector3();
     }
     result *= -0.5f;
 }
Example #3
0
    private void ResetSelection()
    {
        for (int i = 0; i < m_selections.Length; i++)
        {
            m_selections[i] = 0x00;
        }

        m_lastSelected     = NPVoxCoord.INVALID;
        m_lastSelectedData = null;
    }
Example #4
0
    public override void Process(NPVoxModel model, NPVoxMeshData tempdata, Vector3[] inNormals, ref Vector3[] outNormals)
    {
        for (int t = 0; t < tempdata.numVertices; t++)
        {
            outNormals[tempdata.vertexIndexOffsetBegin + t] = inNormals[tempdata.vertexIndexOffsetBegin + t];
        }

        if (m_normalData.ContainsKey(tempdata.voxCoord))
        {
            Vector3 normal = m_normalData[tempdata.voxCoord];
            for (int t = 0; t < tempdata.numVertices; t++)
            {
                outNormals[tempdata.vertexIndexOffsetBegin + t] = normal;
            }
        }
    }
    public override void Process(NPVoxModel model, NPVoxMeshData tempdata, Vector3[] inNormals, ref Vector3[] outNormals)
    {
        // Compute normal variance
        float rX = UnityEngine.Random.value;
        float rY = UnityEngine.Random.value;
        float rZ = UnityEngine.Random.value;

        for (int t = 0; t < tempdata.numVertices; t++)
        {
            Vector3 variance = Vector3.zero;
            if (m_normalVariance.x != 0 || m_normalVariance.y != 0 || m_normalVariance.z != 0)
            {
                variance.x = -m_normalVariance.x * 0.5f + 2 * rX * m_normalVariance.x;
                variance.y = -m_normalVariance.y * 0.5f + 2 * rY * m_normalVariance.y;
                variance.z = -m_normalVariance.z * 0.5f + 2 * rZ * m_normalVariance.z;
            }

            outNormals[tempdata.vertexIndexOffsetBegin + t]  = inNormals[tempdata.vertexIndexOffsetBegin + t];
            outNormals[tempdata.vertexIndexOffsetBegin + t] += variance;
        }
    }
Example #6
0
    protected override void DrawSceneInternal(Rect _rect)
    {
        if (m_context.ViewedProcessor.IsOutputValid())
        {
            NPVoxNormalProcessor_UserOverride processor = (NPVoxNormalProcessor_UserOverride)m_context.ViewedProcessor;
            Vector3 voxSize   = m_context.MeshOutput.VoxelSize;
            Vector3 voxExtent = voxSize * 0.5f;
            Vector3 v1        = new Vector3(voxSize.x, 0, 0);
            Vector3 v2        = new Vector3(0, voxSize.y, 0);
            Vector3 v3        = new Vector3(0, 0, voxSize.z);

            NPVoxMeshData[] voxMeshData = m_context.MeshOutput.GetVoxMeshData();

            foreach (NPVoxMeshData vox in voxMeshData)
            {
                if (!vox.isHidden)
                {
                    Vector3 voxPosition = new Vector3(vox.voxelCenter.x, vox.voxelCenter.y, vox.voxelCenter.z);
                    if (m_previewHighlightOverrides && processor.m_overrideNormalsRT.ContainsKey(vox.voxCoord))
                    {
                        NPipeGL.DrawParallelepiped(voxPosition - voxExtent, v1, v2, v3, new Color(0.5f, 0.0f, 0.0f));
                    }

                    sbyte selection = GetSelection(vox.voxCoord);
                    if (selection != UNSELECTED)
                    {
                        NPipeGL.DrawParallelepiped(voxPosition - voxExtent, v1, v2, v3, selection == SELECTED_TARGET ? Color.red : Color.green);
                    }

                    if (vox.voxCoord.Equals(m_lastSelected))
                    {
                        m_lastSelectedData = vox;
                    }
                }
            }
        }
    }
    public override void Process(NPVoxModel model, NPVoxMeshData tempdata, Vector3[] inNormals, ref Vector3[] outNormals)
    {
        if (m_meshReference != null && !tempdata.isHidden)
        {
            Vector3 sizeVoxel = tempdata.voxToUnity.VoxeSize;
            if (!m_dataAlreadyCollected)
            {
                Vector3 sizeVoxModel = model.BoundingBoxMinimal.Size.ToVector3();
                Bounds  boundsMesh   = m_meshReference.bounds;

                m_offsetVox  = model.BoundingBoxMinimal.LeftDownBack.ToVector3();
                m_offsetMesh = boundsMesh.min;
                m_scaleVox   = model.BoundingBoxMinimal.Size.ToVector3();
                m_scaleMesh  = new Vector3(boundsMesh.size.x, boundsMesh.size.y, boundsMesh.size.z);

                m_meshReference.GetNormals(m_meshNormals);

                m_meshReference.GetVertices(m_meshVertices);
                m_triangleList = m_meshReference.GetTriangles(0);

                m_dataAlreadyCollected = true;
                Swap <bool>(m_swapAxes, ref m_flipX, ref m_flipY, ref m_flipZ);
            }

            Vector3 localOffset;
            ComputeLocalOffset(tempdata, out localOffset);
            Vector3 x = tempdata.voxCoord.ToVector3() - m_offsetVox;
            //x += localOffset;

            x += new Vector3(0.5f, 0.5f, 0.5f);
            x  = LinearAlgebra.DivideComponents(x, m_scaleVox);

            Swap(m_swapAxes, ref x);
            FlipPosition(m_flipX, m_flipY, m_flipZ, new Vector3(1.0f, 1.0f, 1.0f), ref x);

            x  = LinearAlgebra.MultiplyComponents(x, m_scaleMesh);
            x += m_offsetMesh;


            int     bestTriangle        = -1;
            float   bestDistanceSquared = float.PositiveInfinity;
            Vector3 bestNormal          = Vector3.zero;
            Vector3 bestPoint           = Vector3.zero;

            for (int triangle = 0; triangle < m_triangleList.Length; triangle += 3)
            {
                Vector3 v1 = m_meshVertices[m_triangleList[triangle + 0]];
                Vector3 v2 = m_meshVertices[m_triangleList[triangle + 1]];
                Vector3 v3 = m_meshVertices[m_triangleList[triangle + 2]];

                Vector3 n = LinearAlgebra.ComputePlaneNormal(v1, v2, v3);

                Vector3 xProjected;
                LinearAlgebra.ProjectPointToPlane(v1, n, x, out xProjected);

                Vector3 xBarycentric = LinearAlgebra.WorldToBarycentric3(v1, v2, v3, xProjected);

                if (xBarycentric.x < 0.0)
                {
                    xProjected = LinearAlgebra.ClampToLine(v2, v3, xProjected);
                }

                else if (xBarycentric.y < 0.0)
                {
                    xProjected = LinearAlgebra.ClampToLine(v3, v1, xProjected);
                }

                else if (xBarycentric.z < 0.0)
                {
                    xProjected = LinearAlgebra.ClampToLine(v1, v2, xProjected);
                }

                float sqaredDistance = (xProjected - x).sqrMagnitude;

                if (!float.IsNaN(sqaredDistance) && sqaredDistance < bestDistanceSquared)
                {
                    bestDistanceSquared = sqaredDistance;
                    bestTriangle        = triangle;
                    bestNormal          = n;
                    bestPoint           = xProjected;
                }
            }

            Vector3 average = Vector3.zero;

            if (bestTriangle != -1)
            {
                if (m_smoothNormals)
                {
                    average = LinearAlgebra.BarycentricToWorld(
                        m_meshNormals[m_triangleList[bestTriangle + 0]],
                        m_meshNormals[m_triangleList[bestTriangle + 1]],
                        m_meshNormals[m_triangleList[bestTriangle + 2]],
                        LinearAlgebra.WorldToBarycentric3(
                            m_meshVertices[m_triangleList[bestTriangle + 0]],
                            m_meshVertices[m_triangleList[bestTriangle + 1]],
                            m_meshVertices[m_triangleList[bestTriangle + 2]],
                            bestPoint)
                        );
                }
                else
                {
                    average = m_meshNormals[m_triangleList[bestTriangle]];
                }



                average = LinearAlgebra.DivideComponents(average, m_scaleMesh);

                FlipNormal(m_flipX, m_flipY, m_flipZ, ref average);
                Swap(m_swapAxes, ref average);

                average = LinearAlgebra.MultiplyComponents(average, m_scaleVox);

                //Debug.Log("Computed normal for Coord" + tempdata.voxCoord.X + " " + tempdata.voxCoord.Y + " " + tempdata.voxCoord.Z + ": " + average.normalized.ToString() + " Triangle: " + bestTriangle);
            }

            for (int t = 0; t < tempdata.numVertices; t++)
            {
                outNormals[tempdata.vertexIndexOffsetBegin + t] = average;
            }
        }
        else
        {
            for (int t = 0; t < tempdata.numVertices; t++)
            {
                outNormals[tempdata.vertexIndexOffsetBegin + t] = inNormals[tempdata.vertexIndexOffsetBegin + t];
            }
        }
    }
    public override void Process(NPVoxModel model, NPVoxMeshData tempdata, Vector3[] inNormals, ref Vector3[] outNormals)
    {
        // calculate normals based on present neighbour voxels
        Vector3 voxelNormal = Vector3.zero;

        if (!tempdata.isHidden)
        {
            foreach (NPVoxCoord offset in voxelNormalNeighbours.Enumerate())
            {
                NPVoxCoord checkCoord = tempdata.voxCoord + offset;
                checkCoord = model.LoopCoord(checkCoord, tempdata.loop);
                if (!model.HasVoxel(checkCoord))
                {
                    voxelNormal += NPVoxCoordUtil.ToVector(offset);
                }
            }
            voxelNormal.Normalize();
        }
        else
        {
            voxelNormal = tempdata.voxelCenter.normalized;
        }

        for (int t = 0; t < tempdata.numVertices; t++)
        {
            Vector3 normal = Vector3.zero;

            switch (m_normalMode)
            {
            case NPVoxNormalMode.VOXEL:
                normal = voxelNormal;

                normal = Vector3.zero;

                if (tempdata.vertexPositionOffsets[t].x < 0.0f)
                {
                    if (tempdata.hasLeft && !tempdata.hasForward && !tempdata.hasBack && !tempdata.hasUp && !tempdata.hasDown)
                    {
                        normal.x = -1;
                    }
                    else
                    {
                        normal.x = voxelNormal.x;
                    }
                }
                else if (tempdata.vertexPositionOffsets[t].x > 0.0f)
                {
                    if (tempdata.hasRight && !tempdata.hasForward && !tempdata.hasBack && !tempdata.hasUp && !tempdata.hasDown)
                    {
                        normal.x = 1;
                    }
                    else
                    {
                        normal.x = voxelNormal.x;
                    }
                }

                if (tempdata.vertexPositionOffsets[t].y < 0.0f)
                {
                    if (tempdata.hasUp && !tempdata.hasForward && !tempdata.hasBack && !tempdata.hasLeft && !tempdata.hasRight)
                    {
                        normal.y = -1;
                    }
                    else
                    {
                        normal.y = voxelNormal.y;
                    }
                }
                else if (tempdata.vertexPositionOffsets[t].y > 0.0f)
                {
                    if (tempdata.hasDown && !tempdata.hasForward && !tempdata.hasBack && !tempdata.hasLeft && !tempdata.hasRight)
                    {
                        normal.y = +1;
                    }
                    else
                    {
                        normal.y = voxelNormal.y;
                    }
                }

                if (tempdata.vertexPositionOffsets[t].z < 0.0f)
                {
                    if (tempdata.hasBack && !tempdata.hasLeft && !tempdata.hasRight && !tempdata.hasUp && !tempdata.hasDown)
                    {
                        normal.z = -1;
                    }
                    else
                    {
                        normal.z = voxelNormal.z;
                    }
                }
                else if (tempdata.vertexPositionOffsets[t].z > 0.0f)
                {
                    if (tempdata.hasForward && !tempdata.hasLeft && !tempdata.hasRight && !tempdata.hasUp && !tempdata.hasDown)
                    {
                        normal.z = +1;
                    }
                    else
                    {
                        normal.z = voxelNormal.z;
                    }
                }

                if (Mathf.Abs(normal.x) < 0.1f && Mathf.Abs(normal.y) < 0.1f && Mathf.Abs(normal.z) < 0.1f)
                {
                    // we would like to have full color when we are a stand-alone voxel, however there is no way to do so right now, so we just
                    // fallback to the centoid normal
                    normal = tempdata.voxelCenter;
                }

                normal.Normalize();
                break;

            case NPVoxNormalMode.SMOOTH:
                normal = Vector3.zero;

                for (float xx = -0.5f; xx < 1.0f; xx += 1f)
                {
                    for (float yy = -.5f; yy < 1; yy += 1)
                    {
                        for (float zz = -.5f; zz < 1; zz += 1)
                        {
                            sbyte xCoord = ( sbyte )Mathf.Round(tempdata.vertexPositionOffsets[t].x + xx);
                            sbyte yCoord = ( sbyte )Mathf.Round(tempdata.vertexPositionOffsets[t].y + yy);
                            sbyte zCoord = ( sbyte )Mathf.Round(tempdata.vertexPositionOffsets[t].z + zz);

                            if (!model.HasVoxel(tempdata.voxCoord + new NPVoxCoord(( sbyte )xCoord, ( sbyte )yCoord, ( sbyte )zCoord)))
                            {
                                normal += new Vector3(
                                    xx,
                                    yy,
                                    zz
                                    );
                            }
                        }
                    }
                }

                normal.Normalize();
                break;

            case NPVoxNormalMode.FORWARD: normal = Vector3.forward; break;

            case NPVoxNormalMode.BACK: normal = Vector3.back; break;

            case NPVoxNormalMode.UP: normal = Vector3.up; break;

            case NPVoxNormalMode.DOWN: normal = Vector3.down; break;

            case NPVoxNormalMode.LEFT: normal = Vector3.left; break;

            case NPVoxNormalMode.RIGHT: normal = Vector3.right; break;
            }
            outNormals[tempdata.vertexIndexOffsetBegin + t] = normal;
        }
    }
Example #9
0
    public static void CreateMesh(
        NPVoxModel model,
        Mesh mesh,
        Vector3 cubeSize,
        Vector3 NormalVariance,
        int NormalVarianceSeed         = 0,
        NPVoxOptimization optimization = NPVoxOptimization.OFF,
        NPVoxNormalMode NormalMode     = NPVoxNormalMode.SMOOTH,
        int BloodColorIndex            = 0,
        NPVoxFaces loop     = null,
        NPVoxFaces cutout   = null,
        NPVoxFaces include  = null,
        int MinVertexGroups = 1,
        NPVoxNormalMode[] NormalModePerVoxelGroup = null,
        NPVoxNormalProcessorList normalProcessors = null
        )
    {
        bool hasVoxelGroups   = model.HasVoxelGroups();
        var  vertices         = new Vector3[model.NumVoxels * 8];
        byte vertexGroupCount = model.NumVoxelGroups;
        var  triangles        = new int[vertexGroupCount, model.NumVoxels * 36];

        var normals  = new Vector3[model.NumVoxels * 8];
        var tangents = new Vector4[model.NumVoxels * 8];
        var colors   = new Color[model.NumVoxels * 8];

        var tmp = new NPVoxMeshData[model.NumVoxels];

        int currentVertexIndex   = 0;
        var currentTriangleIndex = new int[vertexGroupCount];

        for (int i = 0; i < vertexGroupCount; i++)
        {
            currentTriangleIndex[i] = 0;
        }

        UnityEngine.Random.InitState(NormalVarianceSeed);

        if (loop == null)
        {
            loop = new NPVoxFaces();
        }

        if (include == null)
        {
            include = new NPVoxFaces(1, 1, 1, 1, 1, 1);
        }

        NPVoxBox voxelsToInclude = model.BoundingBox;
        Vector3  cutoutOffset    = Vector3.zero;

        if (cutout != null)
        {
            Vector3 originalCenter = voxelsToInclude.SaveCenter;
            voxelsToInclude.Left    = (sbyte)Mathf.Abs(cutout.Left);
            voxelsToInclude.Down    = (sbyte)Mathf.Abs(cutout.Down);
            voxelsToInclude.Back    = (sbyte)Mathf.Abs(cutout.Back);
            voxelsToInclude.Right   = (sbyte)(voxelsToInclude.Right - (sbyte)Mathf.Abs(cutout.Right));
            voxelsToInclude.Up      = (sbyte)(voxelsToInclude.Up - (sbyte)Mathf.Abs(cutout.Up));
            voxelsToInclude.Forward = (sbyte)(voxelsToInclude.Forward - (sbyte)Mathf.Abs(cutout.Forward));
            cutoutOffset            = Vector3.Scale(originalCenter - voxelsToInclude.SaveCenter, cubeSize);
        }

        NPVoxToUnity npVoxToUnity = new NPVoxToUnity(model, cubeSize);
        Vector3      size         = new Vector3(
            voxelsToInclude.Size.X * cubeSize.x,
            voxelsToInclude.Size.Y * cubeSize.y,
            voxelsToInclude.Size.Z * cubeSize.z
            );

        NPVoxBox voxelNormalNeighbours = new NPVoxBox(new NPVoxCoord(-1, -1, -1), new NPVoxCoord(1, 1, 1));

        // Collect temporary data to use for model generation
        int voxIndex = 0;

        foreach (NPVoxCoord voxCoord in voxelsToInclude.Enumerate())
        {
            if (model.HasVoxel(voxCoord))
            {
                tmp[voxIndex] = new NPVoxMeshData();

                tmp[voxIndex].loop    = loop;
                tmp[voxIndex].cutout  = cutout;
                tmp[voxIndex].include = include;

                // Compute voxel center
                tmp[voxIndex].voxelCenter = npVoxToUnity.ToUnityPosition(voxCoord) + cutoutOffset;
                tmp[voxIndex].voxCoord    = voxCoord;

                tmp[voxIndex].voxToUnity = npVoxToUnity;

                // Determine vertex group index
                tmp[voxIndex].vertexGroupIndex = 0;
                if (hasVoxelGroups)
                {
                    tmp[voxIndex].vertexGroupIndex = model.GetVoxelGroup(voxCoord);
                }

                // Determine normal Mode
                if (NormalModePerVoxelGroup != null && NormalModePerVoxelGroup.Length > tmp[voxIndex].vertexGroupIndex)
                {
                    tmp[voxIndex].normalMode = NormalModePerVoxelGroup[tmp[voxIndex].vertexGroupIndex];
                }
                else
                {
                    tmp[voxIndex].normalMode = NormalMode;
                }

                // do we have this side
                tmp[voxIndex].hasLeft    = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.LEFT, loop));
                tmp[voxIndex].hasRight   = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.RIGHT, loop));
                tmp[voxIndex].hasDown    = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.DOWN, loop));
                tmp[voxIndex].hasUp      = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.UP, loop));
                tmp[voxIndex].hasForward = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.FORWARD, loop));
                tmp[voxIndex].hasBack    = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.BACK, loop));

                // do we actually want to include this side in our mesh
                // NOTE: cutout < 0 means we still render the mesh even though it is cutout
                //       cutout > 0 means we don't render the mesh when cutout
                tmp[voxIndex].includeLeft    = (tmp[voxIndex].hasLeft || (cutout.Left < 0 && voxCoord.X == voxelsToInclude.Left)) && include.Left == 1;
                tmp[voxIndex].includeRight   = (tmp[voxIndex].hasRight || (cutout.Right < 0 && voxCoord.X == voxelsToInclude.Right)) && include.Right == 1;
                tmp[voxIndex].includeUp      = (tmp[voxIndex].hasUp || (cutout.Up < 0 && voxCoord.Y == voxelsToInclude.Up)) && include.Up == 1;
                tmp[voxIndex].includeDown    = (tmp[voxIndex].hasDown || (cutout.Down < 0 && voxCoord.Y == voxelsToInclude.Down)) && include.Down == 1;
                tmp[voxIndex].includeBack    = (tmp[voxIndex].hasBack || (cutout.Back < 0 && voxCoord.Z == voxelsToInclude.Back)) && include.Back == 1;
                tmp[voxIndex].includeForward = (tmp[voxIndex].hasForward || (cutout.Forward < 0 && voxCoord.Z == voxelsToInclude.Forward)) && include.Forward == 1;

                tmp[voxIndex].isHidden = !tmp[voxIndex].hasForward &&
                                         !tmp[voxIndex].hasBack &&
                                         !tmp[voxIndex].hasLeft &&
                                         !tmp[voxIndex].hasRight &&
                                         !tmp[voxIndex].hasUp &&
                                         !tmp[voxIndex].hasDown;


                if (tmp[voxIndex].isHidden && optimization == NPVoxOptimization.PER_VOXEL)
                {
                    continue;
                }

                if (tmp[voxIndex].isHidden && BloodColorIndex > 0)
                {
                    model.SetVoxel(voxCoord, (byte)BloodColorIndex); // WTF WTF WTF?!? we should not modify the MODEL in here !!!!           elfapo: AAAAHHH NOOOO!!!! :O    j.k. ;)
                }

                Color color = model.GetColor(voxCoord);

                // prepare cube vertices
                tmp[voxIndex].numVertices            = 0;
                tmp[voxIndex].vertexIndexOffsetBegin = currentVertexIndex;

                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeBack || tmp[voxIndex].includeLeft || tmp[voxIndex].includeDown)
                {
                    tmp[voxIndex].vertexIndexOffsets[0] = tmp[voxIndex].numVertices++;
                    tmp[voxIndex].vertexPositionOffsets[tmp[voxIndex].vertexIndexOffsets[0]] = new Vector3(-0.5f, -0.5f, -0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeBack || tmp[voxIndex].includeRight || tmp[voxIndex].includeDown)
                {
                    tmp[voxIndex].vertexIndexOffsets[1] = tmp[voxIndex].numVertices++;
                    tmp[voxIndex].vertexPositionOffsets[tmp[voxIndex].vertexIndexOffsets[1]] = new Vector3(0.5f, -0.5f, -0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeBack || tmp[voxIndex].includeLeft || tmp[voxIndex].includeUp)
                {
                    tmp[voxIndex].vertexIndexOffsets[2] = tmp[voxIndex].numVertices++;
                    tmp[voxIndex].vertexPositionOffsets[tmp[voxIndex].vertexIndexOffsets[2]] = new Vector3(-0.5f, 0.5f, -0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeBack || tmp[voxIndex].includeRight || tmp[voxIndex].includeUp)
                {
                    tmp[voxIndex].vertexIndexOffsets[3] = tmp[voxIndex].numVertices++;
                    tmp[voxIndex].vertexPositionOffsets[tmp[voxIndex].vertexIndexOffsets[3]] = new Vector3(0.5f, 0.5f, -0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeForward || tmp[voxIndex].includeLeft || tmp[voxIndex].includeDown)
                {
                    tmp[voxIndex].vertexIndexOffsets[4] = tmp[voxIndex].numVertices++;
                    tmp[voxIndex].vertexPositionOffsets[tmp[voxIndex].vertexIndexOffsets[4]] = new Vector3(-0.5f, -0.5f, 0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeForward || tmp[voxIndex].includeRight || tmp[voxIndex].includeDown)
                {
                    tmp[voxIndex].vertexIndexOffsets[5] = tmp[voxIndex].numVertices++;
                    tmp[voxIndex].vertexPositionOffsets[tmp[voxIndex].vertexIndexOffsets[5]] = new Vector3(0.5f, -0.5f, 0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeForward || tmp[voxIndex].includeLeft || tmp[voxIndex].includeUp)
                {
                    tmp[voxIndex].vertexIndexOffsets[6] = tmp[voxIndex].numVertices++;
                    tmp[voxIndex].vertexPositionOffsets[tmp[voxIndex].vertexIndexOffsets[6]] = new Vector3(-0.5f, 0.5f, 0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeForward || tmp[voxIndex].includeRight || tmp[voxIndex].includeUp)
                {
                    tmp[voxIndex].vertexIndexOffsets[7] = tmp[voxIndex].numVertices++;
                    tmp[voxIndex].vertexPositionOffsets[tmp[voxIndex].vertexIndexOffsets[7]] = new Vector3(0.5f, 0.5f, 0.5f);
                }


                // add cube faces
                int i = currentTriangleIndex[tmp[voxIndex].vertexGroupIndex];

                // back
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeBack)
                {
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[0];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[2];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[1];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[2];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[3];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[1];
                }

                // Forward
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeForward)
                {
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[6];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[4];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[5];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[7];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[6];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[5];
                }

                // right
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeRight)
                {
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[1];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[3];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[5];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[3];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[7];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[5];
                }

                // left
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeLeft)
                {
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[0];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[4];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[2];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[2];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[4];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[6];
                }

                // up
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeUp)
                {
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[2];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[6];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[3];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[3];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[6];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[7];
                }

                // down
                if (optimization != NPVoxOptimization.PER_FACE || tmp[voxIndex].includeDown)
                {
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[0];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[1];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[4];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[1];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[5];
                    triangles[tmp[voxIndex].vertexGroupIndex, i++] = tmp[voxIndex].vertexIndexOffsetBegin + tmp[voxIndex].vertexIndexOffsets[4];
                }


                // Tangents
                for (int t = 0; t < tmp[voxIndex].numVertices; t++)
                {
                    // store voxel center for shader usage
                    Vector4 tangent = new Vector4();
                    tangent.x = tmp[voxIndex].voxelCenter.x;
                    tangent.y = tmp[voxIndex].voxelCenter.y;
                    tangent.z = tmp[voxIndex].voxelCenter.z;
                    // encode model size
                    tangent.w = ((voxelsToInclude.Size.X & 0x7F) << 14) | ((voxelsToInclude.Size.Y & 0x7F) << 7) | (voxelsToInclude.Size.Z & 0x7F);

                    tangents[tmp[voxIndex].vertexIndexOffsetBegin + t] = tangent;
                }

                // UVs
                for (int t = 0; t < tmp[voxIndex].numVertices; t++)
                {
                    colors[tmp[voxIndex].vertexIndexOffsetBegin + t] = color;
                }

                // translate & scale vertices to voxel position
                for (int t = 0; t < tmp[voxIndex].numVertices; t++)
                {
                    vertices[tmp[voxIndex].vertexIndexOffsetBegin + t] = tmp[voxIndex].voxelCenter + Vector3.Scale(tmp[voxIndex].vertexPositionOffsets[t], cubeSize);
                }

                currentTriangleIndex[tmp[voxIndex].vertexGroupIndex] = i;
                currentVertexIndex += tmp[voxIndex].numVertices;
                voxIndex++;
            }
        }

        // elfapo: Remove invalid voxel information
        Array.Resize(ref tmp, voxIndex);


        ////////////////////////////////////// NORMAL STAGES ////////////////////////////////////////
        // elfapo TODO: Test area 'Normal Processor' Move Normal Processor stages to Normal Processor Pipeline:

        //NPVoxNormalProcessor_Voxel generator = ScriptableObject.CreateInstance<NPVoxNormalProcessor_Voxel>();
        //NPVoxNormalProcessor_Variance processor = ScriptableObject.CreateInstance<NPVoxNormalProcessor_Variance>();

        //generator.InitOutputBuffer(normals);
        //processor.InitOutputBuffer(normals);

        //processor.NormalVariance = NormalVariance;
        //processor.NormalVarianceSeed = NormalVarianceSeed;

        //if (NormalModePerVoxelGroup != null && NormalModePerVoxelGroup.Length > 0)
        //{
        //    for (int i = 0; i < NormalModePerVoxelGroup.Length; i++)
        //    {
        //        generator.ClearVoxelGroupFilters();
        //        generator.AddVoxelGroupFilter(i);
        //        generator.NormalMode = NormalModePerVoxelGroup[i];
        //        generator.Process(model, tmp, normals, normals);
        //    }

        //    processor.Process(model, tmp, normals, normals);
        //}
        //else
        //{
        //    generator.NormalMode = NormalMode;
        //    generator.Process(model, tmp, normals, normals);
        //    processor.Process(model, tmp, normals, normals);
        //}


        //ScriptableObject.DestroyImmediate(generator);
        //ScriptableObject.DestroyImmediate(processor);

        if (normalProcessors != null)
        {
            normalProcessors.Run(model, tmp, normals, normals);
        }

        //////////////////////////////////////////////////////////////////////////////////////////////


        // shrink arrays as needed
        if (optimization != NPVoxOptimization.OFF)
        {
            Array.Resize(ref vertices, currentVertexIndex);
            Array.Resize(ref normals, currentVertexIndex);
            Array.Resize(ref tangents, currentVertexIndex);
            Array.Resize(ref colors, currentVertexIndex);
        }

        mesh.vertices = vertices;
        if (hasVoxelGroups)
        {
            mesh.subMeshCount = Math.Max(vertexGroupCount, MinVertexGroups);
            for (int i = 0; i < vertexGroupCount; i++)
            {
                int   numberOfTrianglesForVertexGroup = currentTriangleIndex[i];
                int[] trianglesForVertexGroup         = new int[numberOfTrianglesForVertexGroup];
                for (int j = 0; j < numberOfTrianglesForVertexGroup; j++)
                {
                    trianglesForVertexGroup[j] = triangles[i, j];
                }
                mesh.SetTriangles(trianglesForVertexGroup, i);
            }
        }
        else
        {
            int   numberOfTrianglesForVertexGroup = currentTriangleIndex[0];
            int[] trianglesForVertexGroup         = new int[numberOfTrianglesForVertexGroup];
            Buffer.BlockCopy(triangles, 0,
                             trianglesForVertexGroup, 0,
                             numberOfTrianglesForVertexGroup * sizeof(int));

            if (MinVertexGroups < 2)
            {
                mesh.triangles = trianglesForVertexGroup;
            }
            else
            {
                mesh.subMeshCount = MinVertexGroups;
                mesh.SetTriangles(trianglesForVertexGroup, 0);
            }
        }

        mesh.normals  = normals;
        mesh.tangents = tangents;
        mesh.colors   = colors;
        mesh.bounds   = new Bounds(Vector3.zero, size);

        if (NormalMode == NPVoxNormalMode.AUTO)
        {
            mesh.RecalculateNormals();
        }
    }
Example #10
0
    public static NPVoxMeshData[] GenerateVoxMeshData(
        NPVoxModel model,
        Vector3 cubeSize,
        NPVoxOptimization optimization = NPVoxOptimization.OFF,
        int BloodColorIndex            = 0,
        NPVoxFaces loop    = null,
        NPVoxFaces cutout  = null,
        NPVoxFaces include = null)
    {
        bool hasVoxelGroups   = model.HasVoxelGroups();
        byte vertexGroupCount = model.NumVoxelGroups;

        var voxMeshData = new NPVoxMeshData[model.NumVoxels];

        int currentVertexIndex = 0;

        if (loop == null)
        {
            loop = new NPVoxFaces();
        }

        if (include == null)
        {
            include = new NPVoxFaces(1, 1, 1, 1, 1, 1);
        }

        NPVoxBox voxelsToInclude = model.BoundingBox;
        Vector3  cutoutOffset    = Vector3.zero;

        if (cutout != null)
        {
            Vector3 originalCenter = voxelsToInclude.SaveCenter;
            voxelsToInclude.Left    = ( sbyte )Mathf.Abs(cutout.Left);
            voxelsToInclude.Down    = ( sbyte )Mathf.Abs(cutout.Down);
            voxelsToInclude.Back    = ( sbyte )Mathf.Abs(cutout.Back);
            voxelsToInclude.Right   = ( sbyte )(voxelsToInclude.Right - ( sbyte )Mathf.Abs(cutout.Right));
            voxelsToInclude.Up      = ( sbyte )(voxelsToInclude.Up - ( sbyte )Mathf.Abs(cutout.Up));
            voxelsToInclude.Forward = ( sbyte )(voxelsToInclude.Forward - ( sbyte )Mathf.Abs(cutout.Forward));
            cutoutOffset            = Vector3.Scale(originalCenter - voxelsToInclude.SaveCenter, cubeSize);
        }

        NPVoxToUnity npVoxToUnity = new NPVoxToUnity(model, cubeSize);
        Vector3      size         = new Vector3(
            voxelsToInclude.Size.X * cubeSize.x,
            voxelsToInclude.Size.Y * cubeSize.y,
            voxelsToInclude.Size.Z * cubeSize.z
            );

        NPVoxBox voxelNormalNeighbours = new NPVoxBox(new NPVoxCoord(-1, -1, -1), new NPVoxCoord(1, 1, 1));

        // Collect temporary data to use for model generation
        int voxIndex = 0;

        foreach (NPVoxCoord voxCoord in voxelsToInclude.Enumerate())
        {
            if (model.HasVoxel(voxCoord))
            {
                voxMeshData[voxIndex] = new NPVoxMeshData();

                voxMeshData[voxIndex].loop    = loop;
                voxMeshData[voxIndex].cutout  = cutout;
                voxMeshData[voxIndex].include = include;

                // Compute voxel center
                voxMeshData[voxIndex].voxelCenter = npVoxToUnity.ToUnityPosition(voxCoord) + cutoutOffset;
                voxMeshData[voxIndex].voxCoord    = voxCoord;

                voxMeshData[voxIndex].voxToUnity = npVoxToUnity;

                // Determine vertex group index
                voxMeshData[voxIndex].vertexGroupIndex = 0;
                if (hasVoxelGroups)
                {
                    voxMeshData[voxIndex].vertexGroupIndex = model.GetVoxelGroup(voxCoord);
                }

                // do we have this side
                voxMeshData[voxIndex].hasLeft    = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.LEFT, loop));
                voxMeshData[voxIndex].hasRight   = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.RIGHT, loop));
                voxMeshData[voxIndex].hasDown    = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.DOWN, loop));
                voxMeshData[voxIndex].hasUp      = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.UP, loop));
                voxMeshData[voxIndex].hasForward = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.FORWARD, loop));
                voxMeshData[voxIndex].hasBack    = !model.HasVoxel(model.LoopCoord(voxCoord + NPVoxCoord.BACK, loop));

                // do we actually want to include this side in our mesh
                // NOTE: cutout < 0 means we still render the mesh even though it is cutout
                //       cutout > 0 means we don't render the mesh when cutout
                voxMeshData[voxIndex].includeLeft    = (voxMeshData[voxIndex].hasLeft || (cutout.Left < 0 && voxCoord.X == voxelsToInclude.Left)) && include.Left == 1;
                voxMeshData[voxIndex].includeRight   = (voxMeshData[voxIndex].hasRight || (cutout.Right < 0 && voxCoord.X == voxelsToInclude.Right)) && include.Right == 1;
                voxMeshData[voxIndex].includeUp      = (voxMeshData[voxIndex].hasUp || (cutout.Up < 0 && voxCoord.Y == voxelsToInclude.Up)) && include.Up == 1;
                voxMeshData[voxIndex].includeDown    = (voxMeshData[voxIndex].hasDown || (cutout.Down < 0 && voxCoord.Y == voxelsToInclude.Down)) && include.Down == 1;
                voxMeshData[voxIndex].includeBack    = (voxMeshData[voxIndex].hasBack || (cutout.Back < 0 && voxCoord.Z == voxelsToInclude.Back)) && include.Back == 1;
                voxMeshData[voxIndex].includeForward = (voxMeshData[voxIndex].hasForward || (cutout.Forward < 0 && voxCoord.Z == voxelsToInclude.Forward)) && include.Forward == 1;

                voxMeshData[voxIndex].isHidden = !voxMeshData[voxIndex].hasForward &&
                                                 !voxMeshData[voxIndex].hasBack &&
                                                 !voxMeshData[voxIndex].hasLeft &&
                                                 !voxMeshData[voxIndex].hasRight &&
                                                 !voxMeshData[voxIndex].hasUp &&
                                                 !voxMeshData[voxIndex].hasDown;


                if (voxMeshData[voxIndex].isHidden && optimization == NPVoxOptimization.PER_VOXEL)
                {
                    continue;
                }

                if (voxMeshData[voxIndex].isHidden && BloodColorIndex > 0)
                {
                    model.SetVoxel(voxCoord, ( byte )BloodColorIndex);    // WTF WTF WTF?!? we should not modify the MODEL in here !!!!           elfapo: AAAAHHH NOOOO!!!! :O    j.k. ;)
                }

                // prepare cube vertices
                voxMeshData[voxIndex].numVertices            = 0;
                voxMeshData[voxIndex].vertexIndexOffsetBegin = currentVertexIndex;

                if (optimization != NPVoxOptimization.PER_FACE || voxMeshData[voxIndex].includeBack || voxMeshData[voxIndex].includeLeft || voxMeshData[voxIndex].includeDown)
                {
                    voxMeshData[voxIndex].vertexIndexOffsets[0] = voxMeshData[voxIndex].numVertices++;
                    voxMeshData[voxIndex].vertexPositionOffsets[voxMeshData[voxIndex].vertexIndexOffsets[0]] = new Vector3(-0.5f, -0.5f, -0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || voxMeshData[voxIndex].includeBack || voxMeshData[voxIndex].includeRight || voxMeshData[voxIndex].includeDown)
                {
                    voxMeshData[voxIndex].vertexIndexOffsets[1] = voxMeshData[voxIndex].numVertices++;
                    voxMeshData[voxIndex].vertexPositionOffsets[voxMeshData[voxIndex].vertexIndexOffsets[1]] = new Vector3(0.5f, -0.5f, -0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || voxMeshData[voxIndex].includeBack || voxMeshData[voxIndex].includeLeft || voxMeshData[voxIndex].includeUp)
                {
                    voxMeshData[voxIndex].vertexIndexOffsets[2] = voxMeshData[voxIndex].numVertices++;
                    voxMeshData[voxIndex].vertexPositionOffsets[voxMeshData[voxIndex].vertexIndexOffsets[2]] = new Vector3(-0.5f, 0.5f, -0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || voxMeshData[voxIndex].includeBack || voxMeshData[voxIndex].includeRight || voxMeshData[voxIndex].includeUp)
                {
                    voxMeshData[voxIndex].vertexIndexOffsets[3] = voxMeshData[voxIndex].numVertices++;
                    voxMeshData[voxIndex].vertexPositionOffsets[voxMeshData[voxIndex].vertexIndexOffsets[3]] = new Vector3(0.5f, 0.5f, -0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || voxMeshData[voxIndex].includeForward || voxMeshData[voxIndex].includeLeft || voxMeshData[voxIndex].includeDown)
                {
                    voxMeshData[voxIndex].vertexIndexOffsets[4] = voxMeshData[voxIndex].numVertices++;
                    voxMeshData[voxIndex].vertexPositionOffsets[voxMeshData[voxIndex].vertexIndexOffsets[4]] = new Vector3(-0.5f, -0.5f, 0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || voxMeshData[voxIndex].includeForward || voxMeshData[voxIndex].includeRight || voxMeshData[voxIndex].includeDown)
                {
                    voxMeshData[voxIndex].vertexIndexOffsets[5] = voxMeshData[voxIndex].numVertices++;
                    voxMeshData[voxIndex].vertexPositionOffsets[voxMeshData[voxIndex].vertexIndexOffsets[5]] = new Vector3(0.5f, -0.5f, 0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || voxMeshData[voxIndex].includeForward || voxMeshData[voxIndex].includeLeft || voxMeshData[voxIndex].includeUp)
                {
                    voxMeshData[voxIndex].vertexIndexOffsets[6] = voxMeshData[voxIndex].numVertices++;
                    voxMeshData[voxIndex].vertexPositionOffsets[voxMeshData[voxIndex].vertexIndexOffsets[6]] = new Vector3(-0.5f, 0.5f, 0.5f);
                }
                if (optimization != NPVoxOptimization.PER_FACE || voxMeshData[voxIndex].includeForward || voxMeshData[voxIndex].includeRight || voxMeshData[voxIndex].includeUp)
                {
                    voxMeshData[voxIndex].vertexIndexOffsets[7] = voxMeshData[voxIndex].numVertices++;
                    voxMeshData[voxIndex].vertexPositionOffsets[voxMeshData[voxIndex].vertexIndexOffsets[7]] = new Vector3(0.5f, 0.5f, 0.5f);
                }

                currentVertexIndex += voxMeshData[voxIndex].numVertices;
                voxIndex++;
            }
        }

        Array.Resize(ref voxMeshData, voxIndex);

        return(voxMeshData);
    }
 public abstract void Process(NPVoxModel model, NPVoxMeshData tempdata, Vector3[] inNormals, ref Vector3[] outNormals);