00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "loopsubdiv.h"
00025 #include "paramset.h"
00026 #include <boost/pool/object_pool.hpp>
00027
00028 using namespace lux;
00029
00030
00031 LoopSubdiv::LoopSubdiv(const Transform &o2w, bool ro,
00032 int nfaces, int nvertices,
00033 const int *vertexIndices,
00034 const Point *P,
00035 const float *uv,
00036 int nl,
00037 const boost::shared_ptr<Texture<float> > dismap,
00038 float dmscale, float dmoffset,
00039 bool dmnormalsmooth, bool dmsharpboundary)
00040 : Shape(o2w, ro), displacementMap(dismap), displacementMapScale(dmscale),
00041 displacementMapOffset(dmoffset), displacementMapNormalSmooth(dmnormalsmooth),
00042 displacementMapSharpBoundary(dmsharpboundary) {
00043 nLevels = nl;
00044 hasUV = (uv != NULL);
00045
00046
00047 int i;
00048 SDVertex *verts = new SDVertex[nvertices];
00049 for (i = 0; i < nvertices; ++i) {
00050 if (hasUV)
00051 verts[i] = SDVertex(P[i], uv[2 * i], uv[2 * i + 1]);
00052 else
00053 verts[i] = SDVertex(P[i]);
00054
00055 vertices.push_back(&verts[i]);
00056 }
00057
00058 SDFace *fs = new SDFace[nfaces];
00059 for (i = 0; i < nfaces; ++i)
00060 faces.push_back(&fs[i]);
00061
00062 const int *vp = vertexIndices;
00063 for (i = 0; i < nfaces; ++i) {
00064 SDFace *f = faces[i];
00065 for (int j = 0; j < 3; ++j) {
00066 SDVertex *v = vertices[vp[j]];
00067 f->v[j] = v;
00068 v->startFace = f;
00069 }
00070 vp += 3;
00071 }
00072
00073
00074 set<SDEdge> edges;
00075 for (i = 0; i < nfaces; ++i) {
00076 SDFace *f = faces[i];
00077 for (int edgeNum = 0; edgeNum < 3; ++edgeNum) {
00078
00079 int v0 = edgeNum, v1 = NEXT(edgeNum);
00080 SDEdge e(f->v[v0], f->v[v1]);
00081 if (edges.find(e) == edges.end()) {
00082
00083 e.f[0] = f;
00084 e.f0edgeNum = edgeNum;
00085 edges.insert(e);
00086 }
00087 else {
00088
00089 e = *edges.find(e);
00090 e.f[0]->f[e.f0edgeNum] = f;
00091 f->f[edgeNum] = e.f[0];
00092 edges.erase(e);
00093 }
00094 }
00095 }
00096
00097
00098 for (i = 0; i < nvertices; ++i) {
00099 SDVertex *v = vertices[i];
00100 SDFace *f = v->startFace;
00101 do {
00102 f = f->nextFace(v);
00103 } while (f && f != v->startFace);
00104 v->boundary = (f == NULL);
00105 if (!v->boundary && v->valence() == 6)
00106 v->regular = true;
00107 else if (v->boundary && v->valence() == 4)
00108 v->regular = true;
00109 else
00110 v->regular = false;
00111 }
00112 }
00113
00114 LoopSubdiv::~LoopSubdiv() {
00115 delete[] vertices[0];
00116 delete[] faces[0];
00117 }
00118
00119 BBox LoopSubdiv::ObjectBound() const {
00120
00121 BBox b;
00122 for (u_int i = 0; i < vertices.size(); i++)
00123 b = Union(b, vertices[i]->P);
00124 return b;
00125 }
00126
00127 BBox LoopSubdiv::WorldBound() const {
00128
00129 BBox b;
00130 for (u_int i = 0; i < vertices.size(); i++)
00131 b = Union(b, ObjectToWorld(vertices[i]->P));
00132 return b;
00133 }
00134
00135 bool LoopSubdiv::CanIntersect() const {
00136 return false;
00137 }
00138
00139 void LoopSubdiv::Refine(vector<boost::shared_ptr<Shape> > &refined) const {
00140 std::stringstream ss;
00141 ss << "Refining LoopSubdiv shape, cage mesh size: " << faces.size();
00142 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00143
00144 vector<SDFace *> f = faces;
00145 vector<SDVertex *> v = vertices;
00146 boost::object_pool<SDVertex> vertexArena;
00147 boost::object_pool<SDFace> faceArena;
00148
00149 for (int i = 0; i < nLevels; ++i) {
00150
00151 vector<SDFace *> newFaces;
00152 vector<SDVertex *> newVertices;
00153
00154
00155 for (u_int j = 0; j < v.size(); ++j) {
00156 v[j]->child = vertexArena.malloc();
00157 v[j]->child->regular = v[j]->regular;
00158 v[j]->child->boundary = v[j]->boundary;
00159 newVertices.push_back(v[j]->child);
00160 }
00161 for (u_int j = 0; j < f.size(); ++j)
00162 for (int k = 0; k < 4; ++k) {
00163 f[j]->children[k] = faceArena.malloc();
00164 newFaces.push_back(f[j]->children[k]);
00165 }
00166
00167
00168
00169 for (u_int j = 0; j < v.size(); ++j) {
00170 if (!v[j]->boundary) {
00171
00172 if (v[j]->regular)
00173 weightOneRing(v[j]->child, v[j], 1.f/16.f);
00174 else
00175 weightOneRing(v[j]->child, v[j], beta(v[j]->valence()));
00176 } else {
00177
00178 weightBoundary(v[j]->child, v[j], 1.f/8.f);
00179 }
00180 }
00181
00182
00183 map<SDEdge, SDVertex *> edgeVerts;
00184 for (u_int j = 0; j < f.size(); ++j) {
00185 SDFace *face = f[j];
00186 for (int k = 0; k < 3; ++k) {
00187
00188 SDEdge edge(face->v[k], face->v[NEXT(k)]);
00189 SDVertex *vert = edgeVerts[edge];
00190 if (!vert) {
00191
00192 vert = vertexArena.malloc();
00193 newVertices.push_back(vert);
00194 vert->regular = true;
00195 vert->boundary = (face->f[k] == NULL);
00196 vert->startFace = face->children[3];
00197
00198 if (vert->boundary) {
00199 vert->P = 0.5f * edge.v[0]->P;
00200 vert->P += 0.5f * edge.v[1]->P;
00201
00202 vert->u = 0.5f * (edge.v[0]->u + edge.v[1]->u);
00203 vert->v = 0.5f * (edge.v[0]->v + edge.v[1]->v);
00204 } else {
00205 vert->P = 3.f/8.f * edge.v[0]->P;
00206 vert->P += 3.f/8.f * edge.v[1]->P;
00207 SDVertex *ov1 = face->otherVert(edge.v[0], edge.v[1]);
00208 vert->P += 1.f/8.f * ov1->P;
00209 SDVertex *ov2 = face->f[k]->otherVert(edge.v[0], edge.v[1]);
00210 vert->P += 1.f/8.f * ov2->P;
00211
00212 vert->u = 3.f/8.f * edge.v[0]->u;
00213 vert->u += 3.f/8.f * edge.v[1]->u;
00214 vert->u += 1.f/8.f * ov1->u;
00215 vert->u += 1.f/8.f * ov2->u;
00216
00217 vert->v = 3.f/8.f * edge.v[0]->v;
00218 vert->v += 3.f/8.f * edge.v[1]->v;
00219 vert->v += 1.f/8.f * ov1->v;
00220 vert->v += 1.f/8.f * ov2->v;
00221 }
00222 edgeVerts[edge] = vert;
00223 }
00224 }
00225 }
00226
00227
00228
00229 for (u_int j = 0; j < v.size(); ++j) {
00230 SDVertex *vert = v[j];
00231 int vertNum = vert->startFace->vnum(vert);
00232 vert->child->startFace =
00233 vert->startFace->children[vertNum];
00234 }
00235
00236
00237 for (u_int j = 0; j < f.size(); ++j) {
00238 SDFace *face = f[j];
00239 for (int k = 0; k < 3; ++k) {
00240
00241 face->children[3]->f[k] = face->children[NEXT(k)];
00242 face->children[k]->f[NEXT(k)] = face->children[3];
00243
00244 SDFace *f2 = face->f[k];
00245 face->children[k]->f[k] =
00246 f2 ? f2->children[f2->vnum(face->v[k])] : NULL;
00247 f2 = face->f[PREV(k)];
00248 face->children[k]->f[PREV(k)] =
00249 f2 ? f2->children[f2->vnum(face->v[k])] : NULL;
00250 }
00251 }
00252
00253
00254 for (u_int j = 0; j < f.size(); ++j) {
00255 SDFace *face = f[j];
00256 for (int k = 0; k < 3; ++k) {
00257
00258 face->children[k]->v[k] = face->v[k]->child;
00259
00260 SDVertex *vert =
00261 edgeVerts[SDEdge(face->v[k], face->v[NEXT(k)])];
00262 face->children[k]->v[NEXT(k)] = vert;
00263 face->children[NEXT(k)]->v[k] = vert;
00264 face->children[3]->v[k] = vert;
00265 }
00266 }
00267
00268
00269 f = newFaces;
00270 v = newVertices;
00271 }
00272
00273
00274 SDVertex *Vlimit = new SDVertex[v.size()];
00275 for (u_int i = 0; i < v.size(); ++i) {
00276 if (v[i]->boundary)
00277 weightBoundary(&Vlimit[i], v[i], 1.f/5.f);
00278 else
00279 weightOneRing(&Vlimit[i], v[i], gamma(v[i]->valence()));
00280 }
00281 for (u_int i = 0; i < v.size(); ++i) {
00282 v[i]->P = Vlimit[i].P;
00283 v[i]->u = Vlimit[i].u;
00284 v[i]->v = Vlimit[i].v;
00285 }
00286 delete[] Vlimit;
00287
00288
00289 vector<Normal> Ns;
00290 GenerateNormals(v, Ns);
00291
00292
00293 u_int ntris = u_int(f.size());
00294 int *verts = new int[3*ntris];
00295 int *vp = verts;
00296 u_int totVerts = u_int(v.size());
00297 map<SDVertex *, int> usedVerts;
00298 for (u_int i = 0; i < totVerts; ++i)
00299 usedVerts[v[i]] = i;
00300 for (u_int i = 0; i < ntris; ++i) {
00301 for (int j = 0; j < 3; ++j) {
00302 *vp = usedVerts[f[i]->v[j]];
00303 ++vp;
00304 }
00305 }
00306
00307
00308 float *UVlimit = NULL;
00309 if (hasUV) {
00310 UVlimit = new float[2 * v.size()];
00311 for (u_int i = 0; i < v.size(); ++i) {
00312 UVlimit[2 * i] = v[i]->u;
00313 UVlimit[2 * i + 1] = v[i]->v;
00314 }
00315 }
00316
00317 ss.str("");
00318 ss << "LoopSubdiv shape refined, triangles: " << f.size();
00319 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00320
00321 if (displacementMap.get() != NULL) {
00322
00323
00324 ApplyDisplacementMap(v, &Ns[0], UVlimit);
00325
00326 if (displacementMapNormalSmooth) {
00327
00328 GenerateNormals(v, Ns);
00329 }
00330 }
00331
00332
00333 Point *Plimit = new Point[v.size()];
00334 for (u_int i = 0; i < v.size(); ++i)
00335 Plimit[i] = v[i]->P;
00336
00337 ParamSet paramSet;
00338 paramSet.AddInt("indices", verts, 3*ntris);
00339 paramSet.AddPoint("P", Plimit, totVerts);
00340 paramSet.AddNormal("N", &Ns[0], int(Ns.size()));
00341 if (hasUV)
00342 paramSet.AddFloat("uv", UVlimit, 2 * v.size());
00343
00344 refined.push_back(MakeShape("trianglemesh", ObjectToWorld,
00345 reverseOrientation, paramSet));
00346
00347 delete[] verts;
00348 delete[] Plimit;
00349 if (UVlimit)
00350 delete UVlimit;
00351 }
00352
00353 void LoopSubdiv::GenerateNormals(const vector<SDVertex *> v, vector<Normal> &Ns) {
00354
00355 Ns.clear();
00356 Ns.reserve(v.size());
00357 int ringSize = 16;
00358 Point *Pring = new Point[ringSize];
00359 for (u_int i = 0; i < v.size(); ++i) {
00360 SDVertex *vert = v[i];
00361 Vector S(0,0,0), T(0,0,0);
00362 int valence = vert->valence();
00363 if (valence > ringSize) {
00364 ringSize = valence;
00365 delete[] Pring;
00366 Pring = new Point[ringSize];
00367 }
00368 vert->oneRing(Pring);
00369
00370 if (!vert->boundary) {
00371
00372 for (int k = 0; k < valence; ++k) {
00373 S += cosf(2.f*M_PI*k/valence) * Vector(Pring[k]);
00374 T += sinf(2.f*M_PI*k/valence) * Vector(Pring[k]);
00375 }
00376 } else {
00377
00378 S = Pring[valence-1] - Pring[0];
00379 if (valence == 2)
00380 T = Vector(Pring[0] + Pring[1] - 2 * vert->P);
00381 else if (valence == 3)
00382 T = Pring[1] - vert->P;
00383 else if (valence == 4)
00384 T = Vector(-1*Pring[0] + 2*Pring[1] + 2*Pring[2] +
00385 -1*Pring[3] + -2*vert->P);
00386 else {
00387 float theta = M_PI / float(valence-1);
00388 T = Vector(sinf(theta) * (Pring[0] + Pring[valence-1]));
00389 for (int k = 1; k < valence-1; ++k) {
00390 float wt = (2*cosf(theta) - 2) * sinf((k) * theta);
00391 T += Vector(wt * Pring[k]);
00392 }
00393 T = -T;
00394 }
00395 }
00396 Ns.push_back(Normal(Cross(S, T)));
00397 }
00398 }
00399
00400 void LoopSubdiv::ApplyDisplacementMap(
00401 const vector<SDVertex *> verts,
00402 const Normal *norms,
00403 const float *uvs) const {
00404
00405 std::stringstream ss;
00406 ss << "Applying displacement map to " << verts.size() << " vertices";
00407 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00408
00409 for (u_int i = 0; i < verts.size(); i++) {
00410 Point pp = ObjectToWorld(verts[i]->P);
00411 Normal nn = Normalize(norms[i]);
00412 Vector dpdu, dpdv;
00413 CoordinateSystem(Vector(nn), &dpdu, &dpdv);
00414
00415 float u, v;
00416 if (uvs != NULL) {
00417 u = uvs[2 * i];
00418 v = uvs[2 * i + 1];
00419 } else {
00420 u = pp.x;
00421 v = pp.y;
00422 }
00423
00424 DifferentialGeometry dg = DifferentialGeometry(
00425 pp,
00426 nn,
00427 dpdu, dpdv,
00428 Vector(0, 0, 0), Vector(0, 0, 0),
00429 u, v, this);
00430
00431 Vector displacement(nn);
00432 displacement *= - (
00433 displacementMap.get()->Evaluate(dg) * displacementMapScale +
00434 displacementMapOffset);
00435
00436 verts[i]->P += displacement;
00437 }
00438 }
00439
00440 void LoopSubdiv::weightOneRing(SDVertex *destVert, SDVertex *vert, float beta) const {
00441
00442 int valence = vert->valence();
00443 SDVertex **Vring = (SDVertex **)alloca(valence * sizeof(SDVertex *));
00444 vert->oneRing(Vring);
00445
00446 Point P = (1 - valence * beta) * vert->P;
00447 float u = (1 - valence * beta) * vert->u;
00448 float v = (1 - valence * beta) * vert->v;
00449
00450 for (int i = 0; i < valence; ++i) {
00451 P += beta * Vring[i]->P;
00452 u += beta * Vring[i]->u;
00453 v += beta * Vring[i]->v;
00454 }
00455
00456 destVert->P = P;
00457 destVert->u = u;
00458 destVert->v = v;
00459 }
00460
00461 void SDVertex::oneRing(SDVertex **V) {
00462 if (!boundary) {
00463
00464 SDFace *face = startFace;
00465 do {
00466 *V = face->nextVert(this);
00467 V++;
00468 face = face->nextFace(this);
00469 } while (face != startFace);
00470 } else {
00471
00472 SDFace *face = startFace, *f2;
00473 while ((f2 = face->nextFace(this)) != NULL)
00474 face = f2;
00475 *V = face->nextVert(this);
00476 V++;
00477 do {
00478 *V = face->prevVert(this);
00479 V++;
00480 face = face->prevFace(this);
00481 } while (face != NULL);
00482 }
00483 }
00484
00485 void SDVertex::oneRing(Point *P) {
00486 if (!boundary) {
00487
00488 SDFace *face = startFace;
00489 do {
00490 *P++ = face->nextVert(this)->P;
00491 face = face->nextFace(this);
00492 } while (face != startFace);
00493 } else {
00494
00495 SDFace *face = startFace, *f2;
00496 while ((f2 = face->nextFace(this)) != NULL)
00497 face = f2;
00498 *P++ = face->nextVert(this)->P;
00499 do {
00500 *P++ = face->prevVert(this)->P;
00501 face = face->prevFace(this);
00502 } while (face != NULL);
00503 }
00504 }
00505
00506 void LoopSubdiv::weightBoundary(SDVertex *destVert, SDVertex *vert,
00507 float beta) const {
00508
00509 int valence = vert->valence();
00510 SDVertex **Vring = (SDVertex **)alloca(valence * sizeof(SDVertex *));
00511 vert->oneRing(Vring);
00512
00513 if(displacementMapSharpBoundary) {
00514 Point P = (1 - 2 * beta) * vert->P;
00515 P += beta * Vring[0]->P;
00516 P += beta * Vring[valence - 1]->P;
00517 destVert->P = P;
00518 } else
00519 destVert->P = vert->P;
00520
00521 float u = (1 - 2 * beta) * vert->u;
00522 float v = (1 - 2 * beta) * vert->v;
00523 u += beta * Vring[0]->u;
00524 v += beta * Vring[0]->v;
00525 u += beta * Vring[valence - 1]->u;
00526 v += beta * Vring[valence - 1]->v;
00527
00528 destVert->u = u;
00529 destVert->v = v;
00530 }
00531
00532 Shape *LoopSubdiv::CreateShape(
00533 const Transform &o2w,
00534 bool reverseOrientation,
00535 const ParamSet ¶ms,
00536 map<string, boost::shared_ptr<Texture<float> > > *floatTextures) {
00537 int nlevels = params.FindOneInt("nlevels", 3);
00538 int nps, nIndices, nuvi;
00539 const int *vi = params.FindInt("indices", &nIndices);
00540 const Point *P = params.FindPoint("P", &nps);
00541 if (!vi || !P) return NULL;
00542
00543 const float *uvs = params.FindFloat("uv", &nuvi);
00544
00545
00546 string displacementMapName = params.FindOneString("displacementmap", "");
00547 float displacementMapScale = params.FindOneFloat("dmscale", 0.1f);
00548 float displacementMapOffset = params.FindOneFloat("dmoffset", 0.0f);
00549 bool displacementMapNormalSmooth = params.FindOneBool("dmnormalsmooth", true);
00550 bool displacementMapSharpBoundary = params.FindOneBool("dmsharpboundary", false);
00551
00552 boost::shared_ptr<Texture<float> > displacementMap;
00553 if (displacementMapName != "") {
00554 displacementMap = (*floatTextures)[displacementMapName];
00555
00556 if (displacementMap.get() == NULL) {
00557 std::stringstream ss;
00558 ss << "Unknow float texture '" << displacementMapName << "' in a LoopSubdiv shape.";
00559 luxError(LUX_SYNTAX, LUX_WARNING, ss.str().c_str());
00560 }
00561 }
00562
00563
00564 string scheme = params.FindOneString("scheme", "loop");
00565
00566 return new LoopSubdiv(o2w, reverseOrientation, nIndices/3, nps,
00567 vi, P, uvs, nlevels, displacementMap,
00568 displacementMapScale, displacementMapOffset,
00569 displacementMapNormalSmooth, displacementMapSharpBoundary);
00570 }