Panda3D
|
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