Panda3D
 All Classes Functions Variables Enumerations
maxEggLoader.cxx
00001 // Filename: maxEggImport.cxx
00002 // Created by:  jyelon (15Jul05)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 //
00015 // This file contains the code for class MaxEggLoader.  This class
00016 // does the actual work of copying an EggData tree into the max scene.
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 // MaxEggTex
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 // MaxEggJoint
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 // MaxEggMesh
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 // TraverseEggData
00558 //
00559 // We have an EggData in memory, and now we're going to copy that
00560 // over into the max scene graph.
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 // The two global functions that form the API of this module.
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 
 All Classes Functions Variables Enumerations