Panda3D
|
00001 // Filename: mayaEggImport.cxx 00002 // Created by: jyelon (20Jul05) 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 MayaEggLoader. This class 00016 // does the actual work of copying an EggData tree into the maya scene. 00017 // 00018 //////////////////////////////////////////////////////////////////// 00019 00020 00021 #include "pandatoolbase.h" 00022 #include "notifyCategoryProxy.h" 00023 00024 #include "eggBin.h" 00025 #include "eggData.h" 00026 #include "eggTable.h" 00027 #include "eggVertex.h" 00028 #include "eggPolygon.h" 00029 #include "eggComment.h" 00030 #include "eggXfmSAnim.h" 00031 #include "eggSAnimData.h" 00032 #include "eggPrimitive.h" 00033 #include "eggGroupNode.h" 00034 #include "eggVertexPool.h" 00035 #include "eggPolysetMaker.h" 00036 #include "eggNurbsSurface.h" 00037 #include "texture.h" 00038 #include "texturePool.h" 00039 00040 #include "pre_maya_include.h" 00041 #include <maya/MStatus.h> 00042 #include <maya/MPxCommand.h> 00043 #include <maya/MString.h> 00044 #include <maya/MStringArray.h> 00045 #include <maya/MArgList.h> 00046 #include <maya/MGlobal.h> 00047 #include <maya/MObject.h> 00048 #include <maya/MFloatPoint.h> 00049 #include <maya/MFloatPointArray.h> 00050 #include <maya/MFloatArray.h> 00051 #include <maya/MPointArray.h> 00052 #include <maya/MFnMesh.h> 00053 #include <maya/MFnDependencyNode.h> 00054 #include <maya/MFnTransform.h> 00055 #include <maya/MFnLambertShader.h> 00056 #include <maya/MPlug.h> 00057 #include <maya/MFnSet.h> 00058 #include <maya/MDGModifier.h> 00059 #include <maya/MSelectionList.h> 00060 #include <maya/MDagPath.h> 00061 #include <maya/MFnSingleIndexedComponent.h> 00062 #include <maya/MFnDoubleIndexedComponent.h> 00063 #include <maya/MPlugArray.h> 00064 #include <maya/MDagPathArray.h> 00065 #include <maya/MMatrix.h> 00066 #include <maya/MTransformationMatrix.h> 00067 #include <maya/MFnIkJoint.h> 00068 #include <maya/MFnSkinCluster.h> 00069 #include <maya/MAnimControl.h> 00070 #include <maya/MFnAnimCurve.h> 00071 #include <maya/MFnNurbsSurface.h> 00072 #include <maya/MFnEnumAttribute.h> 00073 #include <maya/MFnSet.h> 00074 #include "post_maya_include.h" 00075 00076 #include "mayaEggLoader.h" 00077 00078 class MayaEggGroup; 00079 class MayaEggGeom; 00080 class MayaEggMesh; 00081 class MayaEggJoint; 00082 class MayaEggTex; 00083 class MayaAnim; 00084 class MayaEggNurbsSurface; 00085 00086 NotifyCategoryDeclNoExport(mayaloader); 00087 NotifyCategoryDef(mayaloader, ""); 00088 00089 class MayaEggLoader 00090 { 00091 public: 00092 bool ConvertEggData(EggData *data, bool merge, bool model, bool anim, bool respect_normals); 00093 bool ConvertEggFile(const char *name, bool merge, bool model, bool anim, bool respect_normals); 00094 00095 00096 public: 00097 void TraverseEggNode(EggNode *node, EggGroup *context, string delim); 00098 MayaEggMesh *GetMesh(EggVertexPool *pool, EggGroup *parent); 00099 MayaEggJoint *FindJoint(EggGroup *joint); 00100 MayaEggJoint *MakeJoint(EggGroup *joint, EggGroup *context); 00101 MayaEggGroup *FindGroup(EggGroup *group); 00102 MayaEggGroup *MakeGroup(EggGroup *group, EggGroup *context); 00103 MayaEggTex *GetTex(EggTexture *etex); 00104 void CreateSkinCluster(MayaEggGeom *M); 00105 00106 MayaAnim *GetAnim(EggXfmSAnim *pool); 00107 MObject GetDependencyNode(string givenName); 00108 00109 MayaEggNurbsSurface *GetSurface(EggVertexPool *pool, EggGroup *parent); 00110 00111 typedef phash_map<EggGroup *, MayaEggMesh *, pointer_hash> MeshTable; 00112 typedef phash_map<EggXfmSAnim *, MayaAnim *, pointer_hash> AnimTable; 00113 typedef phash_map<EggGroup *, MayaEggJoint *, pointer_hash> JointTable; 00114 typedef phash_map<EggGroup *, MayaEggGroup *, pointer_hash> GroupTable; 00115 typedef phash_map<string, MayaEggTex *, string_hash> TexTable; 00116 typedef phash_map<EggGroup *, MayaEggNurbsSurface *, pointer_hash> SurfaceTable; 00117 00118 MeshTable _mesh_tab; 00119 AnimTable _anim_tab; 00120 JointTable _joint_tab; 00121 GroupTable _group_tab; 00122 TexTable _tex_tab; 00123 SurfaceTable _surface_tab; 00124 00125 vector <MayaEggJoint *> _joint_list; 00126 00127 int _start_frame; 00128 int _end_frame; 00129 int _frame_rate; 00130 MTime::Unit _timeUnit; 00131 00132 void ParseFrameInfo(string comment); 00133 void PrintData(MayaEggMesh *mesh); 00134 00135 private: 00136 int _unnamed_idx; 00137 MSelectionList _collision_nodes; 00138 }; 00139 00140 MPoint MakeMPoint(const LVector3d &vec) 00141 { 00142 return MPoint(vec[0], vec[1], vec[2]); 00143 } 00144 00145 MFloatPoint MakeMayaPoint(const LVector3d &vec) 00146 { 00147 return MFloatPoint(vec[0], vec[1], vec[2]); 00148 } 00149 00150 MVector MakeMayaVector(const LVector3d &vec) 00151 { 00152 return MVector(vec[0], vec[1], vec[2]); 00153 } 00154 00155 MColor MakeMayaColor(const LColor &vec) 00156 { 00157 return MColor(vec[0], vec[1], vec[2], vec[3]); 00158 } 00159 00160 // [gjeon] to create enum attribute, 00161 // fieldNames is a stringArray of enum names, and filedIndex is the default index value 00162 MStatus create_enum_attribute(MObject &node, MString fullName, MString briefName, 00163 MStringArray fieldNames, unsigned fieldIndex) { 00164 MStatus stat; 00165 00166 MFnDependencyNode fnDN( node, &stat ); 00167 if ( MS::kSuccess != stat ) { 00168 mayaloader_cat.error() 00169 << "Could not create MFnDependencyNode" << "\n"; 00170 return stat; 00171 } 00172 00173 MFnEnumAttribute fnAttr; 00174 MObject newAttr = fnAttr.create( fullName, briefName, 00175 0, &stat ); 00176 if ( MS::kSuccess != stat ) { 00177 mayaloader_cat.error() 00178 << "Could not create new enum attribute " << fullName << "\n"; 00179 return stat; 00180 } 00181 for (unsigned i = 0; i < fieldNames.length(); i++){ 00182 fnAttr.addField(fieldNames[i], i); 00183 } 00184 00185 stat = fnAttr.setDefault(fieldIndex); 00186 if ( MS::kSuccess != stat ) { 00187 mayaloader_cat.error() 00188 << "Could not set value for enum attribute " << fullName << "\n"; 00189 return stat; 00190 } 00191 00192 fnAttr.setKeyable( true ); 00193 fnAttr.setReadable( true ); 00194 fnAttr.setWritable( true ); 00195 fnAttr.setStorable( true ); 00196 00197 // Now add the new attribute to this dependency node 00198 stat = fnDN.addAttribute(newAttr,MFnDependencyNode::kLocalDynamicAttr); 00199 if ( MS::kSuccess != stat ) { 00200 mayaloader_cat.error() 00201 << "Could not add new enum attribute " << fullName << "\n"; 00202 return stat; 00203 } 00204 00205 return stat; 00206 } 00207 00208 //////////////////////////////////////////////////////////////////////////////////////////////////// 00209 // 00210 // MayaEggTex 00211 // 00212 //////////////////////////////////////////////////////////////////////////////////////////////////// 00213 00214 class MayaEggTex 00215 { 00216 public: 00217 string _name; 00218 string _path; 00219 MObject _file_texture; 00220 MObject _shader; 00221 MObject _shading_group; 00222 00223 MFnSingleIndexedComponent _component; 00224 void AssignNames(void); 00225 }; 00226 00227 void MayaEggTex::AssignNames(void) 00228 { 00229 if (_name == "") { 00230 return; 00231 } 00232 MFnDependencyNode shader(_shader); 00233 MFnDependencyNode sgroup(_shading_group); 00234 MFnDependencyNode filetex(_file_texture); 00235 shader.setName(MString(_name.c_str())+"Shader"); 00236 sgroup.setName(MString(_name.c_str())); 00237 if (_file_texture != MObject::kNullObj) { 00238 filetex.setName(MString(_name.c_str())+"File"); 00239 } 00240 } 00241 00242 MayaEggTex *MayaEggLoader::GetTex(EggTexture* etex) 00243 { 00244 string name = ""; 00245 string fn = ""; 00246 if (etex != NULL) { 00247 name = etex->get_name(); 00248 fn = etex->get_fullpath().to_os_specific(); 00249 } 00250 00251 if (_tex_tab.count(fn)) { 00252 return _tex_tab[fn]; 00253 } 00254 00255 MStatus status; 00256 MFnLambertShader shader; 00257 MFnDependencyNode filetex; 00258 MFnSet sgroup; 00259 MPlugArray oldplugs; 00260 MDGModifier dgmod; 00261 00262 /* 00263 if (fn=="") { 00264 MSelectionList selection; 00265 MObject initGroup; 00266 selection.clear(); 00267 MGlobal::getSelectionListByName("initialShadingGroup",selection); 00268 selection.getDependNode(0, initGroup); 00269 sgroup.setObject(initGroup); 00270 } else { 00271 */ 00272 if (1) { 00273 shader.create(true,&status); 00274 MColor firstColor(1.0,1.0,1.0,1.0); 00275 status = shader.setColor(firstColor); 00276 if (status != MStatus::kSuccess) { 00277 mayaloader_cat.error() << "setColor failed on LambertShader\n"; 00278 status.perror("shader setColor failed!"); 00279 } 00280 sgroup.create(MSelectionList(), MFnSet::kRenderableOnly, &status); 00281 MPlug surfplug = sgroup.findPlug("surfaceShader"); 00282 if (surfplug.connectedTo(oldplugs,true,false)) { 00283 for (unsigned int i=0; i<oldplugs.length(); i++) { 00284 MPlug src = oldplugs[i]; 00285 status = dgmod.disconnect(src, surfplug); 00286 if (status != MStatus::kSuccess) { 00287 status.perror("Disconnecting old shader"); 00288 } 00289 } 00290 } 00291 status = dgmod.connect(shader.findPlug("outColor"),surfplug); 00292 if (status != MStatus::kSuccess) { 00293 status.perror("Connecting shader"); 00294 } 00295 if (fn != "") { 00296 filetex.create("file",&status); 00297 MString fn_str(fn.c_str()); 00298 filetex.findPlug("fileTextureName").setValue(fn_str); 00299 dgmod.connect(filetex.findPlug("outColor"),shader.findPlug("color")); 00300 00301 // [gjeon] to create alpha channel connection 00302 LoaderOptions options; 00303 PT(Texture) tex = TexturePool::load_texture(etex->get_fullpath(), 0, false, options); 00304 if (((tex != NULL) && (tex->get_num_components() == 4)) 00305 || (etex->get_format() == EggTexture::F_alpha) 00306 || (etex->get_format() == EggTexture::F_luminance_alpha)) 00307 dgmod.connect(filetex.findPlug("outTransparency"),shader.findPlug("transparency")); 00308 } 00309 status = dgmod.doIt(); 00310 if (status != MStatus::kSuccess) { 00311 status.perror("DGMod doIt"); 00312 } 00313 } 00314 00315 MayaEggTex *res = new MayaEggTex; 00316 res->_name = name; 00317 res->_path = fn; 00318 res->_file_texture = filetex.object(); 00319 res->_shader = shader.object(); 00320 res->_shading_group = sgroup.object(); 00321 00322 _tex_tab[fn] = res; 00323 return res; 00324 } 00325 00326 //////////////////////////////////////////////////////////////////////////////////////////////////// 00327 // 00328 // MayaEggGroup 00329 // 00330 //////////////////////////////////////////////////////////////////////////////////////////////////// 00331 00332 class MayaEggGroup 00333 { 00334 public: 00335 string _name; 00336 MObject _parent; 00337 MObject _group; 00338 00339 bool _addedEggFlag; 00340 }; 00341 00342 MayaEggGroup *MayaEggLoader::MakeGroup(EggGroup *group, EggGroup *context) 00343 { 00344 MStatus status; 00345 MayaEggGroup *pg = FindGroup(context); 00346 MayaEggGroup *result = new MayaEggGroup; 00347 MFnDagNode dgn; 00348 00349 MObject parent = MObject::kNullObj; 00350 if (pg) { 00351 parent = pg->_group; 00352 if (mayaloader_cat.is_debug()) { 00353 mayaloader_cat.debug() << "parent (group) :" << ((MFnDagNode)parent).name().asChar() << endl; 00354 } 00355 } 00356 00357 result->_name = group->get_name(); 00358 result->_group = dgn.create("transform", MString(result->_name.c_str()), parent, &status); 00359 result->_addedEggFlag = false; 00360 00361 if (group->get_cs_type() != EggGroup::CST_none) 00362 _collision_nodes.add(result->_group, true); 00363 00364 if (group->has_transform3d()) { 00365 LMatrix4d tMat = group->get_transform3d(); 00366 double matData[4][4] = {{tMat.get_cell(0,0), tMat.get_cell(0,1), tMat.get_cell(0,2), tMat.get_cell(0,3)}, 00367 {tMat.get_cell(1,0), tMat.get_cell(1,1), tMat.get_cell(1,2), tMat.get_cell(1,3)}, 00368 {tMat.get_cell(2,0), tMat.get_cell(2,1), tMat.get_cell(2,2), tMat.get_cell(2,3)}, 00369 {tMat.get_cell(3,0), tMat.get_cell(3,1), tMat.get_cell(3,2), tMat.get_cell(3,3)}}; 00370 MMatrix mat(matData); 00371 00372 MTransformationMatrix matrix = MTransformationMatrix(mat); 00373 MFnTransform tFn = MFnTransform(result->_group, &status); 00374 if (status != MStatus::kSuccess) { 00375 status.perror("MFnTransformNode:create failed!"); 00376 } else { 00377 tFn.set(matrix); 00378 } 00379 } 00380 00381 if (status != MStatus::kSuccess) { 00382 status.perror("MFnDagNode:create failed!"); 00383 } 00384 00385 if ((pg) && (pg->_addedEggFlag == false)){ 00386 // [gjeon] to handle other flags 00387 MStringArray eggFlags; 00388 for (int i = 0; i < context->get_num_object_types(); i++) { 00389 eggFlags.append(MString(context->get_object_type(i).c_str())); 00390 } 00391 00392 for (unsigned i = 0; i < eggFlags.length(); i++) { 00393 MString attrName = "eggObjectTypes"; 00394 attrName += (int)(i + 1); 00395 status = create_enum_attribute(parent, attrName, attrName, eggFlags, i); 00396 if (status != MStatus::kSuccess) { 00397 status.perror("create_enum_attribute failed!"); 00398 } 00399 } 00400 pg->_addedEggFlag = true; 00401 } 00402 00403 _group_tab[group] = result; 00404 return result; 00405 } 00406 00407 MayaEggGroup *MayaEggLoader::FindGroup(EggGroup *group) 00408 { 00409 if (group==0) { 00410 return 0; 00411 } 00412 return _group_tab[group]; 00413 } 00414 00415 //////////////////////////////////////////////////////////////////////////////////////////////////// 00416 // 00417 // MayaEggJoint 00418 // 00419 //////////////////////////////////////////////////////////////////////////////////////////////////// 00420 00421 class MayaEggJoint 00422 { 00423 public: 00424 LMatrix4d _trans; 00425 LVector3d _endpos; 00426 LVector3d _perp; 00427 double _thickness; 00428 MObject _joint; 00429 MMatrix _joint_abs; 00430 MDagPath _joint_dag_path; 00431 bool _inskin; 00432 int _index; 00433 EggGroup *_egg_joint; 00434 EggGroup *_egg_parent; 00435 MayaEggJoint *_parent; 00436 vector <MayaEggJoint *> _children; 00437 00438 public: 00439 void GetRotation(LVector3d &xv, LVector3d &yv, LVector3d &zv); 00440 LVector3d GetPos(void) { return _trans.get_row3(3); } 00441 MayaEggJoint *ChooseBestChild(LVector3d dir); 00442 void ChooseEndPos(double thickness); 00443 void CreateMayaBone(MayaEggGroup *eggParent); 00444 void AssignNames(void); 00445 }; 00446 00447 void MayaEggJoint::GetRotation(LVector3d &xv, LVector3d &yv, LVector3d &zv) 00448 { 00449 xv = _trans.get_row3(0); 00450 yv = _trans.get_row3(1); 00451 zv = _trans.get_row3(2); 00452 xv.normalize(); 00453 yv.normalize(); 00454 zv = xv.cross(yv); 00455 zv.normalize(); 00456 yv = zv.cross(xv); 00457 } 00458 00459 void MayaEggJoint::AssignNames(void) 00460 { 00461 string name = _egg_joint->get_name(); 00462 MFnDependencyNode joint(_joint); 00463 joint.setName(name.c_str()); 00464 if (mayaloader_cat.is_spam()) { 00465 mayaloader_cat.spam() << "joint " << joint.name().asChar() << ": -> " << name << endl; 00466 } 00467 } 00468 00469 MayaEggJoint *MayaEggLoader::FindJoint(EggGroup *joint) 00470 { 00471 if (joint==(EggGroup *)NULL) { 00472 if (mayaloader_cat.is_spam()) { 00473 mayaloader_cat.spam() << "joint:" << joint->get_name() << " is null: " << endl; 00474 } 00475 return 0; 00476 } 00477 if (!joint->is_joint()) { 00478 if (mayaloader_cat.is_spam()) { 00479 mayaloader_cat.spam() << "joint:" << joint->get_name() << " is not a joint: " << endl; 00480 } 00481 return 0; 00482 } 00483 return _joint_tab[joint]; 00484 } 00485 00486 MayaEggJoint *MayaEggLoader::MakeJoint(EggGroup *joint, EggGroup *context) 00487 { 00488 MayaEggJoint *parent = FindJoint(context); 00489 if (mayaloader_cat.is_debug()) { 00490 string parent_name = ""; 00491 if (parent) 00492 parent_name = context->get_name(); 00493 } 00494 MayaEggJoint *result = new MayaEggJoint; 00495 LMatrix4d t = joint->get_transform3d(); 00496 if (parent) { 00497 result->_trans = t * parent->_trans; 00498 } else { 00499 result->_trans = t; 00500 } 00501 result->_endpos = LVector3d(0,0,0); 00502 result->_perp = LVector3d(0,0,0); 00503 result->_thickness = 0.0; 00504 result->_egg_joint = joint; 00505 result->_egg_parent = context; 00506 result->_parent = parent; 00507 result->_joint = MObject::kNullObj; 00508 result->_inskin = false; 00509 result->_index = -1; 00510 if (parent) { 00511 parent->_children.push_back(result); 00512 } 00513 _joint_tab[joint] = result; 00514 00515 // [gjeon] since _joint_tab is not always properly sorted 00516 _joint_list.push_back(result); 00517 00518 return result; 00519 } 00520 00521 MayaEggJoint *MayaEggJoint::ChooseBestChild(LVector3d dir) 00522 { 00523 if (dir.length() < 0.001) { 00524 return 0; 00525 } 00526 dir.normalize(); 00527 double firstbest = -1000; 00528 MayaEggJoint *firstchild = 0; 00529 LVector3d firstpos = GetPos(); 00530 double secondbest = 0; 00531 for (unsigned int i=0; i<_children.size(); i++) { 00532 MayaEggJoint *child = _children[i]; 00533 LVector3d tryfwd = child->GetPos() - GetPos(); 00534 if ((child->GetPos() != firstpos) && (tryfwd.length() > 0.001)) { 00535 LVector3d trydir = tryfwd; 00536 trydir.normalize(); 00537 double quality = trydir.dot(dir); 00538 if (quality > firstbest) { 00539 secondbest = firstbest; 00540 firstbest = quality; 00541 firstpos = child->GetPos(); 00542 firstchild = child; 00543 } else if (quality > secondbest) { 00544 secondbest = quality; 00545 } 00546 } 00547 } 00548 if (firstbest > secondbest + 0.1) { 00549 return firstchild; 00550 } 00551 return 0; 00552 } 00553 00554 void MayaEggJoint::ChooseEndPos(double thickness) 00555 { 00556 LVector3d parentpos(0,0,0); 00557 LVector3d parentendpos(0,0,1); 00558 if (_parent) { 00559 parentpos = _parent->GetPos(); 00560 parentendpos = _parent->_endpos; 00561 } 00562 LVector3d fwd = GetPos() - parentpos; 00563 if (fwd.length() < 0.001) { 00564 fwd = parentendpos - parentpos; 00565 } 00566 //mayaloader_cat.debug() << "fwd : " << fwd << endl; 00567 fwd.normalize(); 00568 MayaEggJoint *child = ChooseBestChild(fwd); 00569 if (child == 0) { 00570 _endpos = fwd * thickness * 0.8 + GetPos(); 00571 _thickness = thickness * 0.8; 00572 } else { 00573 _endpos = child->GetPos(); 00574 _thickness = (_endpos - GetPos()).length(); 00575 if (_thickness > thickness) _thickness = thickness; 00576 } 00577 LVector3d orient = _endpos - GetPos(); 00578 orient.normalize(); 00579 LVector3d altaxis = orient.cross(LVector3d(0,-1,0)); 00580 if (altaxis.length() < 0.001) { 00581 altaxis = orient.cross(LVector3d(0,0,1)); 00582 } 00583 _perp = altaxis.cross(orient); 00584 _perp.normalize(); 00585 } 00586 00587 void MayaEggJoint::CreateMayaBone(MayaEggGroup *eggParent) 00588 { 00589 LVector3d rxv, ryv, rzv; 00590 //GetRotation(rxv, ryv, rzv); 00591 // [gjeon] I think we shouldn't need to use this GetRotation function here 00592 // since this function removes scale information from the matrix. 00593 // Let's just use the matrix directly. 00594 rxv = _trans.get_row3(0); 00595 ryv = _trans.get_row3(1); 00596 rzv = _trans.get_row3(2); 00597 00598 MFloatPoint xv(MakeMayaPoint(rxv)); 00599 MFloatPoint yv(MakeMayaPoint(ryv)); 00600 MFloatPoint zv(MakeMayaPoint(rzv)); 00601 MFloatPoint pos(MakeMayaPoint(GetPos())); 00602 MFloatPoint endpos(MakeMayaPoint(_endpos)); 00603 MFloatPoint tzv(MakeMayaPoint(_perp)); 00604 double m[4][4]; 00605 m[0][0]=xv.x; m[0][1]=xv.y; m[0][2]=xv.z; m[0][3]=0; 00606 m[1][0]=yv.x; m[1][1]=yv.y; m[1][2]=yv.z; m[1][3]=0; 00607 m[2][0]=zv.x; m[2][1]=zv.y; m[2][2]=zv.z; m[2][3]=0; 00608 m[3][0]=pos.x; m[3][1]=pos.y; m[3][2]=pos.z; m[3][3]=1; 00609 MMatrix trans(m); 00610 _joint_abs = trans; 00611 if (_parent) { 00612 trans = trans * _parent->_joint_abs.inverse(); 00613 } 00614 MTransformationMatrix mtm(trans); 00615 00616 MFnIkJoint ikj; 00617 if (_parent) { 00618 ikj.create(_parent->_joint); 00619 } 00620 else { 00621 if (eggParent) { 00622 // must be part of a group that is not a joint 00623 ikj.create(eggParent->_group); 00624 } else { 00625 ikj.create(); 00626 } 00627 } 00628 ikj.set(mtm); 00629 00630 _joint = ikj.object(); 00631 ikj.getPath(_joint_dag_path); 00632 } 00633 00634 00635 //////////////////////////////////////////////////////////////////////////////////////////////////// 00636 // 00637 // MayaEggGeom : base abstract class of MayaEggMesh and MayaEggNurbsSurface 00638 // 00639 //////////////////////////////////////////////////////////////////////////////////////////////////// 00640 00641 typedef pair<double, EggGroup *> MayaEggWeight; 00642 00643 struct MayaEggVertex 00644 { 00645 LVertexd _pos; 00646 LNormald _normal; 00647 LTexCoordd _uv; 00648 vector<MayaEggWeight> _weights; 00649 double _sumWeights; // [gjeon] to be used in normalizing weights 00650 int _index; 00651 int _external_index; // masad: use egg's index directly 00652 }; 00653 00654 struct MEV_Compare: public stl_hash_compare<MayaEggVertex> 00655 { 00656 size_t operator()(const MayaEggVertex &key) const 00657 { 00658 return key._pos.add_hash(key._normal.get_hash()); 00659 } 00660 bool operator()(const MayaEggVertex &k1, const MayaEggVertex &k2) const 00661 { 00662 int n = k1._pos.compare_to(k2._pos); 00663 if (n < 0) { 00664 return true; 00665 } 00666 if (n > 0) { 00667 return false; 00668 } 00669 n = k1._normal.compare_to(k2._normal); 00670 if (n < 0) { 00671 return true; 00672 } 00673 if (n > 0) { 00674 return false; 00675 } 00676 n = k1._uv.compare_to(k2._uv); 00677 if (n < 0) { 00678 return true; 00679 } 00680 if (n > 0) { 00681 return false; 00682 } 00683 n = k1._weights.size() - k2._weights.size(); 00684 if (n < 0) { 00685 return true; 00686 } 00687 if (n > 0) { 00688 return false; 00689 } 00690 for (unsigned int i=0; i<k1._weights.size(); i++) { 00691 double d = k1._weights[i].first - k2._weights[i].first; 00692 if (d < 0) { 00693 return true; 00694 } 00695 if (d > 0) { 00696 return false; 00697 } 00698 EggGroup *g1 = k1._weights[i].second; 00699 EggGroup *g2 = k2._weights[i].second; 00700 if (g1 < g2) { 00701 return true; 00702 } 00703 if (g1 > g2) { 00704 return false; 00705 } 00706 } 00707 n = k1._external_index - k2._external_index; 00708 00709 if (n < 0) { 00710 return true; 00711 } 00712 if (n > 0) { 00713 return false; 00714 } 00715 00716 return false; 00717 } 00718 }; 00719 00720 typedef phash_set<MayaEggVertex, MEV_Compare> VertTable; 00721 00722 class MayaEggGeom 00723 { 00724 public: 00725 00726 EggVertexPool *_pool; 00727 MObject _transNode; 00728 MObject _shapeNode; 00729 EggGroup *_parent; 00730 MDagPath _shape_dag_path; 00731 int _vert_count; 00732 00733 string _name; 00734 00735 MFloatPointArray _vertexArray; 00736 MVectorArray _normalArray; 00737 MColorArray _vertColorArray; 00738 MIntArray _vertColorIndices; 00739 MIntArray _vertNormalIndices; 00740 00741 MStringArray _eggObjectTypes; 00742 VertTable _vert_tab; 00743 00744 bool _renameTrans; 00745 00746 int GetVert(EggVertex *vert, EggGroup *context); 00747 EggGroup *GetControlJoint(void); 00748 00749 virtual void ConnectTextures(void) = 0; 00750 void AssignNames(void); 00751 void AddEggFlag(MString); 00752 }; 00753 00754 // [gjeon] moved from MayaEggMesh to MayaEggGeom 00755 int MayaEggGeom::GetVert(EggVertex *vert, EggGroup *context) 00756 { 00757 MayaEggVertex vtx; 00758 vtx._sumWeights = 0.0; 00759 00760 const LMatrix4d &xform = context->get_vertex_to_node(); 00761 00762 vtx._pos = vert->get_pos3() * xform; 00763 if (vert->has_normal()) { 00764 vtx._normal = vert->get_normal() * xform; 00765 } 00766 if (vert->has_uv()) { 00767 vtx._uv = vert->get_uv(); 00768 } 00769 vtx._index = 0; 00770 vtx._external_index = vert->get_index()-1; 00771 00772 EggVertex::GroupRef::const_iterator gri; 00773 //double remaining_weight = 1.0; 00774 for (gri = vert->gref_begin(); gri != vert->gref_end(); ++gri) { 00775 EggGroup *egg_joint = (*gri); 00776 double membership = egg_joint->get_vertex_membership(vert); 00777 00778 if (membership < 0) 00779 { 00780 mayaloader_cat.warning() << "negative weight value " << membership << " is replaced with 0 on: " << context->get_name() << endl; 00781 membership = 0.0; 00782 } 00783 //remaining_weight -= membership; 00784 vtx._weights.push_back(MayaEggWeight(membership, egg_joint)); 00785 vtx._sumWeights += membership; // [gjeon] to be used in normalizing weights 00786 } 00787 00788 if (vtx._weights.size()==0) { 00789 if (context != 0) { 00790 vtx._weights.push_back(MayaEggWeight(1.0, context)); 00791 vtx._sumWeights = 1.0; // [gjeon] to be used in normalizing weights 00792 } 00793 //remaining_weight = 0.0; 00794 }/* else { 00795 // some soft models came up short of 1.0 on vertex membership 00796 // add the remainder of the weight on first joint in the membership 00797 if ((remaining_weight) > 0.01) { 00798 gri = vert->gref_begin(); 00799 EggGroup *egg_joint = (*gri); 00800 double membership = egg_joint->get_vertex_membership(vert); 00801 vtx._weights.push_back(MayaEggWeight(membership+remaining_weight, egg_joint)); 00802 vtx._sumWeights += (membership + remaining_weight); 00803 } 00804 }*/ //[gjeon] we had better nomarlize weights than add remaining weight to first weight 00805 00806 VertTable::const_iterator vti = _vert_tab.find(vtx); 00807 if (vti != _vert_tab.end()) { 00808 /* if ((remaining_weight) > 0.01) { 00809 mayaloader_cat.warning() << "weight munged to 1.0 by " << remaining_weight << " on: " << context->get_name() << " idx:" << vti->_index << endl; 00810 } */ 00811 if (mayaloader_cat.is_spam()) { 00812 ostringstream stream; 00813 stream << "(" << vti->_pos << " " << vti->_normal << " " << vti->_uv << ")\n"; 00814 stream << "[" << vtx._pos << " " << vtx._normal << " " << vtx._uv << "]\n"; 00815 stream << "{" << vert->get_pos3() << " "; 00816 if (vert->has_normal()) { 00817 stream << vert->get_normal() << " "; 00818 } 00819 if (vert->has_uv()) { 00820 stream << vert->get_uv(); 00821 } 00822 stream << "}"; 00823 mayaloader_cat.spam() << "found a matching vertex: " << *vert << endl << stream.str() << endl; 00824 } 00825 return vti->_index; 00826 } 00827 00828 //_vert_count++; 00829 vtx._index = _vert_count++; 00830 /* 00831 if ((remaining_weight) > 0.01) { 00832 mayaloader_cat.warning() << "weight munged to 1.0 by " << remaining_weight << " on: " << context->get_name() << " idx:" << vtx._index << endl; 00833 } */ 00834 00835 _vertexArray.append(MakeMayaPoint(vtx._pos)); 00836 if (vert->has_normal()) { 00837 _normalArray.append(MakeMayaVector(vtx._normal)); 00838 _vertNormalIndices.append(vtx._index); 00839 } 00840 if (vert->has_color()) { 00841 if (mayaloader_cat.is_spam()) { 00842 mayaloader_cat.spam() << "found a vertex color\n"; 00843 } 00844 _vertColorArray.append(MakeMayaColor(vert->get_color())); 00845 _vertColorIndices.append(vtx._index); 00846 } 00847 _vert_tab.insert(vtx); 00848 return vtx._index; 00849 } 00850 00851 // [gjeon] moved from MayaEggMesh to MayaEggGeom 00852 void MayaEggGeom::AssignNames(void) 00853 { 00854 string name = _pool->get_name(); 00855 int nsize = name.size(); 00856 if ((nsize > 6) && (name.rfind(".verts")==(nsize-6))) { 00857 name.resize(nsize-6); 00858 } 00859 if ((nsize > 4) && (name.rfind(".cvs")==(nsize-4))) { 00860 name.resize(nsize-4); 00861 } 00862 00863 MFnDependencyNode dnshape(_shapeNode); 00864 MFnDependencyNode dntrans(_transNode); 00865 00866 if (_renameTrans) { 00867 dntrans.setName(MString(name.c_str())); 00868 } 00869 00870 string shape_name = string(dntrans.name().asChar()); 00871 string numbers ("0123456789"); 00872 size_t found; 00873 00874 found=shape_name.find_last_not_of(numbers); 00875 if (found!=string::npos) 00876 shape_name.insert(found+1, "Shape"); 00877 else 00878 shape_name.append("Shape"); 00879 00880 dnshape.setName(MString(shape_name.c_str())); 00881 } 00882 00883 #define CTRLJOINT_DEFORM ((EggGroup*)((char*)(-1))) 00884 00885 // [gjeon] moved from MayaEggMesh to MayaEggGeom 00886 EggGroup *MayaEggGeom::GetControlJoint(void) 00887 { 00888 EggGroup *result; 00889 VertTable::const_iterator vert = _vert_tab.begin(); 00890 if (vert == _vert_tab.end()) { 00891 return 0; 00892 } 00893 switch (vert->_weights.size()) { 00894 case 0: 00895 for (++vert; vert != _vert_tab.end(); ++vert) { 00896 if (vert->_weights.size() != 0) { 00897 return CTRLJOINT_DEFORM; 00898 } 00899 } 00900 return 0; 00901 case 1: 00902 result = vert->_weights[0].second; 00903 for (++vert; vert != _vert_tab.end(); ++vert) { 00904 if ((vert->_weights.size() != 1) || (vert->_weights[0].second != result)) { 00905 return CTRLJOINT_DEFORM; 00906 } 00907 } 00908 return result; 00909 default: 00910 return CTRLJOINT_DEFORM; 00911 } 00912 } 00913 00914 void MayaEggGeom::AddEggFlag(MString fieldName) { 00915 bool addNewFlag = true; 00916 for (unsigned i = 0; i < _eggObjectTypes.length(); i++) { 00917 if (_eggObjectTypes[i] == fieldName) { 00918 addNewFlag = false; 00919 break; 00920 } 00921 } 00922 if (addNewFlag) { 00923 _eggObjectTypes.append(fieldName); 00924 } 00925 } 00926 00927 //////////////////////////////////////////////////////////////////////////////////////////////////// 00928 // 00929 // MayaEggMesh 00930 // 00931 //////////////////////////////////////////////////////////////////////////////////////////////////// 00932 typedef phash_map<LTexCoordd, int> TVertTable; 00933 typedef phash_map<LColor, int> CVertTable; 00934 00935 class MayaEggMesh : public MayaEggGeom 00936 { 00937 public: 00938 MColorArray _faceColorArray; 00939 MIntArray _faceIndices; 00940 MIntArray _polygonCounts; 00941 MIntArray _polygonConnects; 00942 MFloatArray _uarray; 00943 MFloatArray _varray; 00944 MIntArray _uvIds; 00945 00946 00947 int _tvert_count; 00948 int _cvert_count; 00949 int _face_count; 00950 vector<MayaEggTex*> _face_tex; 00951 00952 TVertTable _tvert_tab; 00953 CVertTable _cvert_tab; 00954 00955 int GetTVert(const LTexCoordd &uv); 00956 int GetCVert(const LColor &col); 00957 int AddFace(unsigned numVertices, MIntArray mvertIndices, MIntArray mtvertIndices, MayaEggTex *tex); 00958 00959 void ConnectTextures(void); 00960 }; 00961 00962 int MayaEggMesh::GetTVert(const LTexCoordd &uv) 00963 { 00964 if (_tvert_tab.count(uv)) { 00965 if (mayaloader_cat.is_spam()) { 00966 mayaloader_cat.spam() << "found uv coords idx: " << _tvert_tab[uv] << endl; 00967 } 00968 return _tvert_tab[uv]; 00969 } 00970 int idx = _tvert_count++; 00971 _uarray.append(uv.get_x()); 00972 _varray.append(uv.get_y()); 00973 _tvert_tab[uv] = idx; 00974 if (mayaloader_cat.is_spam()) { 00975 mayaloader_cat.spam() << "adding uv coords idx:" << idx << endl; 00976 } 00977 return idx; 00978 } 00979 00980 int MayaEggMesh::GetCVert(const LColor &col) 00981 { 00982 // if (_cvert_tab.count(col)) 00983 // return _cvert_tab[col]; 00984 // if (_cvert_count == _mesh->numCVerts) { 00985 // int nsize = _cvert_count*2 + 100; 00986 // _mesh->setNumVertCol(nsize, _cvert_count?TRUE:FALSE); 00987 // } 00988 // int idx = _cvert_count++; 00989 // _mesh->vertCol[idx] = Point3(col.get_x(), col.get_y(), col.get_z()); 00990 // _cvert_tab[col] = idx; 00991 // return idx; 00992 return 0; 00993 } 00994 00995 MayaEggMesh *MayaEggLoader::GetMesh(EggVertexPool *pool, EggGroup *parent) 00996 { 00997 MayaEggMesh *result = _mesh_tab[parent]; 00998 if (result == 0) { 00999 result = new MayaEggMesh; 01000 result->_name = parent->get_name(); 01001 result->_pool = pool; 01002 result->_parent = parent; 01003 result->_vert_count = 0; 01004 result->_tvert_count = 0; 01005 result->_cvert_count = 0; 01006 result->_face_count = 0; 01007 result->_vertColorArray.clear(); 01008 result->_vertNormalIndices.clear(); 01009 result->_vertColorIndices.clear(); 01010 result->_faceColorArray.clear(); 01011 result->_faceIndices.clear(); 01012 result->_eggObjectTypes.clear(); 01013 result->_renameTrans = false; 01014 _mesh_tab[parent] = result; 01015 } 01016 return result; 01017 } 01018 01019 int MayaEggMesh::AddFace(unsigned numVertices, MIntArray mvertIndices, MIntArray mtvertIndices, MayaEggTex *tex) 01020 { 01021 int idx = _face_count++; 01022 _polygonCounts.append(numVertices); 01023 for (unsigned i = 0; i < mvertIndices.length(); i++) 01024 { 01025 _polygonConnects.append(mvertIndices[i]); 01026 _uvIds.append(mtvertIndices[i]); 01027 } 01028 _face_tex.push_back(tex); 01029 return idx; 01030 } 01031 01032 void MayaEggMesh::ConnectTextures(void) 01033 { 01034 bool subtex = false; 01035 for (int i=1; i<_face_count; i++) { 01036 if (_face_tex[i] != _face_tex[0]) { 01037 subtex = true; 01038 } 01039 } 01040 if (!subtex) { 01041 MFnSet sg(_face_tex[0]->_shading_group); 01042 sg.addMember(_shapeNode); 01043 return; 01044 } 01045 for (int i=0; i<_face_count; i++) { 01046 MayaEggTex *tex = _face_tex[i]; 01047 if (tex->_component.object()==MObject::kNullObj) { 01048 tex->_component.create(MFn::kMeshPolygonComponent); 01049 } 01050 tex->_component.addElement(i); 01051 } 01052 for (int i=0; i<_face_count; i++) { 01053 MayaEggTex *tex = _face_tex[i]; 01054 if (tex->_component.object()!=MObject::kNullObj) { 01055 MFnSet sg(tex->_shading_group); 01056 sg.addMember(_shape_dag_path, tex->_component.object()); 01057 tex->_component.setObject(MObject::kNullObj); 01058 } 01059 } 01060 } 01061 01062 01063 //////////////////////////////////////////////////////////////////////////////////////////////////// 01064 // 01065 // MayaEggNurbsSurface 01066 // 01067 //////////////////////////////////////////////////////////////////////////////////////////////////// 01068 class MayaEggNurbsSurface : public MayaEggGeom 01069 { 01070 public: 01071 01072 01073 MPointArray _cvArray; 01074 MDoubleArray _uKnotArray; 01075 MDoubleArray _vKnotArray; 01076 unsigned _uDegree; 01077 unsigned _vDegree; 01078 unsigned _uNumCvs; 01079 unsigned _vNumCvs; 01080 01081 MFnNurbsSurface::Form _uForm; 01082 MFnNurbsSurface::Form _vForm; 01083 01084 MayaEggTex *_tex; 01085 01086 void ConnectTextures(void); 01087 void PrintData(void); 01088 }; 01089 01090 MayaEggNurbsSurface *MayaEggLoader::GetSurface(EggVertexPool *pool, EggGroup *parent) 01091 { 01092 MayaEggNurbsSurface *result = _surface_tab[parent]; 01093 if (result == 0) { 01094 result = new MayaEggNurbsSurface; 01095 result->_pool = pool; 01096 result->_parent = parent; 01097 result->_name = parent->get_name(); 01098 01099 result->_vert_count = 0; 01100 result->_vertColorArray.clear(); 01101 result->_vertNormalIndices.clear(); 01102 result->_vertColorIndices.clear(); 01103 01104 result->_cvArray.clear(); 01105 result->_uKnotArray.clear(); 01106 result->_vKnotArray.clear(); 01107 01108 result->_uDegree = 0; 01109 result->_vDegree = 0; 01110 result->_uNumCvs = 0; 01111 result->_vNumCvs = 0; 01112 result->_uForm = MFnNurbsSurface::kClosed; 01113 result->_vForm = MFnNurbsSurface::kClosed; 01114 01115 result->_eggObjectTypes.clear(); 01116 result->_renameTrans = false; 01117 _surface_tab[parent] = result; 01118 } 01119 return result; 01120 } 01121 01122 void MayaEggNurbsSurface::ConnectTextures(void) 01123 { 01124 // masad: since nurbs surfaces do not support vertex colors 01125 // I am infusing the surface's first vertex color (if any) 01126 // into the shader to achive the color. 01127 // masad: check if there is any vertex color for this surface 01128 MStatus status; 01129 MColor firstColor(0.5,0.5,0.5,1.0); 01130 if (_vertColorArray.length() > 0) { 01131 firstColor = _vertColorArray[0]; 01132 MFnLambertShader sh(_tex->_shader); 01133 status = sh.setColor(firstColor); 01134 if (status != MStatus::kSuccess) { 01135 mayaloader_cat.error() << "setColor failed on " << _name; 01136 status.perror("shader setColor failed!"); 01137 } 01138 } 01139 MFnSet sg(_tex->_shading_group); 01140 status = sg.addMember(_shapeNode); 01141 if (status != MStatus::kSuccess) { 01142 mayaloader_cat.error() << "addMember failed on " << _name; 01143 status.perror("shader addMember failed!"); 01144 } 01145 return; 01146 } 01147 01148 void MayaEggNurbsSurface::PrintData(void) 01149 { 01150 if (mayaloader_cat.is_debug()) { 01151 mayaloader_cat.debug() << "nurbsSurface : " << _name << endl; 01152 01153 mayaloader_cat.debug() << "u_form : " << _uForm << endl; 01154 mayaloader_cat.debug() << "v_form : " << _vForm << endl; 01155 } 01156 01157 /* 01158 for (unsigned i = 0; i < _cvArray.length(); i++) 01159 { 01160 MPoint cv =_cvArray[i]; 01161 mayaloader_cat.debug() << cv[0] << " " << cv[1] << " " << cv[2] << endl; 01162 } 01163 01164 for (unsigned i = 0; i < _uKnotArray.length(); i++) 01165 { 01166 mayaloader_cat.debug() << _uKnotArray[i] << endl; 01167 } 01168 01169 for (unsigned i = 0; i < _vKnotArray.length(); i++) 01170 { 01171 mayaloader_cat.debug() << _vKnotArray[i] << endl; 01172 } 01173 */ 01174 } 01175 01176 /////////////////////////////////////////////////////////////////////////////////////////////////// 01177 // 01178 // MayaAnim: 01179 // 01180 /////////////////////////////////////////////////////////////////////////////////////////////////// 01181 class MayaAnim 01182 { 01183 public: 01184 string _name; 01185 EggTable *_joint; 01186 EggXfmSAnim *_pool; 01187 void PrintData(void); 01188 }; 01189 01190 MayaAnim *MayaEggLoader::GetAnim(EggXfmSAnim *pool) 01191 { 01192 MayaAnim *result = _anim_tab[pool]; 01193 if (result == 0) { 01194 result = new MayaAnim; 01195 result->_pool = pool; 01196 result->_name = pool->get_name(); 01197 _anim_tab[pool] = result; 01198 EggNode *jointNode = (DCAST(EggNode, pool))->get_parent(); 01199 EggTable *joint = DCAST(EggTable, jointNode); 01200 result->_joint = joint; 01201 01202 } 01203 return result; 01204 } 01205 01206 void MayaAnim::PrintData(void) 01207 { 01208 if (mayaloader_cat.is_debug()) { 01209 mayaloader_cat.debug() << "anim on joint : " << _joint->get_name() << endl; 01210 } 01211 _pool->write(mayaloader_cat.debug(), 0); 01212 } 01213 01214 /////////////////////////////////////////////////////////////////////////////////////////////////// 01215 // 01216 // MayaEggLoader functions 01217 // 01218 /////////////////////////////////////////////////////////////////////////////////////////////////// 01219 01220 void MayaEggLoader::CreateSkinCluster(MayaEggGeom *M) 01221 { 01222 MString cmd("skinCluster -mi "); 01223 vector <MayaEggJoint *> joints; 01224 01225 VertTable::const_iterator vert; 01226 int maxInfluences = 0; 01227 for (vert=M->_vert_tab.begin(); vert != M->_vert_tab.end(); ++vert) { 01228 if ((int)(vert->_weights.size()) > maxInfluences) { 01229 maxInfluences = vert->_weights.size(); 01230 } 01231 for (unsigned int i=0; i<vert->_weights.size(); i++) { 01232 MayaEggJoint *joint = FindJoint(vert->_weights[i].second); 01233 if (joint && !joint->_inskin) { 01234 joint->_inskin = true; 01235 joint->_index = joints.size(); 01236 joints.push_back(joint); 01237 /* 01238 if (mayaloader_cat.is_spam()) { 01239 mayaloader_cat.spam() << joints[i]->_egg_joint->get_name() << ": adding to skin\n"; 01240 } 01241 */ 01242 } 01243 } 01244 } 01245 cmd += maxInfluences; 01246 01247 /* 01248 if (mayaloader_cat.is_spam()) { 01249 mayaloader_cat.spam() << joints.size() << " joints have weights on " << M->_pool->get_name() << endl; 01250 } 01251 */ 01252 if (joints.size() == 0) { 01253 // no need to cluster; there are no weights 01254 return; 01255 } 01256 01257 for (unsigned int i=0; i<joints.size(); i++) { 01258 MFnDependencyNode joint(joints[i]->_joint); 01259 cmd = cmd + " "; 01260 cmd = cmd + joint.name(); 01261 } 01262 01263 MFnDependencyNode shape(M->_shapeNode); 01264 cmd = cmd + " "; 01265 cmd = cmd + shape.name(); 01266 01267 MStatus status; 01268 MDGModifier dgmod; 01269 if (mayaloader_cat.is_spam()) { 01270 mayaloader_cat.spam() << cmd.asChar() << endl; 01271 string spamCmd = M->_pool->get_name(); 01272 for (unsigned int i=0; i<joints.size(); i++) { 01273 spamCmd = spamCmd + " "; 01274 spamCmd = spamCmd + joints[i]->_egg_joint->get_name(); 01275 } 01276 mayaloader_cat.spam() << spamCmd << ": total = " << joints.size() << endl; 01277 } 01278 status = dgmod.commandToExecute(cmd); 01279 if (status != MStatus::kSuccess) { 01280 perror("skinCluster commandToExecute"); 01281 return; 01282 } 01283 status = dgmod.doIt(); 01284 if (status != MStatus::kSuccess) { 01285 perror("skinCluster doIt"); 01286 return; 01287 } 01288 01289 MPlugArray oldplugs; 01290 MPlug inPlug; 01291 if (shape.typeName() == "mesh") { 01292 inPlug = shape.findPlug("inMesh"); 01293 } else if (shape.typeName() == "nurbsSurface") { 01294 inPlug = shape.findPlug("create"); 01295 } else { 01296 // we only support mesh and nurbsSurface 01297 return; 01298 } 01299 01300 if ((!inPlug.connectedTo(oldplugs,true,false))||(oldplugs.length() != 1)) { 01301 cerr << "skinCluster command failed"; 01302 return; 01303 } 01304 MFnSkinCluster skinCluster(oldplugs[0].node()); 01305 MIntArray influenceIndices; 01306 MFnSingleIndexedComponent component; 01307 component.create(MFn::kMeshVertComponent); // [gjeon] Interestingly, we can use MFn::kMeshVertComponent for NURBS surface, too 01308 component.setCompleteData(M->_vert_count); 01309 for (unsigned int i=0; i<joints.size(); i++) { 01310 unsigned int index = skinCluster.indexForInfluenceObject(joints[i]->_joint_dag_path, &status); 01311 if (status != MStatus::kSuccess) { 01312 perror("skinCluster index"); 01313 return; 01314 } 01315 influenceIndices.append((int)index); 01316 } 01317 01318 MDagPathArray paths; 01319 unsigned infcount = skinCluster.influenceObjects(paths, &status); 01320 if (status != MStatus::kSuccess) { 01321 perror("influenceObjects"); 01322 return; 01323 } 01324 for (unsigned int i=0; i<infcount; i++) { 01325 unsigned int index = skinCluster.indexForInfluenceObject(paths[i], &status); 01326 if (status != MStatus::kSuccess) { 01327 perror("skinCluster index"); 01328 return; 01329 } 01330 skinCluster.setWeights(M->_shape_dag_path, component.object(), index, 0.0, false, NULL); 01331 } 01332 01333 MFloatArray values; 01334 int tot = M->_vert_count * joints.size(); 01335 values.setLength(tot); 01336 for (int i=0; i<tot; i++) { 01337 values[i] = 0.0; 01338 } 01339 for (vert=M->_vert_tab.begin(); vert != M->_vert_tab.end(); ++vert) { 01340 for (unsigned int i=0; i<vert->_weights.size(); i++) { 01341 double strength = vert->_weights[i].first / vert->_sumWeights; // [gjeon] nomalizing weights 01342 MayaEggJoint *joint = FindJoint(vert->_weights[i].second); 01343 values[vert->_index * joints.size() + joint->_index] = (PN_stdfloat)strength; 01344 } 01345 } 01346 skinCluster.setWeights(M->_shape_dag_path, component.object(), influenceIndices, values, false, NULL); 01347 01348 for (unsigned int i=0; i<joints.size(); i++) { 01349 /* 01350 if (mayaloader_cat.is_spam()) { 01351 mayaloader_cat.spam() << joints[i]->_egg_joint->get_name() << ": clearing skin\n"; 01352 } 01353 */ 01354 joints[i]->_inskin = false; 01355 joints[i]->_index = -1; 01356 } 01357 } 01358 01359 //////////////////////////////////////////////////////////////////////////////////////////////////// 01360 // 01361 // TraverseEggData 01362 // 01363 // We have an EggData in memory, and now we're going to copy that 01364 // over into the maya scene graph. 01365 // 01366 //////////////////////////////////////////////////////////////////////////////////////////////////// 01367 01368 void MayaEggLoader::TraverseEggNode(EggNode *node, EggGroup *context, string delim) 01369 { 01370 vector<int> vertIndices; 01371 vector<int> tvertIndices; 01372 vector<int> cvertIndices; 01373 01374 string delstring = " "; 01375 01376 if (node->is_of_type(EggPolygon::get_class_type())) { 01377 /* 01378 if (mayaloader_cat.is_debug()) { 01379 mayaloader_cat.debug() << delim+delstring << "found an EggMesh: " << node->get_name() << endl; 01380 } 01381 */ 01382 EggPolygon *poly = DCAST(EggPolygon, node); 01383 if (poly->empty()) { 01384 return; 01385 } 01386 poly->cleanup(); 01387 01388 MayaEggTex *tex = 0; 01389 LMatrix3d uvtrans = LMatrix3d::ident_mat(); 01390 01391 if (poly->has_texture()) { 01392 EggTexture *etex = poly->get_texture(0); 01393 if (mayaloader_cat.is_spam()) { 01394 mayaloader_cat.spam() << "Texture format : " << etex->get_format() << endl; 01395 } 01396 tex = GetTex(etex); 01397 if (etex->has_transform()) 01398 uvtrans = etex->get_transform2d(); 01399 } else { 01400 tex = GetTex(NULL); 01401 } 01402 01403 EggPolygon::const_iterator ci; 01404 MayaEggMesh *mesh = GetMesh(poly->get_pool(), context); 01405 if (mayaloader_cat.is_spam()) { 01406 mayaloader_cat.spam() << "traverse mesh pointer " << mesh << "\n"; 01407 } 01408 vertIndices.clear(); 01409 tvertIndices.clear(); 01410 cvertIndices.clear(); 01411 int numVertices = 0; 01412 for (ci = poly->begin(); ci != poly->end(); ++ci) { 01413 EggVertex *vtx = (*ci); 01414 EggVertexPool *pool = poly->get_pool(); 01415 LTexCoordd uv(0,0); 01416 if (vtx->has_uv()) { 01417 uv = vtx->get_uv(); 01418 } 01419 vertIndices.push_back(mesh->GetVert(vtx, context)); 01420 tvertIndices.push_back(mesh->GetTVert(uv * uvtrans)); 01421 cvertIndices.push_back(mesh->GetCVert(vtx->get_color())); 01422 numVertices++; 01423 } 01424 if (mayaloader_cat.is_spam()) { 01425 mayaloader_cat.spam() << "num vertices: " << vertIndices.size() << "\n"; 01426 } 01427 01428 if (numVertices < 3) 01429 return; 01430 01431 MIntArray mvertIndices; 01432 MIntArray mtvertIndices; 01433 for (int i = 0; i < numVertices; i++) { 01434 mvertIndices.append(vertIndices[i]); 01435 mtvertIndices.append(tvertIndices[i]); 01436 } 01437 if (poly->has_color()) { 01438 if (mayaloader_cat.is_spam()) { 01439 mayaloader_cat.spam() << "found a face color of " << poly->get_color() << endl; 01440 } 01441 mesh->_faceIndices.append(mesh->_face_count); 01442 mesh->_faceColorArray.append(MakeMayaColor(poly->get_color())); 01443 } 01444 mesh->AddFace(numVertices, mvertIndices, mtvertIndices, tex); 01445 01446 // [gjeon] to handle double-sided flag 01447 if (poly->get_bface_flag()) { 01448 mesh->AddEggFlag("double-sided"); 01449 } 01450 01451 // [gjeon] to handle model flag 01452 if (context->get_model_flag()) { 01453 mesh->AddEggFlag("model"); 01454 } 01455 01456 // [gjeon] to handle billboard flag 01457 switch (context->get_billboard_type()) { 01458 case EggGroup::BT_axis: 01459 mesh->AddEggFlag("billboard"); 01460 break; 01461 01462 case EggGroup::BT_point_camera_relative: 01463 mesh->AddEggFlag("billboard-point"); 01464 break; 01465 01466 default: 01467 ; 01468 } 01469 01470 // [gjeon] to handle other flags 01471 for (int i = 0; i < context->get_num_object_types(); i++) { 01472 mesh->AddEggFlag(MString(context->get_object_type(i).c_str())); 01473 } 01474 01475 } else if (node->is_of_type(EggNurbsSurface::get_class_type())) { 01476 // [gjeon] to convert nurbsSurface 01477 EggNurbsSurface *eggNurbsSurface = DCAST(EggNurbsSurface, node); 01478 01479 EggNurbsSurface::const_iterator ci; 01480 EggVertexPool *pool = eggNurbsSurface->get_pool(); 01481 MayaEggNurbsSurface *surface = GetSurface(pool, context); 01482 01483 for (ci = eggNurbsSurface->begin(); ci != eggNurbsSurface->end(); ++ci) { 01484 EggVertex *vtx = (*ci); 01485 surface->GetVert(vtx, context); 01486 } 01487 01488 // [gjeon] finding textures 01489 MayaEggTex *tex = 0; 01490 LMatrix3d uvtrans = LMatrix3d::ident_mat(); 01491 01492 if (eggNurbsSurface->has_texture()) { 01493 EggTexture *etex = eggNurbsSurface->get_texture(0); 01494 tex = GetTex(etex); 01495 if (etex->has_transform()) 01496 { 01497 mayaloader_cat.debug() << "uvtrans?" << endl; 01498 uvtrans = etex->get_transform2d(); 01499 } 01500 } else { 01501 tex = GetTex(NULL); 01502 } 01503 01504 surface->_tex = tex; 01505 surface->_uNumCvs = eggNurbsSurface->get_num_u_cvs(); 01506 surface->_vNumCvs = eggNurbsSurface->get_num_v_cvs(); 01507 01508 // [gjeon] building cvArray 01509 for (uint ui = 0; ui < surface->_uNumCvs; ui++) { 01510 for (uint vi = 0; vi < surface->_vNumCvs; vi++) { 01511 EggVertex *vtx = eggNurbsSurface->get_vertex(eggNurbsSurface->get_vertex_index(ui, vi)); 01512 surface->_cvArray.append(MakeMPoint(vtx->get_pos3())); 01513 } 01514 } 01515 01516 // [gjeon] building u knotArray 01517 for (int i = 1; i < eggNurbsSurface->get_num_u_knots()-1; i++) { 01518 surface->_uKnotArray.append(eggNurbsSurface->get_u_knot(i)); 01519 } 01520 01521 // [gjeon] building v knotArray 01522 for (int i = 1; i < eggNurbsSurface->get_num_v_knots()-1; i++) { 01523 surface->_vKnotArray.append(eggNurbsSurface->get_v_knot(i)); 01524 } 01525 01526 surface->_uDegree = eggNurbsSurface->get_u_degree(); 01527 surface->_vDegree = eggNurbsSurface->get_v_degree(); 01528 01529 if (eggNurbsSurface->is_closed_u()) { 01530 surface->_uForm = MFnNurbsSurface::kClosed; 01531 } else { 01532 surface->_vForm = MFnNurbsSurface::kOpen; 01533 } 01534 01535 if (eggNurbsSurface->is_closed_v()) { 01536 surface->_vForm = MFnNurbsSurface::kClosed; 01537 } else { 01538 surface->_vForm = MFnNurbsSurface::kOpen; 01539 } 01540 01541 // [gjeon] to handle double-sided flag 01542 if (eggNurbsSurface->get_bface_flag()) { 01543 surface->AddEggFlag("double-sided"); 01544 } 01545 01546 // [gjeon] to handle model flag 01547 if (context->get_model_flag()) { 01548 surface->AddEggFlag("model"); 01549 } 01550 01551 // [gjeon] to handle other flags 01552 for (int i = 0; i < context->get_num_object_types(); i++) { 01553 surface->AddEggFlag(MString(context->get_object_type(i).c_str())); 01554 } 01555 01556 } else if (node->is_of_type(EggComment::get_class_type())) { 01557 string comment = (DCAST(EggComment, node))->get_comment(); 01558 if (comment.find("2egg") != string::npos) { 01559 if (mayaloader_cat.is_spam()) { 01560 mayaloader_cat.spam() << delim+delstring << "found an EggComment: " << comment << endl; 01561 } 01562 if (comment.find("chan") != string::npos) { 01563 ParseFrameInfo(comment); 01564 } 01565 } 01566 } else if (node->is_of_type(EggSAnimData::get_class_type())) { 01567 if (mayaloader_cat.is_debug()) { 01568 mayaloader_cat.debug() << delim+delstring << "found an EggSAnimData: " << node->get_name() << endl; 01569 } 01570 //EggSAnimData *anim = DCAST(EggSAnimData, node); 01571 //MayaAnimData *animData = GetAnimData(anim, DCAST(EggXfmSAnim, node->get_parent())); 01572 //animData->PrintData(); 01573 //if (_end_frame < animData->_pool->get_num_rows()) { 01574 // _end_frame = animData->_pool->get_num_rows(); 01575 //} 01576 } else if (node->is_of_type(EggGroupNode::get_class_type())) { 01577 EggGroupNode *group = DCAST(EggGroupNode, node); 01578 if (node->is_of_type(EggGroup::get_class_type())) { 01579 EggGroup *group = DCAST(EggGroup, node); 01580 01581 if (group->get_name() == "") { 01582 ostringstream stream; 01583 stream << _unnamed_idx; 01584 group->set_name("unnamed" + stream.str()); 01585 _unnamed_idx++; 01586 } 01587 01588 string group_name = group->get_name(); 01589 size_t found = group_name.find(":"); 01590 if (found != string::npos) 01591 group->set_name(group_name.replace(int(found), 1, "_")); 01592 01593 string parent_name = ""; 01594 if (context) 01595 parent_name = context->get_name(); 01596 if (group->is_joint()) { 01597 if (mayaloader_cat.is_debug()) { 01598 mayaloader_cat.debug() << delim+delstring << group->get_name() << ":" << parent_name << endl; 01599 } 01600 MakeJoint(group, context); 01601 context = group; 01602 } else { 01603 // lets create a group node for it so that it is reflected in Maya 01604 if (mayaloader_cat.is_debug()) { 01605 mayaloader_cat.debug() << delim+delstring << group->get_name() << "@" << parent_name << endl; 01606 } 01607 MakeGroup(group, context); 01608 context = group; 01609 } 01610 } else if (node->is_of_type(EggTable::get_class_type())) { 01611 //EggTable *anim = DCAST(EggTable, node); 01612 if (mayaloader_cat.is_debug()) { 01613 mayaloader_cat.debug() << delim+delstring << "found an EggTable: " << node->get_name() << endl; 01614 } 01615 } else if (node->is_of_type(EggXfmSAnim::get_class_type())) { 01616 MayaAnim *anim = GetAnim(DCAST(EggXfmSAnim, node)); 01617 //anim->PrintData(); 01618 if (mayaloader_cat.is_debug()) { 01619 mayaloader_cat.debug() << delim+delstring << "found an EggXfmSAnim: " << node->get_name() << endl; 01620 } 01621 } 01622 01623 EggGroupNode::const_iterator ci; 01624 for (ci = group->begin(); ci != group->end(); ++ci) { 01625 TraverseEggNode(*ci, context, delim+delstring); 01626 } 01627 } 01628 } 01629 01630 bool MayaEggLoader::ConvertEggData(EggData *data, bool merge, bool model, bool anim, bool respect_normals) 01631 { 01632 if (!merge) { 01633 mayaloader_cat.error() << "Currently, only 'merge' mode is implemented.\n"; 01634 return false; 01635 } 01636 01637 /* 01638 if ((anim) || (!model)) { 01639 mayaloader_cat.error() << "Currently, only model-loading is implemented.\n"; 01640 return false; 01641 } 01642 */ 01643 01644 _start_frame = 0; 01645 _end_frame = 0; 01646 _frame_rate = 24; 01647 _timeUnit = MTime::kFilm; 01648 _unnamed_idx = 1; 01649 01650 MeshTable::const_iterator ci; 01651 JointTable::const_iterator ji; 01652 TexTable::const_iterator ti; 01653 SurfaceTable::const_iterator si; 01654 AnimTable::const_iterator ei; 01655 01656 if (MGlobal::isYAxisUp()) { 01657 data->set_coordinate_system(CS_yup_right); 01658 } else { 01659 data->set_coordinate_system(CS_zup_right); 01660 } 01661 01662 if (mayaloader_cat.is_debug()) { 01663 mayaloader_cat.debug() << "root node: " << data->get_type() << endl; 01664 } 01665 TraverseEggNode(data, NULL, ""); 01666 01667 MStatus status; 01668 01669 MFnSet collision_set; 01670 collision_set.create(_collision_nodes, MFnSet::kNone, &status); 01671 01672 if (mayaloader_cat.is_spam()) { 01673 mayaloader_cat.spam() << "num meshes : " << _mesh_tab.size() << endl; 01674 } 01675 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) { 01676 MayaEggMesh *mesh = (*ci).second; 01677 if (mesh->_face_count==0) { 01678 continue; 01679 } 01680 01681 // MStatus status; 01682 MFnMesh mfn; 01683 MString cset; 01684 01685 MayaEggGroup *parentNode = FindGroup(mesh->_parent); 01686 MObject parent = MObject::kNullObj; 01687 if (parentNode) { 01688 parent = parentNode->_group; 01689 if (mayaloader_cat.is_debug()) { 01690 mayaloader_cat.debug() << "mesh's parent (group) : " << parentNode->_name << endl; 01691 } 01692 } else { 01693 mesh->_renameTrans = true; 01694 if (mayaloader_cat.is_debug()) { 01695 mayaloader_cat.debug() << "mesh's parent (null) : " << endl; 01696 } 01697 } 01698 if (mayaloader_cat.is_spam()) { 01699 mayaloader_cat.spam() << "mesh pointer : " << mesh << " and parent_pointer: " << &parent << endl; 01700 mayaloader_cat.spam() << "mesh vert_count : " << mesh->_vert_count << endl; 01701 mayaloader_cat.spam() << "mesh face_count : " << mesh->_face_count << endl; 01702 mayaloader_cat.spam() << "mesh vertexArray size: " << mesh->_vertexArray.length() << endl; 01703 mayaloader_cat.spam() << "mesh polygonCounts size: " << mesh->_polygonCounts.length() << endl; 01704 mayaloader_cat.spam() << "mesh polygonConnects size: " << mesh->_polygonConnects.length() << endl; 01705 mayaloader_cat.spam() << "mesh uarray size: " << mesh->_uarray.length() << endl; 01706 mayaloader_cat.spam() << "mesh varray size: " << mesh->_varray.length() << endl; 01707 } 01708 mesh->_transNode = mfn.create(mesh->_vert_count, mesh->_face_count, 01709 mesh->_vertexArray, mesh->_polygonCounts, mesh->_polygonConnects, 01710 mesh->_uarray, mesh->_varray, 01711 parent, &status); 01712 if (mayaloader_cat.is_spam()) { 01713 mayaloader_cat.spam() << "transNode created." << endl; 01714 } 01715 01716 if (!mesh->_renameTrans) { 01717 mesh->_transNode = parent; 01718 } 01719 01720 // [gjeon] add eggFlag attributes if any exists 01721 for (unsigned i = 0; i < mesh->_eggObjectTypes.length(); i++) { 01722 MString attrName = "eggObjectTypes"; 01723 attrName += (int)(i + 1); 01724 status = create_enum_attribute(mesh->_transNode, attrName, attrName, mesh->_eggObjectTypes, i); 01725 if (status != MStatus::kSuccess) { 01726 status.perror("create_enum_attribute failed!"); 01727 } 01728 } 01729 01730 mesh->_shapeNode = mfn.object(); 01731 mfn.getPath(mesh->_shape_dag_path); 01732 mesh->ConnectTextures(); 01733 01734 if (mayaloader_cat.is_spam()) { 01735 mayaloader_cat.spam() << "textures connected." << endl; 01736 } 01737 01738 mfn.getCurrentUVSetName(cset); 01739 status = mfn.assignUVs(mesh->_polygonCounts, mesh->_uvIds, &cset); 01740 01741 if (status != MStatus::kSuccess) { 01742 status.perror("assignUVs failed"); 01743 if (mayaloader_cat.is_spam()) { 01744 PrintData(mesh); 01745 } 01746 } 01747 else { 01748 if (mayaloader_cat.is_spam()) { 01749 mayaloader_cat.spam() << "uvs assigned." << endl; 01750 } 01751 } 01752 01753 // lets try to set normals per vertex 01754 if (respect_normals) { 01755 status = mfn.setVertexNormals(mesh->_normalArray, mesh->_vertNormalIndices, MSpace::kTransform); 01756 if (status != MStatus::kSuccess) { 01757 status.perror("setVertexNormals failed!"); 01758 } 01759 } 01760 01761 if (mayaloader_cat.is_spam()) { 01762 mayaloader_cat.spam() << "vertex normals set." << endl; 01763 } 01764 01765 // lets try to set colors per vertex 01766 /* 01767 MDGModifier dgmod; 01768 status = dgmod.doIt(); 01769 if (status != MStatus::kSuccess) { 01770 status.perror("setVertexColors doIt"); 01771 } 01772 status = mfn.setVertexColors(mesh->_vertColorArray, mesh->_vertColorIndices, &dgmod); 01773 */ 01774 status = mfn.setVertexColors(mesh->_vertColorArray, mesh->_vertColorIndices); 01775 if (status != MStatus::kSuccess) { 01776 status.perror("setVertexColors failed!"); 01777 } 01778 status = mfn.setFaceColors(mesh->_faceColorArray, mesh->_faceIndices); 01779 /* 01780 if (status != MStatus::kSuccess) { 01781 status.perror("setFaceColors failed!"); 01782 } 01783 */ 01784 } 01785 01786 for (si = _surface_tab.begin(); si != _surface_tab.end(); ++si) { 01787 MayaEggNurbsSurface *surface = (*si).second; 01788 if (surface->_cvArray.length()==0) { 01789 continue; 01790 } 01791 01792 // MStatus status; 01793 MFnNurbsSurface mfnNurbsSurface; 01794 01795 MayaEggGroup *parentNode = FindGroup(surface->_parent); 01796 MObject parent = MObject::kNullObj; 01797 if (parentNode) { 01798 parent = parentNode->_group; 01799 if (mayaloader_cat.is_debug()) { 01800 mayaloader_cat.debug() << "surface's parent (group) : " << parentNode->_name << endl; 01801 } 01802 } else { 01803 surface->_renameTrans = true; 01804 if (mayaloader_cat.is_debug()) { 01805 mayaloader_cat.debug() << "surface's parent (null) : " << endl; 01806 } 01807 } 01808 01809 surface->_transNode = mfnNurbsSurface.create(surface->_cvArray, surface->_uKnotArray, surface->_vKnotArray, 01810 surface->_uDegree, surface->_vDegree, surface->_uForm, surface->_vForm, 01811 true, parent, &status); 01812 01813 if (!surface->_renameTrans) { 01814 surface->_transNode = parent; 01815 } 01816 01817 // [gjeon] add eggFlag attributes if any exists 01818 for (unsigned i = 0; i < surface->_eggObjectTypes.length(); i++) { 01819 MString attrName = "eggObjectTypes"; 01820 attrName += (int)(i + 1); 01821 status = create_enum_attribute(surface->_transNode, attrName, attrName, surface->_eggObjectTypes, i); 01822 if (status != MStatus::kSuccess) { 01823 status.perror("create_enum_attribute failed!"); 01824 } 01825 } 01826 surface->_shapeNode = mfnNurbsSurface.object(); 01827 mfnNurbsSurface.getPath(surface->_shape_dag_path); 01828 surface->ConnectTextures(); 01829 01830 mayaloader_cat.debug() << status.errorString().asChar() << endl; 01831 } 01832 01833 01834 double thickness = 0.0; 01835 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) { 01836 MayaEggJoint *joint = (*ji).second; 01837 double dfo = ((*ji).second->GetPos()).length(); 01838 if (dfo > thickness) { 01839 thickness = dfo; 01840 } 01841 } 01842 if (mayaloader_cat.is_spam()) { 01843 mayaloader_cat.spam() << "thickness from joints: " << thickness << endl; 01844 } 01845 thickness = thickness * 0.025; 01846 for (unsigned int i=0; i<_joint_list.size(); i++) { 01847 MayaEggJoint *joint = _joint_list[i]; 01848 if (mayaloader_cat.is_spam()) { 01849 mayaloader_cat.spam() << "creating a joint: " << joint->_egg_joint->get_name() << endl; 01850 } 01851 joint->ChooseEndPos(thickness); 01852 joint->CreateMayaBone(FindGroup(joint->_egg_parent)); 01853 } 01854 if (mayaloader_cat.is_spam()) { 01855 mayaloader_cat.spam() << "went past all the joints" << endl; 01856 } 01857 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) { 01858 MayaEggMesh *mesh = (*ci).second; 01859 EggGroup *joint = mesh->GetControlJoint(); 01860 if (joint) { 01861 CreateSkinCluster(mesh); 01862 } 01863 } 01864 for (si = _surface_tab.begin(); si != _surface_tab.end(); ++si) { 01865 MayaEggNurbsSurface *surface = (*si).second; 01866 EggGroup *joint = surface->GetControlJoint(); 01867 if (joint) { 01868 CreateSkinCluster(surface); 01869 } 01870 } 01871 if (mayaloader_cat.is_spam()) { 01872 mayaloader_cat.spam() << "went past creating skin cluster" << endl; 01873 } 01874 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) { 01875 (*ci).second->AssignNames(); 01876 } 01877 for (si = _surface_tab.begin(); si != _surface_tab.end(); ++si) { 01878 (*si).second->AssignNames(); 01879 } 01880 if (mayaloader_cat.is_spam()) { 01881 mayaloader_cat.spam() << "went past mesh AssignNames" << endl; 01882 } 01883 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) { 01884 (*ji).second->AssignNames(); 01885 } 01886 if (mayaloader_cat.is_spam()) { 01887 mayaloader_cat.spam() << "went past joint AssignNames" << endl; 01888 } 01889 for (ti = _tex_tab.begin(); ti != _tex_tab.end(); ++ti) { 01890 (*ti).second->AssignNames(); 01891 } 01892 if (mayaloader_cat.is_spam()) { 01893 mayaloader_cat.spam() << "went past tex AssignNames" << endl; 01894 } 01895 01896 if (mayaloader_cat.is_debug()) { 01897 mayaloader_cat.debug() << "-fri: " << _frame_rate << " -sf: " << _start_frame 01898 << " -ef: " << _end_frame << endl; 01899 } 01900 01901 // masad: keep track of maximum frames of animation on all these joints 01902 MTime maxFrame(_start_frame - 1, _timeUnit); 01903 MTime minFrame = maxFrame; 01904 01905 for (ei = _anim_tab.begin(); ei != _anim_tab.end(); ++ei) { 01906 MayaAnim *anim = (*ei).second; 01907 MObject node = GetDependencyNode(anim->_joint->get_name()); 01908 MFnDagNode mfnNode(node, &status); 01909 01910 MMatrix mMat = mfnNode.transformationMatrix(&status); 01911 01912 MObject attrTX = mfnNode.attribute("translateX", &status); 01913 MObject attrTY = mfnNode.attribute("translateY", &status); 01914 MObject attrTZ = mfnNode.attribute("translateZ", &status); 01915 MObject attrRX = mfnNode.attribute("rotateX", &status); 01916 MObject attrRY = mfnNode.attribute("rotateY", &status); 01917 MObject attrRZ = mfnNode.attribute("rotateZ", &status); 01918 MObject attrSX = mfnNode.attribute("scaleX", &status); 01919 MObject attrSY = mfnNode.attribute("scaleY", &status); 01920 MObject attrSZ = mfnNode.attribute("scaleZ", &status); 01921 01922 MFnAnimCurve mfnAnimCurveTX; 01923 MFnAnimCurve mfnAnimCurveTY; 01924 MFnAnimCurve mfnAnimCurveTZ; 01925 MFnAnimCurve mfnAnimCurveRX; 01926 MFnAnimCurve mfnAnimCurveRY; 01927 MFnAnimCurve mfnAnimCurveRZ; 01928 MFnAnimCurve mfnAnimCurveSX; 01929 MFnAnimCurve mfnAnimCurveSY; 01930 MFnAnimCurve mfnAnimCurveSZ; 01931 01932 mfnAnimCurveTX.create(node, attrTX, MFnAnimCurve::kAnimCurveTL, NULL, &status); 01933 mfnAnimCurveTY.create(node, attrTY, MFnAnimCurve::kAnimCurveTL, NULL, &status); 01934 mfnAnimCurveTZ.create(node, attrTZ, MFnAnimCurve::kAnimCurveTL, NULL, &status); 01935 mfnAnimCurveRX.create(node, attrRX, MFnAnimCurve::kAnimCurveTA, NULL, &status); 01936 mfnAnimCurveRY.create(node, attrRY, MFnAnimCurve::kAnimCurveTA, NULL, &status); 01937 mfnAnimCurveRZ.create(node, attrRZ, MFnAnimCurve::kAnimCurveTA, NULL, &status); 01938 mfnAnimCurveSX.create(node, attrSX, MFnAnimCurve::kAnimCurveTU, NULL, &status); 01939 mfnAnimCurveSY.create(node, attrSY, MFnAnimCurve::kAnimCurveTU, NULL, &status); 01940 mfnAnimCurveSZ.create(node, attrSZ, MFnAnimCurve::kAnimCurveTU, NULL, &status); 01941 01942 MTransformationMatrix matrix( mMat ); 01943 MVector trans = matrix.translation(MSpace::kTransform, &status); 01944 01945 double rot[3]; 01946 MTransformationMatrix::RotationOrder order = MTransformationMatrix::kXYZ; 01947 status = matrix.getRotation(rot, order); 01948 01949 double scale[3]; 01950 status = matrix.getScale(scale, MSpace::kTransform); 01951 MFnAnimCurve::TangentType tangent = MFnAnimCurve::kTangentClamped; 01952 MTime time(_start_frame - 1, _timeUnit); 01953 01954 mfnAnimCurveTX.addKey(time, trans.x, tangent, tangent, NULL, &status); 01955 mfnAnimCurveTY.addKey(time, trans.y, tangent, tangent, NULL, &status); 01956 mfnAnimCurveTZ.addKey(time, trans.z, tangent, tangent, NULL, &status); 01957 mfnAnimCurveRX.addKey(time, rot[0], tangent, tangent, NULL, &status); 01958 mfnAnimCurveRY.addKey(time, rot[1], tangent, tangent, NULL, &status); 01959 mfnAnimCurveRZ.addKey(time, rot[2], tangent, tangent, NULL, &status); 01960 mfnAnimCurveSX.addKey(time, scale[0], tangent, tangent, NULL, &status); 01961 mfnAnimCurveSY.addKey(time, scale[1], tangent, tangent, NULL, &status); 01962 mfnAnimCurveSZ.addKey(time, scale[2], tangent, tangent, NULL, &status); 01963 01964 for (int frame = 0; frame < anim->_pool->get_num_rows(); frame++) 01965 { 01966 LMatrix4d tMat; 01967 anim->_pool->get_value(frame, tMat); 01968 01969 double matData[4][4] = {{tMat.get_cell(0,0), tMat.get_cell(0,1), tMat.get_cell(0,2), tMat.get_cell(0,3)}, 01970 {tMat.get_cell(1,0), tMat.get_cell(1,1), tMat.get_cell(1,2), tMat.get_cell(1,3)}, 01971 {tMat.get_cell(2,0), tMat.get_cell(2,1), tMat.get_cell(2,2), tMat.get_cell(2,3)}, 01972 {tMat.get_cell(3,0), tMat.get_cell(3,1), tMat.get_cell(3,2), tMat.get_cell(3,3)}}; 01973 MMatrix mat(matData); 01974 01975 matrix = MTransformationMatrix(mat); 01976 trans = matrix.translation(MSpace::kTransform, &status); 01977 status = matrix.getRotation(rot, order); 01978 status = matrix.getScale(scale, MSpace::kTransform); 01979 time = MTime(frame + _start_frame, _timeUnit); 01980 01981 mfnAnimCurveTX.addKey(time, trans.x, tangent, tangent, NULL, &status); 01982 mfnAnimCurveTY.addKey(time, trans.y, tangent, tangent, NULL, &status); 01983 mfnAnimCurveTZ.addKey(time, trans.z, tangent, tangent, NULL, &status); 01984 mfnAnimCurveRX.addKey(time, rot[0], tangent, tangent, NULL, &status); 01985 mfnAnimCurveRY.addKey(time, rot[1], tangent, tangent, NULL, &status); 01986 mfnAnimCurveRZ.addKey(time, rot[2], tangent, tangent, NULL, &status); 01987 mfnAnimCurveSX.addKey(time, scale[0], tangent, tangent, NULL, &status); 01988 mfnAnimCurveSY.addKey(time, scale[1], tangent, tangent, NULL, &status); 01989 mfnAnimCurveSZ.addKey(time, scale[2], tangent, tangent, NULL, &status); 01990 } 01991 if (maxFrame < time) { 01992 maxFrame = time; 01993 } 01994 } 01995 if (anim) { 01996 // masad: set the control's max time with maxFrame 01997 MAnimControl::setMaxTime(maxFrame); 01998 MAnimControl::setMinTime(minFrame); 01999 } 02000 02001 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) { 02002 delete (*ci).second; 02003 } 02004 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) { 02005 delete (*ji).second; 02006 } 02007 for (ti = _tex_tab.begin(); ti != _tex_tab.end(); ++ti) { 02008 delete (*ti).second; 02009 } 02010 for (ei = _anim_tab.begin(); ei != _anim_tab.end(); ++ei) { 02011 delete (*ei).second; 02012 } 02013 02014 // ResumeSetKeyMode(); 02015 // ResumeAnimate(); 02016 02017 mayaloader_cat.info() << "Egg import successful\n"; 02018 return true; 02019 } 02020 02021 void MayaEggLoader::PrintData(MayaEggMesh *mesh) 02022 { 02023 if (mayaloader_cat.is_spam()) { 02024 mayaloader_cat.spam() << "Mesh: " << mesh->_name << endl; 02025 mayaloader_cat.spam() << "num vertexArray: " << mesh->_vertexArray.length() << endl; 02026 ostringstream stream3; 02027 for (unsigned int i=0; i < mesh->_vertexArray.length(); ++i) { 02028 stream3 << "[" << mesh->_vertexArray[i].x << " " << mesh->_vertexArray[i].y << " " << mesh->_vertexArray[i].z << "]" << endl; 02029 } 02030 02031 mayaloader_cat.spam() << "vertexArray: \n" << stream3.str() << endl; 02032 mayaloader_cat.spam() << "num polygonConnects: " << mesh->_polygonConnects.length() << endl; 02033 mayaloader_cat.spam() << "num uvCounts: " << mesh->_polygonCounts.length() << endl; 02034 mayaloader_cat.spam() << "num uvIds: " << mesh->_uvIds.length() << endl; 02035 ostringstream stream1, stream4; 02036 unsigned int k=0; 02037 for (unsigned int i=0; i < mesh->_polygonCounts.length(); ++i) { 02038 stream1 << mesh->_polygonCounts[i] << ":->"; 02039 stream4 << mesh->_polygonCounts[i] << ":->"; 02040 for (int j=0; j < mesh->_polygonCounts[i]; ++j, ++k) { 02041 stream1 << mesh->_uvIds[k] << ","; 02042 stream4 << mesh->_polygonConnects[k] << ","; 02043 } 02044 stream1 << endl; 02045 stream4 << endl; 02046 } 02047 mayaloader_cat.spam() << "uvCounts:->uvIds " << endl << stream1.str() << endl; 02048 mayaloader_cat.spam() << "vertexCount:->polygonConnects" << endl << stream4.str() << endl; 02049 } 02050 } 02051 02052 void MayaEggLoader::ParseFrameInfo(string comment) 02053 { 02054 int length = 0; 02055 int pos, ls, le; 02056 02057 pos = comment.find("-fri"); 02058 if (pos != string::npos) { 02059 ls = comment.find(" ", pos+4); 02060 le = comment.find(" ", ls+1); 02061 if (mayaloader_cat.is_debug()) { 02062 mayaloader_cat.debug() << comment.substr(ls+1, le-ls-1) << endl; 02063 } 02064 _frame_rate = atoi(comment.substr(ls+1,le-ls-1).data()); 02065 //mayaloader_cat.debug() << "le = " << le << "; and ls = " << ls << "; frame_rate = " << _frame_rate << endl; 02066 02067 switch (_frame_rate) { 02068 case 15: 02069 _timeUnit = MTime::kGames; 02070 break; 02071 case 24: 02072 _timeUnit = MTime::kFilm; 02073 break; 02074 case 25: 02075 _timeUnit = MTime::kPALFrame; 02076 break; 02077 case 30: 02078 _timeUnit = MTime::kNTSCFrame; 02079 break; 02080 case 48: 02081 _timeUnit = MTime::kShowScan; 02082 break; 02083 case 50: 02084 _timeUnit = MTime::kPALField; 02085 break; 02086 case 60: 02087 _timeUnit = MTime::kNTSCField; 02088 break; 02089 case 2: 02090 _timeUnit = MTime::k2FPS; 02091 break; 02092 case 3: 02093 _timeUnit = MTime::k3FPS; 02094 break; 02095 case 4: 02096 _timeUnit = MTime::k4FPS; 02097 break; 02098 case 5: 02099 _timeUnit = MTime::k5FPS; 02100 break; 02101 case 6: 02102 _timeUnit = MTime::k6FPS; 02103 break; 02104 case 8: 02105 _timeUnit = MTime::k8FPS; 02106 break; 02107 case 10: 02108 _timeUnit = MTime::k10FPS; 02109 break; 02110 case 12: 02111 _timeUnit = MTime::k12FPS; 02112 break; 02113 case 16: 02114 _timeUnit = MTime::k16FPS; 02115 break; 02116 case 20: 02117 _timeUnit = MTime::k20FPS; 02118 break; 02119 case 40: 02120 _timeUnit = MTime::k40FPS; 02121 break; 02122 case 75: 02123 _timeUnit = MTime::k75FPS; 02124 break; 02125 case 80: 02126 _timeUnit = MTime::k80FPS; 02127 break; 02128 case 100: 02129 _timeUnit = MTime::k100FPS; 02130 break; 02131 default: 02132 _timeUnit = MTime::kFilm; 02133 } 02134 02135 } 02136 02137 pos = comment.find("-sf"); 02138 if (pos != string::npos) { 02139 ls = comment.find(" ", pos+3); 02140 le = comment.find(" ", ls+1); 02141 if (mayaloader_cat.is_debug()) { 02142 mayaloader_cat.debug() << comment.substr(ls+1, le-ls-1) << endl; 02143 } 02144 if (le == string::npos) { 02145 _start_frame = atoi(comment.substr(ls+1,le).data()); 02146 } else { 02147 _start_frame = atoi(comment.substr(ls+1,le-ls-1).data()); 02148 } 02149 //mayaloader_cat.debug() << "le = " << le << "; and ls = " << ls << "; start_frame = " << _start_frame << endl; 02150 } 02151 pos = comment.find("-ef"); 02152 if (pos != string::npos) { 02153 ls = comment.find(" ", pos+3); 02154 le = comment.find(" ", ls+1); 02155 if (mayaloader_cat.is_debug()) { 02156 mayaloader_cat.debug() << comment.substr(ls+1, le-ls-1) << endl; 02157 } 02158 if (le == string::npos) { 02159 _end_frame = atoi(comment.substr(ls+1,le).data()); 02160 } else { 02161 _end_frame = atoi(comment.substr(ls+1,le-ls-1).data()); 02162 } 02163 //mayaloader_cat.debug() << "le = " << le << "; and ls = " << ls << "; end_frame = " << _end_frame << endl; 02164 } 02165 02166 02167 } 02168 02169 bool MayaEggLoader::ConvertEggFile(const char *name, bool merge, bool model, bool anim, bool respect_normals) 02170 { 02171 EggData data; 02172 Filename datafn = Filename::from_os_specific(name); 02173 if (!data.read(datafn)) { 02174 mayaloader_cat.error() << "Cannot read Egg file for import\n"; 02175 return false; 02176 } 02177 return ConvertEggData(&data, merge, model, anim, respect_normals); 02178 } 02179 02180 MObject MayaEggLoader::GetDependencyNode(string givenName) 02181 { 02182 MObject node = MObject::kNullObj; 02183 int pos; 02184 string name; 02185 02186 pos = givenName.find(":"); 02187 if (pos != string::npos) { 02188 name = givenName.substr(pos+1); 02189 } else 02190 name = givenName; 02191 02192 /* 02193 //masad: I do not think you want to return a mesh node 02194 //because keyframes should only apply to joint nodes. 02195 MeshTable::const_iterator ci; 02196 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) { 02197 MayaEggMesh *mesh = (*ci).second; 02198 02199 string meshName = mesh->_pool->get_name(); 02200 int nsize = meshName.size(); 02201 if ((nsize > 6) && (meshName.rfind(".verts")==(nsize-6))) { 02202 meshName.resize(nsize-6); 02203 } 02204 if (meshName == name) 02205 { 02206 node = mesh->_transNode; 02207 cerr << "foo get dependency node returning a mesh's transNode? why? : " << givenName << endl; 02208 return node; 02209 } 02210 } 02211 */ 02212 02213 JointTable::const_iterator ji; 02214 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) { 02215 MayaEggJoint *joint = (*ji).second; 02216 if (mayaloader_cat.is_spam()) { 02217 mayaloader_cat.spam() << "traversing a joint: " << joint->_egg_joint->get_name() << endl; 02218 } 02219 string jointName = joint->_egg_joint->get_name(); 02220 if (jointName == name) 02221 { 02222 node = joint->_joint; 02223 return node; 02224 } 02225 } 02226 02227 return node; 02228 } 02229 02230 //////////////////////////////////////////////////////////////////////////////////////////////////// 02231 // 02232 // The two global functions that form the API of this module. 02233 // 02234 //////////////////////////////////////////////////////////////////////////////////////////////////// 02235 02236 bool MayaLoadEggData(EggData *data, bool merge, bool model, bool anim, bool respect_normals) 02237 { 02238 MayaEggLoader loader; 02239 bool temp = loader.ConvertEggData(data, merge, model, anim, respect_normals); 02240 return temp; 02241 } 02242 02243 bool MayaLoadEggFile(const char *name, bool merge, bool model, bool anim, bool respect_normals) 02244 { 02245 MayaEggLoader loader; 02246 return loader.ConvertEggFile(name, merge, model, anim, respect_normals); 02247 } 02248