gKitGL
|
00001 /* version allegee ?? mailto:jean-claude.iehl@liris.cnrs.fr */ 00002 00003 #ifndef _MESH_H 00004 #define _MESH_H 00005 00006 #include <cstring> 00007 #include <vector> 00008 #include <map> 00009 #include <cassert> 00010 00011 #include "IOResource.h" 00012 #include "MeshMaterial.h" 00013 #include "Geometry.h" 00014 #include "Triangle.h" 00015 #include "PNTriangle.h" 00016 #include "PTNTriangle.h" 00017 #include "Name.h" 00018 00019 00020 namespace gk { 00021 00022 //! representation d'une partie d'un maillage associee a une matiere unique identifiee par son indice 'material_id'. 00023 struct SubMesh 00024 { 00025 int begin; //!< premier vertex du submesh. 00026 int end; //!< dernier vertex du submesh. 00027 int material_id; //!< indice de la matiere associee au submesh, cf. gk::Mesh::m_materials. 00028 00029 //! constructeur. 00030 SubMesh( ) 00031 : 00032 begin(0), 00033 end(0), 00034 material_id(0) 00035 {} 00036 00037 //! constructeur par defaut. 00038 SubMesh( const int _begin, const int _end, const int _material_id ) 00039 : 00040 begin(_begin), 00041 end(_end), 00042 material_id(_material_id) 00043 {} 00044 00045 //! destructeur. 00046 ~SubMesh( ) {} 00047 }; 00048 00049 //! representation d'un ensemble d'attributs generiques des sommets du maillage. equivalent a un GLBuffer. 00050 struct MeshBuffer 00051 { 00052 Name semantic; //!< nom de l'attribut 00053 00054 int count; //!< nombre de vecteurs 00055 int size; //!< 1, 2, 3, 4, dimension des vecteurs 00056 00057 std::vector<float> data; //!< stockage des attributs 00058 00059 //! constructeur par defaut. 00060 MeshBuffer( ) 00061 : 00062 count(0), size(0) 00063 {} 00064 00065 //! constructeur. 00066 MeshBuffer( const Name& _semantic, const int _size ) 00067 : 00068 semantic(_semantic), 00069 count(0), size(_size) 00070 {} 00071 00072 //! insertion d'un attribut generique. 00073 void push( const float *attribute ) 00074 { 00075 count++; 00076 00077 for(int i= 0; i < size; i++) 00078 data.push_back(attribute[i]); 00079 } 00080 00081 //! insertion d'un attribut float. 00082 int push( const float& attribute ) 00083 { 00084 if(size != 1) 00085 return -1; 00086 00087 push(&attribute); 00088 return 0; 00089 } 00090 00091 //! insertion d'un attribut point 2d. 00092 int push( const Point2& attribute ) 00093 { 00094 if(size != 2) 00095 return -1; 00096 00097 push(&attribute[0]); 00098 return 0; 00099 } 00100 00101 //! insertion d'un attribut point 3d. 00102 int push( const Point& attribute ) 00103 { 00104 if(size != 3) 00105 return -1; 00106 00107 push(&attribute[0]); 00108 return 0; 00109 } 00110 00111 //! insertion d'un attribut vecteur 3d. 00112 int push( const Vector& attribute ) 00113 { 00114 if(size != 3) 00115 return -1; 00116 00117 push(&attribute[0]); 00118 return 0; 00119 } 00120 00121 //! insertion d'un attribut normale 3d. 00122 int push( const Normal& attribute ) 00123 { 00124 if(size != 3) 00125 return -1; 00126 00127 push(&attribute[0]); 00128 return 0; 00129 } 00130 00131 //! insertion d'un attribut couleur rgba. 00132 int push( const Color& attribute ) 00133 { 00134 if(size != 4) 00135 return -1; 00136 00137 push(&attribute[0]); 00138 return 0; 00139 } 00140 00141 //! renvoie le nombre d'attributs stockes. 00142 int attributeCount( ) const 00143 { 00144 return count; 00145 } 00146 00147 Color asColor( const int id ) const 00148 { 00149 assert(size == 4); 00150 return Color(data[4*id], data[4*id +1], data[4*id +2], data[4*id +3]); 00151 } 00152 00153 Point asPoint( const int id ) const 00154 { 00155 assert(size == 3); 00156 return Point(data[3*id], data[3*id +1], data[3*id +2]); 00157 } 00158 00159 Vector asVector( const int id ) const 00160 { 00161 assert(size == 3); 00162 return Vector(data[3*id], data[3*id +1], data[3*id +2]); 00163 } 00164 00165 Normal asNormal( const int id ) const 00166 { 00167 assert(size == 3); 00168 return Normal(data[3*id], data[3*id +1], data[3*id +2]); 00169 } 00170 00171 Point2 asPoint2( const int id ) const 00172 { 00173 assert(size == 2); 00174 return Point2(data[2*id], data[2*id +1]); 00175 } 00176 00177 float asFloat( const int id ) const 00178 { 00179 assert(size == 1); 00180 return data[id]; 00181 } 00182 }; 00183 00184 00185 class Mesh; 00186 00187 //! representation indexee des sommets d'un triangle. 00188 struct MeshTriangle 00189 { 00190 const Mesh *mesh; 00191 int a, b, c; 00192 00193 //! constructeur par defaut. 00194 MeshTriangle( ) 00195 : 00196 mesh(NULL), 00197 a(-1), b(-1), c(-1) 00198 {} 00199 00200 //! constructeur. 00201 MeshTriangle( const Mesh *_mesh, const int _a, const int _b, const int _c ) 00202 : 00203 mesh(_mesh), 00204 a(_a), b(_b), c(_c) 00205 {} 00206 00207 //! renvoie l'indice du sommet k. 00208 int vertex( const int k ) const 00209 { 00210 assert((&a)[k] != -1); 00211 return (&a)[k]; 00212 } 00213 00214 //! renvoie l'indice du sommet k. 00215 int operator[] ( const int k ) const 00216 { 00217 assert((&a)[k] != -1); 00218 return (&a)[k]; 00219 } 00220 00221 //! renvoie la position du sommet k. 00222 const Point& position( const int k ) const; 00223 //! renvoie la position du sommet k. 00224 Point position( const int k ); 00225 00226 //! renvoie la normale du sommet k. 00227 const Normal& normal( const int k ) const; 00228 //! renvoie la normale du sommet k. 00229 Normal normal( const int k ); 00230 00231 //! renvoie les coordonnees de texture du sommet k. 00232 const Point2& texcoords( const int k ) const; 00233 //! renvoie les coordonnees de texture du sommet k. 00234 Point2 texcoords( const int k ); 00235 00236 //! renvoie les autres attributs associes au sommet k. 00237 Color asColor( const Name& attribute, const int k ); 00238 //! renvoie les autres attributs associes au sommet k. 00239 Color asColor( const int attribute_id, const int k ); 00240 00241 //! renvoie les autres attributs associes au sommet k. 00242 Point asPoint( const Name& attribute, const int k ); 00243 //! renvoie les autres attributs associes au sommet k. 00244 Point asPoint( const int attribute_id, const int k ); 00245 00246 //! renvoie les autres attributs associes au sommet k. 00247 Vector asVector( const Name& attribute, const int k ); 00248 //! renvoie les autres attributs associes au sommet k. 00249 Vector asVector( const int attribute_id, const int k ); 00250 00251 //! renvoie les autres attributs associes au sommet k. 00252 Normal asNormal( const Name& attribute, const int k ); 00253 //! renvoie les autres attributs associes au sommet k. 00254 Normal asNormal( const int attribute_id, const int k ); 00255 00256 //! renvoie les autres attributs associes au sommet k. 00257 Point2 asPoint2( const Name& attribute, const int k ); 00258 //! renvoie les autres attributs associes au sommet k. 00259 Point2 asPoint2( const int attribute_id, const int k ); 00260 00261 //! renvoie les autres attributs associes au sommet k. 00262 float asFloat( const Name& attribute, const int k ); 00263 //! renvoie les autres attributs associes au sommet k. 00264 float asFloat( const int attribute_id, const int k ); 00265 }; 00266 00267 class MeshIO; 00268 00269 //! representation d'un maillage triangule. 00270 00271 //! un mesh est un ensemble de triangles. 00272 //! un triangle est un triplet <abc> d'indices permettant de retrouver la position, la normale et les coordonnees de texture de chaque sommet a, b, c. 00273 //! un triangle (cf. gk::MeshMaterial) a egalement une matiere associee. 00274 //! les triangles partageants la meme matiere peuvent etre groupes dans un gk::SubMesh pour un affichage efficace. 00275 class Mesh : public IOResource 00276 { 00277 friend class MeshIO; 00278 00279 std::vector<Point> m_positions; 00280 std::vector<Normal> m_normals; 00281 std::vector<Point2> m_texcoords; 00282 00283 std::vector<int> m_indices; //!< 3*triangles.size() 00284 std::vector<int> m_materials_id; //!< triangles.size() 00285 00286 std::vector<int> m_smooth_groups; //!< triangles.size() 00287 00288 std::vector<int> m_position_adjacency; //!< positions.size(), premier element de la liste d'adjacence du sommet. 00289 std::vector<int> m_adjacency; //!< 2* positions.size() ? liste globale m_adjacency[m_position_adjacency[id]] .. -1 00290 00291 std::vector<SubMesh> m_submeshes; 00292 00293 std::vector<MeshMaterial *> m_materials; 00294 MeshMaterial m_default_material; 00295 00296 std::vector<MeshBuffer *> m_attributes_buffer; 00297 00298 BBox m_bbox; 00299 00300 //! declare un ensemble d'attributs point 2d. 00301 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Point2& attribute_tag ) 00302 { 00303 MeshBuffer *buffer= findBuffer(semantic); 00304 if(buffer != NULL) 00305 return NULL; // deja attache 00306 00307 buffer= new MeshBuffer(semantic, 2); 00308 m_attributes_buffer.push_back(buffer); 00309 return buffer; 00310 } 00311 00312 //! declare un ensemble d'attributs point 3d. 00313 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Point& attribute_tag ) 00314 { 00315 MeshBuffer *buffer= findBuffer(semantic); 00316 if(buffer != NULL) 00317 return NULL; // deja attache 00318 00319 buffer= new MeshBuffer(semantic, 3); 00320 m_attributes_buffer.push_back(buffer); 00321 return buffer; 00322 } 00323 00324 //! declare un ensemble d'attributs vecteur 3d. 00325 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Vector& attribute_tag ) 00326 { 00327 MeshBuffer *buffer= findBuffer(semantic); 00328 if(buffer != NULL) 00329 return NULL; // deja attache 00330 00331 buffer= new MeshBuffer(semantic, 3); 00332 m_attributes_buffer.push_back(buffer); 00333 return buffer; 00334 } 00335 00336 //! declare un ensemble d'attributs normale 3d. 00337 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Normal& attribute_tag ) 00338 { 00339 MeshBuffer *buffer= findBuffer(semantic); 00340 if(buffer != NULL) 00341 return NULL; // deja attache 00342 00343 buffer= new MeshBuffer(semantic, 3); 00344 m_attributes_buffer.push_back(buffer); 00345 return buffer; 00346 } 00347 00348 //! declare un ensemble d'attributs couleur rgba. 00349 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Color& attribute_tag ) 00350 { 00351 MeshBuffer *buffer= findBuffer(semantic); 00352 if(buffer != NULL) 00353 return NULL; // deja attache 00354 00355 buffer= new MeshBuffer(semantic, 4); 00356 m_attributes_buffer.push_back(buffer); 00357 return buffer; 00358 } 00359 00360 //! declare un ensemble d'attributs float. 00361 MeshBuffer *attachAttributeBuffer( const Name& semantic, const float& attribute_tag ) 00362 { 00363 MeshBuffer *buffer= findBuffer(semantic); 00364 if(buffer != NULL) 00365 return NULL; // deja attache 00366 00367 buffer= new MeshBuffer(semantic, 1); 00368 m_attributes_buffer.push_back(buffer); 00369 return buffer; 00370 } 00371 00372 public: 00373 //! renvoie la position d'un sommet. 00374 Point& position( const int id ) 00375 { 00376 assert(id >= 0 && id < (int) m_positions.size()); 00377 return m_positions[id]; 00378 } 00379 00380 //! renvoie la position d'un sommet. 00381 const Point& position( const int id ) const 00382 { 00383 assert(id >= 0 && id < (int) m_positions.size()); 00384 return m_positions[id]; 00385 } 00386 00387 //! renvoie la normale d'un sommet. 00388 Normal& normal( const int id ) 00389 { 00390 return m_normals[id]; 00391 } 00392 00393 //! renvoie la normale d'un sommet. 00394 const Normal& normal( const int id ) const 00395 { 00396 return m_normals[id]; 00397 } 00398 00399 //! renvoie la coordonnee de texture d'un sommet. 00400 Point2& texcoords( const int id ) 00401 { 00402 return m_texcoords[id]; 00403 } 00404 00405 //! renvoie la coordonnees de texture d'un sommet. 00406 const Point2& texcoords( const int id ) const 00407 { 00408 return m_texcoords[id]; 00409 } 00410 00411 00412 //! constructeur par defaut. 00413 Mesh( ) 00414 : 00415 IOResource(), 00416 m_default_material("default") 00417 {} 00418 00419 //! destructeur. 00420 ~Mesh( ) 00421 { 00422 const int n= (int) m_attributes_buffer.size(); 00423 for(int i= 0; i < n; i++) 00424 delete m_attributes_buffer[i]; 00425 } 00426 00427 //! ajoute un sommet. 00428 int pushPosition( const Point& point ) 00429 { 00430 m_positions.push_back( point ); 00431 m_bbox.Union(point); 00432 return m_positions.size() -1; 00433 } 00434 00435 //! ajoute un ensemble de sommets. 00436 void attachPositionBuffer( const std::vector<Point>& positions ) 00437 { 00438 m_positions= positions; 00439 } 00440 00441 //! ajoute un ensemble de sommets. 00442 void attachPositionBuffer( const int n, const Point *positions ) 00443 { 00444 m_positions= std::vector<Point>(&positions[0], &positions[n]); 00445 } 00446 00447 //! renvoie le nombre de sommets du maillage. 00448 int positionCount( ) const 00449 { 00450 return (int) m_positions.size(); 00451 } 00452 00453 //! renvoie les positions des sommets du maillage. 00454 std::vector<Point>& positions( ) 00455 { 00456 return m_positions; 00457 } 00458 00459 //! renvoie les positions des sommets du maillage. 00460 const std::vector<Point>& positions( ) const 00461 { 00462 return m_positions; 00463 } 00464 00465 //! ajoute une normale. 00466 int pushNormal( const Normal& normal ) 00467 { 00468 m_normals.push_back( normal ); 00469 return m_normals.size() -1; 00470 } 00471 00472 //! ajoute un ensemble de normales 00473 void attachNormalBuffer( const std::vector<Normal>& normals ) 00474 { 00475 m_normals= normals; 00476 } 00477 00478 //! ajoute un ensemble de normales 00479 void attachNormalBuffer( const int n, const Normal *normals ) 00480 { 00481 m_normals= std::vector<Normal>(&normals[0], &normals[n]); 00482 } 00483 00484 //! renvoie le nombre de normales du maillage. 00485 int normalCount( ) const 00486 { 00487 return (int) m_normals.size(); 00488 } 00489 00490 //! renvoie les normales. 00491 std::vector<Normal>& normals( ) 00492 { 00493 return m_normals; 00494 } 00495 00496 //! renvoie les normales. 00497 const std::vector<Normal>& normals( ) const 00498 { 00499 return m_normals; 00500 } 00501 00502 //! ajoute une coordonnee de texture. 00503 int pushTexcoord( const Point2& texcoord ) 00504 { 00505 m_texcoords.push_back( texcoord ); 00506 return m_texcoords.size() -1; 00507 } 00508 00509 //! ajoute un ensemble de coordonnees de texture. 00510 void attachTexcoordBuffer( const std::vector<Point2>& texcoords ) 00511 { 00512 m_texcoords= texcoords; 00513 } 00514 00515 //! ajoute un ensemble de coordonnees de texture. 00516 void attachTexcoordBuffer( const int n, const Point2 *texcoords ) 00517 { 00518 m_texcoords= std::vector<Point2>(&texcoords[0], &texcoords[n]); 00519 } 00520 00521 //! renvoie le nombre de coordonnees de textures des sommets du maillage. 00522 int texcoordCount( ) const 00523 { 00524 return (int) m_texcoords.size(); 00525 } 00526 00527 //! renvoie les coordonnees de textures des sommets du maillage. 00528 std::vector<Point2>& texcoords( ) 00529 { 00530 return m_texcoords; 00531 } 00532 00533 //! renvoie les coordonnees de textures des sommets du maillage. 00534 const std::vector<Point2>& texcoords( ) const 00535 { 00536 return m_texcoords; 00537 } 00538 00539 //! renvoie les groupes de lissage de normales du maillage. 00540 const std::vector<int>& smoothGroups( ) 00541 { 00542 return m_smooth_groups; 00543 } 00544 00545 //! renvoie les groupes de lissage de normales du maillage. 00546 const std::vector<int>& smoothGroups( ) const 00547 { 00548 return m_smooth_groups; 00549 } 00550 00551 //! attache un ensemble d'attributs. 00552 template< class T > 00553 int attachAttributeBuffer( const Name& semantic, const std::vector<T>& attributes ) 00554 { 00555 MeshBuffer *buffer= attachAttributeBuffer(semantic, T()); 00556 if(buffer == NULL) 00557 return -1; 00558 00559 const int n= (int) attributes.size(); 00560 for(int i= 0; i < n; i++) 00561 buffer->push(attributes[i]); 00562 return 0; 00563 } 00564 00565 //! attache un ensemble d'attributs. 00566 template< class T > 00567 int attachAttributeBuffer( const Name& semantic, const int n, const T *attributes ) 00568 { 00569 MeshBuffer *buffer= attachAttributeBuffer(semantic, T()); 00570 if(buffer == NULL) 00571 return -1; 00572 00573 for(int i= 0; i < n; i++) 00574 buffer->push(attributes[i]); 00575 return 0; 00576 } 00577 00578 //! renvoie un buffer d'apres son nom / semantique. 00579 MeshBuffer *findBuffer( const Name& semantic ) const 00580 { 00581 const int n= (int) m_attributes_buffer.size(); 00582 for(int i= 0; i < n; i++) 00583 if(m_attributes_buffer[i]->semantic == semantic) 00584 return m_attributes_buffer[i]; 00585 00586 return NULL; 00587 } 00588 00589 //! renvoie le nombre de buffers d'attributs. 00590 int bufferCount( ) const 00591 { 00592 return (int) m_attributes_buffer.size(); 00593 } 00594 00595 //! renvoie un buffer. 00596 MeshBuffer *buffer( const int id ) 00597 { 00598 return m_attributes_buffer[id]; 00599 } 00600 00601 //! renvoie un buffer. 00602 const MeshBuffer *buffer( const int id ) const 00603 { 00604 return m_attributes_buffer[id]; 00605 } 00606 00607 //! insere un attribut dans l'ensemble associe. 00608 template < class T > 00609 void pushAttribute( const Name& semantic, const T& attribute ) 00610 { 00611 MeshBuffer *buffer= findBuffer(semantic); 00612 if(buffer == NULL) 00613 return; 00614 buffer->push(attribute); 00615 } 00616 00617 //! ajoute un triangle 00618 void pushTriangle( const int a, const int b, const int c, const int material_id, const int smooth_group= -1 ) 00619 { 00620 m_indices.push_back(a); 00621 m_indices.push_back(b); 00622 m_indices.push_back(c); 00623 00624 m_materials_id.push_back(material_id); 00625 m_smooth_groups.push_back(smooth_group); 00626 } 00627 00628 //! renvoie la bbox du mesh. 00629 BBox& bbox( ) 00630 { 00631 return m_bbox; 00632 } 00633 00634 const BBox& getBBox( ) const 00635 { 00636 return m_bbox; 00637 } 00638 00639 //! renvoie le nombre de triangles du maillage. 00640 int triangleCount( ) const 00641 { 00642 return (int) m_indices.size() / 3; 00643 } 00644 00645 //! renvoie le nombre d'indices du maillage. 00646 int indiceCount( ) const 00647 { 00648 return (int) m_indices.size(); 00649 } 00650 00651 //! renvoie les indices du maillage. 00652 std::vector<int>& indices( ) 00653 { 00654 return m_indices; 00655 } 00656 00657 //! renvoie les indices du maillage. 00658 const std::vector<int>& indices( ) const 00659 { 00660 return m_indices; 00661 } 00662 00663 //! ajoute un submesh. 00664 void pushSubMesh( const int begin, const int end, const int material_id ) 00665 { 00666 m_submeshes.push_back( SubMesh(begin, end, material_id) ); 00667 } 00668 00669 //! renvoie le nombre de submesh. 00670 int subMeshCount( ) const 00671 { 00672 return (int) m_submeshes.size(); 00673 } 00674 00675 //! renvoie un submesh. 00676 SubMesh& subMesh( const int submesh_id ) 00677 { 00678 return m_submeshes[submesh_id]; 00679 } 00680 00681 //! renvoie un submesh. 00682 const SubMesh& subMesh( const int submesh_id ) const 00683 { 00684 return m_submeshes[submesh_id]; 00685 } 00686 00687 //! renvoie la matiere d'un submesh. 00688 const MeshMaterial& subMeshMaterial( const int id ) const 00689 { 00690 const int material_id= m_submeshes[id].material_id; 00691 if(material_id < 0) 00692 return m_default_material; 00693 else 00694 return *m_materials[material_id]; 00695 } 00696 00697 //! renvoie la matiere d'un submesh. 00698 const MeshMaterial& subMeshMaterial( const int id ) 00699 { 00700 const int material_id= m_submeshes[id].material_id; 00701 if(material_id < 0) 00702 return m_default_material; 00703 else 00704 return *m_materials[material_id]; 00705 } 00706 00707 //! renvoie les parties du maillage. 00708 const std::vector<SubMesh>& subMeshes( ) 00709 { 00710 return m_submeshes; 00711 } 00712 00713 //! renvoie les parties du maillage. 00714 const std::vector<SubMesh>& subMeshes( ) const 00715 { 00716 return m_submeshes; 00717 } 00718 00719 //! construit les submeshes, sequences de triangles utilisant la meme matiere. 00720 //! tri les triangles en fonction de leur indice de matiere, eventuellement utilise un autre tableau d'indices, cf map). 00721 int buildSubMeshes( std::vector<int> *map= NULL ); 00722 00723 //! definit la matiere par defaut. 00724 int pushDefaultMaterial( ) 00725 { 00726 m_materials.push_back(&m_default_material); 00727 return (int) m_materials.size() - 1; 00728 } 00729 00730 //! insere une matiere. 00731 int pushMaterial( MeshMaterial *material ) 00732 { 00733 m_materials.push_back(material); 00734 return (int) m_materials.size() - 1; 00735 } 00736 00737 //! remplace l'ensemble de matieres. 00738 void attachMaterials( const std::vector<MeshMaterial *>& materials ) 00739 { 00740 m_materials= materials; 00741 } 00742 00743 //! renvoie le nombre de matieres. 00744 int materialCount( ) const 00745 { 00746 return (int) m_materials.size(); 00747 } 00748 00749 //! renvoie une matiere. 00750 MeshMaterial& material( const int material_id ) 00751 { 00752 if(m_materials.empty()) 00753 return m_default_material; 00754 else 00755 return *m_materials[material_id]; 00756 } 00757 00758 //! renvoie une matiere. 00759 const MeshMaterial& material( const int material_id ) const 00760 { 00761 if(m_materials.empty()) 00762 return m_default_material; 00763 else 00764 return *m_materials[material_id]; 00765 } 00766 00767 //! renvoie l'ensemble de matieres. 00768 std::vector<MeshMaterial *>& materials( ) 00769 { 00770 return m_materials; 00771 } 00772 00773 //! renvoie l'ensemble de matieres. 00774 const std::vector<MeshMaterial *>& materials( ) const 00775 { 00776 return m_materials; 00777 } 00778 00779 //! renvoie l'ensemble d'identifiants de matieres des triangles. 00780 const std::vector<int>& triangleMaterialsId( ) const 00781 { 00782 return m_materials_id; 00783 } 00784 00785 //! renvoie l'ensemble d'identifiants de matieres des triangles. 00786 std::vector<int>& triangleMaterialsId( ) 00787 { 00788 return m_materials_id; 00789 } 00790 00791 //! renvoie la matiere d'un triangle. 00792 MeshMaterial& triangleMaterial( const int id ) 00793 { 00794 const int material_id= m_materials_id[id]; 00795 00796 if(material_id < 0) 00797 return m_default_material; 00798 else 00799 return material(material_id); 00800 } 00801 00802 //! renvoie la matiere d'un triangle. 00803 const MeshMaterial& triangleMaterial( const int id ) const 00804 { 00805 const int material_id= m_materials_id[id]; 00806 00807 if(material_id < 0) 00808 return m_default_material; 00809 else 00810 return material(material_id); 00811 } 00812 00813 //! renvoie l'indice de la matiere d'un triangle. 00814 int getTriangleMaterialId( const int id ) const 00815 { 00816 return m_materials_id[id]; 00817 } 00818 00819 //! renvoie un triangle 'indexe', les 3 indices des sommets du triangle. 00820 MeshTriangle getMeshTriangle( const int id ) const 00821 { 00822 assert(id >= 0 && id < triangleCount()); 00823 return MeshTriangle(this, m_indices[3*id], m_indices[3*id +1], m_indices[3*id +2]); 00824 } 00825 //! renvoie un triangle 'geometrique' pour le calcul d'intersection avec un rayon. 00826 //! utiliser les resultats de l'intersection pour calculer la normale et les texcoords interpolees au point d'intersection. 00827 //! cf. Mesh::getUVPoint(), Mesh::getUVNormal(), Mesh::getUVTexcoord(). 00828 Triangle getTriangle( const int id ) const 00829 { 00830 const Point& a= position(m_indices[3*id]); 00831 const Point& b= position(m_indices[3*id +1]); 00832 const Point& c= position(m_indices[3*id +2]); 00833 00834 return Triangle(a, b, c); 00835 } 00836 00837 //! renvoie un pn triangle. 00838 PNTriangle getPNTriangle( const int id ) const 00839 { 00840 if(m_normals.size() != m_positions.size()) 00841 { 00842 // pas de normales associees aux sommets, calcule la normale geometrique. 00843 const Point& a= position(m_indices[3*id]); 00844 const Point& b= position(m_indices[3*id +1]); 00845 const Point& c= position(m_indices[3*id +2]); 00846 const Vector ab(a, b); 00847 const Vector ac(a, c); 00848 Normal nn( Normalize(Cross(ab, ac)) ); 00849 00850 return PNTriangle(getTriangle(id), nn, nn, nn); 00851 } 00852 00853 // renvoie les normales associees aux sommets du triangle 00854 const Normal& na= normal(m_indices[3*id]); 00855 const Normal& nb= normal(m_indices[3*id +1]); 00856 const Normal& nc= normal(m_indices[3*id +2]); 00857 return PNTriangle(getTriangle(id), na, nb, nc); 00858 } 00859 00860 //! renvoie un ptn triangle 00861 PTNTriangle getPTNTriangle( const int id ) const 00862 { 00863 if(m_texcoords.size() != m_positions.size()) 00864 { 00865 // pas de coordonnees de textures associees aux sommets, domaine parametrique unitaire. 00866 return PTNTriangle(getPNTriangle(id), Point2(0.f, 0.f), Point2(1.f, 0.f), Point2(1.f, 1.f)); 00867 } 00868 00869 // renvoie les normales associees aux sommets du triangle 00870 const Point2& ta= texcoords(m_indices[3*id]); 00871 const Point2& tb= texcoords(m_indices[3*id +1]); 00872 const Point2& tc= texcoords(m_indices[3*id +2]); 00873 return PTNTriangle(getPNTriangle(id), ta, tb, tc); 00874 } 00875 00876 //! renvoie la boite englobante d'un triangle. 00877 BBox getTriangleBBox( const int id ) 00878 { 00879 const Point& a= position(m_indices[3*id]); 00880 const Point& b= position(m_indices[3*id +1]); 00881 const Point& c= position(m_indices[3*id +2]); 00882 00883 BBox bbox; 00884 bbox.Union(a); 00885 bbox.Union(b); 00886 bbox.Union(c); 00887 00888 return bbox; 00889 } 00890 00891 //! renvoie l'aire d'un triangle. 00892 float getTriangleArea( const int id ) 00893 { 00894 const Point& a= position(m_indices[3*id]); 00895 const Point& b= position(m_indices[3*id +1]); 00896 const Point& c= position(m_indices[3*id +2]); 00897 const Vector ab(a, b); 00898 const Vector ac(a, c); 00899 return .5f * Cross(ab, ac).Length(); 00900 } 00901 00902 //! calcule et renvoie la normale geometrique d'un triangle. 00903 Normal getTriangleNormal( const int id ) const 00904 { 00905 const Point& a= position(m_indices[3*id]); 00906 const Point& b= position(m_indices[3*id +1]); 00907 const Point& c= position(m_indices[3*id +2]); 00908 00909 const Vector ab(a, b); 00910 const Vector ac(a, c); 00911 Vector n= Cross(Normalize(ab), Normalize(ac)); 00912 return Normal(Normalize(n)); 00913 } 00914 00915 //! interpole une position a l'interieur d'un triangle, connaissant les coordonnees barycentriques du point. 00916 //! convention p(u, v)= (1 - u - v) * a + u * b + v * c 00917 Point getUVPoint( const int id, const float u, const float v ) const 00918 { 00919 const Point& a= position(m_indices[3*id]); 00920 const Point& b= position(m_indices[3*id +1]); 00921 const Point& c= position(m_indices[3*id +2]); 00922 00923 const float w= 1.f - u - v; 00924 return a * w + b * u + c * v; 00925 } 00926 00927 //! interpole une normale a l'interieur d'un triangle, connaissant ses coordonnees barycentriques. 00928 //! convention n(u, v)= (1 - u - v) * a + u * b + v * c 00929 Normal getUVNormal( const int id, const float u, const float v ) const 00930 { 00931 if(m_normals.empty()) 00932 // renvoie la normale geometrique, si les normales des sommets n'existent pas 00933 return getTriangleNormal(id); 00934 00935 const Normal& a= normal(m_indices[3*id]); 00936 const Normal& b= normal(m_indices[3*id +1]); 00937 const Normal& c= normal(m_indices[3*id +2]); 00938 00939 const float w= 1.f - u - v; 00940 return Normalize(a * w + b * u + c * v); 00941 } 00942 00943 //! interpole une coordonnee de texture a l'interieur du triangle, connaissant ses coordonnees barycentriques. 00944 //! convention t(u, v)= (1 - u - v) * a + u * b + v * c 00945 Point2 getUVTexcoord( const int id, const float u, const float v ) const 00946 { 00947 if(m_texcoords.empty()) 00948 // pas de coordonnee de textures dans le maillage. 00949 return Point2(); 00950 00951 const Point2& a= texcoords(m_indices[3*id]); 00952 const Point2& b= texcoords(m_indices[3*id +1]); 00953 const Point2& c= texcoords(m_indices[3*id +2]); 00954 00955 const float w= 1.f - u - v; 00956 return a * w + b * u + c * v; 00957 } 00958 00959 //! renvoie le smooth group du triangle. 00960 int getTriangleSmoothGroup( const int id ) 00961 { 00962 if(m_smooth_groups.empty()) 00963 return -1; 00964 return m_smooth_groups[id]; 00965 } 00966 00967 //! construit la liste d'adjacence des sommets (liste de triangles). 00968 //! \todo acces a l'adjacence. 00969 int buildAdjacency( ); 00970 00971 //! construit les smooth groups en fonction de l'angle entre les normales des triangles adjacents. 00972 int buildNormalSmoothGroups( const float max_angle ); 00973 00974 //! construit les smooth groups en fonction de la distance entre les coordonnees de textures des triangles adjacents. 00975 int buildTexcoordSmoothGroups( const float max ); 00976 00977 //! construit les normales du maillage. 00978 //! \todo utiliser les smooth groups s'ils sont presents. 00979 int buildNormals( ); 00980 }; 00981 00982 00983 // mesh triangle impl 00984 inline 00985 const Point& MeshTriangle::position( const int k ) const 00986 { 00987 assert(mesh != NULL); 00988 return mesh->position(vertex(k)); 00989 } 00990 00991 inline 00992 Point MeshTriangle::position( const int k ) 00993 { 00994 assert(mesh != NULL); 00995 return mesh->position(vertex(k)); 00996 } 00997 00998 inline 00999 const Normal& MeshTriangle::normal( const int k ) const 01000 { 01001 assert(mesh != NULL); 01002 return mesh->normal(vertex(k)); 01003 } 01004 01005 inline 01006 Normal MeshTriangle::normal( const int k ) 01007 { 01008 assert(mesh != NULL); 01009 return mesh->normal(vertex(k)); 01010 } 01011 01012 inline 01013 const Point2& MeshTriangle::texcoords( const int k ) const 01014 { 01015 assert(mesh != NULL); 01016 return mesh->texcoords(vertex(k)); 01017 } 01018 01019 inline 01020 Point2 MeshTriangle::texcoords( const int k ) 01021 { 01022 assert(mesh != NULL); 01023 return mesh->texcoords(vertex(k)); 01024 } 01025 01026 inline 01027 Color MeshTriangle::asColor( const Name& attribute, const int k ) 01028 { 01029 assert(mesh != NULL); 01030 const MeshBuffer *buffer= mesh->findBuffer(attribute); 01031 assert(buffer != NULL); 01032 return buffer->asColor(vertex(k)); 01033 } 01034 01035 inline 01036 Color MeshTriangle::asColor( const int attribute_id, const int k ) 01037 { 01038 assert(mesh != NULL); 01039 const MeshBuffer *buffer= mesh->buffer(attribute_id); 01040 assert(buffer != NULL); 01041 return buffer->asColor(vertex(k)); 01042 } 01043 01044 inline 01045 Point MeshTriangle::asPoint( const Name& attribute, const int k ) 01046 { 01047 assert(mesh != NULL); 01048 const MeshBuffer *buffer= mesh->findBuffer(attribute); 01049 assert(buffer != NULL); 01050 return buffer->asPoint(vertex(k)); 01051 } 01052 01053 inline 01054 Point MeshTriangle::asPoint( const int attribute_id, const int k ) 01055 { 01056 assert(mesh != NULL); 01057 const MeshBuffer *buffer= mesh->buffer(attribute_id); 01058 assert(buffer != NULL); 01059 return buffer->asPoint(vertex(k)); 01060 } 01061 01062 inline 01063 Vector MeshTriangle::asVector( const Name& attribute, const int k ) 01064 { 01065 assert(mesh != NULL); 01066 const MeshBuffer *buffer= mesh->findBuffer(attribute); 01067 assert(buffer != NULL); 01068 return buffer->asVector(vertex(k)); 01069 } 01070 01071 inline 01072 Vector MeshTriangle::asVector( const int attribute_id, const int k ) 01073 { 01074 assert(mesh != NULL); 01075 const MeshBuffer *buffer= mesh->buffer(attribute_id); 01076 assert(buffer != NULL); 01077 return buffer->asVector(vertex(k)); 01078 } 01079 01080 inline 01081 Normal MeshTriangle::asNormal( const Name& attribute, const int k ) 01082 { 01083 assert(mesh != NULL); 01084 const MeshBuffer *buffer= mesh->findBuffer(attribute); 01085 assert(buffer != NULL); 01086 return buffer->asNormal(vertex(k)); 01087 } 01088 01089 inline 01090 Normal MeshTriangle::asNormal( const int attribute_id, const int k ) 01091 { 01092 assert(mesh != NULL); 01093 const MeshBuffer *buffer= mesh->buffer(attribute_id); 01094 assert(buffer != NULL); 01095 return buffer->asNormal(vertex(k)); 01096 } 01097 01098 inline 01099 Point2 MeshTriangle::asPoint2( const Name& attribute, const int k ) 01100 { 01101 assert(mesh != NULL); 01102 const MeshBuffer *buffer= mesh->findBuffer(attribute); 01103 assert(buffer != NULL); 01104 return buffer->asPoint2(vertex(k)); 01105 } 01106 01107 inline 01108 Point2 MeshTriangle::asPoint2( const int attribute_id, const int k ) 01109 { 01110 assert(mesh != NULL); 01111 const MeshBuffer *buffer= mesh->buffer(attribute_id); 01112 assert(buffer != NULL); 01113 return buffer->asPoint2(vertex(k)); 01114 } 01115 01116 inline 01117 float MeshTriangle::asFloat( const Name& attribute, const int k ) 01118 { 01119 assert(mesh != NULL); 01120 const MeshBuffer *buffer= mesh->findBuffer(attribute); 01121 assert(buffer != NULL); 01122 return buffer->asFloat(vertex(k)); 01123 } 01124 01125 inline 01126 float MeshTriangle::asFloat( const int attribute_id, const int k ) 01127 { 01128 assert(mesh != NULL); 01129 const MeshBuffer *buffer= mesh->buffer(attribute_id); 01130 assert(buffer != NULL); 01131 return buffer->asFloat(vertex(k)); 01132 } 01133 01134 } // namespace 01135 01136 #endif