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 m_begin;
00025 int m_end;
00026 int m_material_id;
00027
00028
00029 SubMesh( )
00030 :
00031 m_begin(0),
00032 m_end(0),
00033 m_material_id(0)
00034 {}
00035
00036
00037 SubMesh( const int begin, const int end, const int material_id )
00038 :
00039 m_begin(begin),
00040 m_end(end),
00041 m_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 const std::vector<Point>& positions( )
00262 {
00263 return m_positions;
00264 }
00265
00266
00267 const std::vector<Point>& positions( ) const
00268 {
00269 return m_positions;
00270 }
00271
00272
00273 void pushNormal( const Normal& normal )
00274 {
00275 m_normals.push_back( normal );
00276 }
00277
00278
00279 void attachNormalBuffer( const std::vector<Normal>& normals )
00280 {
00281 m_normals= normals;
00282 }
00283
00284
00285 void attachNormalBuffer( const int n, const Normal *normals )
00286 {
00287 m_normals= std::vector<Normal>(&normals[0], &normals[n]);
00288 }
00289
00290
00291 int normalCount( ) const
00292 {
00293 return (int) m_normals.size();
00294 }
00295
00296
00297 const std::vector<Normal>& normals( )
00298 {
00299 return m_normals;
00300 }
00301
00302
00303 const std::vector<Normal>& normals( ) const
00304 {
00305 return m_normals;
00306 }
00307
00308
00309 void pushTexCoord( const Point2& texcoord )
00310 {
00311 m_texcoords.push_back( texcoord );
00312 }
00313
00314
00315 void attachTexCoordBuffer( const std::vector<Point2>& texcoords )
00316 {
00317 m_texcoords= texcoords;
00318 }
00319
00320
00321 void attachTexCoordBuffer( const int n, const Point2 *texcoords )
00322 {
00323 m_texcoords= std::vector<Point2>(&texcoords[0], &texcoords[n]);
00324 }
00325
00326
00327 int texCoordCount( ) const
00328 {
00329 return (int) m_texcoords.size();
00330 }
00331
00332
00333 const std::vector<Point2>& texCoords( )
00334 {
00335 return m_texcoords;
00336 }
00337
00338
00339 const std::vector<Point2>& texCoords( ) const
00340 {
00341 return m_texcoords;
00342 }
00343
00344
00345 const std::vector<int>& smoothGroups( )
00346 {
00347 return m_smooth_groups;
00348 }
00349
00350
00351 const std::vector<int>& smoothGroups( ) const
00352 {
00353 return m_smooth_groups;
00354 }
00355
00356
00357 template< class T >
00358 int attachAttributeBuffer( const Name& semantic, const std::vector<T>& attributes )
00359 {
00360 MeshBuffer *buffer= attachAttributeBuffer(semantic, T());
00361 if(buffer == NULL)
00362 return -1;
00363
00364 const int n= (int) attributes.size();
00365 for(int i= 0; i < n; i++)
00366 buffer->push(attributes[i]);
00367 return 0;
00368 }
00369
00370
00371 template< class T >
00372 int attachAttributeBuffer( const Name& semantic, const int n, const T *attributes )
00373 {
00374 MeshBuffer *buffer= attachAttributeBuffer(semantic, T());
00375 if(buffer == NULL)
00376 return -1;
00377
00378 for(int i= 0; i < n; i++)
00379 buffer->push(attributes[i]);
00380 return 0;
00381 }
00382
00383
00384 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Point2& attribute_tag )
00385 {
00386 MeshBuffer *buffer= findBuffer(semantic);
00387 if(buffer != NULL)
00388 return NULL;
00389
00390 buffer= new MeshBuffer(semantic, 2);
00391 m_attributes_buffer.push_back(buffer);
00392 return buffer;
00393 }
00394
00395
00396 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Point& attribute_tag )
00397 {
00398 MeshBuffer *buffer= findBuffer(semantic);
00399 if(buffer != NULL)
00400 return NULL;
00401
00402 buffer= new MeshBuffer(semantic, 3);
00403 m_attributes_buffer.push_back(buffer);
00404 return buffer;
00405 }
00406
00407
00408 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Vector& attribute_tag )
00409 {
00410 MeshBuffer *buffer= findBuffer(semantic);
00411 if(buffer != NULL)
00412 return NULL;
00413
00414 buffer= new MeshBuffer(semantic, 3);
00415 m_attributes_buffer.push_back(buffer);
00416 return buffer;
00417 }
00418
00419
00420 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Normal& attribute_tag )
00421 {
00422 MeshBuffer *buffer= findBuffer(semantic);
00423 if(buffer != NULL)
00424 return NULL;
00425
00426 buffer= new MeshBuffer(semantic, 3);
00427 m_attributes_buffer.push_back(buffer);
00428 return buffer;
00429 }
00430
00431
00432 MeshBuffer *attachAttributeBuffer( const Name& semantic, const Color& attribute_tag )
00433 {
00434 MeshBuffer *buffer= findBuffer(semantic);
00435 if(buffer != NULL)
00436 return NULL;
00437
00438 buffer= new MeshBuffer(semantic, 4);
00439 m_attributes_buffer.push_back(buffer);
00440 return buffer;
00441 }
00442
00443
00444 MeshBuffer *findBuffer( const Name& semantic )
00445 {
00446 const int n= (int) m_attributes_buffer.size();
00447 for(int i= 0; i < n; i++)
00448 if(m_attributes_buffer[i]->semantic == semantic)
00449 return m_attributes_buffer[i];
00450
00451 return NULL;
00452 }
00453
00454
00455 int bufferCount( ) const
00456 {
00457 return (int) m_attributes_buffer.size();
00458 }
00459
00460
00461 const MeshBuffer *buffer( const int id ) const
00462 {
00463 return m_attributes_buffer[id];
00464 }
00465
00466
00467 template < class T >
00468 void pushAttribute( const Name& semantic, const T& attribute )
00469 {
00470 MeshBuffer *buffer= findBuffer(semantic);
00471 if(buffer == NULL)
00472 return;
00473 buffer->push(attribute);
00474 }
00475
00476
00477
00478 void pushTriangle( const int a, const int b, const int c, const int material_id, const int smooth_group= -1 )
00479 {
00480 m_indices.push_back(a);
00481 m_indices.push_back(b);
00482 m_indices.push_back(c);
00483
00484 m_materials_id.push_back(material_id);
00485 m_smooth_groups.push_back(smooth_group);
00486 }
00487
00488
00489 const BBox& getBBox( ) const
00490 {
00491 return m_bbox;
00492 }
00493
00494
00495 int triangleCount( ) const
00496 {
00497 return (int) m_indices.size() / 3;
00498 }
00499
00500
00501 int indiceCount( ) const
00502 {
00503 return (int) m_indices.size();
00504 }
00505
00506
00507 const std::vector<int>& indices( )
00508 {
00509 return m_indices;
00510 }
00511
00512
00513 const std::vector<int>& indices( ) const
00514 {
00515 return m_indices;
00516 }
00517
00518
00519 void pushSubMesh( const int begin, const int end, const int material_id )
00520 {
00521 m_submeshes.push_back( SubMesh(begin, end, material_id) );
00522 }
00523
00524
00525 int subMeshCount( ) const
00526 {
00527 return (int) m_submeshes.size();
00528 }
00529
00530
00531 const MeshMaterial& subMeshMaterial( const int id ) const
00532 {
00533 const int material_id= m_submeshes[id].m_material_id;
00534 if(material_id < 0)
00535 return m_default_material;
00536 else
00537 return *m_materials[material_id];
00538 }
00539
00540
00541 const MeshMaterial& subMeshMaterial( const int id )
00542 {
00543 const int material_id= m_submeshes[id].m_material_id;
00544 if(material_id < 0)
00545 return m_default_material;
00546 else
00547 return *m_materials[material_id];
00548 }
00549
00550
00551 const std::vector<SubMesh>& subMeshes( )
00552 {
00553 return m_submeshes;
00554 }
00555
00556
00557 const std::vector<SubMesh>& subMeshes( ) const
00558 {
00559 return m_submeshes;
00560 }
00561
00562
00563 void setMaterials( const std::vector<MeshMaterial *>& materials )
00564 {
00565 m_materials= materials;
00566 }
00567
00568
00569 int materialCount( ) const
00570 {
00571 return (int) m_materials.size();
00572 }
00573
00574
00575 const std::vector<MeshMaterial *>& materials( )
00576 {
00577 return m_materials;
00578 }
00579
00580
00581 const std::vector<MeshMaterial *>& materials( ) const
00582 {
00583 return m_materials;
00584 }
00585
00586
00587 const std::vector<int>& triangleMaterialsId( ) const
00588 {
00589 return m_materials_id;
00590 }
00591
00592
00593 MeshMaterial& triangleMaterial( const int id )
00594 {
00595 const int material_id= m_materials_id[id];
00596
00597 if(material_id < 0)
00598 return m_default_material;
00599 else
00600 return material(material_id);
00601 }
00602
00603
00604 const MeshMaterial& triangleMaterial( const int id ) const
00605 {
00606 const int material_id= m_materials_id[id];
00607
00608 if(material_id < 0)
00609 return m_default_material;
00610 else
00611 return material(material_id);
00612 }
00613
00614
00615 int getTriangleMaterialId( const int id ) const
00616 {
00617 return m_materials_id[id];
00618 }
00619
00620
00621
00622
00623 Triangle getTriangle( const int id ) const
00624 {
00625 const Point& a= position(m_indices[3*id]);
00626 const Point& b= position(m_indices[3*id +1]);
00627 const Point& c= position(m_indices[3*id +2]);
00628
00629 return Triangle(a, b, c);
00630 }
00631
00632
00633 PNTriangle getPNTriangle( const int id ) const
00634 {
00635 const Point& a= position(m_indices[3*id]);
00636 const Point& b= position(m_indices[3*id +1]);
00637 const Point& c= position(m_indices[3*id +2]);
00638
00639 if(m_normals.size() != m_positions.size())
00640 {
00641
00642 const Vector ab(a, b);
00643 const Vector ac(a, c);
00644 Normal nn( Normalize(Cross(ab, ac)) );
00645
00646 return PNTriangle(a, nn, b, nn, c, nn);
00647 }
00648
00649
00650 const Normal& na= normal(m_indices[3*id]);
00651 const Normal& nb= normal(m_indices[3*id +1]);
00652 const Normal& nc= normal(m_indices[3*id +2]);
00653 return PNTriangle(a, na, b, nb, c, nc);
00654 }
00655
00656
00657 BBox getTriangleBBox( const int id )
00658 {
00659 const Point& a= position(m_indices[3*id]);
00660 const Point& b= position(m_indices[3*id +1]);
00661 const Point& c= position(m_indices[3*id +2]);
00662
00663 BBox bbox;
00664 bbox.Union(a);
00665 bbox.Union(b);
00666 bbox.Union(c);
00667
00668 return bbox;
00669 }
00670
00671
00672 float getTriangleArea( const int id )
00673 {
00674 const Point& a= position(m_indices[3*id]);
00675 const Point& b= position(m_indices[3*id +1]);
00676 const Point& c= position(m_indices[3*id +2]);
00677 const Vector ab(a, b);
00678 const Vector ac(a, c);
00679 return .5f * Cross(ab, ac).Length();
00680 }
00681
00682
00683 Normal getTriangleNormal( const int id ) const
00684 {
00685 const Point& a= position(m_indices[3*id]);
00686 const Point& b= position(m_indices[3*id +1]);
00687 const Point& c= position(m_indices[3*id +2]);
00688 const Vector ab(a, b);
00689 const Vector ac(a, c);
00690 return Normal(Normalize(Cross(ab, ac)));
00691 }
00692
00693
00694
00695 Point getUVPoint( const int id, const float u, const float v ) const
00696 {
00697 const Point& a= position(m_indices[3*id]);
00698 const Point& b= position(m_indices[3*id +1]);
00699 const Point& c= position(m_indices[3*id +2]);
00700
00701 const float w= 1.f - u - v;
00702 return a * u + b * v + c * w;
00703 }
00704
00705
00706
00707 Normal getUVNormal( const int id, const float u, const float v ) const
00708 {
00709 if(m_normals.empty())
00710
00711 return getTriangleNormal(id);
00712
00713 const Normal& a= normal(m_indices[3*id]);
00714 const Normal& b= normal(m_indices[3*id +1]);
00715 const Normal& c= normal(m_indices[3*id +2]);
00716
00717 const float w= 1.f - u - v;
00718 return a * u + b * v + c * w;
00719 }
00720
00721
00722
00723 Point2 getUVTexCoord( const int id, const float u, const float v ) const
00724 {
00725 if(m_texcoords.empty())
00726
00727 return Point2();
00728
00729 const Point2& a= texcoords(m_indices[3*id]);
00730 const Point2& b= texcoords(m_indices[3*id +1]);
00731 const Point2& c= texcoords(m_indices[3*id +2]);
00732
00733 const float w= 1.f - u - v;
00734 return a * u + b * v + c * w;
00735 }
00736
00737
00738 int getTriangleSmoothGroup( const int id )
00739 {
00740 if(m_smooth_groups.empty())
00741 return -1;
00742 return m_smooth_groups[id];
00743 }
00744
00745
00746 int buildAdjacency( );
00747
00748
00749 int buildNormalSmoothGroups( const float max_angle );
00750
00751
00752 int buildTexCoordSmoothGropus( const float max );
00753
00754
00755
00756 int buildNormals( );
00757 };
00758
00759 }
00760
00761 #endif