Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

bmesh_curvature.C

Go to the documentation of this file.
00001 /*!
00002  *  \file bmesh_curvature.C
00003  *  \brief Contains the implementation of the curvature computation classes
00004  *  for the BMESH class.
00005  *
00006  *  \note This code is taken almost verbatim from the TriMesh2 library written by
00007  *  Szymon Rusinkiewicz of Princeton University
00008  *  (http://www.cs.princeton.edu/gfx/proj/trimesh2/).
00009  *
00010  */
00011 
00012 #include <iostream>
00013 #include <vector>
00014 #include <algorithm>
00015 #include <cmath>
00016 
00017 using namespace std;
00018 
00019 #include "mlib/points.H"
00020 #include "mlib/linear_sys.H"
00021 
00022 using namespace mlib;
00023 
00024 #include "mesh/bvert.H"
00025 #include "mesh/bface.H"
00026 #include "mesh/bmesh.H"
00027 
00028 #include "mesh/bmesh_curvature.H"
00029 
00030 /* Helper Functions for Computing Curvature */
00031 
00032 void rot_coord_sys(const Wvec &old_u, const Wvec &old_v,
00033                    const Wvec &new_norm, Wvec &new_u, Wvec &new_v);
00034 void proj_curv(const Wvec &old_u, const Wvec &old_v,
00035                double old_ku, double old_kuv, double old_kv,
00036                const Wvec &new_u, const Wvec &new_v,
00037                double &new_ku, double &new_kuv, double &new_kv);
00038 void proj_dcurv(const Wvec &old_u, const Wvec &old_v,
00039                 const BMESHcurvature_data::dcurv_tensor_t &old_dcurv,
00040                 const Wvec &new_u, const Wvec &new_v,
00041                 BMESHcurvature_data::dcurv_tensor_t &new_dcurv);
00042 void diagonalize_curv(const Wvec &old_u, const Wvec &old_v,
00043                       double ku, double kuv, double kv,
00044                       const Wvec &new_norm,
00045                       Wvec &pdir1, Wvec &pdir2, double &k1, double &k2);
00046 
00047 inline void compute_edge_vectors(const BMESH *mesh, int face_idx, Wvec edges[3]);
00048 inline void compute_ntb_coord_sys(const Wvec edges[3], Wvec &n, Wvec &t, Wvec &b);
00049 inline void compute_initial_vertex_coord_sys(const BMESH *mesh,
00050                                              vector<Wvec> &pdir1, vector<Wvec> &pdir2);
00051 
00052 /* BMESHcurvature_data Constructors */
00053 
00054 /*!
00055  *  Computes curvature and curvature derivatives for the given BMESH.
00056  *
00057  */
00058 BMESHcurvature_data::BMESHcurvature_data(const BMESH *mesh_in)
00059    : mesh(mesh_in), mesh_feature_size(0.0)
00060 {
00061    
00062    compute_corner_areas();
00063    compute_vertex_areas();
00064    compute_face_curvatures();
00065    compute_vertex_curvatures();
00066    diagonalize_vertex_curvatures();
00067    compute_face_dcurv();
00068    compute_vertex_dcurv();
00069    compute_feature_size();
00070    
00071 }
00072 
00073 /* BMESHcurvature_data Curvature Data Queries */
00074 
00075 BMESHcurvature_data::curv_tensor_t
00076 BMESHcurvature_data::curv_tensor(const Bvert *v)
00077 {
00078    
00079    return vertex_curv[v->index()];
00080    
00081 }
00082       
00083 BMESHcurvature_data::diag_curv_t
00084 BMESHcurvature_data::diag_curv(const Bvert *v)
00085 {
00086    
00087    return diag_vertex_curv[v->index()];
00088    
00089 }
00090 
00091 double
00092 BMESHcurvature_data::k1(const Bvert *v)
00093 {
00094    
00095    return diag_vertex_curv[v->index()].k1();
00096    
00097 }
00098 
00099 double
00100 BMESHcurvature_data::k2(const Bvert *v)
00101 {
00102    
00103    return diag_vertex_curv[v->index()].k2();
00104    
00105 }
00106 
00107 Wvec
00108 BMESHcurvature_data::pdir1(const Bvert *v)
00109 {
00110    
00111    return diag_vertex_curv[v->index()].pdir1();
00112    
00113 }
00114 
00115 Wvec
00116 BMESHcurvature_data::pdir2(const Bvert *v)
00117 {
00118    
00119    return diag_vertex_curv[v->index()].pdir2();
00120    
00121 }
00122 
00123 BMESHcurvature_data::dcurv_tensor_t
00124 BMESHcurvature_data::dcurv_tensor(const Bvert *v)
00125 {
00126    
00127    return vertex_dcurv[v->index()];
00128    
00129 }
00130 
00131 /* BMESHcurvature_data Curvature Computation Functions */
00132 
00133 /*!
00134  *  Computes the corner areas for all faces in the given BMESH.  These are used
00135  *  for weighting purposes when computing the curvatures for the BMESH's vertices.
00136  *
00137  */
00138 void
00139 BMESHcurvature_data::compute_corner_areas()
00140 {
00141 
00142    int nf = mesh->nfaces();
00143    
00144    corner_areas.clear();
00145    corner_areas.resize(nf);
00146 
00147    for (int i = 0; i < nf; i++) {
00148       
00149       Wvec e[3];
00150       compute_edge_vectors(mesh, i, e);
00151 
00152       // Compute corner weights
00153       double area = mesh->bf(i)->area();// 0.5 * cross(e[0],e[1]).length();
00154       double l2[3] = { e[0].length_sqrd(), e[1].length_sqrd(), e[2].length_sqrd() };
00155       double ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]),
00156                        l2[1] * (l2[2] + l2[0] - l2[1]),
00157                        l2[2] * (l2[0] + l2[1] - l2[2]) };
00158                        
00159       if (ew[0] <= 0.0f) {
00160          
00161          corner_areas[i][1] = -0.25f * l2[2] * area / (e[0] * e[2]);
00162          corner_areas[i][2] = -0.25f * l2[1] * area / (e[0] * e[1]);
00163          corner_areas[i][0] = area - corner_areas[i][1] - corner_areas[i][2];
00164          
00165       } else if (ew[1] <= 0.0f) {
00166          
00167          corner_areas[i][2] = -0.25f * l2[0] * area / (e[1] * e[0]);
00168          corner_areas[i][0] = -0.25f * l2[2] * area / (e[1] * e[2]);
00169          corner_areas[i][1] = area - corner_areas[i][2] - corner_areas[i][0];
00170          
00171       } else if (ew[2] <= 0.0f) {
00172          
00173          corner_areas[i][0] = -0.25f * l2[1] * area / (e[2] * e[1]);
00174          corner_areas[i][1] = -0.25f * l2[0] * area / (e[2] * e[0]);
00175          corner_areas[i][2] = area - corner_areas[i][0] - corner_areas[i][1];
00176          
00177       } else {
00178          
00179          double ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]);
00180          for (int j = 0; j < 3; j++)
00181             corner_areas[i][j] = ewscale * (ew[(j+1)%3] + ew[(j+2)%3]);
00182             
00183       }
00184       
00185    }
00186    
00187 }
00188 
00189 /*!
00190  *  Computes vertex areas for all vertices in the given BMESH.  These are used for
00191  *  weighting purposes when computing the curvatures for the BMESH's vertices.
00192  *
00193  */
00194 void
00195 BMESHcurvature_data::compute_vertex_areas()
00196 {
00197    
00198    int nf = mesh->nfaces();
00199    
00200    vertex_areas.clear();
00201    vertex_areas.resize(mesh->nverts());
00202 
00203    for (int i = 0; i < nf; i++) {
00204       
00205       vertex_areas[mesh->bf(i)->v1()->index()] += corner_areas[i][0];
00206       vertex_areas[mesh->bf(i)->v2()->index()] += corner_areas[i][1];
00207       vertex_areas[mesh->bf(i)->v3()->index()] += corner_areas[i][2];
00208       
00209    }
00210    
00211 }
00212 
00213 /*!
00214  *  Computes the curvatures per face for all faces in the given BMESH.  Each
00215  *  face's curvature is estimated based on the variation of normals along its
00216  *  edges.
00217  *
00218  */
00219 void
00220 BMESHcurvature_data::compute_face_curvatures()
00221 {
00222    
00223    int nf = mesh->nfaces();
00224    
00225    face_curv.clear();
00226    face_curv.resize(nf);
00227    
00228    // Compute curvature per-face
00229    for (int i = 0; i < nf; ++i) {
00230       
00231       Wvec e[3];
00232       compute_edge_vectors(mesh, i, e);
00233 
00234       Wvec n, t, b;
00235       compute_ntb_coord_sys(e, n, t, b);
00236 
00237       // Estimate curvature based on variation of normals
00238       // along edges
00239       double m[3] = { 0, 0, 0 };
00240       double w[3][3] = { {0,0,0}, {0,0,0}, {0,0,0} };
00241       for (int j = 0; j < 3; ++j) {
00242          
00243          double u = e[j] * t;
00244          double v = e[j] * b;
00245          w[0][0] += u*u;
00246          w[0][1] += u*v;
00247          //w[1][1] += v*v + u*u; 
00248          //w[1][2] += u*v; 
00249          w[2][2] += v*v;
00250          Wvec dn = mesh->bf(i)->v(((j+2)%3)+1)->norm()
00251                  - mesh->bf(i)->v(((j+1)%3)+1)->norm();
00252          double dnu = dn * t;
00253          double dnv = dn * b;
00254          m[0] += dnu*u;
00255          m[1] += dnu*v + dnv*u;
00256          m[2] += dnv*v;
00257          
00258       }
00259       
00260       w[1][1] = w[0][0] + w[2][2];
00261       w[1][2] = w[0][1];
00262 
00263       // Least squares solution
00264       double diag[3];
00265       if (!ldltdc<double,3>(w, diag)) {
00266          //fprintf(stderr, "ldltdc failed!\n");
00267          continue;
00268       }
00269       ldltsl<double,3>(w, diag, m, m);
00270       
00271       face_curv[i][0] = m[0];
00272       face_curv[i][1] = m[1];
00273       face_curv[i][2] = m[2];
00274 
00275    }
00276    
00277 }
00278 
00279 /*!
00280  *  Computes the curvatures per vertex for all vertices in the given BMESH.  The
00281  *  curvature of each vertex is estimated based on the weighted average of
00282  *  curvatures for each face surrounding that vertex.
00283  *
00284  */
00285 void
00286 BMESHcurvature_data::compute_vertex_curvatures()
00287 {
00288    
00289    int nv = mesh->nverts();
00290    
00291    vertex_curv.clear();
00292    vertex_curv.resize(nv);
00293    
00294    // Set up an initial coordinate system per vertex
00295    vector<Wvec> pdir1(nv), pdir2(nv);
00296    
00297    compute_initial_vertex_coord_sys(mesh, pdir1, pdir2);
00298    
00299    for(int i = 0; i < mesh->nfaces(); ++i) {
00300       
00301       Wvec e[3];
00302       compute_edge_vectors(mesh, i, e);
00303 
00304       Wvec n, t, b;
00305       compute_ntb_coord_sys(e, n, t, b);
00306 
00307       // Compute curvature per vertex:
00308       for(int j = 0; j < 3; ++j){
00309          
00310          int vj = mesh->bf(i)->v(j+1)->index();
00311          double c1, c12, c2;
00312          proj_curv(t, b, face_curv[i][0], face_curv[i][1], face_curv[i][2],
00313                    pdir1[vj], pdir2[vj], c1, c12, c2);
00314          double wt = corner_areas[i][j] / vertex_areas[vj];
00315          vertex_curv[vj][0] += wt * c1;
00316          vertex_curv[vj][1] += wt * c12;
00317          vertex_curv[vj][2] += wt * c2;
00318          
00319       }
00320       
00321    }
00322    
00323 }
00324 
00325 /*!
00326  *  Computes the principal directions and curvatures per vertex for the given
00327  *  BMESH.  These values are computed based on precomputed per vertex curvature
00328  *  tensors from the compute_vertex_curvature() function.
00329  *
00330  */
00331 void
00332 BMESHcurvature_data::diagonalize_vertex_curvatures()
00333 {
00334    
00335    int nv = mesh->nverts();
00336    
00337    diag_vertex_curv.clear();
00338    diag_vertex_curv.resize(nv);
00339    
00340    vector<Wvec> pdir1(nv), pdir2(nv);
00341    compute_initial_vertex_coord_sys(mesh, pdir1, pdir2);
00342    
00343    // Compute principal directions and curvatures at each vertex
00344    vector<double> k1(nv), k2(nv);
00345    
00346    for (int i = 0; i < nv; i++){
00347       
00348       diagonalize_curv(pdir1[i], pdir2[i],
00349                        vertex_curv[i][0], vertex_curv[i][1], vertex_curv[i][2],
00350                        mesh->bv(i)->norm(), pdir1[i], pdir2[i],
00351                        k1[i], k2[i]);
00352       
00353       diag_vertex_curv[i]._k1 = k1[i];
00354       diag_vertex_curv[i]._k2 = k2[i];
00355       diag_vertex_curv[i]._pdir1 = pdir1[i];
00356       diag_vertex_curv[i]._pdir2 = pdir2[i];
00357                        
00358 //       diag_vertex_curv[i].curv1 = pdir1[i]*k1[i];
00359 //       diag_vertex_curv[i].curv2 = pdir2[i]*k2[i];
00360                        
00361    }
00362    
00363 }
00364 
00365 /*!
00366  *  Computes the derivative of curvature per face for all faces in the given
00367  *  BMESH.  Each face's curvature derivative is estimated based on the variation
00368  *  of the per vertex curvatures along its edges.
00369  *
00370  */
00371 void
00372 BMESHcurvature_data::compute_face_dcurv()
00373 {
00374    
00375    int nf = mesh->nfaces();
00376    
00377    face_dcurv.clear();
00378    face_dcurv.resize(nf);
00379    
00380    // Compute dcurv per-face
00381    for(int i = 0; i < nf; ++i){
00382       
00383       Wvec e[3];
00384       compute_edge_vectors(mesh, i, e);
00385 
00386       Wvec n, t, b;
00387       compute_ntb_coord_sys(e, n, t, b);
00388 
00389       // Project curvature tensor from each vertex into this
00390       // face's coordinate system
00391       curv_tensor_t fcurv[3];
00392       for(int j = 0; j < 3; ++j){
00393          int vj = mesh->bf(i)->v(j+1)->index();
00394          proj_curv(diag_vertex_curv[vj].pdir1(), diag_vertex_curv[vj].pdir2(),
00395                    diag_vertex_curv[vj].k1(), 0, diag_vertex_curv[vj].k2(),
00396                    t, b, fcurv[j][0], fcurv[j][1], fcurv[j][2]);
00397 
00398       }
00399 
00400       // Estimate dcurv based on variation of curvature along edges
00401       double m[4] = { 0, 0, 0, 0 };
00402       double w[4][4] = { {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} };
00403       for(int j = 0; j < 3; ++j){
00404          // Variation of curvature along each edge
00405          curv_tensor_t dfcurv = fcurv[(j+2)%3] - fcurv[(j+1)%3];
00406          double u = e[j] * t;
00407          double v = e[j] * b;
00408          double u2 = u*u, v2 = v*v, uv = u*v;
00409          w[0][0] += u2;
00410          w[0][1] += uv;
00411          //w[1][1] += 2.0f*u2 + v2;
00412          //w[1][2] += 2.0f*uv;
00413          //w[2][2] += u2 + 2.0f*v2;
00414          //w[2][3] += uv;
00415          w[3][3] += v2;
00416          m[0] += u*dfcurv[0];
00417          m[1] += v*dfcurv[0] + 2.0f*u*dfcurv[1];
00418          m[2] += 2.0f*v*dfcurv[1] + u*dfcurv[2];
00419          m[3] += v*dfcurv[2];
00420       }
00421       w[1][1] = 2.0f * w[0][0] + w[3][3];
00422       w[1][2] = 2.0f * w[0][1];
00423       w[2][2] = w[0][0] + 2.0f * w[3][3];
00424       w[2][3] = w[0][1];
00425 
00426       // Least squares solution
00427       double d[4];
00428       if(!ldltdc<double,4>(w, d)){
00429          //fprintf(stderr, "ldltdc failed!\n");
00430          continue;
00431       }
00432       ldltsl<double,4>(w, d, m, m);
00433       
00434       face_dcurv[i][0] = m[0];
00435       face_dcurv[i][1] = m[1];
00436       face_dcurv[i][2] = m[2];
00437       face_dcurv[i][3] = m[3];
00438 
00439    }
00440    
00441 }
00442 
00443 /*!
00444  *  Computes the derivative of curvature per vertex for all vertices in the given
00445  *  BMESH.  The curvature derivative of each vertex is estimated based on the
00446  *  weighted average of curvature derivatives for each face surrounding that vertex.
00447  *
00448  */
00449 void
00450 BMESHcurvature_data::compute_vertex_dcurv()
00451 {
00452    
00453    int nv = mesh->nverts();
00454    int nf = mesh->nfaces();
00455    
00456    vertex_dcurv.clear();
00457    vertex_dcurv.resize(nv);
00458    
00459    for(int i = 0; i < nf; ++i){
00460       
00461       Wvec e[3];
00462       compute_edge_vectors(mesh, i, e);
00463 
00464       Wvec n, t, b;
00465       compute_ntb_coord_sys(e, n, t, b);
00466 
00467       // Compute dcurv per vertex:
00468       for(int j = 0; j < 3; ++j){
00469          
00470          int vj = mesh->bf(i)->v(j+1)->index();
00471          dcurv_tensor_t this_vert_dcurv;
00472          proj_dcurv(t, b, face_dcurv[i],
00473                     diag_vertex_curv[vj].pdir1(), diag_vertex_curv[vj].pdir2(),
00474                     this_vert_dcurv);
00475          double wt = corner_areas[i][j] / vertex_areas[vj];
00476          vertex_dcurv[vj] += wt * this_vert_dcurv;
00477          
00478       }
00479       
00480    }
00481    
00482 }
00483 
00484 /*!
00485  *  \brief Compute a "feature size" for the mesh: computed as 1% of
00486  *  the reciprocal of the 10-th percentile curvature.
00487  *
00488  */
00489 void
00490 BMESHcurvature_data::compute_feature_size()
00491 {
00492    
00493    int nv = mesh->nverts();
00494    int nsamp = min(nv, 500);
00495 
00496    vector<double> samples;
00497    samples.reserve(nsamp * 2);
00498 
00499    for(int i = 0; i < nsamp; ++i){
00500       
00501       // Quick 'n dirty portable random number generator 
00502       static unsigned randq = 0;
00503       randq = unsigned(1664525) * randq + unsigned(1013904223);
00504 
00505       int ind = randq % nv;
00506       samples.push_back(fabs(diag_vertex_curv[ind].k1()));
00507       samples.push_back(fabs(diag_vertex_curv[ind].k2()));
00508       
00509    }
00510    
00511    const double frac = 0.1f;
00512    const double mult = 0.01f;
00513    int which = int(frac * samples.size());
00514    nth_element(samples.begin(), samples.begin() + which, samples.end());
00515    
00516    mesh_feature_size = mult / samples[which];
00517    
00518 }
00519 
00520 /* Helper Functions for Computing Curvature */
00521 
00522 /*!
00523  *  \brief  Rotate a coordinate system to be perpendicular to the given normal.
00524  *
00525  */
00526 void
00527 rot_coord_sys(const Wvec &old_u, const Wvec &old_v,
00528               const Wvec &new_norm, Wvec &new_u, Wvec &new_v)
00529 {
00530    new_u = old_u;
00531    new_v = old_v;
00532    Wvec old_norm = cross(old_u, old_v);
00533    double ndot = old_norm * new_norm;
00534    if (ndot <= -1.0f) {
00535       new_u = -new_u;
00536       new_v = -new_v;
00537       return;
00538    }
00539    Wvec perp_old = new_norm - ndot * old_norm;
00540    Wvec dperp = 1.0f / (1 + ndot) * (old_norm + new_norm);
00541    new_u -= dperp * (new_u * perp_old);
00542    new_v -= dperp * (new_v * perp_old);
00543 }
00544 
00545 
00546 /*!
00547  *  \brief Reproject a curvature tensor from the basis spanned by old_u and
00548  *  old_v (which are assumed to be unit-length and perpendicular) to the new_u,
00549  *  new_v basis.
00550  *
00551  */
00552 void
00553 proj_curv(const Wvec &old_u, const Wvec &old_v,
00554           double old_ku, double old_kuv, double old_kv,
00555           const Wvec &new_u, const Wvec &new_v,
00556           double &new_ku, double &new_kuv, double &new_kv)
00557 {
00558    Wvec r_new_u, r_new_v;
00559    rot_coord_sys(new_u, new_v, cross(old_u, old_v), r_new_u, r_new_v);
00560 
00561    double u1 = r_new_u * old_u;
00562    double v1 = r_new_u * old_v;
00563    double u2 = r_new_v * old_u;
00564    double v2 = r_new_v * old_v;
00565    new_ku  = old_ku * u1*u1 + old_kuv * (2.0f  * u1*v1) + old_kv * v1*v1;
00566    new_kuv = old_ku * u1*u2 + old_kuv * (u1*v2 + u2*v1) + old_kv * v1*v2;
00567    new_kv  = old_ku * u2*u2 + old_kuv * (2.0f  * u2*v2) + old_kv * v2*v2;
00568 }
00569 
00570 
00571 /*!
00572  * \brief Like proj_curv(), but for the derivative of curvature.
00573  *
00574  */
00575 void
00576 proj_dcurv(const Wvec &old_u, const Wvec &old_v,
00577            const BMESHcurvature_data::dcurv_tensor_t &old_dcurv,
00578            const Wvec &new_u, const Wvec &new_v,
00579            BMESHcurvature_data::dcurv_tensor_t &new_dcurv)
00580 {
00581    Wvec r_new_u, r_new_v;
00582    rot_coord_sys(new_u, new_v, cross(old_u, old_v), r_new_u, r_new_v);
00583 
00584    double u1 = r_new_u * old_u;
00585    double v1 = r_new_u * old_v;
00586    double u2 = r_new_v * old_u;
00587    double v2 = r_new_v * old_v;
00588 
00589    new_dcurv[0] = old_dcurv[0]*u1*u1*u1 +
00590              old_dcurv[1]*3.0f*u1*u1*v1 +
00591              old_dcurv[2]*3.0f*u1*v1*v1 +
00592              old_dcurv[3]*v1*v1*v1;
00593    new_dcurv[1] = old_dcurv[0]*u1*u1*u2 +
00594              old_dcurv[1]*(u1*u1*v2 + 2.0f*u2*u1*v1) +
00595              old_dcurv[2]*(u2*v1*v1 + 2.0f*u1*v1*v2) +
00596              old_dcurv[3]*v1*v1*v2;
00597    new_dcurv[2] = old_dcurv[0]*u1*u2*u2 +
00598              old_dcurv[1]*(u2*u2*v1 + 2.0f*u1*u2*v2) +
00599              old_dcurv[2]*(u1*v2*v2 + 2.0f*u2*v2*v1) +
00600              old_dcurv[3]*v1*v2*v2;
00601    new_dcurv[3] = old_dcurv[0]*u2*u2*u2 +
00602              old_dcurv[1]*3.0f*u2*u2*v2 +
00603              old_dcurv[2]*3.0f*u2*v2*v2 +
00604              old_dcurv[3]*v2*v2*v2;
00605 }
00606 
00607 
00608 /*!
00609  *  \brief Given a curvature tensor, find principal directions and curvatures.
00610  *
00611  *  Makes sure that pdir1 and pdir2 are perpendicular to normal.
00612  *
00613  */
00614 void
00615 diagonalize_curv(const Wvec &old_u, const Wvec &old_v,
00616                  double ku, double kuv, double kv,
00617                  const Wvec &new_norm,
00618                  Wvec &pdir1, Wvec &pdir2, double &k1, double &k2)
00619 {
00620    Wvec r_old_u, r_old_v;
00621    rot_coord_sys(old_u, old_v, new_norm, r_old_u, r_old_v);
00622 
00623    double c = 1, s = 0, tt = 0;
00624    if (kuv != 0.0f) {
00625       // Jacobi rotation to diagonalize
00626       double h = 0.5f * (kv - ku) / kuv;
00627       tt = (h < 0.0f) ?
00628          1.0f / (h - sqrt(1.0f + h*h)) :
00629          1.0f / (h + sqrt(1.0f + h*h));
00630       c = 1.0f / sqrt(1.0f + tt*tt);
00631       s = tt * c;
00632    }
00633 
00634    k1 = ku - tt * kuv;
00635    k2 = kv + tt * kuv;
00636 
00637    if (fabs(k1) >= fabs(k2)) {
00638       pdir1 = c*r_old_u - s*r_old_v;
00639    } else {
00640       swap(k1, k2);
00641       pdir1 = s*r_old_u + c*r_old_v;
00642    }
00643    pdir2 = cross(new_norm, pdir1);
00644 }
00645 
00646 inline
00647 void
00648 compute_edge_vectors(const BMESH *mesh, int face_idx, Wvec edges[3])
00649 {
00650    
00651    // Edges
00652    edges[0] = mesh->bf(face_idx)->v3()->loc() - mesh->bf(face_idx)->v2()->loc();
00653    edges[1] = mesh->bf(face_idx)->v1()->loc() - mesh->bf(face_idx)->v3()->loc();
00654    edges[2] = mesh->bf(face_idx)->v2()->loc() - mesh->bf(face_idx)->v1()->loc();
00655    
00656 }
00657 
00658 inline
00659 void
00660 compute_ntb_coord_sys(const Wvec edges[3], Wvec &n, Wvec &t, Wvec &b)
00661 {
00662    
00663    // N-T-B coordinate system per face
00664    t = edges[0].normalized();
00665    n = cross(edges[0], edges[1]);
00666    b = cross(n, t).normalized();
00667    
00668 }
00669 
00670 inline
00671 void
00672 compute_initial_vertex_coord_sys(const BMESH *mesh,
00673                                  vector<Wvec> &pdir1, vector<Wvec> &pdir2)
00674 {
00675    
00676    // Set up an initial coordinate system per vertex
00677       
00678    for(int i = 0; i < mesh->nfaces(); ++i){
00679       
00680       pdir1[mesh->bf(i)->v1()->index()] = mesh->bf(i)->v2()->loc()
00681                                         - mesh->bf(i)->v1()->loc();
00682       pdir1[mesh->bf(i)->v2()->index()] = mesh->bf(i)->v3()->loc()
00683                                         - mesh->bf(i)->v2()->loc();
00684       pdir1[mesh->bf(i)->v3()->index()] = mesh->bf(i)->v1()->loc()
00685                                         - mesh->bf(i)->v3()->loc();
00686       
00687    }
00688    
00689    for(int i = 0; i < mesh->nverts(); i++){
00690       
00691       pdir1[i] = cross(pdir1[i], mesh->bv(i)->norm()).normalized();
00692       pdir2[i] = cross(mesh->bv(i)->norm(), pdir1[i]);
00693       
00694    }
00695    
00696 }

Generated on Mon Sep 18 11:39:28 2006 for jot by  doxygen 1.4.4