Esempio n. 1
0
        public static CellInfo[,,] GenVertices(int resolution, UtilFuncs.Sampler samp)
        {
            CellInfo[,,] cellInfos = new CellInfo[resolution, resolution, resolution];

            for (int x = 0; x < resolution; x++)
            {
                for (int y = 0; y < resolution; y++)
                {
                    for (int z = 0; z < resolution; z++)
                    {
                        //Vector3 p = new Vector3(x, y, z);
                        byte    caseCode  = 0;
                        sbyte[] densities = new sbyte[8];

                        for (int i = 0; i < 8; i++)
                        {
                            Vector3 pos = new Vector3(x, y, z) + DCC.vfoffsets[i];
                            densities[i] = (sbyte)Mathf.Clamp((samp(pos.x, pos.y, pos.z) * 127f), -127f, 127f);                             //data[index + inArray[i]];

                            if (densities[i] < 0)
                            {
                                caseCode |= (byte)(1 << i);
                            }
                        }

                        Vector3[] cpositions = new Vector3[4];
                        Vector3[] cnormals   = new Vector3[4];
                        int       edgeCount  = 0;
                        for (int i = 0; i < 12 && edgeCount < 4; i++)
                        {
                            byte c1 = (byte)DCC.edgevmap[i][0];
                            byte c2 = (byte)DCC.edgevmap[i][1];

                            Vector3 p1 = new Vector3(x, y, z) + DCC.vfoffsets[c1];
                            Vector3 p2 = new Vector3(x, y, z) + DCC.vfoffsets[c2];

                            bool m1 = ((caseCode >> c1) & 1) == 1;
                            bool m2 = ((caseCode >> c2) & 1) == 1;


                            if (m1 != m2)
                            {
                                cpositions[edgeCount] = ApproximateZeroCrossingPosition(p1, p2, samp);
                                cnormals[edgeCount]   = CalculateSurfaceNormal(cpositions[edgeCount], samp);
                                edgeCount++;
                            }
                        }

                        if (edgeCount == 0)
                        {
                            continue;
                        }

                        CellInfo      cellInfo = new CellInfo();
                        QEF.QEFSolver qef      = new QEF.QEFSolver();
                        for (int i = 0; i < edgeCount; i++)
                        {
                            qef.Add(cpositions[i], cnormals[i]);
                        }
                        cellInfo.Position = qef.Solve(0.0001f, 4, 0.0001f);
                        //drawInfo.index = vertices.Count;

                        Vector3 max = new Vector3(x, y, z) + Vector3.one;
                        if (cellInfo.Position.x < x || cellInfo.Position.x > max.x ||
                            cellInfo.Position.y < y || cellInfo.Position.y > max.y ||
                            cellInfo.Position.z < z || cellInfo.Position.z > max.z)
                        {
                            cellInfo.Position = qef.MassPoint;
                        }

                        //vertices.Add(drawInfo.position);

                        for (int i = 0; i < edgeCount; i++)
                        {
                            cellInfo.Normal += cnormals[i];
                        }
                        cellInfo.Normal = Vector3.Normalize(cellInfo.Normal);                         //CalculateSurfaceNormal(drawInfo.position, samp);
                        //normals.Add(drawInfo.averageNormal);
                        cellInfo.Corners   = caseCode;
                        cellInfos[x, y, z] = cellInfo;
                    }
                }
            }

            return(cellInfos);
        }
