Blender V2.61 - r43446
|
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