Blender V2.61 - r43446

subd_ring.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
00003  * 
00004  * Modifications copyright (c) 2011, Blender Foundation.
00005  * All rights reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a copy
00008  * of this software and associated documentation files (the "Software"), to deal
00009  * in the Software without restriction, including without limitation the rights
00010  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011  * copies of the Software, and to permit persons to whom the Software is
00012  * furnished to do so, subject to the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice shall be included in
00015  * all copies or substantial portions of the Software.
00016  * 
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00020  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00022  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00023  * THE SOFTWARE.
00024  */
00025 
00026 #include "subd_face.h"
00027 #include "subd_ring.h"
00028 #include "subd_stencil.h"
00029 #include "subd_vert.h"
00030 
00031 #include "util_algorithm.h"
00032 #include "util_debug.h"
00033 #include "util_math.h"
00034 
00035 CCL_NAMESPACE_BEGIN
00036 
00037 /* Utility for sorting verts by index */
00038 
00039 class vertex_compare
00040 {
00041 public:
00042     const vector<int>& index;
00043     vertex_compare(const vector<int>& index_) : index(index_) {}
00044     bool operator()(int a, int b) const { return index[a] < index[b]; }
00045 };
00046 
00047 /* Subd Face Ring */
00048 
00049 SubdFaceRing::SubdFaceRing(SubdFace *face, SubdEdge *firstEdge)
00050 {
00051     m_face = face;
00052     m_firstEdge = firstEdge;
00053     m_num_edges = face->num_edges();
00054 
00055     assert(m_num_edges == 3 || m_num_edges == 4);
00056 
00057     initVerts();
00058 }
00059 
00060 int SubdFaceRing::num_verts()
00061 {
00062     return m_verts.size();
00063 }
00064 
00065 SubdVert *SubdFaceRing::vertexAt(int i)
00066 {
00067     return m_verts[i];
00068 }
00069 
00070 int SubdFaceRing::vert_index(SubdVert *vertex)
00071 {
00072     int count = this->num_verts();
00073 
00074     for(int i = 0; i < count; i++)
00075         if(m_verts[i] == vertex)
00076             return i;
00077     
00078     assert(0);
00079     return 0;
00080 }
00081 
00082 void SubdFaceRing::evaluate_stencils(float3 *P, StencilMask *mask, int num)
00083 {
00084     /* first we sort verts by id. this way verts will always be added
00085        in the same order to ensure the exact same float ops happen for control
00086        points of other patches, so we get water-tight patches */
00087     int num_verts = m_verts.size();
00088 
00089     vector<int> vmap(num_verts);
00090     vector<int> vertid(num_verts);
00091 
00092     for(int v = 0; v < num_verts; v++) {
00093         vmap[v] = v;
00094         vertid[v] = m_verts[v]->id;
00095     }
00096 
00097     sort(vmap.begin(), vmap.end(), vertex_compare(vertid));
00098 
00099     /* then evaluate the stencils */
00100     for(int j = 0; j < num; j++) {
00101         float3 p = make_float3(0.0f, 0.0f, 0.0f);
00102 
00103         for(int i = 0; i < num_verts; i++) {
00104             int idx = vmap[i];
00105             p += m_verts[idx]->co * mask[j][idx];
00106         }
00107 
00108         P[j] = p;
00109     }
00110 }
00111 
00112 bool SubdFaceRing::is_triangle()
00113 {
00114     return m_num_edges == 3;
00115 }
00116 
00117 bool SubdFaceRing::is_quad()
00118 {
00119     return m_num_edges == 4;
00120 }
00121 
00122 int SubdFaceRing::num_edges()
00123 {
00124     return m_num_edges;
00125 }
00126 
00127 bool SubdFaceRing::is_regular(SubdFace *face)
00128 {
00129     if(!is_quad(face))
00130         return false;
00131 
00132     for(SubdFace::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
00133         SubdEdge *edge = it.current();
00134 
00135         /* regular faces don't have boundary edges */
00136         if(edge->is_boundary())
00137             return false;
00138 
00139         /* regular faces only have ordinary verts */
00140         if(edge->vert->valence() != 4)
00141             return false;
00142 
00143         /* regular faces are only adjacent to quads */
00144         for(SubdVert::EdgeIterator eit(edge); !eit.isDone(); eit.advance())
00145             if(eit.current()->face == NULL || eit.current()->face->num_edges() != 4)
00146                 return false;
00147     }
00148 
00149     return true;
00150 }
00151 
00152 bool SubdFaceRing::is_triangle(SubdFace *face)
00153 {
00154     return face->num_edges() == 3;
00155 }
00156 bool SubdFaceRing::is_quad(SubdFace *face)
00157 {
00158     return face->num_edges() == 4;
00159 }
00160 
00161 bool SubdFaceRing::is_boundary(SubdFace *face)
00162 {
00163     /* note that face->is_boundary() returns a different result. That function
00164        returns true when any of the *edges* are on the boundary. however, this
00165        function returns true if any of the face *verts* are on the boundary.  */
00166 
00167     for(SubdFace::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
00168         SubdEdge *edge = it.current();
00169 
00170         if(edge->vert->is_boundary())
00171             return true;
00172     }
00173 
00174     return false;
00175 }
00176 
00177 void SubdFaceRing::initVerts()
00178 {
00179     m_verts.reserve(16);
00180 
00181     /* add face verts */
00182     for(SubdFace::EdgeIterator it(m_firstEdge); !it.isDone(); it.advance()) {
00183         SubdEdge *edge = it.current();
00184         m_verts.push_back(edge->from());
00185     }
00186     
00187     // @@ Add support for non manifold surfaces!
00188     // The fix: 
00189     // - not all colocals should point to the same edge.
00190     // - multiple colocals could belong to different boundaries, make sure they point to the right one.
00191 
00192     // @@ When the face neighborhood wraps that could result in overlapping stencils. 
00193 
00194     // Add surronding verts.
00195     for(SubdFace::EdgeIterator it(m_firstEdge); !it.isDone(); it.advance()) {
00196         SubdEdge *firstEdge = it.current();
00197     
00198         int i = 0;
00199 
00200         /* traverse edges around vertex */
00201         for(SubdVert::ReverseEdgeIterator eit(firstEdge); !eit.isDone(); eit.advance(), i++) {
00202             SubdEdge *edge = eit.current();
00203 
00204             assert(edge->from()->co == firstEdge->from()->co);
00205 
00206             add_vert(edge->to());
00207 
00208             if(edge->face != NULL)
00209                 add_vert(edge->next->to());
00210         }
00211 
00212         assert(i == firstEdge->from()->valence());
00213     }
00214 }
00215 
00216 
00217 void SubdFaceRing::add_vert(SubdVert *vertex)
00218 {
00219     /* avoid having duplicate verts */
00220     if(!has_vert(vertex))
00221         m_verts.push_back(vertex);
00222 }
00223 
00224 bool SubdFaceRing::has_vert(SubdVert *vertex)
00225 {
00226     int num_verts = m_verts.size();
00227 
00228     for(int i = 0; i < num_verts; i++)
00229         if(m_verts[i]->co == vertex->co)
00230             return true;
00231 
00232     return false;
00233 }
00234 
00235 CCL_NAMESPACE_END
00236