00001
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 "Name.h"
00017
00018
00019 namespace gk {
00020
00021
00022 struct SubMesh
00023 {
00024 int begin;
00025 int end;
00026 int material_id;
00027
00028
00029 SubMesh( )
00030 :
00031 begin(0),
00032 end(0),
00033 material_id(0)
00034 {}
00035
00036
00037 SubMesh( const int _begin, const int _end, const int _material_id )
00038 :
00039 begin(_begin),
00040 end(_end),
00041 material_id(_material_id)
00042 {}
00043
00044
00045 ~SubMesh( ) {}
00046 };
00047
00048
00049 struct MeshBuffer
00050 {
00051 Name semantic;
00052
00053 int count;
00054 int size;
00055
00056 std::vector<float> data;
00057
00058
00059 MeshBuffer( )
00060 :
00061 count(0), size(0)
00062 {}
00063
00064
00065 MeshBuffer( const Name& _semantic, const int _size )
00066 :
00067 semantic(_semantic),
00068 count(0), size(_size)
00069 {}
00070
00071
00072 void push( const float *attribute )
00073 {
00074 count++;
00075
00076 for(int i= 0; i < size; i++)
00077 data.push_back(attribute[i]);
00078 }
00079
00080
00081 int push( const Point2& attribute )
00082 {
00083 if(size != 2)
00084 return -1;
00085
00086 push(&attribute[0]);
00087 return 0;
00088 }
00089
00090
00091 int push( const Point& attribute )
00092 {
00093 if(size != 3)
00094 return -1;
00095
00096 push(&attribute[0]);
00097 return 0;
00098 }
00099
00100
00101 int push( const Vector& attribute )
00102 {
00103 if(size != 3)
00104 return -1;
00105
00106 push(&attribute[0]);
00107 return 0;
00108 }
00109
00110
00111 int push( const Normal& attribute )
00112 {
00113 if(size != 3)
00114 return -1;
00115
00116 push(&attribute[0]);
00117 return 0;
00118 }
00119
00120
00121 int push( const Color& attribute )
00122 {
00123 if(size != 4)
00124 return -1;
00125
00126 push(&attribute[0]);
00127 return 0;
00128 }
00129
00130
00131 int attributeCount( ) const
00132 {
00133 return count;
00134 }
00135 };
00136
00137
00138 class MeshIO;
00139
00140
00141
00142
00143
00144
00145
00146 class Mesh : public IOResource
00147 {
00148
00149 friend class MeshIO;
00150
00151 std::vector<Point> m_positions;
00152 std::vector<Normal> m_normals;
00153 std::vector<Point2> m_texcoords;
00154
00155 std::vector<int> m_indices;
00156 std::vector<int> m_materials_id;
00157
00158 std::vector<int> m_smooth_groups;
00159
00160 std::vector<int> m_position_adjacency;
00161 std::vector<int> m_adjacency;
00162
00163 std::vector<SubMesh> m_submeshes;
00164
00165 std::vector<MeshMaterial *> m_materials;
00166 MeshMaterial m_default_material;
00167
00168 std::vector<MeshBuffer *> m_attributes_buffer;
00169
00170 BBox m_bbox;
00171
00172
00173 Point& position( const int id )
00174 {
00175 assert(id >= 0 && id < (int) m_positions.size());
00176 return m_positions[id];
00177 }
00178
00179
00180 const Point& position( const int id ) const
00181 {
00182 assert(id >= 0 && id < (int) m_positions.size());
00183 return m_positions[id];
00184 }
00185
00186
00187 Normal& normal( const int id )
00188 {
00189 return m_normals[id];
00190 }
00191
00192
00193 const Normal& normal( const int id ) const
00194 {
00195 return m_normals[id];
00196 }
00197
00198
00199 Point2& texcoords( const int id )
00200 {
00201 return m_texcoords[id];
00202 }
00203
00204
00205 const Point2& texcoords( const int id ) const
00206 {
00207 return m_texcoords[id];
00208 }
00209
00210
00211 MeshMaterial& material( const int id )
00212 {
00213 return *m_materials[id];
00214 }
00215
00216
00217 const MeshMaterial& material( const int id ) const
00218 {
00219 return *m_materials[id];
00220 }
00221
00222 public:
00223
00224 Mesh( )
00225 :
00226 IOResource(),
00227 m_default_material("default")
00228 {}
00229
00230
00231 ~Mesh( )
00232 {
00233 const int n= (int) m_attributes_buffer.size();
00234 for(int i= 0; i < n; i++)
00235 delete m_attributes_buffer[i];
00236 }
00237
00238
00239 void pushPosition( const Point& point )
00240 {
00241 m_positions.push_back( point );
00242 m_bbox.Union(point);
00243 }
00244
00245
00246 void attachPositionBuffer( const std::vector<Point>& positions )
00247 {
00248 m_positions= positions;
00249 }
00250
00251
00252 void attachPositionBuffer( const int n, const Point *positions )
00253 {
00254 m_positions= std::vector<Point>(&positions[0], &positions[n]);
00255 }
00256
00257
00258 int positionCount( ) const
00259 {
00260 return (int) m_positions.size();
00261 }
00262
00263
00264
00265 std::vector<Point>& positions( )
00266 {
00267 return m_positions;
00268 }
00269
00270
00271 const std::vector<Point>& positions( ) const
00272 {
00273 return m_positions;
00274 }
00275
00276
00277 void pushNormal( const Normal& normal )
00278 {
00279 m_normals.push_back( normal );
00280 }
00281
00282
00283 void attachNormalBuffer( const std::vector<Normal>& normals )
00284 {
00285 m_normals= normals;
00286 }
00287
00288
00289 void attachNormalBuffer( const int n, const Normal *normals )
00290 {
00291 m_normals= std::vector<Normal>(&normals[0], &normals[n]);
00292 }
00293
00294
00295 int normalCount( ) const
00296 {
00297 return (int) m_normals.size();
00298 }
00299
00300
00301
00302 std::vector<Normal>& normals( )
00303 {
00304 return m_normals;
00305 }
00306
00307
00308 const std::vector<Normal>& normals( ) const
00309 {
00310 return m_normals;
00311 }
00312
00313
00314 void pushTexCoord( const Point2& texcoord )
00315 {
00316 m_texcoords.push_back( texcoord );
00317 }
00318
00319
00320 void attachTexCoordBuffer( const std::vector<Point2>& texcoords )
00321 {
00322 m_texcoords= texcoords;
00323 }
00324
00325
00326 void attachTexCoordBuffer( const int n, const Point2 *texcoords )
00327 {
00328 m_texcoords= std::vector<Point2>(&texcoords[0], &texcoords[n]);
00329 }
00330
00331
00332 int texCoordCount( ) const
00333 {
00334 return (int) m_texcoords.size();
00335 }
00336
00337
00338
00339 std::vector<Point2>& texCoords( )
00340 {
00341 return m_texcoords;
00342 }
00343
00344
00345 const std::vector<Point2>& texCoords( ) const
00346 {
00347 return m_texcoords;
00348 }
00349
00350
00351 const std::vector<int>& smoothGroups( )
00352 {
00353 return m_smooth_groups;
00354 }
00355
00356
00357 const std::vector<int>& smoothGroups( ) const
00358 {
00359 return m_smooth_groups;
00360 }
00361
00362
00363 template< class T >
00364 int attachAttributeBuffer( const Name& semantic, const std::vector<T>& attributes )
00365 {
00366 MeshBuffer *buffer= attachAttributeBuffer(semantic, T());
00367 if(buffer == NULL)
00368 return -1;
00369
00370 const int n= (int) attributes.size();
00371 for(int i= 0; i < n; i++)
00372 buffer->push(attributes[i]);
00373 return 0;
00374 }
00375
00376
00377 template< class T >
00378 int attachAttributeBuffer( const Name& semantic, const int n, const T *attributes )
00379 {
00380 MeshBuffer *buffer= attachAttributeBuffer(semantic, T());
00381 if(buffer == NULL)
00382 return -1;
00383
00384 for(int i= 0; i < n; i++)
00385 buffer->push(attributes[i]);
00386 return 0;
00387 }
00388
00389
00390 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Point2& attribute_tag )
00391 {
00392 MeshBuffer *buffer= findBuffer(semantic);
00393 if(buffer != NULL)
00394 return NULL;
00395
00396 buffer= new MeshBuffer(semantic, 2);
00397 m_attributes_buffer.push_back(buffer);
00398 return buffer;
00399 }
00400
00401
00402 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Point& attribute_tag )
00403 {
00404 MeshBuffer *buffer= findBuffer(semantic);
00405 if(buffer != NULL)
00406 return NULL;
00407
00408 buffer= new MeshBuffer(semantic, 3);
00409 m_attributes_buffer.push_back(buffer);
00410 return buffer;
00411 }
00412
00413
00414 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Vector& attribute_tag )
00415 {
00416 MeshBuffer *buffer= findBuffer(semantic);
00417 if(buffer != NULL)
00418 return NULL;
00419
00420 buffer= new MeshBuffer(semantic, 3);
00421 m_attributes_buffer.push_back(buffer);
00422 return buffer;
00423 }
00424
00425
00426 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Normal& attribute_tag )
00427 {
00428 MeshBuffer *buffer= findBuffer(semantic);
00429 if(buffer != NULL)
00430 return NULL;
00431
00432 buffer= new MeshBuffer(semantic, 3);
00433 m_attributes_buffer.push_back(buffer);
00434 return buffer;
00435 }
00436
00437
00438 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Color& attribute_tag )
00439 {
00440 MeshBuffer *buffer= findBuffer(semantic);
00441 if(buffer != NULL)
00442 return NULL;
00443
00444 buffer= new MeshBuffer(semantic, 4);
00445 m_attributes_buffer.push_back(buffer);
00446 return buffer;
00447 }
00448
00449
00450 MeshBuffer *findBuffer( const Name& semantic )
00451 {
00452 const int n= (int) m_attributes_buffer.size();
00453 for(int i= 0; i < n; i++)
00454 if(m_attributes_buffer[i]->semantic == semantic)
00455 return m_attributes_buffer[i];
00456
00457 return NULL;
00458 }
00459
00460
00461 int bufferCount( ) const
00462 {
00463 return (int) m_attributes_buffer.size();
00464 }
00465
00466
00467
00468 MeshBuffer *buffer( const int id )
00469 {
00470 return m_attributes_buffer[id];
00471 }
00472
00473
00474 const MeshBuffer *buffer( const int id ) const
00475 {
00476 return m_attributes_buffer[id];
00477 }
00478
00479
00480 template < class T >
00481 void pushAttribute( const Name& semantic, const T& attribute )
00482 {
00483 MeshBuffer *buffer= findBuffer(semantic);
00484 if(buffer == NULL)
00485 return;
00486 buffer->push(attribute);
00487 }
00488
00489
00490 void pushTriangle( const int a, const int b, const int c, const int material_id, const int smooth_group= -1 )
00491 {
00492 m_indices.push_back(a);
00493 m_indices.push_back(b);
00494 m_indices.push_back(c);
00495
00496 m_materials_id.push_back(material_id);
00497 m_smooth_groups.push_back(smooth_group);
00498 }
00499
00500
00501 BBox& bbox( )
00502 {
00503 return m_bbox;
00504 }
00505
00506 const BBox& getBBox( ) const
00507 {
00508 return m_bbox;
00509 }
00510
00511
00512 int triangleCount( ) const
00513 {
00514 return (int) m_indices.size() / 3;
00515 }
00516
00517
00518 int indiceCount( ) const
00519 {
00520 return (int) m_indices.size();
00521 }
00522
00523
00524 std::vector<int>& indices( )
00525 {
00526 return m_indices;
00527 }
00528
00529
00530 const std::vector<int>& indices( ) const
00531 {
00532 return m_indices;
00533 }
00534
00535
00536 void pushSubMesh( const int begin, const int end, const int material_id )
00537 {
00538 m_submeshes.push_back( SubMesh(begin, end, material_id) );
00539 }
00540
00541
00542 int subMeshCount( ) const
00543 {
00544 return (int) m_submeshes.size();
00545 }
00546
00547
00548 const MeshMaterial& subMeshMaterial( const int id ) const
00549 {
00550 const int material_id= m_submeshes[id].material_id;
00551 if(material_id < 0)
00552 return m_default_material;
00553 else
00554 return *m_materials[material_id];
00555 }
00556
00557
00558 const MeshMaterial& subMeshMaterial( const int id )
00559 {
00560 const int material_id= m_submeshes[id].material_id;
00561 if(material_id < 0)
00562 return m_default_material;
00563 else
00564 return *m_materials[material_id];
00565 }
00566
00567
00568 const std::vector<SubMesh>& subMeshes( )
00569 {
00570 return m_submeshes;
00571 }
00572
00573
00574 const std::vector<SubMesh>& subMeshes( ) const
00575 {
00576 return m_submeshes;
00577 }
00578
00579
00580 int pushDefaultMaterial( )
00581 {
00582 m_materials.push_back(&m_default_material);
00583 return (int) m_materials.size() - 1;
00584 }
00585
00586
00587 void setMaterials( const std::vector<MeshMaterial *>& materials )
00588 {
00589 m_materials= materials;
00590 }
00591
00592
00593
00594 int buildSubMeshes( std::vector<int> *map= NULL );
00595
00596
00597 int materialCount( ) const
00598 {
00599 return (int) m_materials.size();
00600 }
00601
00602
00603 const std::vector<MeshMaterial *>& materials( )
00604 {
00605 return m_materials;
00606 }
00607
00608
00609 const std::vector<MeshMaterial *>& materials( ) const
00610 {
00611 return m_materials;
00612 }
00613
00614
00615 const std::vector<int>& triangleMaterialsId( ) const
00616 {
00617 return m_materials_id;
00618 }
00619
00620
00621 MeshMaterial& triangleMaterial( const int id )
00622 {
00623 const int material_id= m_materials_id[id];
00624
00625 if(material_id < 0)
00626 return m_default_material;
00627 else
00628 return material(material_id);
00629 }
00630
00631
00632 const MeshMaterial& triangleMaterial( const int id ) const
00633 {
00634 const int material_id= m_materials_id[id];
00635
00636 if(material_id < 0)
00637 return m_default_material;
00638 else
00639 return material(material_id);
00640 }
00641
00642
00643 int getTriangleMaterialId( const int id ) const
00644 {
00645 return m_materials_id[id];
00646 }
00647
00648
00649
00650
00651 Triangle getTriangle( const int id ) const
00652 {
00653 const Point& a= position(m_indices[3*id]);
00654 const Point& b= position(m_indices[3*id +1]);
00655 const Point& c= position(m_indices[3*id +2]);
00656
00657 return Triangle(a, b, c);
00658 }
00659
00660
00661 PNTriangle getPNTriangle( const int id ) const
00662 {
00663 const Point& a= position(m_indices[3*id]);
00664 const Point& b= position(m_indices[3*id +1]);
00665 const Point& c= position(m_indices[3*id +2]);
00666
00667 if(m_normals.size() != m_positions.size())
00668 {
00669
00670 const Vector ab(a, b);
00671 const Vector ac(a, c);
00672 Normal nn( Normalize(Cross(ab, ac)) );
00673
00674 return PNTriangle(a, nn, b, nn, c, nn);
00675 }
00676
00677
00678 const Normal& na= normal(m_indices[3*id]);
00679 const Normal& nb= normal(m_indices[3*id +1]);
00680 const Normal& nc= normal(m_indices[3*id +2]);
00681 return PNTriangle(a, na, b, nb, c, nc);
00682 }
00683
00684
00685 BBox getTriangleBBox( const int id )
00686 {
00687 const Point& a= position(m_indices[3*id]);
00688 const Point& b= position(m_indices[3*id +1]);
00689 const Point& c= position(m_indices[3*id +2]);
00690
00691 BBox bbox;
00692 bbox.Union(a);
00693 bbox.Union(b);
00694 bbox.Union(c);
00695
00696 return bbox;
00697 }
00698
00699
00700 float getTriangleArea( const int id )
00701 {
00702 const Point& a= position(m_indices[3*id]);
00703 const Point& b= position(m_indices[3*id +1]);
00704 const Point& c= position(m_indices[3*id +2]);
00705 const Vector ab(a, b);
00706 const Vector ac(a, c);
00707 return .5f * Cross(ab, ac).Length();
00708 }
00709
00710
00711 Normal getTriangleNormal( const int id ) const
00712 {
00713 const Point& a= position(m_indices[3*id]);
00714 const Point& b= position(m_indices[3*id +1]);
00715 const Point& c= position(m_indices[3*id +2]);
00716 const Vector ab(a, b);
00717 const Vector ac(a, c);
00718
00719 if(ab.LengthSquared() == 0.f || ac.LengthSquared() == 0.f)
00720 return Normal();
00721
00722 return Normal(Normalize(Cross(ab, ac)));
00723 }
00724
00725
00726
00727 Point getUVPoint( const int id, const float u, const float v ) const
00728 {
00729 const Point& a= position(m_indices[3*id]);
00730 const Point& b= position(m_indices[3*id +1]);
00731 const Point& c= position(m_indices[3*id +2]);
00732
00733 const float w= 1.f - u - v;
00734 return a * w + b * u + c * v;
00735 }
00736
00737
00738
00739 Normal getUVNormal( const int id, const float u, const float v ) const
00740 {
00741 if(m_normals.empty())
00742
00743 return getTriangleNormal(id);
00744
00745 const Normal& a= normal(m_indices[3*id]);
00746 const Normal& b= normal(m_indices[3*id +1]);
00747 const Normal& c= normal(m_indices[3*id +2]);
00748
00749 const float w= 1.f - u - v;
00750 return a * w + b * u + c * v;
00751 }
00752
00753
00754
00755 Point2 getUVTexCoord( const int id, const float u, const float v ) const
00756 {
00757 if(m_texcoords.empty())
00758
00759 return Point2();
00760
00761 const Point2& a= texcoords(m_indices[3*id]);
00762 const Point2& b= texcoords(m_indices[3*id +1]);
00763 const Point2& c= texcoords(m_indices[3*id +2]);
00764
00765 const float w= 1.f - u - v;
00766 return a * w + b * u + c * v;
00767 }
00768
00769
00770 int getTriangleSmoothGroup( const int id )
00771 {
00772 if(m_smooth_groups.empty())
00773 return -1;
00774 return m_smooth_groups[id];
00775 }
00776
00777
00778
00779 int buildAdjacency( );
00780
00781
00782 int buildNormalSmoothGroups( const float max_angle );
00783
00784
00785 int buildTexCoordSmoothGroups( const float max );
00786
00787
00788
00789 int buildNormals( );
00790 };
00791
00792 }
00793
00794 #endif