Exemplo n.º 1
0
void LoopSubdiv::GenerateNormals(const vector<SDVertex *> v) {
	// Compute vertex tangents on limit surface
	u_int ringSize = 16;
	Point *Pring = new Point[ringSize];
	for (u_int i = 0; i < v.size(); ++i) {
		SDVertex *vert = v[i];
		Vector S(0,0,0), T(0,0,0);
		u_int valence = vert->valence();
		if (valence > ringSize) {
			ringSize = valence;
			delete[] Pring;
			Pring = new Point[ringSize];
		}
		vert->oneRing(Pring);
	
		if (!vert->boundary) {
			// Compute tangents of interior face
			for (u_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 / static_cast<float>(valence - 1);
				T = Vector(sinf(theta) * (Pring[0] + Pring[valence-1]));
				for (u_int k = 1; k < valence - 1; ++k) {
					float wt = (2*cosf(theta) - 2) * sinf((k) * theta);
					T += Vector(wt * Pring[k]);
				}
				T = -T;
			}
		}
		vert->n = Normal(Normalize(Cross(T, S)));
	}
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
// LoopSubdiv Method Definitions
LoopSubdiv::LoopSubdiv(const Transform *o2w, const Transform *w2o,
                       bool ro, int nfaces, int nvertices,
                       const int *vertexIndices, const PbrtPoint *P, int nl)
    : Shape(o2w, w2o, ro) {
    nLevels = nl;
    // Allocate _LoopSubdiv_ vertices and faces
    int i;
    SDVertex *verts = new SDVertex[nvertices];
    for (i = 0; i < nvertices; ++i) {
        verts[i] = SDVertex(P[i]);
        vertices.push_back(&verts[i]);
    }
    SDFace *fs = new SDFace[nfaces];
    for (i = 0; i < nfaces; ++i)
        faces.push_back(&fs[i]);

    // Set face to vertex pointers
    const int *vp = vertexIndices;
    for (i = 0; i < nfaces; ++i) {
        SDFace *f = faces[i];
        for (int j = 0; j < 3; ++j) {
            SDVertex *v = vertices[vp[j]];
            f->v[j] = v;
            v->startFace = f;
        }
        vp += 3;
    }

    // Set neighbor pointers in _faces_
    set<SDEdge> edges;
    for (i = 0; i < nfaces; ++i) {
        SDFace *f = faces[i];
        for (int edgeNum = 0; edgeNum < 3; ++edgeNum) {
            // Update neighbor pointer for _edgeNum_
            int v0 = edgeNum, v1 = NEXT(edgeNum);
            SDEdge e(f->v[v0], f->v[v1]);
            if (edges.find(e) == edges.end()) {
                // Handle new edge
                e.f[0] = f;
                e.f0edgeNum = edgeNum;
                edges.insert(e);
            }
            else {
                // Handle previously seen edge
                e = *edges.find(e);
                e.f[0]->f[e.f0edgeNum] = f;
                f->f[edgeNum] = e.f[0];
                edges.erase(e);
            }
        }
    }

    // Finish vertex initialization
    for (i = 0; i < nvertices; ++i) {
        SDVertex *v = vertices[i];
        SDFace *f = v->startFace;
        do {
            f = f->nextFace(v);
        } while (f && f != v->startFace);
        v->boundary = (f == NULL);
        if (!v->boundary && v->valence() == 6)
            v->regular = true;
        else if (v->boundary && v->valence() == 4)
            v->regular = true;
        else
            v->regular = false;
    }
}
Exemplo n.º 4
0
void LoopSubdiv::ApplyDisplacementMap(const vector<SDVertex *> verts) const
{
	// Dade - apply the displacement map
	SHAPE_LOG(name, LUX_INFO,LUX_NOERROR) << "Applying displacement map to " << verts.size() << " vertices";
	SpectrumWavelengths swl;
	swl.Sample(.5f);

	for (u_int i = 0; i < verts.size(); i++) {
		SDVertex *v = verts[i];
		// Special use of the child member to detect that
		// the vertex has already been displaced
		if (v->child == v)
			continue;
		Vector dpdu, dpdv;
		CoordinateSystem(Vector(v->n), &dpdu, &dpdv);
		Vector displacement(v->n);

		SDFace *face = v->startFace;
		u_int nf = 0;
		float dl = 0.f;
		vector<SDVertex *> vlist;
		vlist.reserve(v->valence());
		if (v->boundary) {
			do {
				SDVertex *vv = face->v[face->vnum(v->P)];
				DifferentialGeometry dg(v->P, v->n, dpdu, dpdv,
					Normal(0, 0, 0), Normal(0, 0, 0),
					vv->u, vv->v, NULL);

				dl += displacementMap->Evaluate(swl, dg);
				++nf;
				if (vv->child != vv) {
					vlist.push_back(vv);
					vv->child = vv;
				}
				face = face->nextFace(v->P);
			} while (face);
			face = v->startFace->prevFace(v->P);
			while (face) {
				SDVertex *vv = face->v[face->vnum(v->P)];
				DifferentialGeometry dg(v->P, v->n, dpdu, dpdv,
					Normal(0, 0, 0), Normal(0, 0, 0),
					vv->u, vv->v, NULL);

				dl += displacementMap->Evaluate(swl, dg);
				++nf;
				if (vv->child != vv) {
					vlist.push_back(vv);
					vv->child = vv;
				}
				face = face->prevFace(v->P);
			}
		} else {
			do {
				SDVertex *vv = face->v[face->vnum(v->P)];
				DifferentialGeometry dg(v->P, v->n, dpdu, dpdv,
					Normal(0, 0, 0), Normal(0, 0, 0),
					vv->u, vv->v, NULL);

				dl += displacementMap->Evaluate(swl, dg);
				++nf;
				if (vv->child != vv) {
					vlist.push_back(vv);
					vv->child = vv;
				}
				face = face->nextFace(v->P);
			} while (face != v->startFace);
		}
		dl = (dl * displacementMapScale / nf + displacementMapOffset);
		// Average the displacement
		displacement *= dl;

		// Apply displacement to all vertices in the list
		for (u_int j = 0; j < vlist.size(); ++j)
			vlist[j]->P += displacement;
	}
}
Exemplo n.º 5
0
// LoopSubdiv Method Definitions
LoopSubdiv::LoopSubdiv(u_int nfaces, u_int nvertices, const int *vertexIndices,
	const Point *P, const float *uv, const Normal *n, u_int nl,
	const boost::shared_ptr<Texture<float> > &dismap, float dmscale,
	float dmoffset, bool dmnormalsmooth, bool dmsharpboundary,
	bool normalsplit, const string &sname)
	: displacementMap(dismap),
	displacementMapScale(dmscale), displacementMapOffset(dmoffset),
	displacementMapNormalSmooth(dmnormalsmooth),
	displacementMapSharpBoundary(dmsharpboundary),
	name(sname)
{
	nLevels = nl;
	hasUV = (uv != NULL);
	normalSplit = normalsplit && n != NULL;

	// Allocate _LoopSubdiv_ vertices and faces
	SDVertex *verts = new SDVertex[nvertices];
	vertices.reserve(nvertices);
	for (u_int i = 0; i < nvertices; ++i) {
		if (hasUV)
			verts[i] = SDVertex(P[i], uv[2 * i], uv[2 * i + 1]);
		else
			verts[i] = SDVertex(P[i]);
		if (normalSplit)
			verts[i].n = n[i];

		vertices.push_back(&verts[i]);
	}

	SDFace *fs = new SDFace[nfaces];
	faces.reserve(nfaces);
	for (u_int i = 0; i < nfaces; ++i)
		faces.push_back(&fs[i]);
	// Set face to vertex pointers
	const int *vp = vertexIndices;
	for (u_int i = 0; i < nfaces; ++i) {
		SDFace *f = faces[i];
		for (u_int j = 0; j < 3; ++j) {
			SDVertex *v = vertices[vp[j]];
			f->v[j] = v;
			f->f[j] = NULL;
			f->children[j] = NULL;
			v->startFace = f;
		}
		f->children[3] = NULL;
		vp += 3;
	}

	// Set neighbor pointers in _faces_
	set<SDEdge> edges;
	for (u_int i = 0; i < nfaces; ++i) {
		SDFace *f = faces[i];
		for (u_int edgeNum = 0; edgeNum < 3; ++edgeNum) {
			// Update neighbor pointer for _edgeNum_
			u_int v0 = edgeNum, v1 = NEXT(edgeNum);
			Normal n0, n1;
			SDEdge e(f->v[v0], f->v[v1]);
			if (edges.find(e) == edges.end()) {
				// Handle new edge
				e.f[0] = f;
				e.f0edgeNum = edgeNum;
				edges.insert(e);
			} else {
				// Handle previously-seen edge
				e = *edges.find(e);
				e.f[0]->f[e.f0edgeNum] = f;
				f->f[edgeNum] = e.f[0];
				// NOTE - lordcrc - check winding of 
				// other face is opposite of the 
				// current face, otherwise we have 
				// inconsistent winding
				u_int otherv0 = e.f[0]->vnum(f->v[v0]->P);
				u_int otherv1 = e.f[0]->vnum(f->v[v1]->P);
				if (PREV(otherv0) != otherv1) {
					SHAPE_LOG(name, LUX_ERROR,LUX_CONSISTENCY)<< "Inconsistent vertex winding in mesh, aborting subdivision.";
					// prevent subdivision
					nLevels = 0;
					return;
				};
				edges.erase(e);
			}
		}
	}

	// Finish vertex initialization
	for (u_int i = 0; i < nvertices; ++i) {
		SDVertex *v = vertices[i];
		SDFace *f = v->startFace;
		do {
			f = f->nextFace(v->P);
		} while (f && f != v->startFace);
		v->boundary = (f == NULL);
		if (!v->boundary && v->valence() == 6)
			v->regular = true;
		else if (v->boundary && v->valence() == 4)
			v->regular = true;
		else
			v->regular = false;
	}
}
Exemplo n.º 6
0
boost::shared_ptr<LoopSubdiv::SubdivResult> LoopSubdiv::Refine() const {

	// check that we should do any subdivision
	if (nLevels < 1) {
		return boost::shared_ptr<LoopSubdiv::SubdivResult>();
	}

	SHAPE_LOG(name, LUX_INFO,LUX_NOERROR) << "Applying " << nLevels << " levels of loop subdivision to " << faces.size() << " triangles";

	vector<SDFace *> f = faces;
	vector<SDVertex *> v = vertices;
	boost::object_pool<SDVertex> vertexArena;
	boost::object_pool<SDFace> faceArena;

	for (u_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
		newVertices.reserve(v.size());
		for (u_int j = 0; j < v.size(); ++j) {
			v[j]->child = vertexArena.construct();//new (vertexArena) SDVertex;
			v[j]->child->regular = v[j]->regular;
			v[j]->child->boundary = v[j]->boundary;
			newVertices.push_back(v[j]->child);
		}
		newFaces.reserve(f.size());
		for (u_int j = 0; j < f.size(); ++j) {
			for (u_int k = 0; k < 4; ++k) {
				f[j]->children[k] = faceArena.construct();//new (faceArena) SDFace;
				newFaces.push_back(f[j]->children[k]);
			}
		}

		// Update vertex positions and create new edge vertices
		// Update vertex positions for even vertices
		for (u_int j = 0; j < v.size(); ++j) {
			SDVertex *vert = v[j];
			if (!vert->boundary) {
				// Apply one-ring rule for even vertex
				if (vert->regular)
					weightOneRing(vert->child, vert, 1.f/16.f);
				else
					weightOneRing(vert->child, vert, beta(vert->valence()));
			} else {
				// Apply boundary rule for even vertex
				weightBoundary(vert->child, vert, 1.f/8.f);
			}
			// Update even vertex face pointers
			const SDFace *sf = vert->startFace;
			vert->child->startFace = sf->children[sf->vnum(vert->P)];
		}

		// Compute new odd edge vertices
		// Update new mesh topology
		map<SDEdge, SDVertex *> edgeVerts;
		for (u_int j = 0; j < f.size(); ++j) {
			SDFace *face = f[j];
			for (u_int k = 0; k < 3; ++k) {
				// Update face neighbor pointers
				// 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[PREV(k)];
				face->children[k]->f[PREV(k)] =
					f2 ? f2->children[f2->vnum(face->v[k]->P)] : NULL;
				f2 = face->f[k];
				face->children[k]->f[k] =
					f2 ? f2->children[f2->vnum(face->v[k]->P)] : NULL;
				// Update child vertex pointer to new even vertex
				face->children[k]->v[k] = face->v[k]->child;
				// Compute odd vertex on _k_th edge
				SDVertex *v0 = face->v[k], *v1 = face->v[NEXT(k)];
				SDEdge edge(v0, v1);
				SDVertex *vert = edgeVerts[edge];
				if (!vert) {
					edge.f[0] = face;
					edge.f0edgeNum = k;
					// Create and initialize new odd vertex
					vert = vertexArena.construct();//new (vertexArena) SDVertex;
					newVertices.push_back(vert);
					vert->regular = true;
					vert->boundary = (f2 == NULL);
					vert->startFace = face->children[3];
					// Apply edge rules to compute new vertex position
					if (vert->boundary) {
						vert->P =  0.5f * (v0->P + v1->P);

						vert->u = 0.5f * (v0->u + v1->u);
						vert->v = 0.5f * (v0->v + v1->v);
						vert->n = 0.5f * (v0->n + v1->n);
					} else {
						SDVertex *ov1 = face->v[PREV(k)];
						SDVertex *ov2 = f2->otherVert(edge.v[0]->P, edge.v[1]->P);
						vert->P =  3.f/8.f * (v0->P + v1->P);
						vert->P += 1.f/8.f * (ov1->P + ov2->P);

						// If UV are different on each side of the edge interpolate as boundary
						if (f2->v[f2->vnum(v0->P)]->u == v0->u &&
							f2->v[f2->vnum(v0->P)]->v == v0->v &&
							f2->v[f2->vnum(v1->P)]->u == v1->u &&
							f2->v[f2->vnum(v1->P)]->v == v1->v) {
							vert->u = 3.f/8.f * (v0->u + v1->u);
							vert->u += 1.f/8.f * (ov1->u + ov2->u);

							vert->v = 3.f/8.f * (v0->v + v1->v);
							vert->v += 1.f/8.f * (ov1->v + ov2->v);
						} else {
							vert->u = 0.5f * (v0->u + v1->u);
							vert->v = 0.5f * (v0->v + v1->v);
						}
						vert->n =  3.f/8.f * (v0->n + v1->n);
						vert->n += 1.f/8.f * (ov1->n + ov2->n);
					}
					edgeVerts[edge] = vert;
				} else {
					// If UV are different on each side of the edge create a new vertex
					if (!vert->boundary &&
						(f2->v[f2->vnum(v0->P)]->u != v0->u ||
						f2->v[f2->vnum(v0->P)]->v != v0->v ||
						f2->v[f2->vnum(v1->P)]->u != v1->u ||
						f2->v[f2->vnum(v1->P)]->v != v1->v)) {
						const Point &P(vert->P);
						const Normal &N(vert->n);
						SDFace *startFace = vert->startFace;
						vert = vertexArena.construct();//new (vertexArena) SDVertex;
						newVertices.push_back(vert);
						vert->regular = true;
						vert->boundary = false;
						vert->startFace = startFace;
						// Standard point interpolation
						vert->P = P;
						// Boundary interpolation for UV
						vert->u = 0.5f * (v0->u + v1->u);
						vert->v = 0.5f * (v0->v + v1->v);
						vert->n = N;
					}
					edgeVerts.erase(edge);
				}
				// Update face vertex pointers
				// Update child vertex pointer to new odd vertex
				face->children[k]->v[NEXT(k)] = vert;
				face->children[NEXT(k)]->v[k] = vert;
				face->children[3]->v[k] = vert;
			}
		}
		edgeVerts.clear();

		// Prepare for next level of subdivision
		f = newFaces;
		v = newVertices;
	}

	// Push vertices to limit surface
	SDVertex *Vlimit = new SDVertex[v.size()];
	for (u_int i = 0; i < v.size(); ++i) {
		if (v[i]->boundary)
			weightBoundary(&Vlimit[i], v[i], 1.f/5.f);
		else
			weightOneRing(&Vlimit[i], v[i], gamma(v[i]->valence()));
	}
	for (u_int i = 0; i < v.size(); ++i) {
		v[i]->P = Vlimit[i].P;
		v[i]->u = Vlimit[i].u;
		v[i]->v = Vlimit[i].v;
		v[i]->n = Vlimit[i].n;
	}
	delete[] Vlimit;

	// Create _TriangleMesh_ from subdivision mesh
	u_int ntris = f.size();
	u_int nverts = v.size();
	int *verts = new int[3*ntris];
	int *vp = verts;
	map<SDVertex *, int> usedVerts;
	for (u_int i = 0; i < nverts; ++i)
		usedVerts[v[i]] = i;
	for (u_int i = 0; i < ntris; ++i) {
		for (u_int j = 0; j < 3; ++j) {
			*vp = usedVerts[f[i]->v[j]];
			++vp;
		}
	}

	// Dade - calculate vertex UVs if required
	float *UVlimit = NULL;
	if (hasUV) {
		UVlimit = new float[2 * nverts];
		for (u_int i = 0; i < nverts; ++i) {
			UVlimit[2 * i] = v[i]->u;
			UVlimit[2 * i + 1] = v[i]->v;
		}
	}

	SHAPE_LOG(name, LUX_INFO,LUX_NOERROR) << "Subdivision complete, got " << ntris << " triangles";

	if (displacementMap) {
		// Dade - apply the displacement map
		GenerateNormals(v);
		ApplyDisplacementMap(v);
	}

	// Dade - create trianglemesh vertices
	Point *Plimit = new Point[nverts];
	for (u_int i = 0; i < nverts; ++i)
		Plimit[i] = v[i]->P;

	Normal *Ns = NULL;
	if (displacementMapNormalSmooth) {
		// Dade - calculate normals
		// FIXME - GenerateNormals should be called in all cases
		// but the displacement messes the data in some rare cases
		// when using the normal split option
		if (!displacementMap || !normalSplit)
			GenerateNormals(v);

		Ns = new Normal[nverts];
		for (u_int i = 0; i < nverts; ++i)
			Ns[i] = v[i]->n;
	}

	return boost::shared_ptr<SubdivResult>(new SubdivResult(ntris, nverts, verts, Plimit, Ns, UVlimit));
}