Exemplo n.º 1
0
void LoopSubdiv::Refine(vector<Reference<Shape> > &refined) const {
    vector<SDFace *> f = faces;
    vector<SDVertex *> v = vertices;
    MemoryArena arena;
    for (int i = 0; i < nLevels; ++i) {
        // Update _f_ and _v_ for next level of subdivision
        vector<SDFace *> newFaces;
        vector<SDVertex *> newVertices;

        // Allocate next level of children in mesh tree
        for (uint32_t j = 0; j < v.size(); ++j) {
            v[j]->child = arena.Alloc<SDVertex>();
            v[j]->child->regular = v[j]->regular;
            v[j]->child->boundary = v[j]->boundary;
            newVertices.push_back(v[j]->child);
        }
        for (uint32_t j = 0; j < f.size(); ++j)
            for (int k = 0; k < 4; ++k) {
                f[j]->children[k] = arena.Alloc<SDFace>();
                newFaces.push_back(f[j]->children[k]);
            }

        // Update vertex positions and create new edge vertices

        // Update vertex positions for even vertices
        for (uint32_t j = 0; j < v.size(); ++j) {
            if (!v[j]->boundary) {
                // Apply one-ring rule for even vertex
                if (v[j]->regular)
                    v[j]->child->P = weightOneRing(v[j], 1.f/16.f);
                else
                    v[j]->child->P = weightOneRing(v[j], beta(v[j]->valence()));
            }
            else {
                // Apply boundary rule for even vertex
                v[j]->child->P = weightBoundary(v[j], 1.f/8.f);
            }
        }

        // Compute new odd edge vertices
        map<SDEdge, SDVertex *> edgeVerts;
        for (uint32_t j = 0; j < f.size(); ++j) {
            SDFace *face = f[j];
            for (int k = 0; k < 3; ++k) {
                // Compute odd vertex on _k_th edge
                SDEdge edge(face->v[k], face->v[NEXT(k)]);
                SDVertex *vert = edgeVerts[edge];
                if (!vert) {
                    // Create and initialize new odd vertex
                    vert = arena.Alloc<SDVertex>();
                    newVertices.push_back(vert);
                    vert->regular = true;
                    vert->boundary = (face->f[k] == NULL);
                    vert->startFace = face->children[3];

                    // Apply edge rules to compute new vertex position
                    if (vert->boundary) {
                        vert->P =  0.5f * edge.v[0]->P;
                        vert->P += 0.5f * edge.v[1]->P;
                    }
                    else {
                        vert->P =  3.f/8.f * edge.v[0]->P;
                        vert->P += 3.f/8.f * edge.v[1]->P;
                        vert->P += 1.f/8.f * face->otherVert(edge.v[0], edge.v[1])->P;
                        vert->P += 1.f/8.f *
                            face->f[k]->otherVert(edge.v[0], edge.v[1])->P;
                    }
                    edgeVerts[edge] = vert;
                }
            }
        }

        // Update new mesh topology

        // Update even vertex face pointers
        for (uint32_t j = 0; j < v.size(); ++j) {
            SDVertex *vert = v[j];
            int vertNum = vert->startFace->vnum(vert);
            vert->child->startFace =
                vert->startFace->children[vertNum];
        }

        // Update face neighbor pointers
        for (uint32_t j = 0; j < f.size(); ++j) {
            SDFace *face = f[j];
            for (int k = 0; k < 3; ++k) {
                // Update children _f_ pointers for siblings
                face->children[3]->f[k] = face->children[NEXT(k)];
                face->children[k]->f[NEXT(k)] = face->children[3];

                // Update children _f_ pointers for neighbor children
                SDFace *f2 = face->f[k];
                face->children[k]->f[k] =
                    f2 ? f2->children[f2->vnum(face->v[k])] : NULL;
                f2 = face->f[PREV(k)];
                face->children[k]->f[PREV(k)] =
                    f2 ? f2->children[f2->vnum(face->v[k])] : NULL;
            }
        }

        // Update face vertex pointers
        for (uint32_t j = 0; j < f.size(); ++j) {
            SDFace *face = f[j];
            for (int k = 0; k < 3; ++k) {
                // Update child vertex pointer to new even vertex
                face->children[k]->v[k] = face->v[k]->child;

                // Update child vertex pointer to new odd vertex
                SDVertex *vert = edgeVerts[SDEdge(face->v[k], face->v[NEXT(k)])];
                face->children[k]->v[NEXT(k)] = vert;
                face->children[NEXT(k)]->v[k] = vert;
                face->children[3]->v[k] = vert;
            }
        }

        // Prepare for next level of subdivision
        f = newFaces;
        v = newVertices;
    }
    // Push vertices to limit surface
    PbrtPoint *Plimit = new PbrtPoint[v.size()];
    for (uint32_t i = 0; i < v.size(); ++i) {
        if (v[i]->boundary)
            Plimit[i] =  weightBoundary(v[i], 1.f/5.f);
        else
            Plimit[i] =  weightOneRing(v[i], gamma(v[i]->valence()));
    }
    for (uint32_t i = 0; i < v.size(); ++i)
        v[i]->P = Plimit[i];

    // Compute vertex tangents on limit surface
    vector<Normal> Ns;
    Ns.reserve(v.size());
    vector<PbrtPoint> Pring(16, PbrtPoint());
    for (uint32_t i = 0; i < v.size(); ++i) {
        SDVertex *vert = v[i];
        Vector S(0,0,0), T(0,0,0);
        int valence = vert->valence();
        if (valence > (int)Pring.size())
            Pring.resize(valence);
        vert->oneRing(&Pring[0]);
        if (!vert->boundary) {
            // Compute tangents of interior face
            for (int k = 0; k < valence; ++k) {
                S += cosf(2.f*M_PI*k/valence) * Vector(Pring[k]);
                T += sinf(2.f*M_PI*k/valence) * Vector(Pring[k]);
            }
        } else {
            // Compute tangents of boundary face
            S = Pring[valence-1] - Pring[0];
            if (valence == 2)
                T = Vector(Pring[0] + Pring[1] - 2 * vert->P);
            else if (valence == 3)
                T = Pring[1] - vert->P;
            else if (valence == 4) // regular
                T = Vector(-1*Pring[0] + 2*Pring[1] + 2*Pring[2] +
                           -1*Pring[3] + -2*vert->P);
            else {
                float theta = M_PI / float(valence-1);
                T = Vector(sinf(theta) * (Pring[0] + Pring[valence-1]));
                for (int k = 1; k < valence-1; ++k) {
                    float wt = (2*cosf(theta) - 2) * sinf((k) * theta);
                    T += Vector(wt * Pring[k]);
                }
                T = -T;
            }
        }
        Ns.push_back(Normal(Cross(S, T)));
    }

    // Create _TriangleMesh_ from subdivision mesh
    uint32_t ntris = uint32_t(f.size());
    int *verts = new int[3*ntris];
    int *vp = verts;
    uint32_t totVerts = uint32_t(v.size());
    map<SDVertex *, int> usedVerts;
    for (uint32_t i = 0; i < totVerts; ++i)
        usedVerts[v[i]] = i;
    for (uint32_t i = 0; i < ntris; ++i) {
        for (int j = 0; j < 3; ++j) {
            *vp = usedVerts[f[i]->v[j]];
            ++vp;
        }
    }
    ParamSet paramSet;
    paramSet.AddInt("indices", verts, 3*ntris);
    paramSet.AddPoint("P", Plimit, totVerts);
    paramSet.AddNormal("N", &Ns[0], int(Ns.size()));
    refined.push_back(CreateTriangleMeshShape(ObjectToWorld,
            WorldToObject, ReverseOrientation, paramSet));
    delete[] verts;
    delete[] Plimit;
}