00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "maxEgg.h"
00028
00029
00030
00031
00032
00033
00034 MaxToEggConverter::
00035 MaxToEggConverter()
00036 {
00037 reset();
00038 }
00039
00040
00041
00042
00043
00044
00045 MaxToEggConverter::
00046 ~MaxToEggConverter()
00047 {
00048 }
00049
00050
00051
00052
00053 void MaxToEggConverter::reset() {
00054 _cur_tref = 0;
00055 _current_frame = 0;
00056 _textures.clear();
00057 _egg_data = NULL;
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 bool MaxToEggConverter::convert(MaxEggOptions *options) {
00070
00071 _options = options;
00072
00073 Filename fn = Filename::from_os_specific(_options->_file_name);
00074 _options->_path_replace->_path_directory = fn.get_dirname();
00075
00076 _egg_data = new EggData;
00077 if (_egg_data->get_coordinate_system() == CS_default) {
00078 _egg_data->set_coordinate_system(CS_zup_right);
00079 }
00080
00081
00082
00083
00084
00085 Interval anim_range = _options->_max_interface->GetAnimRange();
00086 int start_frame = anim_range.Start()/GetTicksPerFrame();
00087 int end_frame = anim_range.End()/GetTicksPerFrame();
00088
00089 if (!_options->_export_all_frames) {
00090 if (_options->_start_frame < start_frame) _options->_start_frame = start_frame;
00091 if (_options->_start_frame > end_frame) _options->_start_frame = end_frame;
00092 if (_options->_end_frame < start_frame) _options->_end_frame = start_frame;
00093 if (_options->_end_frame > end_frame) _options->_end_frame = end_frame;
00094 if (_options->_end_frame < _options->_start_frame) _options->_end_frame = _options->_start_frame;
00095 start_frame = _options->_start_frame;
00096 end_frame = _options->_end_frame;
00097 }
00098
00099 int frame_inc = 1;
00100 int output_frame_rate = GetFrameRate();
00101
00102 bool all_ok = true;
00103
00104 if (_options->_export_whole_scene) {
00105 _tree._export_mesh = false;
00106 all_ok = _tree.build_complete_hierarchy(_options->_max_interface->GetRootNode(), NULL, 0);
00107 } else {
00108 _tree._export_mesh = true;
00109 all_ok = _tree.build_complete_hierarchy(_options->_max_interface->GetRootNode(), &_options->_node_list.front(), _options->_node_list.size());
00110 }
00111
00112 if (all_ok) {
00113 switch (_options->_anim_type) {
00114 case MaxEggOptions::AT_pose:
00115
00116
00117
00118
00119 _current_frame = start_frame;
00120 all_ok = convert_hierarchy(_egg_data);
00121 break;
00122
00123 case MaxEggOptions::AT_model:
00124
00125
00126 all_ok = convert_char_model();
00127 break;
00128
00129 case MaxEggOptions::AT_chan:
00130
00131 all_ok = convert_char_chan(start_frame, end_frame, frame_inc,
00132 output_frame_rate);
00133 break;
00134
00135 case MaxEggOptions::AT_both:
00136
00137 _options->_anim_type = MaxEggOptions::AT_model;
00138 if (!convert_char_model()) {
00139 all_ok = false;
00140 }
00141 _options->_anim_type = MaxEggOptions::AT_chan;
00142 if (!convert_char_chan(start_frame, end_frame, frame_inc,
00143 output_frame_rate)) {
00144 all_ok = false;
00145 }
00146
00147 _options->_anim_type = MaxEggOptions::AT_both;
00148 break;
00149
00150 default:
00151 all_ok = false;
00152 };
00153
00154 reparent_decals(_egg_data);
00155 }
00156
00157 if (all_ok) {
00158 _egg_data->recompute_tangent_binormal_auto();
00159 _egg_data->remove_unused_vertices(true);
00160 }
00161
00162 _options->_successful = all_ok;
00163
00164 if (all_ok) {
00165 Filename fn = Filename::from_os_specific(_options->_file_name);
00166 return _egg_data->write_egg(fn);
00167 } else {
00168 return false;
00169 }
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 bool MaxToEggConverter::
00179 convert_char_model() {
00180 std::string character_name = "character";
00181 _current_frame = _options->_start_frame;
00182
00183 EggGroup *char_node = new EggGroup(character_name);
00184 _egg_data->add_child(char_node);
00185 char_node->set_dart_type(EggGroup::DT_default);
00186
00187 return convert_hierarchy(char_node);
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197 bool MaxToEggConverter::
00198 convert_char_chan(double start_frame, double end_frame, double frame_inc,
00199 double output_frame_rate) {
00200 std::string character_name = "character";
00201
00202 EggTable *root_table_node = new EggTable();
00203 _egg_data->add_child(root_table_node);
00204 EggTable *bundle_node = new EggTable(character_name);
00205 bundle_node->set_table_type(EggTable::TT_bundle);
00206 root_table_node->add_child(bundle_node);
00207 EggTable *skeleton_node = new EggTable("<skeleton>");
00208 bundle_node->add_child(skeleton_node);
00209
00210
00211
00212 _tree._fps = output_frame_rate / frame_inc;
00213 _tree.clear_egg(_egg_data, NULL, skeleton_node);
00214
00215
00216
00217
00218
00219
00220
00221 EggGroup* tgroup;
00222
00223 int num_nodes = _tree.get_num_nodes();
00224 int i;
00225
00226 TimeValue frame = start_frame;
00227 TimeValue frame_stop = end_frame;
00228 while (frame <= frame_stop) {
00229 _current_frame = frame;
00230 for (i = 0; i < num_nodes; i++) {
00231
00232 MaxNodeDesc *node_desc = _tree.get_node(i);
00233 if (node_desc->is_joint()) {
00234 tgroup = new EggGroup();
00235 INode *max_node = node_desc->get_max_node();
00236
00237 if (node_desc->_parent && node_desc->_parent->is_joint()) {
00238
00239
00240 get_joint_transform(max_node, node_desc->_parent->get_max_node(),
00241 tgroup);
00242 } else {
00243 get_joint_transform(max_node, NULL, tgroup);
00244 }
00245
00246 EggXfmSAnim *anim = _tree.get_egg_anim(node_desc);
00247 if (!anim->add_data(tgroup->get_transform3d())) {
00248
00249 }
00250 delete tgroup;
00251 }
00252 }
00253
00254 frame += frame_inc;
00255 }
00256
00257
00258
00259
00260 for (i = 0; i < num_nodes; i++) {
00261 MaxNodeDesc *node_desc = _tree.get_node(i);
00262 if (node_desc->is_joint()) {
00263 _tree.get_egg_anim(node_desc)->optimize();
00264 }
00265 }
00266
00267 return true;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276 bool MaxToEggConverter::
00277 convert_hierarchy(EggGroupNode *egg_root) {
00278
00279
00280 _tree.clear_egg(_egg_data, egg_root, NULL);
00281 for (int i = 0; i < _tree.get_num_nodes(); i++) {
00282 if (!process_model_node(_tree.get_node(i))) {
00283 return false;
00284 }
00285 }
00286
00287 return true;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297 bool MaxToEggConverter::
00298 process_model_node(MaxNodeDesc *node_desc) {
00299 if (!node_desc->has_max_node()) {
00300
00301 return true;
00302 }
00303
00304
00305
00306 if (node_desc->is_node_joint()) {
00307 return true;
00308 }
00309
00310 TimeValue time = 0;
00311 INode *max_node = node_desc->get_max_node();
00312
00313 ObjectState state;
00314 state = max_node->EvalWorldState(_current_frame * GetTicksPerFrame());
00315
00316 if (node_desc->is_joint()) {
00317 EggGroup *egg_group = _tree.get_egg_group(node_desc);
00318
00319
00320 if (_options->_anim_type == MaxEggOptions::AT_model) {
00321 get_joint_transform(max_node, egg_group);
00322 }
00323 } else {
00324 if (state.obj) {
00325 EggGroup *egg_group = NULL;
00326 TriObject *myMaxTriObject;
00327 Mesh max_mesh;
00328
00329 switch( state.obj->SuperClassID() ){
00330
00331 case GEOMOBJECT_CLASS_ID:
00332 egg_group = _tree.get_egg_group(node_desc);
00333 get_transform(max_node, egg_group);
00334
00335
00336 if (!state.obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) {
00337 return false;
00338 }
00339
00340 myMaxTriObject = (TriObject *) state.obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0 ));
00341
00342
00343
00344
00345
00346 max_mesh = myMaxTriObject->GetMesh();
00347 make_polyset(max_node, &max_mesh, egg_group);
00348
00349 if (myMaxTriObject != state.obj)
00350 delete myMaxTriObject;
00351 break;
00352
00353 case SHAPE_CLASS_ID:
00354 if (state.obj->ClassID() == EDITABLE_SURF_CLASS_ID) {
00355 NURBSSet getSet;
00356 if (GetNURBSSet(state.obj, time, getSet, TRUE)) {
00357 NURBSObject *nObj = getSet.GetNURBSObject(0);
00358 if (nObj->GetType() == kNCVCurve) {
00359
00360 egg_group = _tree.get_egg_group(node_desc);
00361 get_transform(max_node, egg_group);
00362 make_nurbs_curve((NURBSCVCurve *)nObj, string(max_node->GetName()),
00363 time, egg_group);
00364 }
00365 }
00366 }
00367 break;
00368
00369 case CAMERA_CLASS_ID:
00370 break;
00371
00372 case LIGHT_CLASS_ID:
00373 break;
00374
00375 case HELPER_CLASS_ID:
00376
00377 if (state.obj->ClassID() == Class_ID(POINTHELP_CLASS_ID, 0)) {
00378
00379 egg_group = _tree.get_egg_group(node_desc);
00380 get_transform(max_node, egg_group);
00381
00382 } else {
00383
00384 break;
00385
00386 }
00387
00388
00389
00390
00391 }
00392 }
00393 }
00394
00395 return true;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404 void MaxToEggConverter::
00405 get_transform(INode *max_node, EggGroup *egg_group) {
00406 if (_options->_anim_type == MaxEggOptions::AT_model) {
00407
00408
00409 return;
00410 }
00411
00412 if ( !egg_group ) {
00413 return;
00414 }
00415
00416
00417
00418 Matrix3 pivot = max_node->GetNodeTM(_current_frame * GetTicksPerFrame());
00419
00420
00421 Point3 row0 = pivot.GetRow(0);
00422 Point3 row1 = pivot.GetRow(1);
00423 Point3 row2 = pivot.GetRow(2);
00424 Point3 row3 = pivot.GetRow(3);
00425
00426 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
00427 row1.x, row1.y, row1.z, 0.0f,
00428 row2.x, row2.y, row2.z, 0.0f,
00429 row3.x, row3.y, row3.z, 1.0f );
00430
00431
00432
00433
00434
00435 m4d = m4d * egg_group->get_node_frame_inv();
00436 if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
00437 egg_group->add_matrix4(m4d);
00438 }
00439 }
00440
00441
00442
00443
00444
00445
00446
00447 LMatrix4d MaxToEggConverter::
00448 get_object_transform(INode *max_node) {
00449
00450
00451
00452 Matrix3 pivot = max_node->GetObjectTM(_current_frame * GetTicksPerFrame());
00453
00454 Point3 row0 = pivot.GetRow(0);
00455 Point3 row1 = pivot.GetRow(1);
00456 Point3 row2 = pivot.GetRow(2);
00457 Point3 row3 = pivot.GetRow(3);
00458
00459 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
00460 row1.x, row1.y, row1.z, 0.0f,
00461 row2.x, row2.y, row2.z, 0.0f,
00462 row3.x, row3.y, row3.z, 1.0f );
00463 return m4d;
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 void MaxToEggConverter::
00477 get_joint_transform(INode *max_node, EggGroup *egg_group) {
00478
00479 if ( !egg_group ) {
00480 return;
00481 }
00482
00483
00484
00485 Matrix3 pivot = max_node->GetNodeTM(_current_frame * GetTicksPerFrame());
00486 Point3 row0 = pivot.GetRow(0);
00487 Point3 row1 = pivot.GetRow(1);
00488 Point3 row2 = pivot.GetRow(2);
00489 Point3 row3 = pivot.GetRow(3);
00490
00491 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
00492 row1.x, row1.y, row1.z, 0.0f,
00493 row2.x, row2.y, row2.z, 0.0f,
00494 row3.x, row3.y, row3.z, 1.0f );
00495
00496
00497
00498
00499
00500 m4d = m4d * egg_group->get_node_frame_inv();
00501 if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
00502 egg_group->add_matrix4(m4d);
00503 }
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 void MaxToEggConverter::
00517 get_joint_transform(INode *max_node, INode *parent_node, EggGroup *egg_group) {
00518
00519 if ( !egg_group ) {
00520 return;
00521 }
00522
00523
00524
00525 Matrix3 pivot = max_node->GetNodeTM(_current_frame * GetTicksPerFrame());
00526 Point3 row0 = pivot.GetRow(0);
00527 Point3 row1 = pivot.GetRow(1);
00528 Point3 row2 = pivot.GetRow(2);
00529 Point3 row3 = pivot.GetRow(3);
00530
00531 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
00532 row1.x, row1.y, row1.z, 0.0f,
00533 row2.x, row2.y, row2.z, 0.0f,
00534 row3.x, row3.y, row3.z, 1.0f );
00535
00536 if (parent_node) {
00537 Matrix3 parent_pivot = parent_node->GetNodeTM(_current_frame * GetTicksPerFrame());
00538
00539 row0 = parent_pivot.GetRow(0);
00540 row1 = parent_pivot.GetRow(1);
00541 row2 = parent_pivot.GetRow(2);
00542 row3 = parent_pivot.GetRow(3);
00543
00544 LMatrix4d pi_m4d(row0.x, row0.y, row0.z, 0.0f,
00545 row1.x, row1.y, row1.z, 0.0f,
00546 row2.x, row2.y, row2.z, 0.0f,
00547 row3.x, row3.y, row3.z, 1.0f );
00548
00549
00550
00551
00552
00553 pi_m4d.invert_in_place();
00554 m4d = m4d * pi_m4d;
00555 }
00556 if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
00557 egg_group->add_matrix4(m4d);
00558 }
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568 bool MaxToEggConverter::
00569 make_nurbs_curve(NURBSCVCurve *curve, const string &name,
00570 TimeValue time, EggGroup *egg_group)
00571 {
00572 int degree = curve->GetOrder();
00573 int cvs = curve->GetNumCVs();
00574 int knots = curve->GetNumKnots();
00575 int i;
00576
00577 if (knots != cvs + degree) {
00578 return false;
00579 }
00580
00581 string vpool_name = name + ".cvs";
00582 EggVertexPool *vpool = new EggVertexPool(vpool_name);
00583 egg_group->add_child(vpool);
00584
00585 EggNurbsCurve *egg_curve = new EggNurbsCurve(name);
00586 egg_group->add_child(egg_curve);
00587 egg_curve->setup(degree, knots);
00588
00589 for (i = 0; i < knots; i++)
00590 egg_curve->set_knot(i, curve->GetKnot(i));
00591
00592 LMatrix4d vertex_frame_inv = egg_group->get_vertex_frame_inv();
00593
00594 for (i = 0; i < cvs; i++) {
00595 NURBSControlVertex *cv = curve->GetCV(i);
00596 if (!cv) {
00597 char buf[1024];
00598 sprintf(buf, "Error getting CV %d", i);
00599 return false;
00600 } else {
00601 EggVertex vert;
00602 LPoint4d p4d(0, 0, 0, 1.0);
00603 cv->GetPosition(time, p4d[0], p4d[1], p4d[2]);
00604 p4d = p4d * vertex_frame_inv;
00605 vert.set_pos(p4d);
00606 egg_curve->add_vertex(vpool->create_unique_vertex(vert));
00607 }
00608 }
00609
00610 return true;
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620 void MaxToEggConverter::
00621 make_polyset(INode *max_node, Mesh *mesh,
00622 EggGroup *egg_group, Shader *default_shader) {
00623
00624 mesh->buildNormals();
00625
00626 if (mesh->getNumFaces() == 0) {
00627 return;
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 string vpool_name = string(max_node->GetName()) + ".verts";
00643 EggVertexPool *vpool = new EggVertexPool(vpool_name);
00644 egg_group->add_child(vpool);
00645
00646
00647
00648
00649
00650
00651
00652 LMatrix4d vertex_frame = get_object_transform(max_node) *
00653 egg_group->get_vertex_frame_inv();
00654
00655
00656 for ( int iFace=0; iFace < mesh->getNumFaces(); iFace++ ) {
00657 EggPolygon *egg_poly = new EggPolygon;
00658 egg_group->add_child(egg_poly);
00659
00660 egg_poly->set_bface_flag(_options->_double_sided);
00661
00662 Face face = mesh->faces[iFace];
00663
00664 const PandaMaterial &pmat = get_panda_material(max_node->GetMtl(), face.getMatID());
00665
00666
00667 for ( int iVertex=0; iVertex < 3; iVertex++ ) {
00668 EggVertex vert;
00669
00670
00671 Point3 vertex = mesh->getVert(face.v[iVertex]);
00672 LPoint3d p3d(vertex.x, vertex.y, vertex.z);
00673 p3d = p3d * vertex_frame;
00674 vert.set_pos(p3d);
00675
00676
00677 Point3 normal = get_max_vertex_normal(mesh, iFace, iVertex);
00678 LVector3d n3d(normal.x, normal.y, normal.z);
00679
00680
00681 n3d = n3d * vertex_frame;
00682 vert.set_normal(n3d);
00683
00684
00685 if(mesh->vcFace)
00686 {
00687 VertColor vertexColor = get_max_vertex_color(mesh, iFace, iVertex);
00688 LColor pVC(vertexColor.x, vertexColor.y, vertexColor.z, 1);
00689 vert.set_color(pVC);
00690 }
00691
00692
00693
00694
00695
00696
00697 if (pmat._map_channels.size() == 0) {
00698
00699
00700 UVVert uvw = get_max_vertex_texcoord(mesh, iFace, iVertex, 1);
00701 vert.set_uv( LTexCoordd(uvw.x, uvw.y));
00702 }
00703
00704
00705
00706 for (int iChan=0; iChan<pmat._map_channels.size(); iChan++) {
00707 int channel = pmat._map_channels[iChan];
00708 ostringstream uvname;
00709 uvname << "m" << channel;
00710 UVVert uvw = get_max_vertex_texcoord(mesh, iFace, iVertex, channel);
00711
00712 if(channel == 1)
00713 vert.set_uv( LTexCoordd(uvw.x, uvw.y));
00714 else
00715 vert.set_uv( uvname.str(), LTexCoordd(uvw.x, uvw.y));
00716
00717 }
00718
00719 vert.set_external_index(face.v[iVertex]);
00720
00721 egg_poly->add_vertex(vpool->create_unique_vertex(vert));
00722 }
00723
00724
00725
00726
00727 EggVertex *verts[3];
00728 LPoint3d points[3];
00729
00730 for (int i = 0; i < 3; i++) {
00731 verts[i] = egg_poly->get_vertex(i);
00732 points[i] = verts[i]->get_pos3();
00733 }
00734
00735 LVector3d realNorm = ((points[1] - points[0]).cross(points[2] - points[0]));
00736 Point3 maxNormTemp = mesh->getFaceNormal(iFace);
00737 LVector3d maxNorm = (LVector3d(maxNormTemp.x, maxNormTemp.y, maxNormTemp.z) *
00738 vertex_frame);
00739
00740 if (realNorm.dot(maxNorm) < 0.0) {
00741 egg_poly->set_vertex(0, verts[2]);
00742 egg_poly->set_vertex(2, verts[0]);
00743 }
00744
00745 for (int i=0; i<pmat._texture_list.size(); i++) {
00746 egg_poly->add_texture(pmat._texture_list[i]);
00747 }
00748 egg_poly->set_color(pmat._color);
00749
00750
00751 }
00752
00753
00754
00755
00756
00757 if (_options->_anim_type == MaxEggOptions::AT_model) {
00758 get_vertex_weights(max_node, vpool);
00759 }
00760 }
00761
00762 UVVert MaxToEggConverter::get_max_vertex_texcoord(Mesh *mesh, int faceNo, int vertNo, int channel) {
00763
00764
00765 UVVert uvVert(0,0,0);
00766 if(mesh->mapSupport(channel)) {
00767 TVFace *pTVFace = mesh->mapFaces(channel);
00768 UVVert *pUVVert = mesh->mapVerts(channel);
00769 uvVert = pUVVert[pTVFace[faceNo].t[vertNo]];
00770 } else if(mesh->numTVerts > 0) {
00771 uvVert = mesh->tVerts[mesh->tvFace[faceNo].t[vertNo]];
00772 }
00773 return uvVert;
00774 }
00775
00776 VertColor MaxToEggConverter::get_max_vertex_color(Mesh *mesh,int FaceNo,int VertexNo, int channel) {
00777
00778 VertColor vc(0,0,0);
00779 if(mesh->mapSupport(channel))
00780 {
00781
00782 TVFace& _vcface = mesh->vcFace[FaceNo];
00783
00784 int VertexColorIndex = _vcface.t[VertexNo];
00785
00786 vc =mesh->vertCol[VertexColorIndex];
00787 }
00788 else
00789 {
00790 TVFace *pTVFace = mesh->mapFaces(channel);
00791 vc = mesh->vertCol[pTVFace[FaceNo].t[VertexNo]];
00792 }
00793 return vc;
00794 }
00795
00796 VertColor MaxToEggConverter::get_max_vertex_color(Mesh *mesh,int FaceNo,int VertexNo)
00797 {
00798 VertColor vc(0,0,0);
00799
00800 TVFace& _vcface = mesh->vcFace[FaceNo];
00801
00802 int VertexColorIndex = _vcface.t[VertexNo];
00803
00804 vc =mesh->vertCol[VertexColorIndex];
00805 return vc;
00806 }
00807
00808 Point3 MaxToEggConverter::get_max_vertex_normal(Mesh *mesh, int faceNo, int vertNo)
00809 {
00810 Face f = mesh->faces[faceNo];
00811 DWORD smGroup = f.smGroup;
00812 int vert = f.getVert(vertNo);
00813 RVertex *rv = mesh->getRVertPtr(vert);
00814
00815 int numNormals;
00816 Point3 vertexNormal;
00817
00818
00819
00820 if (rv->rFlags & SPECIFIED_NORMAL) {
00821 vertexNormal = rv->rn.getNormal();
00822 }
00823
00824
00825 else if ((numNormals = rv->rFlags & NORCT_MASK) && smGroup) {
00826
00827 if (numNormals == 1) {
00828 vertexNormal = rv->rn.getNormal();
00829 }
00830 else {
00831
00832
00833
00834 for (int i = 0; i < numNormals; i++) {
00835 if (rv->ern[i].getSmGroup() & smGroup) {
00836 vertexNormal = rv->ern[i].getNormal();
00837 }
00838 }
00839 }
00840 }
00841 else {
00842
00843 vertexNormal = mesh->getFaceNormal(faceNo);
00844 }
00845
00846 return vertexNormal;
00847 }
00848
00849
00850
00851
00852
00853
00854 void MaxToEggConverter::
00855 get_vertex_weights(INode *max_node, EggVertexPool *vpool) {
00856
00857 Modifier *mod = FindSkinModifier(max_node, PHYSIQUE_CLASSID);
00858 EggVertexPool::iterator vi;
00859
00860 if (mod) {
00861
00862 IPhysiqueExport *pPhysiqueExport = (IPhysiqueExport *)mod->GetInterface(I_PHYINTERFACE);
00863 if (pPhysiqueExport) {
00864
00865 IPhyContextExport *pContextExport =
00866 (IPhyContextExport *)pPhysiqueExport->GetContextInterface(max_node);
00867 if (pContextExport) {
00868
00869 pContextExport->ConvertToRigid(TRUE);
00870 pContextExport->AllowBlending(TRUE);
00871
00872 for (vi = vpool->begin(); vi != vpool->end(); ++vi) {
00873 EggVertex *vert = (*vi);
00874 int max_vi = vert->get_external_index();
00875
00876
00877 IPhyVertexExport *pVertexExport =
00878 (IPhyVertexExport *)pContextExport->GetVertexInterface(max_vi);
00879 if (pVertexExport) {
00880 int vertexType = pVertexExport->GetVertexType();
00881
00882
00883 if(vertexType == RIGID_TYPE) {
00884
00885 IPhyRigidVertex *pTypeVertex = (IPhyRigidVertex *)pVertexExport;
00886 INode *bone_node = pTypeVertex->GetNode();
00887 MaxNodeDesc *joint_node_desc = _tree.find_joint(bone_node);
00888 if (joint_node_desc){
00889 EggGroup *joint = _tree.get_egg_group(joint_node_desc);
00890 if (joint != (EggGroup *)NULL)
00891 joint->ref_vertex(vert, 1.0f);
00892 }
00893 }
00894 else if(vertexType == RIGID_BLENDED_TYPE) {
00895
00896 IPhyBlendedRigidVertex *pTypeVertex = (IPhyBlendedRigidVertex *)pVertexExport;
00897
00898 for (int ji = 0; ji < pTypeVertex->GetNumberNodes(); ++ji) {
00899 PN_stdfloat weight = pTypeVertex->GetWeight(ji);
00900 if (weight > 0.0f) {
00901 INode *bone_node = pTypeVertex->GetNode(ji);
00902 MaxNodeDesc *joint_node_desc = _tree.find_joint(bone_node);
00903 if (joint_node_desc){
00904 EggGroup *joint = _tree.get_egg_group(joint_node_desc);
00905 if (joint != (EggGroup *)NULL)
00906 joint->ref_vertex(vert, weight);
00907 }
00908 }
00909 }
00910 }
00911
00912 pContextExport->ReleaseVertexInterface(pVertexExport);
00913 }
00914 }
00915
00916 pPhysiqueExport->ReleaseContextInterface(pContextExport);
00917 }
00918
00919 mod->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
00920 }
00921 }
00922 else {
00923
00924 mod = FindSkinModifier(max_node, SKIN_CLASSID);
00925 if (mod) {
00926 ISkin *skin = (ISkin*)mod->GetInterface(I_SKIN);
00927 if (skin) {
00928 ISkinContextData *skinMC = skin->GetContextInterface(max_node);
00929 if (skinMC) {
00930 for (vi = vpool->begin(); vi != vpool->end(); ++vi) {
00931 EggVertex *vert = (*vi);
00932 int max_vi = vert->get_external_index();
00933
00934 for (int ji = 0; ji < skinMC->GetNumAssignedBones(max_vi); ++ji) {
00935 PN_stdfloat weight = skinMC->GetBoneWeight(max_vi, ji);
00936 if (weight > 0.0f) {
00937 INode *bone_node = skin->GetBone(skinMC->GetAssignedBone(max_vi, ji));
00938 MaxNodeDesc *joint_node_desc = _tree.find_joint(bone_node);
00939 if (joint_node_desc){
00940 EggGroup *joint = _tree.get_egg_group(joint_node_desc);
00941 if (joint != (EggGroup *)NULL) {
00942 joint->ref_vertex(vert, weight);
00943 }
00944 }
00945 }
00946 }
00947 }
00948 }
00949 }
00950 }
00951 }
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961 const MaxToEggConverter::PandaMaterial &MaxToEggConverter::
00962 get_panda_material(Mtl *mtl, MtlID matID) {
00963
00964 MaterialMap::iterator it = _material_map.find(mtl);
00965 if (it != _material_map.end()) {
00966 return (*it).second;
00967 }
00968
00969 PandaMaterial &pandaMat = _material_map[mtl];
00970 pandaMat._color = LColor(1,1,1,1);
00971 pandaMat._any_diffuse = false;
00972 pandaMat._any_opacity = false;
00973 pandaMat._any_gloss = false;
00974 pandaMat._any_normal = false;
00975
00976
00977
00978
00979
00980
00981 while (( mtl != 0) && (mtl->ClassID() == Class_ID(MULTI_CLASS_ID, 0 ))) {
00982 if (matID < mtl->NumSubMtls()) {
00983 mtl = mtl->GetSubMtl(matID);
00984 } else {
00985 mtl = 0;
00986 }
00987 }
00988
00989
00990
00991 if ((mtl != 0) && (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0 ))) {
00992 StdMat *maxMaterial = (StdMat*)mtl;
00993 analyze_diffuse_maps(pandaMat, maxMaterial->GetSubTexmap(ID_DI));
00994 analyze_opacity_maps(pandaMat, maxMaterial->GetSubTexmap(ID_OP));
00995 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SP));
00996 if (!pandaMat._any_gloss)
00997 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SS));
00998 if (!pandaMat._any_gloss)
00999 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SH));
01000 analyze_glow_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SI));
01001 analyze_normal_maps(pandaMat, maxMaterial->GetSubTexmap(ID_BU));
01002 for (int i=0; i<pandaMat._texture_list.size(); i++) {
01003 EggTexture *src = pandaMat._texture_list[i];
01004 pandaMat._texture_list[i] =
01005 _textures.create_unique_texture(*src, ~EggTexture::E_tref_name);
01006 }
01007
01008
01009
01010 if (!pandaMat._any_diffuse) {
01011
01012 Point3 diffuseColor = Point3(maxMaterial->GetDiffuse(0));
01013 pandaMat._color[0] = diffuseColor.x;
01014 pandaMat._color[1] = diffuseColor.y;
01015 pandaMat._color[2] = diffuseColor.z;
01016 }
01017 if (!pandaMat._any_opacity) {
01018
01019 pandaMat._color[3] = (maxMaterial->GetOpacity(_current_frame * GetTicksPerFrame()));
01020 }
01021 if (pandaMat._texture_list.size() < 1) {
01022
01023
01024
01025 pandaMat._map_channels.push_back(1);
01026 }
01027 return pandaMat;
01028 }
01029
01030
01031 return pandaMat;
01032 }
01033
01034
01035
01036
01037
01038 void MaxToEggConverter::analyze_diffuse_maps(PandaMaterial &pandaMat, Texmap *mat) {
01039 if (mat == 0) return;
01040
01041 if (mat->ClassID() == Class_ID(RGBMULT_CLASS_ID, 0)) {
01042 for (int i=0; i<mat->NumSubTexmaps(); i++) {
01043 analyze_diffuse_maps(pandaMat, mat->GetSubTexmap(i));
01044 }
01045 return;
01046 }
01047
01048 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
01049 pandaMat._any_diffuse = true;
01050 PT(EggTexture) tex = new EggTexture(generate_tex_name(), "");
01051
01052 BitmapTex *diffuseTex = (BitmapTex *)mat;
01053
01054 Filename fullpath, outpath;
01055 Filename filename = Filename::from_os_specific(diffuseTex->GetMapName());
01056 _options->_path_replace->full_convert_path(filename, get_model_path(),
01057 fullpath, outpath);
01058 tex->set_filename(outpath);
01059 tex->set_fullpath(fullpath);
01060
01061 apply_texture_properties(*tex, diffuseTex->GetMapChannel());
01062 add_map_channel(pandaMat, diffuseTex->GetMapChannel());
01063
01064 Bitmap *diffuseBitmap = diffuseTex->GetBitmap(0);
01065 if ( diffuseBitmap && diffuseBitmap->HasAlpha()) {
01066 tex->set_format(EggTexture::F_rgba);
01067 } else {
01068 tex->set_format(EggTexture::F_rgb);
01069 }
01070 tex->set_env_type(EggTexture::ET_modulate);
01071
01072 pandaMat._texture_list.push_back(tex);
01073 }
01074 }
01075
01076
01077
01078
01079
01080
01081 void MaxToEggConverter::analyze_opacity_maps(PandaMaterial &pandaMat, Texmap *mat) {
01082 if (mat == 0) return;
01083
01084 if (mat->ClassID() == Class_ID(RGBMULT_CLASS_ID, 0)) {
01085 for (int i=0; i<mat->NumSubTexmaps(); i++) {
01086 analyze_opacity_maps(pandaMat, mat->GetSubTexmap(i));
01087 }
01088 return;
01089 }
01090
01091 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
01092 pandaMat._any_opacity = true;
01093 BitmapTex *transTex = (BitmapTex *)mat;
01094
01095 Filename fullpath, outpath;
01096 Filename filename = Filename::from_os_specific(transTex->GetMapName());
01097 _options->_path_replace->full_convert_path(filename, get_model_path(),
01098 fullpath, outpath);
01099
01100
01101 for (int i=0; i<pandaMat._texture_list.size(); i++) {
01102 EggTexture *tex = pandaMat._texture_list[i];
01103 if ((tex->get_env_type()==EggTexture::ET_modulate)&&(tex->get_fullpath() == fullpath)) {
01104 tex->set_format(EggTexture::F_rgba);
01105 return;
01106 }
01107 }
01108
01109
01110 std::string uvname = get_uv_name(transTex->GetMapChannel());
01111 for (int i=0; i<pandaMat._texture_list.size(); i++) {
01112 EggTexture *tex = pandaMat._texture_list[i];
01113 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
01114 (tex->get_format() == EggTexture::F_rgb)&&
01115 (tex->get_uv_name() == uvname)) {
01116 tex->set_format(EggTexture::F_rgba);
01117 tex->set_alpha_filename(outpath);
01118 tex->set_alpha_fullpath(fullpath);
01119 return;
01120 }
01121 }
01122
01123
01124 PT(EggTexture) tex = new EggTexture(generate_tex_name(), "");
01125 tex->set_filename(outpath);
01126 tex->set_fullpath(fullpath);
01127
01128 apply_texture_properties(*tex, transTex->GetMapChannel());
01129 add_map_channel(pandaMat, transTex->GetMapChannel());
01130 tex->set_format(EggTexture::F_alpha);
01131
01132 pandaMat._texture_list.push_back(tex);
01133 }
01134 }
01135
01136
01137
01138
01139
01140
01141 void MaxToEggConverter::analyze_glow_maps(PandaMaterial &pandaMat, Texmap *mat) {
01142 if (mat == 0) return;
01143
01144 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
01145 BitmapTex *gtex = (BitmapTex *)mat;
01146
01147 Filename fullpath, outpath;
01148 Filename filename = Filename::from_os_specific(gtex->GetMapName());
01149 _options->_path_replace->full_convert_path(filename, get_model_path(),
01150 fullpath, outpath);
01151
01152
01153 std::string uvname = get_uv_name(gtex->GetMapChannel());
01154 for (int i=0; i<pandaMat._texture_list.size(); i++) {
01155 EggTexture *tex = pandaMat._texture_list[i];
01156 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
01157 (tex->get_format() == EggTexture::F_rgb)&&
01158 (tex->get_uv_name() == uvname)) {
01159 tex->set_env_type(EggTexture::ET_modulate_glow);
01160 tex->set_format(EggTexture::F_rgba);
01161 tex->set_alpha_filename(outpath);
01162 tex->set_alpha_fullpath(fullpath);
01163 return;
01164 }
01165 }
01166
01167
01168 PT(EggTexture) tex = new EggTexture(generate_tex_name(), "");
01169 tex->set_env_type(EggTexture::ET_glow);
01170 tex->set_filename(outpath);
01171 tex->set_fullpath(fullpath);
01172 apply_texture_properties(*tex, gtex->GetMapChannel());
01173 add_map_channel(pandaMat, gtex->GetMapChannel());
01174 tex->set_format(EggTexture::F_alpha);
01175
01176 pandaMat._texture_list.push_back(tex);
01177 }
01178 }
01179
01180
01181
01182
01183
01184
01185 void MaxToEggConverter::analyze_gloss_maps(PandaMaterial &pandaMat, Texmap *mat) {
01186 if (mat == 0) return;
01187
01188 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
01189 pandaMat._any_gloss = true;
01190 BitmapTex *gtex = (BitmapTex *)mat;
01191
01192 Filename fullpath, outpath;
01193 Filename filename = Filename::from_os_specific(gtex->GetMapName());
01194 _options->_path_replace->full_convert_path(filename, get_model_path(),
01195 fullpath, outpath);
01196
01197
01198 std::string uvname = get_uv_name(gtex->GetMapChannel());
01199 for (int i=0; i<pandaMat._texture_list.size(); i++) {
01200 EggTexture *tex = pandaMat._texture_list[i];
01201 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
01202 (tex->get_format() == EggTexture::F_rgb)&&
01203 (tex->get_uv_name() == uvname)) {
01204 tex->set_env_type(EggTexture::ET_modulate_gloss);
01205 tex->set_format(EggTexture::F_rgba);
01206 tex->set_alpha_filename(outpath);
01207 tex->set_alpha_fullpath(fullpath);
01208 return;
01209 }
01210 }
01211
01212
01213 PT(EggTexture) tex = new EggTexture(generate_tex_name(), "");
01214 tex->set_env_type(EggTexture::ET_gloss);
01215 tex->set_filename(outpath);
01216 tex->set_fullpath(fullpath);
01217 apply_texture_properties(*tex, gtex->GetMapChannel());
01218 add_map_channel(pandaMat, gtex->GetMapChannel());
01219 tex->set_format(EggTexture::F_alpha);
01220
01221 pandaMat._texture_list.push_back(tex);
01222 }
01223 }
01224
01225
01226
01227
01228
01229
01230 void MaxToEggConverter::analyze_normal_maps(PandaMaterial &pandaMat, Texmap *mat) {
01231 if (mat == 0) return;
01232
01233 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
01234 pandaMat._any_normal = true;
01235 BitmapTex *ntex = (BitmapTex *)mat;
01236
01237 Filename fullpath, outpath;
01238 Filename filename = Filename::from_os_specific(ntex->GetMapName());
01239 _options->_path_replace->full_convert_path(filename, get_model_path(),
01240 fullpath, outpath);
01241
01242 PT(EggTexture) tex = new EggTexture(generate_tex_name(), "");
01243 tex->set_env_type(EggTexture::ET_normal);
01244 tex->set_filename(outpath);
01245 tex->set_fullpath(fullpath);
01246 apply_texture_properties(*tex, ntex->GetMapChannel());
01247 add_map_channel(pandaMat, ntex->GetMapChannel());
01248 tex->set_format(EggTexture::F_rgb);
01249
01250 pandaMat._texture_list.push_back(tex);
01251 }
01252 }
01253
01254
01255
01256
01257
01258
01259
01260 void MaxToEggConverter::add_map_channel(PandaMaterial &pandaMat, int chan) {
01261 for (int i=0; i<pandaMat._map_channels.size(); i++) {
01262 if (pandaMat._map_channels[i] == chan) {
01263 return;
01264 }
01265 }
01266 pandaMat._map_channels.push_back(chan);
01267 }
01268
01269
01270
01271
01272
01273
01274 std::string MaxToEggConverter::generate_tex_name() {
01275 ostringstream name_strm;
01276 name_strm << "Tex" << ++_cur_tref;
01277 return name_strm.str();
01278 }
01279
01280
01281
01282
01283
01284
01285 std::string MaxToEggConverter::get_uv_name(int channel) {
01286 ostringstream uvname;
01287 uvname << "m" << channel;
01288 return uvname.str();
01289 }
01290
01291
01292
01293
01294
01295
01296
01297
01298 void MaxToEggConverter::
01299 apply_texture_properties(EggTexture &tex, int channel) {
01300
01301
01302 if(channel == 1)
01303 tex.set_uv_name("");
01304 else
01305 tex.set_uv_name(get_uv_name(channel));
01306
01307 tex.set_minfilter(EggTexture::FT_linear_mipmap_linear);
01308 tex.set_magfilter(EggTexture::FT_linear);
01309
01310 EggTexture::WrapMode wrap_u = EggTexture::WM_repeat;
01311 EggTexture::WrapMode wrap_v = EggTexture::WM_repeat;
01312
01313 tex.set_wrap_u(wrap_u);
01314 tex.set_wrap_v(wrap_v);
01315 }
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328 bool MaxToEggConverter::
01329 reparent_decals(EggGroupNode *egg_parent) {
01330 bool okflag = true;
01331
01332
01333
01334 EggGroup *decal_base = (EggGroup *)NULL;
01335 pvector<EggGroup *> decal_children;
01336
01337 EggGroupNode::iterator ci;
01338 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
01339 EggNode *child = (*ci);
01340 if (child->is_of_type(EggGroup::get_class_type())) {
01341 EggGroup *child_group = (EggGroup *) child;
01342 if (child_group->has_object_type("decalbase")) {
01343 if (decal_base != (EggNode *)NULL) {
01344
01345 okflag = false;
01346 }
01347 child_group->remove_object_type("decalbase");
01348 decal_base = child_group;
01349
01350 } else if (child_group->has_object_type("decal")) {
01351 child_group->remove_object_type("decal");
01352 decal_children.push_back(child_group);
01353 }
01354 }
01355 }
01356
01357 if (decal_base == (EggGroup *)NULL) {
01358 if (!decal_children.empty()) {
01359
01360 }
01361
01362 } else {
01363 if (decal_children.empty()) {
01364
01365
01366 } else {
01367
01368
01369
01370
01371 pvector<EggGroup *>::iterator di;
01372 for (di = decal_children.begin(); di != decal_children.end(); ++di) {
01373 EggGroup *child_group = (*di);
01374 decal_base->add_child(child_group);
01375 }
01376
01377
01378 decal_base->set_decal_flag(true);
01379 }
01380 }
01381
01382
01383 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
01384 EggNode *child = (*ci);
01385 if (child->is_of_type(EggGroupNode::get_class_type())) {
01386 EggGroupNode *child_group = (EggGroupNode *) child;
01387 if (!reparent_decals(child_group)) {
01388 okflag = false;
01389 }
01390 }
01391 }
01392
01393 return okflag;
01394 }
01395
01396 Modifier* MaxToEggConverter::FindSkinModifier (INode* node, const Class_ID &type)
01397 {
01398
01399 Object* pObj = node->GetObjectRef();
01400 if (!pObj) return NULL;
01401
01402
01403 while (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) {
01404
01405 IDerivedObject* pDerObj = static_cast<IDerivedObject*>(pObj);
01406
01407
01408 for (int stackId = 0; stackId < pDerObj->NumModifiers(); ++stackId) {
01409
01410 Modifier* mod = pDerObj->GetModifier(stackId);
01411
01412
01413 if (mod->ClassID() == type )
01414 return mod;
01415 }
01416
01417
01418 pObj = pDerObj->GetObjRef();
01419 }
01420
01421
01422 return NULL;
01423 }