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