00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "pandatoolbase.h"
00022 #include "notifyCategoryProxy.h"
00023
00024 #include "eggData.h"
00025 #include "eggVertexPool.h"
00026 #include "eggVertex.h"
00027 #include "eggPolygon.h"
00028 #include "eggPrimitive.h"
00029 #include "eggGroupNode.h"
00030 #include "eggPolysetMaker.h"
00031 #include "eggBin.h"
00032
00033 #include <stdio.h>
00034 #include "Max.h"
00035 #include "istdplug.h"
00036 #include "stdmat.h"
00037 #include "decomp.h"
00038 #include "shape.h"
00039 #include "simpobj.h"
00040 #include "iparamb2.h"
00041 #include "iskin.h"
00042 #include "modstack.h"
00043
00044 #include "maxEggLoader.h"
00045
00046 class MaxEggMesh;
00047 class MaxEggJoint;
00048 class MaxEggTex;
00049
00050 NotifyCategoryDeclNoExport(maxloader);
00051 NotifyCategoryDef(maxloader, "");
00052
00053 class MaxEggLoader
00054 {
00055 public:
00056 bool ConvertEggData(EggData *data, bool merge, bool model, bool anim);
00057 bool ConvertEggFile(const char *name, bool merge, bool model, bool anim);
00058
00059 public:
00060 void TraverseEggNode(EggNode *node, EggGroup *context);
00061 MaxEggMesh *GetMesh(EggVertexPool *pool);
00062 MaxEggJoint *FindJoint(EggGroup *joint);
00063 MaxEggJoint *MakeJoint(EggGroup *joint, EggGroup *context);
00064 MaxEggTex *GetTex(const string &fn);
00065 void CreateSkinModifier(MaxEggMesh *M);
00066
00067 typedef phash_map<EggVertexPool *, MaxEggMesh *> MeshTable;
00068 typedef second_of_pair_iterator<MeshTable::const_iterator> MeshIterator;
00069 typedef phash_map<EggGroup *, MaxEggJoint *> JointTable;
00070 typedef second_of_pair_iterator<JointTable::const_iterator> JointIterator;
00071 typedef phash_map<string, MaxEggTex *> TexTable;
00072 typedef second_of_pair_iterator<TexTable::const_iterator> TexIterator;
00073
00074 MeshTable _mesh_tab;
00075 JointTable _joint_tab;
00076 TexTable _tex_tab;
00077 int _next_tex;
00078 };
00079
00080 Point3 MakeMaxPoint(LVector3d vec)
00081 {
00082 return Point3(vec[0], vec[1], vec[2]);
00083 }
00084
00085
00086
00087
00088
00089
00090
00091 class MaxEggTex
00092 {
00093 public:
00094 string _path;
00095 int _id;
00096 StdMat *_mat;
00097 BitmapTex *_bmt;
00098 };
00099
00100 MaxEggTex *MaxEggLoader::GetTex(const string &fn)
00101 {
00102 if (_tex_tab.count(fn))
00103 return _tex_tab[fn];
00104
00105 BitmapTex *bmt = NewDefaultBitmapTex();
00106 bmt->SetMapName((TCHAR*)(fn.c_str()));
00107 StdMat *mat = NewDefaultStdMat();
00108 mat->SetSubTexmap(ID_DI, bmt);
00109 mat->SetTexmapAmt(ID_DI, 1.0, 0);
00110 mat->EnableMap(ID_DI, TRUE);
00111 mat->SetActiveTexmap(bmt);
00112 GetCOREInterface()->ActivateTexture(bmt, mat);
00113
00114 MaxEggTex *res = new MaxEggTex;
00115 res->_path = fn;
00116 res->_id = _next_tex ++;
00117 res->_bmt = bmt;
00118 res->_mat = mat;
00119
00120 _tex_tab[fn] = res;
00121 return res;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130 class MaxEggJoint
00131 {
00132 public:
00133 LMatrix4d _trans;
00134 LVector3d _endpos;
00135 LVector3d _perp;
00136 double _thickness;
00137 bool _inskin;
00138 SimpleObject2 *_bone;
00139 INode *_node;
00140 EggGroup *_egg_joint;
00141 MaxEggJoint *_parent;
00142 vector <MaxEggJoint *> _children;
00143
00144 public:
00145 void GetRotation(LVector3d &xv, LVector3d &yv, LVector3d &zv);
00146 LVector3d GetPos(void) { return _trans.get_row3(3); }
00147 MaxEggJoint *ChooseBestChild(LVector3d dir);
00148 void ChooseEndPos(double thickness);
00149 void CreateMaxBone(void);
00150 };
00151
00152 void MaxEggJoint::GetRotation(LVector3d &xv, LVector3d &yv, LVector3d &zv)
00153 {
00154 xv = _trans.get_row3(0);
00155 yv = _trans.get_row3(1);
00156 zv = _trans.get_row3(2);
00157 xv.normalize();
00158 yv.normalize();
00159 zv = xv.cross(yv);
00160 zv.normalize();
00161 yv = zv.cross(xv);
00162 }
00163
00164 MaxEggJoint *MaxEggLoader::FindJoint(EggGroup *joint)
00165 {
00166 if (joint==0) return 0;
00167 return _joint_tab[joint];
00168 }
00169
00170 MaxEggJoint *MaxEggLoader::MakeJoint(EggGroup *joint, EggGroup *context)
00171 {
00172 MaxEggJoint *parent = FindJoint(context);
00173 MaxEggJoint *result = new MaxEggJoint;
00174 LMatrix4d t = joint->get_transform3d();
00175 if (parent) {
00176 result->_trans = t * parent->_trans;
00177 } else {
00178 result->_trans = t;
00179 }
00180 result->_endpos = LVector3d(0,0,0);
00181 result->_perp = LVector3d(0,0,0);
00182 result->_thickness = 0.0;
00183 result->_inskin = false;
00184 result->_bone = 0;
00185 result->_node = 0;
00186 result->_egg_joint = joint;
00187 result->_parent = parent;
00188 if (parent) parent->_children.push_back(result);
00189 _joint_tab[joint] = result;
00190 return result;
00191 }
00192
00193 MaxEggJoint *MaxEggJoint::ChooseBestChild(LVector3d dir)
00194 {
00195 if (dir.length() < 0.001) return 0;
00196 dir.normalize();
00197 double firstbest = -1000;
00198 MaxEggJoint *firstchild = 0;
00199 LVector3d firstpos = GetPos();
00200 double secondbest = 0;
00201 for (int i=0; i<_children.size(); i++) {
00202 MaxEggJoint *child = _children[i];
00203 LVector3d tryfwd = child->GetPos() - GetPos();
00204 if ((child->GetPos() != firstpos) && (tryfwd.length() > 0.001)) {
00205 LVector3d trydir = tryfwd;
00206 trydir.normalize();
00207 double quality = trydir.dot(dir);
00208 if (quality > firstbest) {
00209 secondbest = firstbest;
00210 firstbest = quality;
00211 firstpos = child->GetPos();
00212 firstchild = child;
00213 } else if (quality > secondbest) {
00214 secondbest = quality;
00215 }
00216 }
00217 }
00218 if (firstbest > secondbest + 0.1)
00219 return firstchild;
00220 return 0;
00221 }
00222
00223 void MaxEggJoint::ChooseEndPos(double thickness)
00224 {
00225 LVector3d parentpos(0,0,0);
00226 LVector3d parentendpos(0,0,1);
00227 if (_parent) {
00228 parentpos = _parent->GetPos();
00229 parentendpos = _parent->_endpos;
00230 }
00231 LVector3d fwd = GetPos() - parentpos;
00232 if (fwd.length() < 0.001) {
00233 fwd = parentendpos - parentpos;
00234 }
00235 fwd.normalize();
00236 MaxEggJoint *child = ChooseBestChild(fwd);
00237 if (child == 0) {
00238 _endpos = fwd * thickness * 0.8 + GetPos();
00239 _thickness = thickness * 0.8;
00240 } else {
00241 _endpos = child->GetPos();
00242 _thickness = (_endpos - GetPos()).length();
00243 if (_thickness > thickness) _thickness = thickness;
00244 }
00245 LVector3d orient = _endpos - GetPos();
00246 orient.normalize();
00247 LVector3d altaxis = orient.cross(LVector3d(0,-1,0));
00248 if (altaxis.length() < 0.001) altaxis = orient.cross(LVector3d(0,0,1));
00249 _perp = altaxis.cross(orient);
00250 _perp.normalize();
00251 }
00252
00253 void MaxEggJoint::CreateMaxBone(void)
00254 {
00255 LVector3d rxv,ryv,rzv;
00256 GetRotation(rxv, ryv, rzv);
00257 Point3 xv(MakeMaxPoint(rxv));
00258 Point3 yv(MakeMaxPoint(ryv));
00259 Point3 zv(MakeMaxPoint(rzv));
00260 Point3 pos(MakeMaxPoint(GetPos()));
00261 Point3 endpos(MakeMaxPoint(_endpos));
00262 Point3 tzv(MakeMaxPoint(_perp));
00263
00264 Point3 fwd = endpos - pos;
00265 double len = fwd.Length();
00266 Point3 txv = fwd * ((PN_stdfloat)(1.0/len));
00267 Point3 tyv = tzv ^ txv;
00268 Point3 row1 = Point3(txv % xv, txv % yv, txv % zv);
00269 Point3 row2 = Point3(tyv % xv, tyv % yv, tyv % zv);
00270 Point3 row3 = Point3(tzv % xv, tzv % yv, tzv % zv);
00271 Matrix3 oomat(row1,row2,row3,Point3(0,0,0));
00272 Quat ooquat(oomat);
00273 _bone = (SimpleObject2*)CreateInstance(GEOMOBJECT_CLASS_ID, BONE_OBJ_CLASSID);
00274 _node = GetCOREInterface()->CreateObjectNode(_bone);
00275 _node->SetNodeTM(0, Matrix3(xv, yv, zv, pos));
00276 IParamBlock2 *blk = _bone->pblock2;
00277 for (int i=0; i<blk->NumParams(); i++) {
00278 TSTR n = blk->GetLocalName(i);
00279 if (strcmp(n, "Length")==0) blk->SetValue(i,0,(PN_stdfloat)len);
00280 else if (strcmp(n, "Width")==0) blk->SetValue(i,0,(PN_stdfloat)_thickness);
00281 else if (strcmp(n, "Height")==0) blk->SetValue(i,0,(PN_stdfloat)_thickness);
00282 }
00283 Point3 boneColor = GetUIColor(COLOR_BONES);
00284 _node->SetWireColor(RGB(int(boneColor.x*255.0f), int(boneColor.y*255.0f), int(boneColor.z*255.0f) ));
00285 _node->SetBoneNodeOnOff(TRUE, 0);
00286 _node->SetRenderable(FALSE);
00287 _node->SetName((TCHAR*)(_egg_joint->get_name().c_str()));
00288 _node->SetObjOffsetRot(ooquat);
00289 if (_parent) {
00290 _node->Detach(0, 1);
00291 _parent->_node->AttachChild(_node, 1);
00292 }
00293 }
00294
00295
00296
00297
00298
00299
00300
00301 typedef pair<double, EggGroup *> MaxEggWeight;
00302
00303 struct MaxEggVertex
00304 {
00305 LVertexd _pos;
00306 LNormald _normal;
00307 vector<MaxEggWeight> _weights;
00308 int _index;
00309 };
00310
00311 struct MEV_Compare: public stl_hash_compare<MaxEggVertex>
00312 {
00313 size_t operator()(const MaxEggVertex &key) const
00314 {
00315 return key._pos.add_hash(key._normal.get_hash());
00316 }
00317 bool operator()(const MaxEggVertex &k1, const MaxEggVertex &k2) const
00318 {
00319 int n = k1._pos.compare_to(k2._pos);
00320 if (n < 0) return true;
00321 if (n > 0) return false;
00322 n = k1._normal.compare_to(k2._normal);
00323 if (n < 0) return true;
00324 if (n > 0) return false;
00325 n = k1._weights.size() - k2._weights.size();
00326 if (n < 0) return true;
00327 if (n > 0) return false;
00328 for (int i=0; i<k1._weights.size(); i++) {
00329 double d = k1._weights[i].first - k2._weights[i].first;
00330 if (d < 0) return true;
00331 if (d > 0) return false;
00332 EggGroup *g1 = k1._weights[i].second;
00333 EggGroup *g2 = k2._weights[i].second;
00334 if (g1 < g2) return true;
00335 if (g1 > g2) return false;
00336 }
00337 return false;
00338 }
00339 };
00340
00341 typedef phash_set<MaxEggVertex, MEV_Compare> VertTable;
00342 typedef phash_map<LTexCoordd, int> TVertTable;
00343 typedef phash_map<LColor, int> CVertTable;
00344
00345 class MaxEggMesh
00346 {
00347 public:
00348
00349 string _name;
00350 TriObject *_obj;
00351 Mesh *_mesh;
00352 INode *_node;
00353 IDerivedObject *_dobj;
00354 Modifier *_skin_mod;
00355 ISkin *_iskin;
00356 ISkinImportData *_iskin_import;
00357 int _vert_count;
00358 int _tvert_count;
00359 int _cvert_count;
00360 int _face_count;
00361
00362 VertTable _vert_tab;
00363 TVertTable _tvert_tab;
00364 CVertTable _cvert_tab;
00365
00366 int GetVert(EggVertex *vert, EggGroup *context);
00367 int GetTVert(const LTexCoordd &uv);
00368 int GetCVert(const LColor &col);
00369 int AddFace(int v0, int v1, int v2, int tv0, int tv1, int tv2, int cv0, int cv1, int cv2, int tex);
00370 EggGroup *GetControlJoint(void);
00371 };
00372
00373 #define CTRLJOINT_DEFORM ((EggGroup*)((char*)(-1)))
00374
00375 int MaxEggMesh::GetVert(EggVertex *vert, EggGroup *context)
00376 {
00377 MaxEggVertex vtx;
00378 vtx._pos = vert->get_pos3();
00379 vtx._normal = vert->get_normal();
00380 vtx._index = 0;
00381
00382 EggVertex::GroupRef::const_iterator gri;
00383 for (gri = vert->gref_begin(); gri != vert->gref_end(); ++gri) {
00384 EggGroup *egg_joint = (*gri);
00385 double membership = egg_joint->get_vertex_membership(vert);
00386 vtx._weights.push_back(MaxEggWeight(membership, egg_joint));
00387 }
00388 if (vtx._weights.size()==0) {
00389 if (context != 0)
00390 vtx._weights.push_back(MaxEggWeight(1.0, context));
00391 }
00392
00393 VertTable::const_iterator vti = _vert_tab.find(vtx);
00394 if (vti != _vert_tab.end())
00395 return vti->_index;
00396
00397 if (_vert_count == _mesh->numVerts) {
00398 int nsize = _vert_count*2 + 100;
00399 _mesh->setNumVerts(nsize, _vert_count?TRUE:FALSE);
00400 }
00401 vtx._index = _vert_count++;
00402 _vert_tab.insert(vtx);
00403 _mesh->setVert(vtx._index, MakeMaxPoint(vtx._pos));
00404 return vtx._index;
00405 }
00406
00407 int MaxEggMesh::GetTVert(const LTexCoordd &uv)
00408 {
00409 if (_tvert_tab.count(uv))
00410 return _tvert_tab[uv];
00411 if (_tvert_count == _mesh->numTVerts) {
00412 int nsize = _tvert_count*2 + 100;
00413 _mesh->setNumTVerts(nsize, _tvert_count?TRUE:FALSE);
00414 }
00415 int idx = _tvert_count++;
00416 _mesh->setTVert(idx, uv.get_x(), uv.get_y(), 0.0);
00417 _tvert_tab[uv] = idx;
00418 return idx;
00419 }
00420
00421 int MaxEggMesh::GetCVert(const LColor &col)
00422 {
00423 if (_cvert_tab.count(col))
00424 return _cvert_tab[col];
00425 if (_cvert_count == _mesh->numCVerts) {
00426 int nsize = _cvert_count*2 + 100;
00427 _mesh->setNumVertCol(nsize, _cvert_count?TRUE:FALSE);
00428 }
00429 int idx = _cvert_count++;
00430 _mesh->vertCol[idx] = Point3(col.get_x(), col.get_y(), col.get_z());
00431 _cvert_tab[col] = idx;
00432 return idx;
00433 }
00434
00435 MaxEggMesh *MaxEggLoader::GetMesh(EggVertexPool *pool)
00436 {
00437 MaxEggMesh *result = _mesh_tab[pool];
00438 if (result == 0) {
00439 string name = pool->get_name();
00440 int nsize = name.size();
00441 if ((nsize > 6) && (name.rfind(".verts")==(nsize-6)))
00442 name.resize(nsize-6);
00443 result = new MaxEggMesh;
00444 result->_name = name;
00445 result->_obj = CreateNewTriObject();
00446 result->_mesh = &result->_obj->GetMesh();
00447 result->_mesh->setMapSupport(0, TRUE);
00448 result->_node = GetCOREInterface()->CreateObjectNode(result->_obj);
00449 result->_dobj = 0;
00450 result->_skin_mod = 0;
00451 result->_iskin = 0;
00452 result->_iskin_import = 0;
00453 result->_vert_count = 0;
00454 result->_tvert_count = 0;
00455 result->_cvert_count = 0;
00456 result->_face_count = 0;
00457 result->_node->SetName((TCHAR*)(name.c_str()));
00458 _mesh_tab[pool] = result;
00459 }
00460 return result;
00461 }
00462
00463 int MaxEggMesh::AddFace(int v0, int v1, int v2, int tv0, int tv1, int tv2, int cv0, int cv1, int cv2, int tex)
00464 {
00465 static int dump = 0;
00466 if (_face_count == _mesh->numFaces) {
00467 int nsize = _face_count*2 + 100;
00468 BOOL keep = _mesh->numFaces ? TRUE:FALSE;
00469 _mesh->setNumFaces(nsize, keep);
00470 _mesh->setNumTVFaces(nsize, keep, _face_count);
00471 _mesh->setNumVCFaces(nsize, keep, _face_count);
00472 }
00473 int idx = _face_count++;
00474 _mesh->faces[idx].setVerts(v0,v1,v2);
00475 _mesh->faces[idx].smGroup = 1;
00476 _mesh->faces[idx].flags = EDGE_ALL | HAS_TVERTS;
00477 _mesh->faces[idx].setMatID(tex);
00478 _mesh->tvFace[idx].setTVerts(tv0,tv1,tv2);
00479 _mesh->vcFace[idx].setTVerts(cv0,cv1,cv2);
00480 return idx;
00481 }
00482
00483 EggGroup *MaxEggMesh::GetControlJoint(void)
00484 {
00485 EggGroup *result;
00486 VertTable::const_iterator vert = _vert_tab.begin();
00487 if (vert == _vert_tab.end()) return 0;
00488 switch (vert->_weights.size()) {
00489 case 0:
00490 for (++vert; vert != _vert_tab.end(); ++vert)
00491 if (vert->_weights.size() != 0)
00492 return CTRLJOINT_DEFORM;
00493 return 0;
00494 case 1:
00495 result = vert->_weights[0].second;
00496 for (++vert; vert != _vert_tab.end(); ++vert)
00497 if ((vert->_weights.size() != 1) || (vert->_weights[0].second != result))
00498 return CTRLJOINT_DEFORM;
00499 return result;
00500 default:
00501 return CTRLJOINT_DEFORM;
00502 }
00503 }
00504
00505 void MaxEggLoader::CreateSkinModifier(MaxEggMesh *M)
00506 {
00507 vector <MaxEggJoint *> joints;
00508
00509 M->_dobj = CreateDerivedObject(M->_obj);
00510 M->_node->SetObjectRef(M->_dobj);
00511 M->_skin_mod = (Modifier*)CreateInstance(OSM_CLASS_ID, SKIN_CLASSID);
00512 M->_iskin = (ISkin*)M->_skin_mod->GetInterface(I_SKIN);
00513 M->_iskin_import = (ISkinImportData*)M->_skin_mod->GetInterface(I_SKINIMPORTDATA);
00514 M->_dobj->SetAFlag(A_LOCK_TARGET);
00515 M->_dobj->AddModifier(M->_skin_mod);
00516 M->_dobj->ClearAFlag(A_LOCK_TARGET);
00517 GetCOREInterface()->ForceCompleteRedraw();
00518
00519 VertTable::const_iterator vert;
00520 for (vert=M->_vert_tab.begin(); vert != M->_vert_tab.end(); ++vert) {
00521 for (int i=0; i<vert->_weights.size(); i++) {
00522 double strength = vert->_weights[i].first;
00523 MaxEggJoint *joint = FindJoint(vert->_weights[i].second);
00524 if (!joint->_inskin) {
00525 joint->_inskin = true;
00526 joints.push_back(joint);
00527 }
00528 }
00529 }
00530 for (int i=0; i<joints.size(); i++) {
00531 BOOL last = (i == (joints.size()-1)) ? TRUE : FALSE;
00532 M->_iskin_import->AddBoneEx(joints[i]->_node, last);
00533 joints[i]->_inskin = false;
00534 }
00535
00536 GetCOREInterface()->SetCommandPanelTaskMode(TASK_MODE_MODIFY);
00537 GetCOREInterface()->SelectNode(M->_node);
00538 GetCOREInterface()->ForceCompleteRedraw();
00539
00540 for (vert=M->_vert_tab.begin(); vert != M->_vert_tab.end(); ++vert) {
00541 Tab<INode*> maxJoints;
00542 Tab<PN_stdfloat> maxWeights;
00543 maxJoints.ZeroCount();
00544 maxWeights.ZeroCount();
00545 for (int i=0; i<vert->_weights.size(); i++) {
00546 PN_stdfloat strength = (PN_stdfloat)(vert->_weights[i].first);
00547 MaxEggJoint *joint = FindJoint(vert->_weights[i].second);
00548 maxWeights.Append(1,&strength);
00549 maxJoints.Append(1,&(joint->_node));
00550 }
00551 M->_iskin_import->AddWeights(M->_node, vert->_index, maxJoints, maxWeights);
00552 }
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564 void MaxEggLoader::TraverseEggNode(EggNode *node, EggGroup *context)
00565 {
00566 vector<int> vertIndices;
00567 vector<int> tvertIndices;
00568 vector<int> cvertIndices;
00569
00570 if (node->is_of_type(EggPolygon::get_class_type())) {
00571 EggPolygon *poly = DCAST(EggPolygon, node);
00572
00573 int texid;
00574 LMatrix3d uvtrans = LMatrix3d::ident_mat();
00575 if (poly->has_texture()) {
00576 EggTexture *tex = poly->get_texture(0);
00577 texid = GetTex(tex->get_fullpath().to_os_specific())->_id;
00578 if (tex->has_transform())
00579 uvtrans = tex->get_transform2d();
00580 } else {
00581 texid = GetTex("")->_id;
00582 }
00583
00584 EggPolygon::const_iterator ci;
00585 MaxEggMesh *mesh = GetMesh(poly->get_pool());
00586 vertIndices.clear();
00587 tvertIndices.clear();
00588 cvertIndices.clear();
00589 for (ci = poly->begin(); ci != poly->end(); ++ci) {
00590 EggVertex *vtx = (*ci);
00591 EggVertexPool *pool = poly->get_pool();
00592 LTexCoordd uv = vtx->get_uv();
00593 vertIndices.push_back(mesh->GetVert(vtx, context));
00594 tvertIndices.push_back(mesh->GetTVert(uv * uvtrans));
00595 cvertIndices.push_back(mesh->GetCVert(vtx->get_color()));
00596 }
00597 for (int i=1; i<vertIndices.size()-1; i++)
00598 mesh->AddFace(vertIndices[0], vertIndices[i], vertIndices[i+1],
00599 tvertIndices[0], tvertIndices[i], tvertIndices[i+1],
00600 cvertIndices[0], cvertIndices[i], cvertIndices[i+1],
00601 texid);
00602 } else if (node->is_of_type(EggGroupNode::get_class_type())) {
00603 EggGroupNode *group = DCAST(EggGroupNode, node);
00604 if (node->is_of_type(EggGroup::get_class_type())) {
00605 EggGroup *group = DCAST(EggGroup, node);
00606 if (group->is_joint()) {
00607 MakeJoint(group, context);
00608 context = group;
00609 }
00610 }
00611 EggGroupNode::const_iterator ci;
00612 for (ci = group->begin(); ci != group->end(); ++ci) {
00613 TraverseEggNode(*ci, context);
00614 }
00615 }
00616 }
00617
00618 bool MaxEggLoader::ConvertEggData(EggData *data, bool merge, bool model, bool anim)
00619 {
00620 if (!merge) {
00621 maxloader_cat.error() << "Currently, only 'merge' mode is implemented.\n";
00622 return false;
00623 }
00624
00625 if ((anim) || (!model)) {
00626 maxloader_cat.error() << "Currently, only model-loading is implemented.\n";
00627 return false;
00628 }
00629
00630 MeshIterator ci;
00631 JointIterator ji;
00632 TexIterator ti;
00633
00634 data->set_coordinate_system(CS_zup_right);
00635
00636 SuspendAnimate();
00637 SuspendSetKeyMode();
00638 AnimateOff();
00639 _next_tex = 0;
00640
00641 TraverseEggNode(data, NULL);
00642
00643 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
00644 MaxEggMesh *mesh = (*ci);
00645 mesh->_mesh->setNumVerts(mesh->_vert_count, TRUE);
00646 mesh->_mesh->setNumTVerts(mesh->_tvert_count, TRUE);
00647 mesh->_mesh->setNumVertCol(mesh->_cvert_count, TRUE);
00648 mesh->_mesh->setNumFaces(mesh->_face_count, TRUE);
00649 mesh->_mesh->setNumTVFaces(mesh->_face_count, TRUE, mesh->_face_count);
00650 mesh->_mesh->setNumVCFaces(mesh->_face_count, TRUE, mesh->_face_count);
00651 mesh->_mesh->InvalidateTopologyCache();
00652 mesh->_mesh->InvalidateGeomCache();
00653 mesh->_mesh->buildNormals();
00654 }
00655
00656 double thickness = 0.0;
00657 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) {
00658 double dfo = ((*ji)->GetPos()).length();
00659 if (dfo > thickness) thickness = dfo;
00660 }
00661 thickness = thickness * 0.025;
00662 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) {
00663 MaxEggJoint *joint = *ji;
00664 joint->ChooseEndPos(thickness);
00665 joint->CreateMaxBone();
00666 }
00667
00668 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
00669 MaxEggMesh *mesh = (*ci);
00670 EggGroup *joint = mesh->GetControlJoint();
00671 if (joint) CreateSkinModifier(mesh);
00672 }
00673
00674 if (_next_tex) {
00675 TSTR name;
00676 MultiMtl *mtl = NewDefaultMultiMtl();
00677 mtl->SetNumSubMtls(_next_tex);
00678 for (ti = _tex_tab.begin(); ti != _tex_tab.end(); ++ti) {
00679 MaxEggTex *tex = *ti;
00680 mtl->SetSubMtlAndName(tex->_id, tex->_mat, name);
00681 }
00682 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
00683 MaxEggMesh *mesh = *ci;
00684 mesh->_node->SetMtl(mtl);
00685 }
00686 }
00687
00688 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) delete *ci;
00689 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) delete *ji;
00690 for (ti = _tex_tab.begin(); ti != _tex_tab.end(); ++ti) delete *ti;
00691
00692 ResumeSetKeyMode();
00693 ResumeAnimate();
00694
00695 maxloader_cat.info() << "Egg import successful\n";
00696 return true;
00697 }
00698
00699 bool MaxEggLoader::ConvertEggFile(const char *name, bool merge, bool model, bool anim)
00700 {
00701 EggData data;
00702 Filename datafn = Filename::from_os_specific(name);
00703 if (!data.read(datafn)) {
00704 maxloader_cat.error() << "Cannot read Egg file for import\n";
00705 return false;
00706 }
00707 return ConvertEggData(&data, merge, model, anim);
00708 }
00709
00710
00711
00712
00713
00714
00715
00716 bool MaxLoadEggData(EggData *data, bool merge, bool model, bool anim)
00717 {
00718 MaxEggLoader loader;
00719 return loader.ConvertEggData(data, merge, model, anim);
00720 }
00721
00722 bool MaxLoadEggFile(const char *name, bool merge, bool model, bool anim)
00723 {
00724 MaxEggLoader loader;
00725 return loader.ConvertEggFile(name, merge, model, anim);
00726 }
00727