Пример #1
0
    //Calcola la normale del punto passato
    public Vector3 CalculateSurfaceNormal(Vector3 p)
    {
        float   H   = 0.001f;
        float   dx  = Density.DensityFunc(p + new Vector3(H, 0, 0)) - Density.DensityFunc(p - new Vector3(H, 0, 0));
        float   dy  = Density.DensityFunc(p + new Vector3(0, H, 0)) - Density.DensityFunc(p - new Vector3(0, H, 0));
        float   dz  = Density.DensityFunc(p + new Vector3(0, 0, H)) - Density.DensityFunc(p - new Vector3(0, 0, H));
        Vector3 res = new Vector3(dx, dy, dz);

        return(res.normalized);
    }
Пример #2
0
    //approssima il punto di incontro dei vettori
    public Vector3 ApproximateZeroCrossingPosition(Vector3 p1, Vector3 p2, int steps)
    {
        float minVal = float.MaxValue;
        float t = 0, curT = 0;
        float increment = 1.0f / (float)steps;

        while (curT <= 1.0f)
        {
            Vector3 p       = p1 + ((p2 - p1) * curT);
            float   density = Mathf.Abs(Density.DensityFunc(p));
            if (density < minVal)
            {
                minVal = density;
                t      = curT;
            }
            curT += increment;
        }
        return(p1 + ((p2 - p1) * t));
    }
Пример #3
0
    //costruisce il nodo terminale (foglia) calcolando le NodeInfo per la generazione della mesh
    public OctreeNode BuildLeaf(OctreeNode leaf, int size)
    {
        if (leaf == null || leaf.size != size)
        {
            return(null);
        }

        int corners = 0;

        for (int i = 0; i < 8; i++)
        {
            Vector3 cornerPos = leaf.min + (CHILD_MIN_OFFSETS[i] * size);
            float   density   = Density.DensityFunc(cornerPos);
            int     material  = density < 0.0f ? SOLID : AIR;
            corners |= (material << i);
        }

        if (corners == 0 || corners == 255)
        {
            leaf = null;
            return(null);
        }

        int       edgeCount     = 0;
        Vector3   averageNormal = new Vector3();
        QefSolver qef           = new QefSolver();

        for (int i = 0; i < 12 && edgeCount < MAX_CROSSINGS; i++)
        {
            int c1 = edgevmap[i][0];
            int c2 = edgevmap[i][1];

            int m1 = (corners >> c1) & 1;
            int m2 = (corners >> c2) & 1;

            if ((m1 == AIR && m2 == AIR) || (m1 == SOLID && m2 == SOLID))
            {
                continue;
            }

            Vector3 p1 = leaf.min + (CHILD_MIN_OFFSETS[c1] * size);
            Vector3 p2 = leaf.min + (CHILD_MIN_OFFSETS[c2] * size);
            Vector3 p  = ApproximateZeroCrossingPosition(p1, p2, 8);
            Vector3 n  = CalculateSurfaceNormal(p);
            qef.Add(p.x, p.y, p.z, n.x, n.y, n.z);

            averageNormal += n;
            edgeCount++;
        }

        Vector3 qefPosition = new Vector3();

        qef.Solve(qefPosition, QEF_ERROR, QEF_SWEEPS, QEF_ERROR);

        NodeInfo info = new NodeInfo();

        info.index    = -1;
        info.corners  = 0;
        info.position = qefPosition;
        info.qef      = qef.GetData();

        Vector3 min = leaf.min;
        Vector3 max = new Vector3(leaf.min.x + leaf.size, leaf.min.y + leaf.size, leaf.min.z + leaf.size);

        if (info.position.x < min.x || info.position.x > max.x ||
            info.position.y < min.y || info.position.y > max.y ||
            info.position.z < min.z || info.position.z > max.z)
        {
            info.position = qef.GetMassPoint();
        }

        info.avgNormal = (averageNormal / (float)edgeCount).normalized;
        info.corners   = corners;

        leaf.type     = NodeType.LEAF;
        leaf.nodeInfo = info;
        return(leaf);
    }