00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "xFileMesh.h"
00020 #include "xFileFace.h"
00021 #include "xFileVertex.h"
00022 #include "xFileNormal.h"
00023 #include "xFileMaterial.h"
00024
00025 #include "eggVertexPool.h"
00026 #include "eggVertex.h"
00027 #include "eggPolygon.h"
00028 #include "eggGroupNode.h"
00029
00030
00031
00032
00033
00034
00035 XFileMesh::
00036 XFileMesh() {
00037 _has_normals = false;
00038 _has_colors = false;
00039 _has_uvs = false;
00040 _has_materials = false;
00041 }
00042
00043
00044
00045
00046
00047
00048 XFileMesh::
00049 ~XFileMesh() {
00050 clear();
00051 }
00052
00053
00054
00055
00056
00057
00058 void XFileMesh::
00059 clear() {
00060 Vertices::iterator vi;
00061 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
00062 XFileVertex *vertex = (*vi);
00063 delete vertex;
00064 }
00065 Normals::iterator ni;
00066 for (ni = _normals.begin(); ni != _normals.end(); ++ni) {
00067 XFileNormal *normal = (*ni);
00068 delete normal;
00069 }
00070 Materials::iterator mi;
00071 for (mi = _materials.begin(); mi != _materials.end(); ++mi) {
00072 XFileMaterial *material = (*mi);
00073 delete material;
00074 }
00075 Faces::iterator fi;
00076 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
00077 XFileFace *face = (*fi);
00078 delete face;
00079 }
00080
00081 _vertices.clear();
00082 _normals.clear();
00083 _materials.clear();
00084 _faces.clear();
00085
00086 _unique_vertices.clear();
00087 _unique_normals.clear();
00088 _unique_materials.clear();
00089
00090 _has_normals = false;
00091 _has_colors = false;
00092 _has_uvs = false;
00093 _has_materials = false;
00094 }
00095
00096
00097
00098
00099
00100
00101 void XFileMesh::
00102 add_polygon(EggPolygon *egg_poly) {
00103 XFileFace *face = new XFileFace;
00104 face->set_from_egg(this, egg_poly);
00105 _faces.push_back(face);
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115 int XFileMesh::
00116 add_vertex(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
00117 int next_index = _vertices.size();
00118 XFileVertex *vertex = new XFileVertex;
00119 vertex->set_from_egg(egg_vertex, egg_prim);
00120 if (vertex->_has_color) {
00121 _has_colors = true;
00122 }
00123 if (vertex->_has_uv) {
00124 _has_uvs = true;
00125 }
00126
00127 pair<UniqueVertices::iterator, bool> result =
00128 _unique_vertices.insert(UniqueVertices::value_type(vertex, next_index));
00129
00130 if (result.second) {
00131
00132 _vertices.push_back(vertex);
00133 return next_index;
00134 } else {
00135
00136
00137 delete vertex;
00138 return (*result.first).second;
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 int XFileMesh::
00151 add_normal(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
00152 int next_index = _normals.size();
00153 XFileNormal *normal = new XFileNormal;
00154 normal->set_from_egg(egg_vertex, egg_prim);
00155 if (normal->_has_normal) {
00156 _has_normals = true;
00157 }
00158
00159 pair<UniqueNormals::iterator, bool> result =
00160 _unique_normals.insert(UniqueNormals::value_type(normal, next_index));
00161
00162 if (result.second) {
00163
00164 _normals.push_back(normal);
00165 return next_index;
00166 } else {
00167
00168
00169 delete normal;
00170 return (*result.first).second;
00171 }
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181 int XFileMesh::
00182 add_material(EggPrimitive *egg_prim) {
00183 int next_index = _materials.size();
00184 XFileMaterial *material = new XFileMaterial;
00185 material->set_from_egg(egg_prim);
00186 if (material->has_material()) {
00187 _has_materials = true;
00188 }
00189
00190 pair<UniqueMaterials::iterator, bool> result =
00191 _unique_materials.insert(UniqueMaterials::value_type(material, next_index));
00192
00193 if (result.second) {
00194
00195 _materials.push_back(material);
00196 return next_index;
00197 } else {
00198
00199
00200 delete material;
00201 return (*result.first).second;
00202 }
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 int XFileMesh::
00215 add_vertex(XFileVertex *vertex) {
00216 int next_index = _vertices.size();
00217 _unique_vertices.insert(UniqueVertices::value_type(vertex, next_index));
00218 _vertices.push_back(vertex);
00219 return next_index;
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 int XFileMesh::
00231 add_normal(XFileNormal *normal) {
00232 int next_index = _normals.size();
00233 _unique_normals.insert(UniqueNormals::value_type(normal, next_index));
00234 _normals.push_back(normal);
00235 return next_index;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 int XFileMesh::
00247 add_material(XFileMaterial *material) {
00248 int next_index = _materials.size();
00249 _unique_materials.insert(UniqueMaterials::value_type(material, next_index));
00250 _materials.push_back(material);
00251 return next_index;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261 bool XFileMesh::
00262 create_polygons(EggGroupNode *egg_parent, XFileToEggConverter *converter) {
00263 EggVertexPool *vpool = new EggVertexPool(get_name());
00264 egg_parent->add_child(vpool);
00265 Faces::const_iterator fi;
00266 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
00267 XFileFace *face = (*fi);
00268
00269 EggPolygon *egg_poly = new EggPolygon;
00270 egg_parent->add_child(egg_poly);
00271
00272
00273 XFileFace::Vertices::reverse_iterator vi;
00274 for (vi = face->_vertices.rbegin(); vi != face->_vertices.rend(); ++vi) {
00275 int vertex_index = (*vi)._vertex_index;
00276 int normal_index = (*vi)._normal_index;
00277 if (vertex_index < 0 || vertex_index >= (int)_vertices.size()) {
00278 nout << "Vertex index out of range in Mesh.\n";
00279 return false;
00280 }
00281 XFileVertex *vertex = _vertices[vertex_index];
00282 XFileNormal *normal = (XFileNormal *)NULL;
00283
00284 if (normal_index >= 0 && normal_index < (int)_normals.size()) {
00285 normal = _normals[normal_index];
00286 }
00287
00288
00289 EggVertex temp_vtx;
00290 temp_vtx.set_pos(LCAST(double, vertex->_point));
00291 if (vertex->_has_color) {
00292 temp_vtx.set_color(vertex->_color);
00293 }
00294 if (vertex->_has_uv) {
00295 TexCoordd uv = LCAST(double, vertex->_uv);
00296
00297 uv[1] = 1.0 - uv[1];
00298 temp_vtx.set_uv(uv);
00299 }
00300
00301 if (normal != (XFileNormal *)NULL && normal->_has_normal) {
00302 temp_vtx.set_normal(LCAST(double, normal->_normal));
00303 }
00304
00305
00306 EggVertex *egg_vtx = vpool->create_unique_vertex(temp_vtx);
00307 egg_poly->add_vertex(egg_vtx);
00308 }
00309
00310
00311 int material_index = face->_material_index;
00312 if (material_index >= 0 && material_index < (int)_materials.size()) {
00313 XFileMaterial *material = _materials[material_index];
00314 material->apply_to_egg(egg_poly, converter);
00315 }
00316 }
00317
00318 return true;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327 bool XFileMesh::
00328 has_normals() const {
00329 return _has_normals;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338 bool XFileMesh::
00339 has_colors() const {
00340 return _has_colors;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349 bool XFileMesh::
00350 has_uvs() const {
00351 return _has_uvs;
00352 }
00353
00354
00355
00356
00357
00358
00359
00360 bool XFileMesh::
00361 has_materials() const {
00362 return _has_materials;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371 int XFileMesh::
00372 get_num_materials() const {
00373 return _materials.size();
00374 }
00375
00376
00377
00378
00379
00380
00381
00382 XFileMaterial *XFileMesh::
00383 get_material(int n) const {
00384 nassertr(n >= 0 && n < (int)_materials.size(), (XFileMaterial *)NULL);
00385 return _materials[n];
00386 }
00387
00388
00389
00390
00391
00392
00393
00394 void XFileMesh::
00395 make_mesh_data(Datagram &raw_data) {
00396 raw_data.clear();
00397 raw_data.add_int32(_vertices.size());
00398
00399 Vertices::const_iterator vi;
00400 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
00401 XFileVertex *vertex = (*vi);
00402 const Vertexf &point = vertex->_point;
00403 raw_data.add_float32(point[0]);
00404 raw_data.add_float32(point[1]);
00405 raw_data.add_float32(point[2]);
00406 }
00407
00408 raw_data.add_int32(_faces.size());
00409 Faces::const_iterator fi;
00410 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
00411 XFileFace *face = (*fi);
00412
00413 raw_data.add_int32(face->_vertices.size());
00414 XFileFace::Vertices::const_iterator fvi;
00415 for (fvi = face->_vertices.begin();
00416 fvi != face->_vertices.end();
00417 ++fvi) {
00418 raw_data.add_int32((*fvi)._vertex_index);
00419 }
00420 }
00421 }
00422
00423
00424
00425
00426
00427
00428
00429 void XFileMesh::
00430 make_normal_data(Datagram &raw_data) {
00431 raw_data.clear();
00432 raw_data.add_int32(_normals.size());
00433
00434 Normals::const_iterator ni;
00435 for (ni = _normals.begin(); ni != _normals.end(); ++ni) {
00436 XFileNormal *normal = (*ni);
00437 const Normalf &norm = normal->_normal;
00438 raw_data.add_float32(norm[0]);
00439 raw_data.add_float32(norm[1]);
00440 raw_data.add_float32(norm[2]);
00441 }
00442
00443 raw_data.add_int32(_faces.size());
00444 Faces::const_iterator fi;
00445 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
00446 XFileFace *face = (*fi);
00447
00448 raw_data.add_int32(face->_vertices.size());
00449 XFileFace::Vertices::const_iterator fvi;
00450 for (fvi = face->_vertices.begin();
00451 fvi != face->_vertices.end();
00452 ++fvi) {
00453 raw_data.add_int32((*fvi)._normal_index);
00454 }
00455 }
00456 }
00457
00458
00459
00460
00461
00462
00463
00464 void XFileMesh::
00465 make_color_data(Datagram &raw_data) {
00466 raw_data.clear();
00467 raw_data.add_int32(_vertices.size());
00468
00469 Vertices::const_iterator vi;
00470 int i = 0;
00471 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
00472 XFileVertex *vertex = (*vi);
00473 const Colorf &color = vertex->_color;
00474 raw_data.add_int32(i);
00475 raw_data.add_float32(color[0]);
00476 raw_data.add_float32(color[1]);
00477 raw_data.add_float32(color[2]);
00478 raw_data.add_float32(color[3]);
00479 i++;
00480 }
00481 }
00482
00483
00484
00485
00486
00487
00488
00489 void XFileMesh::
00490 make_uv_data(Datagram &raw_data) {
00491 raw_data.clear();
00492 raw_data.add_int32(_vertices.size());
00493
00494 Vertices::const_iterator vi;
00495 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
00496 XFileVertex *vertex = (*vi);
00497 const TexCoordf &uv = vertex->_uv;
00498 raw_data.add_float32(uv[0]);
00499 raw_data.add_float32(uv[1]);
00500 }
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 void XFileMesh::
00510 make_material_list_data(Datagram &raw_data) {
00511 raw_data.clear();
00512 raw_data.add_int32(_materials.size());
00513 raw_data.add_int32(_faces.size());
00514 Faces::const_iterator fi;
00515 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
00516 XFileFace *face = (*fi);
00517 raw_data.add_int32(face->_material_index);
00518 }
00519 }
00520
00521
00522
00523
00524
00525
00526
00527 bool XFileMesh::
00528 read_mesh_data(const Datagram &raw_data) {
00529 DatagramIterator di(raw_data);
00530
00531 clear();
00532
00533 int i, j;
00534 int num_vertices = di.get_int32();
00535 for (i = 0; i < num_vertices; i++) {
00536 XFileVertex *vertex = new XFileVertex;
00537 vertex->_point[0] = di.get_float32();
00538 vertex->_point[1] = di.get_float32();
00539 vertex->_point[2] = di.get_float32();
00540 add_vertex(vertex);
00541 }
00542
00543 int num_faces = di.get_int32();
00544 for (i = 0; i < num_faces; i++) {
00545 XFileFace *face = new XFileFace;
00546
00547 num_vertices = di.get_int32();
00548 for (j = 0; j < num_vertices; j++) {
00549 XFileFace::Vertex vertex;
00550 vertex._vertex_index = di.get_int32();
00551 vertex._normal_index = -1;
00552
00553 face->_vertices.push_back(vertex);
00554 }
00555 _faces.push_back(face);
00556 }
00557
00558 if (di.get_remaining_size() != 0) {
00559 nout << "Ignoring " << di.get_remaining_size() << " trailing Mesh.\n";
00560 }
00561
00562 return true;
00563 }
00564
00565
00566
00567
00568
00569
00570
00571 bool XFileMesh::
00572 read_normal_data(const Datagram &raw_data) {
00573 DatagramIterator di(raw_data);
00574
00575 int num_normals = di.get_int32();
00576 int i;
00577 for (i = 0; i < num_normals; i++) {
00578 XFileNormal *normal = new XFileNormal;
00579 normal->_normal[0] = di.get_float32();
00580 normal->_normal[1] = di.get_float32();
00581 normal->_normal[2] = di.get_float32();
00582 normal->_has_normal = true;
00583 add_normal(normal);
00584 }
00585
00586 int num_faces = di.get_int32();
00587
00588 if (num_faces != _faces.size()) {
00589 nout << "Incorrect number of faces in MeshNormals.\n";
00590 return false;
00591 }
00592
00593 for (i = 0; i < num_faces; i++) {
00594 XFileFace *face = _faces[i];
00595 int num_vertices = di.get_int32();
00596 if (num_vertices != face->_vertices.size()) {
00597 nout << "Incorrect number of vertices for face in MeshNormals.\n";
00598 return false;
00599 }
00600 for (int j = 0; j < num_vertices; j++) {
00601 face->_vertices[j]._normal_index = di.get_int32();
00602 }
00603 }
00604
00605 if (di.get_remaining_size() != 0) {
00606 nout << "Ignoring " << di.get_remaining_size()
00607 << " trailing MeshNormals.\n";
00608 }
00609
00610 return true;
00611 }
00612
00613
00614
00615
00616
00617
00618
00619 bool XFileMesh::
00620 read_color_data(const Datagram &raw_data) {
00621 DatagramIterator di(raw_data);
00622
00623 int num_colors = di.get_int32();
00624 int i;
00625 for (i = 0; i < num_colors; i++) {
00626 unsigned int vertex_index = di.get_int32();
00627 if (vertex_index < 0 || vertex_index >= _vertices.size()) {
00628 nout << "Vertex index out of range in MeshVertexColors.\n";
00629 return false;
00630 }
00631 XFileVertex *vertex = _vertices[vertex_index];
00632 vertex->_color[0] = di.get_float32();
00633 vertex->_color[1] = di.get_float32();
00634 vertex->_color[2] = di.get_float32();
00635 vertex->_color[3] = di.get_float32();
00636 vertex->_has_color = true;
00637 }
00638
00639 if (di.get_remaining_size() != 0) {
00640 nout << "Ignoring " << di.get_remaining_size()
00641 << " trailing MeshVertexColors.\n";
00642 }
00643
00644 return true;
00645 }
00646
00647
00648
00649
00650
00651
00652
00653 bool XFileMesh::
00654 read_uv_data(const Datagram &raw_data) {
00655 DatagramIterator di(raw_data);
00656
00657 int num_vertices = di.get_int32();
00658 if (num_vertices != _vertices.size()) {
00659 nout << "Wrong number of vertices in MeshTextureCoords.\n";
00660 return false;
00661 }
00662
00663 int i;
00664 for (i = 0; i < num_vertices; i++) {
00665 XFileVertex *vertex = _vertices[i];
00666 vertex->_uv[0] = di.get_float32();
00667 vertex->_uv[1] = di.get_float32();
00668 vertex->_has_uv = true;
00669 }
00670
00671 if (di.get_remaining_size() != 0) {
00672 nout << "Ignoring " << di.get_remaining_size()
00673 << " trailing MeshTextureCoords.\n";
00674 }
00675
00676 return true;
00677 }
00678
00679
00680
00681
00682
00683
00684
00685 bool XFileMesh::
00686 read_material_list_data(const Datagram &raw_data) {
00687 DatagramIterator di(raw_data);
00688
00689 di.get_int32();
00690 unsigned int num_faces = di.get_int32();
00691
00692 if (num_faces > _faces.size()) {
00693 nout << "Too many faces in MaterialList.\n";
00694 return false;
00695 }
00696
00697 int material_index = -1;
00698 unsigned int i = 0;
00699 while (i < num_faces) {
00700 XFileFace *face = _faces[i];
00701 material_index = di.get_int32();
00702 face->_material_index = material_index;
00703 i++;
00704 }
00705
00706
00707
00708 while (i < (int)_faces.size()) {
00709 XFileFace *face = _faces[i];
00710 face->_material_index = material_index;
00711 i++;
00712 }
00713
00714 if (di.get_remaining_size() != 0) {
00715 nout << "Ignoring " << di.get_remaining_size()
00716 << " trailing MeshMaterialList.\n";
00717 }
00718
00719 return true;
00720 }