Esempio n. 2
0
        public static OctreeNode SimplifyOctree(OctreeNode node, float threshold)
        {
            if (node == null)
            {
                return(null);
            }
            if (node.type != DCC.OctreeNodeType.Node_Internal)
            {
                return(node);
            }

            QEF.QEFSolver qef           = new QEF.QEFSolver();
            int[]         signs         = { -1, -1, -1, -1, -1, -1, -1, -1 };
            int           midsign       = -1;
            int           edgeCount     = 0;
            bool          isCollapsible = true;

            for (int i = 0; i < 8; i++)
            {
                node.children[i] = SimplifyOctree(node.children[i], threshold);
                if (node.children[i] != null)
                {
                    OctreeNode child = node.children[i];
                    if (child.type == DCC.OctreeNodeType.Node_Internal)
                    {
                        isCollapsible = false;
                    }
                    else
                    {
                        qef.Add(ref child.drawInfo.qef.data);

                        if (qef.data.numPoints == 0)
                        {
                            Debug.Log("warning: zero points in qef");
                            Debug.Log("child number of points: " + child.drawInfo.qef.data.numPoints);
                        }

                        //Debug.LogError("Qef points: " + qef.data.numPoints);

                        midsign  = (child.drawInfo.corners >> (7 - i)) & 1;
                        signs[i] = (child.drawInfo.corners >> i) & 1;

                        edgeCount++;
                    }
                }
                else
                {
                    //Debug.LogError("Null child! type: " + node.type);
                }
            }

            if (!isCollapsible)
            {
                // at least one child is an internal node, can't collapse
                return(node);
            }

            float QEF_ERROR  = 0.1f;
            int   QEF_SWEEPS = 4;
            float PINV_TOL   = 0.1f;

            if (qef.data.numPoints == 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    //DestroyOctree(node->children[i]);
                    node.children[i] = null;
                }

                node.type = DCC.OctreeNodeType.Node_Psuedo;

                OctreeDrawInfo drawInfo2 = new OctreeDrawInfo();

                for (int i = 0; i < 8; i++)
                {
                    if (signs[i] == -1)
                    {
                        // Undetermined, use centre sign instead
                        drawInfo2.corners |= (midsign << i);
                    }
                    else
                    {
                        drawInfo2.corners |= (signs[i] << i);
                    }
                }

                drawInfo2.averageNormal = Vector3.zero;


                node.drawInfo = drawInfo2;

                return(node);
            }

            Vector3 position = qef.Solve(QEF_ERROR, QEF_SWEEPS, PINV_TOL);
            //if(qef.data.num)
            float error = qef.GetError();

            // at this point the masspoint will actually be a sum, so divide to make it the average
            if (error > threshold)
            {
                // this collapse breaches the threshold
                return(node);
            }

            if (position.x < node.min.x || position.x > (node.min.x + node.size) ||
                position.y < node.min.y || position.y > (node.min.y + node.size) ||
                position.z < node.min.z || position.z > (node.min.z + node.size))
            {
                Vector3 mp = qef.MassPoint;
                position = new Vector3(mp.x, mp.y, mp.z);
            }

            // change the node from an internal node to a 'psuedo leaf' node
            OctreeDrawInfo drawInfo = new OctreeDrawInfo();

            for (int i = 0; i < 8; i++)
            {
                if (signs[i] == -1)
                {
                    // Undetermined, use centre sign instead
                    drawInfo.corners |= (midsign << i);
                }
                else
                {
                    drawInfo.corners |= (signs[i] << i);
                }
            }

            drawInfo.averageNormal = Vector3.zero;
            for (int i = 0; i < 8; i++)
            {
                if (node.children[i] != null)
                {
                    OctreeNode child = node.children[i];
                    if (child.type == DCC.OctreeNodeType.Node_Psuedo ||
                        child.type == DCC.OctreeNodeType.Node_Leaf)
                    {
                        drawInfo.averageNormal += child.drawInfo.averageNormal;
                    }
                }
            }

            drawInfo.averageNormal = Vector3.Normalize(drawInfo.averageNormal);
            drawInfo.position      = position;

            QEF.QEFSolver qef2 = new QEF.QEFSolver();

            qef2.data = qef.data;

            drawInfo.qef = qef2;

            for (int i = 0; i < 8; i++)
            {
                //DestroyOctree(node->children[i]);
                node.children[i] = null;
            }

            node.type     = DCC.OctreeNodeType.Node_Psuedo;
            node.drawInfo = drawInfo;

            return(node);
        }