Panda3D
Loading...
Searching...
No Matches
mayaEggLoader.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file mayaEggLoader.cxx
10 * @author jyelon
11 * @date 2005-07-20
12 *
13 * This file contains the code for class MayaEggLoader. This class
14 * does the actual work of copying an EggData tree into the maya scene.
15 */
16
17#include "pandatoolbase.h"
18#include "notifyCategoryProxy.h"
19
20#include "eggBin.h"
21#include "eggData.h"
22#include "eggTable.h"
23#include "eggVertex.h"
24#include "eggPolygon.h"
25#include "eggComment.h"
26#include "eggXfmSAnim.h"
27#include "eggSAnimData.h"
28#include "eggPrimitive.h"
29#include "eggGroupNode.h"
30#include "eggVertexPool.h"
31#include "eggPolysetMaker.h"
32#include "eggNurbsSurface.h"
33#include "texture.h"
34#include "texturePool.h"
35
36#include "pre_maya_include.h"
37#include <maya/MStatus.h>
38#include <maya/MPxCommand.h>
39#include <maya/MString.h>
40#include <maya/MStringArray.h>
41#include <maya/MArgList.h>
42#include <maya/MGlobal.h>
43#include <maya/MObject.h>
44#include <maya/MFloatPoint.h>
45#include <maya/MFloatPointArray.h>
46#include <maya/MFloatArray.h>
47#include <maya/MPointArray.h>
48#include <maya/MFnMesh.h>
49#include <maya/MFnDependencyNode.h>
50#include <maya/MFnTransform.h>
51#include <maya/MFnLambertShader.h>
52#include <maya/MPlug.h>
53#include <maya/MFnSet.h>
54#include <maya/MDGModifier.h>
55#include <maya/MSelectionList.h>
56#include <maya/MDagPath.h>
57#include <maya/MFnSingleIndexedComponent.h>
58#include <maya/MFnDoubleIndexedComponent.h>
59#include <maya/MPlugArray.h>
60#include <maya/MDagPathArray.h>
61#include <maya/MMatrix.h>
62#include <maya/MTransformationMatrix.h>
63#include <maya/MFnIkJoint.h>
64#include <maya/MFnSkinCluster.h>
65#include <maya/MAnimControl.h>
66#include <maya/MFnAnimCurve.h>
67#include <maya/MFnNurbsSurface.h>
68#include <maya/MFnEnumAttribute.h>
69#include <maya/MFnSet.h>
70#include "post_maya_include.h"
71
72#include "mayaEggLoader.h"
73
74using std::cerr;
75using std::endl;
76using std::ostringstream;
77using std::string;
78using std::vector;
79
80class MayaEggGroup;
81class MayaEggGeom;
82class MayaEggMesh;
83class MayaEggJoint;
84class MayaEggTex;
85class MayaAnim;
86class MayaEggNurbsSurface;
87
88NotifyCategoryDeclNoExport(mayaloader);
89NotifyCategoryDef(mayaloader, "");
90
91class MayaEggLoader
92{
93public:
94 bool ConvertEggData(EggData *data, bool merge, bool model, bool anim, bool respect_normals);
95 bool ConvertEggFile(const char *name, bool merge, bool model, bool anim, bool respect_normals);
96
97
98public:
99 void TraverseEggNode(EggNode *node, EggGroup *context, string delim);
100 MayaEggMesh *GetMesh(EggVertexPool *pool, EggGroup *parent);
101 MayaEggJoint *FindJoint(EggGroup *joint);
102 MayaEggJoint *MakeJoint(EggGroup *joint, EggGroup *context);
103 MayaEggGroup *FindGroup(EggGroup *group);
104 MayaEggGroup *MakeGroup(EggGroup *group, EggGroup *context);
105 MayaEggTex *GetTex(EggTexture *etex);
106 void CreateSkinCluster(MayaEggGeom *M);
107
108 MayaAnim *GetAnim(EggXfmSAnim *pool);
109 MObject GetDependencyNode(string givenName);
110
111 MayaEggNurbsSurface *GetSurface(EggVertexPool *pool, EggGroup *parent);
112
113 typedef phash_map<EggGroup *, MayaEggMesh *, pointer_hash> MeshTable;
114 typedef phash_map<EggXfmSAnim *, MayaAnim *, pointer_hash> AnimTable;
115 typedef phash_map<EggGroup *, MayaEggJoint *, pointer_hash> JointTable;
116 typedef phash_map<EggGroup *, MayaEggGroup *, pointer_hash> GroupTable;
117 typedef phash_map<string, MayaEggTex *, string_hash> TexTable;
118 typedef phash_map<EggGroup *, MayaEggNurbsSurface *, pointer_hash> SurfaceTable;
119
120 MeshTable _mesh_tab;
121 AnimTable _anim_tab;
122 JointTable _joint_tab;
123 GroupTable _group_tab;
124 TexTable _tex_tab;
125 SurfaceTable _surface_tab;
126
127 vector <MayaEggJoint *> _joint_list;
128
129 int _start_frame;
130 int _end_frame;
131 int _frame_rate;
132 MTime::Unit _timeUnit;
133
134 void ParseFrameInfo(string comment);
135 void PrintData(MayaEggMesh *mesh);
136
137private:
138 int _unnamed_idx;
139 MSelectionList _collision_nodes;
140};
141
142MPoint MakeMPoint(const LVector3d &vec)
143{
144 return MPoint(vec[0], vec[1], vec[2]);
145}
146
147MFloatPoint MakeMayaPoint(const LVector3d &vec)
148{
149 return MFloatPoint(vec[0], vec[1], vec[2]);
150}
151
152MVector MakeMayaVector(const LVector3d &vec)
153{
154 return MVector(vec[0], vec[1], vec[2]);
155}
156
157MColor MakeMayaColor(const LColor &vec)
158{
159 return MColor(vec[0], vec[1], vec[2], vec[3]);
160}
161
162// [gjeon] to create enum attribute, fieldNames is a stringArray of enum
163// names, and filedIndex is the default index value
164MStatus create_enum_attribute(MObject &node, MString fullName, MString briefName,
165 MStringArray fieldNames, unsigned fieldIndex) {
166 MStatus stat;
167
168 MFnDependencyNode fnDN( node, &stat );
169 if ( MS::kSuccess != stat ) {
170 mayaloader_cat.error()
171 << "Could not create MFnDependencyNode" << "\n";
172 return stat;
173 }
174
175 MFnEnumAttribute fnAttr;
176 MObject newAttr = fnAttr.create( fullName, briefName,
177 0, &stat );
178 if ( MS::kSuccess != stat ) {
179 mayaloader_cat.error()
180 << "Could not create new enum attribute " << fullName.asChar() << "\n";
181 return stat;
182 }
183 for (unsigned i = 0; i < fieldNames.length(); i++){
184 fnAttr.addField(fieldNames[i], i);
185 }
186
187 stat = fnAttr.setDefault(fieldIndex);
188 if ( MS::kSuccess != stat ) {
189 mayaloader_cat.error()
190 << "Could not set value for enum attribute " << fullName.asChar() << "\n";
191 return stat;
192 }
193
194 fnAttr.setKeyable( true );
195 fnAttr.setReadable( true );
196 fnAttr.setWritable( true );
197 fnAttr.setStorable( true );
198
199 // Now add the new attribute to this dependency node
200 stat = fnDN.addAttribute(newAttr, MFnDependencyNode::kLocalDynamicAttr);
201 if ( MS::kSuccess != stat ) {
202 mayaloader_cat.error()
203 << "Could not add new enum attribute " << fullName.asChar() << "\n";
204 return stat;
205 }
206
207 return stat;
208}
209
210// MayaEggTex
211
212class MayaEggTex
213{
214public:
215 string _name;
216 string _path;
217 MObject _file_texture;
218 MObject _shader;
219 MObject _shading_group;
220
221 MFnSingleIndexedComponent _component;
222 void AssignNames(void);
223};
224
225void MayaEggTex::AssignNames(void)
226{
227 if (_name == "") {
228 return;
229 }
230 MFnDependencyNode shader(_shader);
231 MFnDependencyNode sgroup(_shading_group);
232 MFnDependencyNode filetex(_file_texture);
233 shader.setName(MString(_name.c_str())+"Shader");
234 sgroup.setName(MString(_name.c_str()));
235 if (_file_texture != MObject::kNullObj) {
236 filetex.setName(MString(_name.c_str())+"File");
237 }
238}
239
240MayaEggTex *MayaEggLoader::GetTex(EggTexture* etex)
241{
242 string name = "";
243 string fn = "";
244 if (etex != nullptr) {
245 name = etex->get_name();
246 fn = etex->get_fullpath().to_os_specific();
247 }
248
249 if (_tex_tab.count(fn)) {
250 return _tex_tab[fn];
251 }
252
253 MStatus status;
254 MFnLambertShader shader;
255 MFnDependencyNode filetex;
256 MFnSet sgroup;
257 MPlugArray oldplugs;
258 MDGModifier dgmod;
259
260 /*
261 if (fn=="") {
262 MSelectionList selection;
263 MObject initGroup;
264 selection.clear();
265 MGlobal::getSelectionListByName("initialShadingGroup",selection);
266 selection.getDependNode(0, initGroup);
267 sgroup.setObject(initGroup);
268 } else {
269 */
270 if (1) {
271 shader.create(true,&status);
272 MColor firstColor(1.0,1.0,1.0,1.0);
273 status = shader.setColor(firstColor);
274 if (status != MStatus::kSuccess) {
275 mayaloader_cat.error() << "setColor failed on LambertShader\n";
276 status.perror("shader setColor failed!");
277 }
278 sgroup.create(MSelectionList(), MFnSet::kRenderableOnly, &status);
279 MPlug surfplug = sgroup.findPlug("surfaceShader");
280 if (surfplug.connectedTo(oldplugs,true,false)) {
281 for (unsigned int i=0; i<oldplugs.length(); i++) {
282 MPlug src = oldplugs[i];
283 status = dgmod.disconnect(src, surfplug);
284 if (status != MStatus::kSuccess) {
285 status.perror("Disconnecting old shader");
286 }
287 }
288 }
289 status = dgmod.connect(shader.findPlug("outColor"),surfplug);
290 if (status != MStatus::kSuccess) {
291 status.perror("Connecting shader");
292 }
293 if (fn != "") {
294 filetex.create("file",&status);
295 MString fn_str(fn.c_str());
296 filetex.findPlug("fileTextureName").setValue(fn_str);
297 dgmod.connect(filetex.findPlug("outColor"),shader.findPlug("color"));
298
299 // [gjeon] to create alpha channel connection
300 LoaderOptions options;
301 PT(Texture) tex = TexturePool::load_texture(etex->get_fullpath(), 0, false, options);
302 if (((tex != nullptr) && (tex->get_num_components() == 4))
303 || (etex->get_format() == EggTexture::F_alpha)
304 || (etex->get_format() == EggTexture::F_luminance_alpha))
305 dgmod.connect(filetex.findPlug("outTransparency"),shader.findPlug("transparency"));
306 }
307 status = dgmod.doIt();
308 if (status != MStatus::kSuccess) {
309 status.perror("DGMod doIt");
310 }
311 }
312
313 MayaEggTex *res = new MayaEggTex;
314 res->_name = name;
315 res->_path = fn;
316 res->_file_texture = filetex.object();
317 res->_shader = shader.object();
318 res->_shading_group = sgroup.object();
319
320 _tex_tab[fn] = res;
321 return res;
322}
323
324// MayaEggGroup
325
326class MayaEggGroup
327{
328public:
329 string _name;
330 MObject _parent;
331 MObject _group;
332
333 bool _addedEggFlag;
334};
335
336MayaEggGroup *MayaEggLoader::MakeGroup(EggGroup *group, EggGroup *context)
337{
338 MStatus status;
339 MayaEggGroup *pg = FindGroup(context);
340 MayaEggGroup *result = new MayaEggGroup;
341 MFnDagNode dgn;
342
343 MObject parent = MObject::kNullObj;
344 if (pg) {
345 parent = pg->_group;
346 if (mayaloader_cat.is_debug()) {
347 mayaloader_cat.debug() << "parent (group) :" << ((MFnDagNode)parent).name().asChar() << endl;
348 }
349 }
350
351 result->_name = group->get_name();
352 result->_group = dgn.create("transform", MString(result->_name.c_str()), parent, &status);
353 result->_addedEggFlag = false;
354
355 if (group->get_cs_type() != EggGroup::CST_none)
356 _collision_nodes.add(result->_group, true);
357
358 if (group->has_transform3d()) {
359 LMatrix4d tMat = group->get_transform3d();
360 double matData[4][4] = {{tMat.get_cell(0,0), tMat.get_cell(0,1), tMat.get_cell(0,2), tMat.get_cell(0,3)},
361 {tMat.get_cell(1,0), tMat.get_cell(1,1), tMat.get_cell(1,2), tMat.get_cell(1,3)},
362 {tMat.get_cell(2,0), tMat.get_cell(2,1), tMat.get_cell(2,2), tMat.get_cell(2,3)},
363 {tMat.get_cell(3,0), tMat.get_cell(3,1), tMat.get_cell(3,2), tMat.get_cell(3,3)}};
364 MMatrix mat(matData);
365
366 MTransformationMatrix matrix = MTransformationMatrix(mat);
367 MFnTransform tFn(result->_group, &status);
368 if (status != MStatus::kSuccess) {
369 status.perror("MFnTransformNode:create failed!");
370 } else {
371 tFn.set(matrix);
372 }
373 }
374
375 if (status != MStatus::kSuccess) {
376 status.perror("MFnDagNode:create failed!");
377 }
378
379 if ((pg) && (pg->_addedEggFlag == false)){
380 // [gjeon] to handle other flags
381 MStringArray eggFlags;
382 for (int i = 0; i < context->get_num_object_types(); i++) {
383 eggFlags.append(MString(context->get_object_type(i).c_str()));
384 }
385
386 for (unsigned i = 0; i < eggFlags.length(); i++) {
387 MString attrName = "eggObjectTypes";
388 attrName += (int)(i + 1);
389 status = create_enum_attribute(parent, attrName, attrName, eggFlags, i);
390 if (status != MStatus::kSuccess) {
391 status.perror("create_enum_attribute failed!");
392 }
393 }
394 pg->_addedEggFlag = true;
395 }
396
397 _group_tab[group] = result;
398 return result;
399}
400
401MayaEggGroup *MayaEggLoader::FindGroup(EggGroup *group)
402{
403 if (group==0) {
404 return 0;
405 }
406 return _group_tab[group];
407}
408
409// MayaEggJoint
410
411class MayaEggJoint
412{
413public:
414 LMatrix4d _trans;
415 LVector3d _endpos;
416 LVector3d _perp;
417 double _thickness;
418 MObject _joint;
419 MMatrix _joint_abs;
420 MDagPath _joint_dag_path;
421 bool _inskin;
422 int _index;
423 EggGroup *_egg_joint;
424 EggGroup *_egg_parent;
425 MayaEggJoint *_parent;
426 vector <MayaEggJoint *> _children;
427
428public:
429 void GetRotation(LVector3d &xv, LVector3d &yv, LVector3d &zv);
430 LVector3d GetPos(void) { return _trans.get_row3(3); }
431 MayaEggJoint *ChooseBestChild(LVector3d dir);
432 void ChooseEndPos(double thickness);
433 void CreateMayaBone(MayaEggGroup *eggParent);
434 void AssignNames(void);
435};
436
437void MayaEggJoint::GetRotation(LVector3d &xv, LVector3d &yv, LVector3d &zv)
438{
439 xv = _trans.get_row3(0);
440 yv = _trans.get_row3(1);
441 zv = _trans.get_row3(2);
442 xv.normalize();
443 yv.normalize();
444 zv = xv.cross(yv);
445 zv.normalize();
446 yv = zv.cross(xv);
447}
448
449void MayaEggJoint::AssignNames(void)
450{
451 string name = _egg_joint->get_name();
452 MFnDependencyNode joint(_joint);
453 joint.setName(name.c_str());
454 if (mayaloader_cat.is_spam()) {
455 mayaloader_cat.spam() << "joint " << joint.name().asChar() << ": -> " << name << endl;
456 }
457}
458
459MayaEggJoint *MayaEggLoader::FindJoint(EggGroup *joint)
460{
461 if (joint==nullptr) {
462 if (mayaloader_cat.is_spam()) {
463 mayaloader_cat.spam() << "joint:" << joint->get_name() << " is null: " << endl;
464 }
465 return 0;
466 }
467 if (!joint->is_joint()) {
468 if (mayaloader_cat.is_spam()) {
469 mayaloader_cat.spam() << "joint:" << joint->get_name() << " is not a joint: " << endl;
470 }
471 return 0;
472 }
473 return _joint_tab[joint];
474}
475
476MayaEggJoint *MayaEggLoader::MakeJoint(EggGroup *joint, EggGroup *context)
477{
478 MayaEggJoint *parent = FindJoint(context);
479 if (mayaloader_cat.is_debug()) {
480 string parent_name = "";
481 if (parent)
482 parent_name = context->get_name();
483 }
484 MayaEggJoint *result = new MayaEggJoint;
485 LMatrix4d t = joint->get_transform3d();
486 if (parent) {
487 result->_trans = t * parent->_trans;
488 } else {
489 result->_trans = t;
490 }
491 result->_endpos = LVector3d(0,0,0);
492 result->_perp = LVector3d(0,0,0);
493 result->_thickness = 0.0;
494 result->_egg_joint = joint;
495 result->_egg_parent = context;
496 result->_parent = parent;
497 result->_joint = MObject::kNullObj;
498 result->_inskin = false;
499 result->_index = -1;
500 if (parent) {
501 parent->_children.push_back(result);
502 }
503 _joint_tab[joint] = result;
504
505 // [gjeon] since _joint_tab is not always properly sorted
506 _joint_list.push_back(result);
507
508 return result;
509}
510
511MayaEggJoint *MayaEggJoint::ChooseBestChild(LVector3d dir)
512{
513 if (dir.length() < 0.001) {
514 return 0;
515 }
516 dir.normalize();
517 double firstbest = -1000;
518 MayaEggJoint *firstchild = 0;
519 LVector3d firstpos = GetPos();
520 double secondbest = 0;
521 for (unsigned int i=0; i<_children.size(); i++) {
522 MayaEggJoint *child = _children[i];
523 LVector3d tryfwd = child->GetPos() - GetPos();
524 if ((child->GetPos() != firstpos) && (tryfwd.length() > 0.001)) {
525 LVector3d trydir = tryfwd;
526 trydir.normalize();
527 double quality = trydir.dot(dir);
528 if (quality > firstbest) {
529 secondbest = firstbest;
530 firstbest = quality;
531 firstpos = child->GetPos();
532 firstchild = child;
533 } else if (quality > secondbest) {
534 secondbest = quality;
535 }
536 }
537 }
538 if (firstbest > secondbest + 0.1) {
539 return firstchild;
540 }
541 return 0;
542}
543
544void MayaEggJoint::ChooseEndPos(double thickness)
545{
546 LVector3d parentpos(0,0,0);
547 LVector3d parentendpos(0,0,1);
548 if (_parent) {
549 parentpos = _parent->GetPos();
550 parentendpos = _parent->_endpos;
551 }
552 LVector3d fwd = GetPos() - parentpos;
553 if (fwd.length() < 0.001) {
554 fwd = parentendpos - parentpos;
555 }
556 // mayaloader_cat.debug() << "fwd : " << fwd << endl;
557 fwd.normalize();
558 MayaEggJoint *child = ChooseBestChild(fwd);
559 if (child == 0) {
560 _endpos = fwd * thickness * 0.8 + GetPos();
561 _thickness = thickness * 0.8;
562 } else {
563 _endpos = child->GetPos();
564 _thickness = (_endpos - GetPos()).length();
565 if (_thickness > thickness) _thickness = thickness;
566 }
567 LVector3d orient = _endpos - GetPos();
568 orient.normalize();
569 LVector3d altaxis = orient.cross(LVector3d(0,-1,0));
570 if (altaxis.length() < 0.001) {
571 altaxis = orient.cross(LVector3d(0,0,1));
572 }
573 _perp = altaxis.cross(orient);
574 _perp.normalize();
575}
576
577void MayaEggJoint::CreateMayaBone(MayaEggGroup *eggParent)
578{
579 LVector3d rxv, ryv, rzv;
580 // GetRotation(rxv, ryv, rzv); [gjeon] I think we shouldn't need to use this
581 // GetRotation function here since this function removes scale information
582 // from the matrix. Let's just use the matrix directly.
583 rxv = _trans.get_row3(0);
584 ryv = _trans.get_row3(1);
585 rzv = _trans.get_row3(2);
586
587 MFloatPoint xv(MakeMayaPoint(rxv));
588 MFloatPoint yv(MakeMayaPoint(ryv));
589 MFloatPoint zv(MakeMayaPoint(rzv));
590 MFloatPoint pos(MakeMayaPoint(GetPos()));
591 MFloatPoint endpos(MakeMayaPoint(_endpos));
592 MFloatPoint tzv(MakeMayaPoint(_perp));
593 double m[4][4];
594 m[0][0]=xv.x; m[0][1]=xv.y; m[0][2]=xv.z; m[0][3]=0;
595 m[1][0]=yv.x; m[1][1]=yv.y; m[1][2]=yv.z; m[1][3]=0;
596 m[2][0]=zv.x; m[2][1]=zv.y; m[2][2]=zv.z; m[2][3]=0;
597 m[3][0]=pos.x; m[3][1]=pos.y; m[3][2]=pos.z; m[3][3]=1;
598 MMatrix trans(m);
599 _joint_abs = trans;
600 if (_parent) {
601 trans = trans * _parent->_joint_abs.inverse();
602 }
603 MTransformationMatrix mtm(trans);
604
605 MFnIkJoint ikj;
606 if (_parent) {
607 ikj.create(_parent->_joint);
608 }
609 else {
610 if (eggParent) {
611 // must be part of a group that is not a joint
612 ikj.create(eggParent->_group);
613 } else {
614 ikj.create();
615 }
616 }
617 ikj.set(mtm);
618
619 _joint = ikj.object();
620 ikj.getPath(_joint_dag_path);
621}
622
623
624// MayaEggGeom : base abstract class of MayaEggMesh and MayaEggNurbsSurface
625
626typedef std::pair<double, EggGroup *> MayaEggWeight;
627
628struct MayaEggVertex
629{
630 LVertexd _pos;
631 LNormald _normal;
632 LTexCoordd _uv;
633 vector<MayaEggWeight> _weights;
634 double _sumWeights; // [gjeon] to be used in normalizing weights
635 int _index;
636 int _external_index; // masad: use egg's index directly
637};
638
639struct MEV_Compare: public stl_hash_compare<MayaEggVertex>
640{
641 size_t operator()(const MayaEggVertex &key) const
642 {
643 return key._pos.add_hash(key._normal.get_hash());
644 }
645 bool operator()(const MayaEggVertex &k1, const MayaEggVertex &k2) const
646 {
647 int n = k1._pos.compare_to(k2._pos);
648 if (n < 0) {
649 return true;
650 }
651 if (n > 0) {
652 return false;
653 }
654 n = k1._normal.compare_to(k2._normal);
655 if (n < 0) {
656 return true;
657 }
658 if (n > 0) {
659 return false;
660 }
661 n = k1._uv.compare_to(k2._uv);
662 if (n < 0) {
663 return true;
664 }
665 if (n > 0) {
666 return false;
667 }
668 n = k1._weights.size() - k2._weights.size();
669 if (n < 0) {
670 return true;
671 }
672 if (n > 0) {
673 return false;
674 }
675 for (unsigned int i=0; i<k1._weights.size(); i++) {
676 double d = k1._weights[i].first - k2._weights[i].first;
677 if (d < 0) {
678 return true;
679 }
680 if (d > 0) {
681 return false;
682 }
683 EggGroup *g1 = k1._weights[i].second;
684 EggGroup *g2 = k2._weights[i].second;
685 if (g1 < g2) {
686 return true;
687 }
688 if (g1 > g2) {
689 return false;
690 }
691 }
692 n = k1._external_index - k2._external_index;
693
694 if (n < 0) {
695 return true;
696 }
697 if (n > 0) {
698 return false;
699 }
700
701 return false;
702 }
703};
704
705typedef phash_set<MayaEggVertex, MEV_Compare> VertTable;
706
707class MayaEggGeom
708{
709public:
710
711 EggVertexPool *_pool;
712 MObject _transNode;
713 MObject _shapeNode;
714 EggGroup *_parent;
715 MDagPath _shape_dag_path;
716 int _vert_count;
717
718 string _name;
719
720 MFloatPointArray _vertexArray;
721 MVectorArray _normalArray;
722 MColorArray _vertColorArray;
723 MIntArray _vertColorIndices;
724 MIntArray _vertNormalIndices;
725
726 MStringArray _eggObjectTypes;
727 VertTable _vert_tab;
728
729 bool _renameTrans;
730
731 int GetVert(EggVertex *vert, EggGroup *context);
732 EggGroup *GetControlJoint(void);
733
734 virtual void ConnectTextures(void) = 0;
735 void AssignNames(void);
736 void AddEggFlag(MString);
737};
738
739// [gjeon] moved from MayaEggMesh to MayaEggGeom
740int MayaEggGeom::GetVert(EggVertex *vert, EggGroup *context)
741{
742 MayaEggVertex vtx;
743 vtx._sumWeights = 0.0;
744
745 const LMatrix4d &xform = context->get_vertex_to_node();
746
747 vtx._pos = vert->get_pos3() * xform;
748 if (vert->has_normal()) {
749 vtx._normal = vert->get_normal() * xform;
750 }
751 if (vert->has_uv()) {
752 vtx._uv = vert->get_uv();
753 }
754 vtx._index = 0;
755 vtx._external_index = vert->get_index()-1;
756
757 EggVertex::GroupRef::const_iterator gri;
758 // double remaining_weight = 1.0;
759 for (gri = vert->gref_begin(); gri != vert->gref_end(); ++gri) {
760 EggGroup *egg_joint = (*gri);
761 double membership = egg_joint->get_vertex_membership(vert);
762
763 if (membership < 0)
764 {
765 mayaloader_cat.warning() << "negative weight value " << membership << " is replaced with 0 on: " << context->get_name() << endl;
766 membership = 0.0;
767 }
768 // remaining_weight -= membership;
769 vtx._weights.push_back(MayaEggWeight(membership, egg_joint));
770 vtx._sumWeights += membership; // [gjeon] to be used in normalizing weights
771 }
772
773 if (vtx._weights.size()==0) {
774 if (context != 0) {
775 vtx._weights.push_back(MayaEggWeight(1.0, context));
776 vtx._sumWeights = 1.0; // [gjeon] to be used in normalizing weights
777 }
778 // remaining_weight = 0.0;
779 }/* else {
780 // some soft models came up short of 1.0 on vertex membership add the
781 // remainder of the weight on first joint in the membership
782 if ((remaining_weight) > 0.01) {
783 gri = vert->gref_begin();
784 EggGroup *egg_joint = (*gri);
785 double membership = egg_joint->get_vertex_membership(vert);
786 vtx._weights.push_back(MayaEggWeight(membership+remaining_weight, egg_joint));
787 vtx._sumWeights += (membership + remaining_weight);
788 }
789 }*/ //[gjeon] we had better nomarlize weights than add remaining weight to first weight
790
791 VertTable::const_iterator vti = _vert_tab.find(vtx);
792 if (vti != _vert_tab.end()) {
793 /* if ((remaining_weight) > 0.01) {
794 mayaloader_cat.warning() << "weight munged to 1.0 by " << remaining_weight << " on: " << context->get_name() << " idx:" << vti->_index << endl;
795 } */
796 if (mayaloader_cat.is_spam()) {
797 ostringstream stream;
798 stream << "(" << vti->_pos << " " << vti->_normal << " " << vti->_uv << ")\n";
799 stream << "[" << vtx._pos << " " << vtx._normal << " " << vtx._uv << "]\n";
800 stream << "{" << vert->get_pos3() << " ";
801 if (vert->has_normal()) {
802 stream << vert->get_normal() << " ";
803 }
804 if (vert->has_uv()) {
805 stream << vert->get_uv();
806 }
807 stream << "}";
808 mayaloader_cat.spam() << "found a matching vertex: " << *vert << endl << stream.str() << endl;
809 }
810 return vti->_index;
811 }
812
813 // _vert_count++;
814 vtx._index = _vert_count++;
815 /*
816 if ((remaining_weight) > 0.01) {
817 mayaloader_cat.warning() << "weight munged to 1.0 by " << remaining_weight << " on: " << context->get_name() << " idx:" << vtx._index << endl;
818 } */
819
820 _vertexArray.append(MakeMayaPoint(vtx._pos));
821 if (vert->has_normal()) {
822 _normalArray.append(MakeMayaVector(vtx._normal));
823 _vertNormalIndices.append(vtx._index);
824 }
825 if (vert->has_color()) {
826 if (mayaloader_cat.is_spam()) {
827 mayaloader_cat.spam() << "found a vertex color\n";
828 }
829 _vertColorArray.append(MakeMayaColor(vert->get_color()));
830 _vertColorIndices.append(vtx._index);
831 }
832 _vert_tab.insert(vtx);
833 return vtx._index;
834}
835
836// [gjeon] moved from MayaEggMesh to MayaEggGeom
837void MayaEggGeom::AssignNames(void)
838{
839 string name = _pool->get_name();
840 size_t nsize = name.size();
841 if (nsize > 6 && name.rfind(".verts") == (nsize - 6)) {
842 name.resize(nsize - 6);
843 }
844 if (nsize > 4 && name.rfind(".cvs") == (nsize - 4)) {
845 name.resize(nsize - 4);
846 }
847
848 MFnDependencyNode dnshape(_shapeNode);
849 MFnDependencyNode dntrans(_transNode);
850
851 if (_renameTrans) {
852 dntrans.setName(MString(name.c_str()));
853 }
854
855 string shape_name = string(dntrans.name().asChar());
856 string numbers ("0123456789");
857 size_t found;
858
859 found=shape_name.find_last_not_of(numbers);
860 if (found!=string::npos)
861 shape_name.insert(found+1, "Shape");
862 else
863 shape_name.append("Shape");
864
865 dnshape.setName(MString(shape_name.c_str()));
866}
867
868#define CTRLJOINT_DEFORM ((EggGroup*)((char*)(-1)))
869
870// [gjeon] moved from MayaEggMesh to MayaEggGeom
871EggGroup *MayaEggGeom::GetControlJoint(void)
872{
873 EggGroup *result;
874 VertTable::const_iterator vert = _vert_tab.begin();
875 if (vert == _vert_tab.end()) {
876 return 0;
877 }
878 switch (vert->_weights.size()) {
879 case 0:
880 for (++vert; vert != _vert_tab.end(); ++vert) {
881 if (vert->_weights.size() != 0) {
882 return CTRLJOINT_DEFORM;
883 }
884 }
885 return 0;
886 case 1:
887 result = vert->_weights[0].second;
888 for (++vert; vert != _vert_tab.end(); ++vert) {
889 if ((vert->_weights.size() != 1) || (vert->_weights[0].second != result)) {
890 return CTRLJOINT_DEFORM;
891 }
892 }
893 return result;
894 default:
895 return CTRLJOINT_DEFORM;
896 }
897}
898
899void MayaEggGeom::AddEggFlag(MString fieldName) {
900 bool addNewFlag = true;
901 for (unsigned i = 0; i < _eggObjectTypes.length(); i++) {
902 if (_eggObjectTypes[i] == fieldName) {
903 addNewFlag = false;
904 break;
905 }
906 }
907 if (addNewFlag) {
908 _eggObjectTypes.append(fieldName);
909 }
910}
911
912// MayaEggMesh
913typedef phash_map<LTexCoordd, int> TVertTable;
914typedef phash_map<LColor, int> CVertTable;
915
916class MayaEggMesh final : public MayaEggGeom
917{
918public:
919 MColorArray _faceColorArray;
920 MIntArray _faceIndices;
921 MIntArray _polygonCounts;
922 MIntArray _polygonConnects;
923 MFloatArray _uarray;
924 MFloatArray _varray;
925 MIntArray _uvIds;
926
927
928 int _tvert_count;
929 int _cvert_count;
930 int _face_count;
931 vector<MayaEggTex*> _face_tex;
932
933 TVertTable _tvert_tab;
934 CVertTable _cvert_tab;
935
936 int GetTVert(const LTexCoordd &uv);
937 int GetCVert(const LColor &col);
938 int AddFace(unsigned numVertices, MIntArray mvertIndices, MIntArray mtvertIndices, MayaEggTex *tex);
939
940 void ConnectTextures(void) override;
941};
942
943int MayaEggMesh::GetTVert(const LTexCoordd &uv)
944{
945 if (_tvert_tab.count(uv)) {
946 if (mayaloader_cat.is_spam()) {
947 mayaloader_cat.spam() << "found uv coords idx: " << _tvert_tab[uv] << endl;
948 }
949 return _tvert_tab[uv];
950 }
951 int idx = _tvert_count++;
952 _uarray.append(uv.get_x());
953 _varray.append(uv.get_y());
954 _tvert_tab[uv] = idx;
955 if (mayaloader_cat.is_spam()) {
956 mayaloader_cat.spam() << "adding uv coords idx:" << idx << endl;
957 }
958 return idx;
959}
960
961int MayaEggMesh::GetCVert(const LColor &col)
962{
963/*
964 * if (_cvert_tab.count(col)) return _cvert_tab[col]; if (_cvert_count ==
965 * _mesh->numCVerts) { int nsize = _cvert_count*2 + 100;
966 * _mesh->setNumVertCol(nsize, _cvert_count?TRUE:FALSE); } int idx =
967 * _cvert_count++; _mesh->vertCol[idx] = Point3(col.get_x(), col.get_y(),
968 * col.get_z()); _cvert_tab[col] = idx; return idx;
969 */
970 return 0;
971}
972
973MayaEggMesh *MayaEggLoader::GetMesh(EggVertexPool *pool, EggGroup *parent)
974{
975 MayaEggMesh *result = _mesh_tab[parent];
976 if (result == 0) {
977 result = new MayaEggMesh;
978 if (parent != nullptr) {
979 result->_name = parent->get_name();
980 }
981 result->_pool = pool;
982 result->_parent = parent;
983 result->_vert_count = 0;
984 result->_tvert_count = 0;
985 result->_cvert_count = 0;
986 result->_face_count = 0;
987 result->_vertColorArray.clear();
988 result->_vertNormalIndices.clear();
989 result->_vertColorIndices.clear();
990 result->_faceColorArray.clear();
991 result->_faceIndices.clear();
992 result->_eggObjectTypes.clear();
993 result->_renameTrans = false;
994 _mesh_tab[parent] = result;
995 }
996 return result;
997}
998
999int MayaEggMesh::AddFace(unsigned numVertices, MIntArray mvertIndices, MIntArray mtvertIndices, MayaEggTex *tex)
1000{
1001 int idx = _face_count++;
1002 _polygonCounts.append(numVertices);
1003 for (unsigned i = 0; i < mvertIndices.length(); i++)
1004 {
1005 _polygonConnects.append(mvertIndices[i]);
1006 _uvIds.append(mtvertIndices[i]);
1007 }
1008 _face_tex.push_back(tex);
1009 return idx;
1010}
1011
1012void MayaEggMesh::ConnectTextures(void)
1013{
1014 bool subtex = false;
1015 for (int i=1; i<_face_count; i++) {
1016 if (_face_tex[i] != _face_tex[0]) {
1017 subtex = true;
1018 }
1019 }
1020 if (!subtex) {
1021 MFnSet sg(_face_tex[0]->_shading_group);
1022 sg.addMember(_shapeNode);
1023 return;
1024 }
1025 for (int i=0; i<_face_count; i++) {
1026 MayaEggTex *tex = _face_tex[i];
1027 if (tex->_component.object()==MObject::kNullObj) {
1028 tex->_component.create(MFn::kMeshPolygonComponent);
1029 }
1030 tex->_component.addElement(i);
1031 }
1032 for (int i=0; i<_face_count; i++) {
1033 MayaEggTex *tex = _face_tex[i];
1034 if (tex->_component.object()!=MObject::kNullObj) {
1035 MFnSet sg(tex->_shading_group);
1036 sg.addMember(_shape_dag_path, tex->_component.object());
1037 tex->_component.setObject(MObject::kNullObj);
1038 }
1039 }
1040}
1041
1042
1043// MayaEggNurbsSurface
1044class MayaEggNurbsSurface : public MayaEggGeom
1045{
1046public:
1047
1048
1049 MPointArray _cvArray;
1050 MDoubleArray _uKnotArray;
1051 MDoubleArray _vKnotArray;
1052 unsigned _uDegree;
1053 unsigned _vDegree;
1054 unsigned _uNumCvs;
1055 unsigned _vNumCvs;
1056
1057 MFnNurbsSurface::Form _uForm;
1058 MFnNurbsSurface::Form _vForm;
1059
1060 MayaEggTex *_tex;
1061
1062 void ConnectTextures(void);
1063 void PrintData(void);
1064};
1065
1066MayaEggNurbsSurface *MayaEggLoader::GetSurface(EggVertexPool *pool, EggGroup *parent)
1067{
1068 MayaEggNurbsSurface *result = _surface_tab[parent];
1069 if (result == 0) {
1070 result = new MayaEggNurbsSurface;
1071 result->_pool = pool;
1072 result->_parent = parent;
1073 result->_name = parent->get_name();
1074
1075 result->_vert_count = 0;
1076 result->_vertColorArray.clear();
1077 result->_vertNormalIndices.clear();
1078 result->_vertColorIndices.clear();
1079
1080 result->_cvArray.clear();
1081 result->_uKnotArray.clear();
1082 result->_vKnotArray.clear();
1083
1084 result->_uDegree = 0;
1085 result->_vDegree = 0;
1086 result->_uNumCvs = 0;
1087 result->_vNumCvs = 0;
1088 result->_uForm = MFnNurbsSurface::kClosed;
1089 result->_vForm = MFnNurbsSurface::kClosed;
1090
1091 result->_eggObjectTypes.clear();
1092 result->_renameTrans = false;
1093 _surface_tab[parent] = result;
1094 }
1095 return result;
1096}
1097
1098void MayaEggNurbsSurface::ConnectTextures(void)
1099{
1100 // masad: since nurbs surfaces do not support vertex colors I am infusing
1101 // the surface's first vertex color (if any) into the shader to achive the
1102 // color. masad: check if there is any vertex color for this surface
1103 MStatus status;
1104 MColor firstColor(0.5,0.5,0.5,1.0);
1105 if (_vertColorArray.length() > 0) {
1106 firstColor = _vertColorArray[0];
1107 MFnLambertShader sh(_tex->_shader);
1108 status = sh.setColor(firstColor);
1109 if (status != MStatus::kSuccess) {
1110 mayaloader_cat.error() << "setColor failed on " << _name;
1111 status.perror("shader setColor failed!");
1112 }
1113 }
1114 MFnSet sg(_tex->_shading_group);
1115 status = sg.addMember(_shapeNode);
1116 if (status != MStatus::kSuccess) {
1117 mayaloader_cat.error() << "addMember failed on " << _name;
1118 status.perror("shader addMember failed!");
1119 }
1120 return;
1121}
1122
1123void MayaEggNurbsSurface::PrintData(void)
1124{
1125 if (mayaloader_cat.is_debug()) {
1126 mayaloader_cat.debug() << "nurbsSurface : " << _name << endl;
1127
1128 mayaloader_cat.debug() << "u_form : " << _uForm << endl;
1129 mayaloader_cat.debug() << "v_form : " << _vForm << endl;
1130 }
1131
1132 /*
1133 for (unsigned i = 0; i < _cvArray.length(); i++)
1134 {
1135 MPoint cv =_cvArray[i];
1136 mayaloader_cat.debug() << cv[0] << " " << cv[1] << " " << cv[2] << endl;
1137 }
1138
1139 for (unsigned i = 0; i < _uKnotArray.length(); i++)
1140 {
1141 mayaloader_cat.debug() << _uKnotArray[i] << endl;
1142 }
1143
1144 for (unsigned i = 0; i < _vKnotArray.length(); i++)
1145 {
1146 mayaloader_cat.debug() << _vKnotArray[i] << endl;
1147 }
1148 */
1149}
1150
1151// MayaAnim:
1152class MayaAnim
1153{
1154public:
1155 string _name;
1156 EggTable *_joint;
1157 EggXfmSAnim *_pool;
1158 void PrintData(void);
1159};
1160
1161MayaAnim *MayaEggLoader::GetAnim(EggXfmSAnim *pool)
1162{
1163 MayaAnim *result = _anim_tab[pool];
1164 if (result == 0) {
1165 result = new MayaAnim;
1166 result->_pool = pool;
1167 result->_name = pool->get_name();
1168 _anim_tab[pool] = result;
1169 EggNode *jointNode = (DCAST(EggNode, pool))->get_parent();
1170 EggTable *joint = DCAST(EggTable, jointNode);
1171 result->_joint = joint;
1172
1173 }
1174 return result;
1175}
1176
1177void MayaAnim::PrintData(void)
1178{
1179 if (mayaloader_cat.is_debug()) {
1180 mayaloader_cat.debug() << "anim on joint : " << _joint->get_name() << endl;
1181 }
1182 _pool->write(mayaloader_cat.debug(), 0);
1183}
1184
1185// MayaEggLoader functions
1186
1187void MayaEggLoader::CreateSkinCluster(MayaEggGeom *M)
1188{
1189 MString cmd("skinCluster -mi ");
1190 vector <MayaEggJoint *> joints;
1191
1192 VertTable::const_iterator vert;
1193 int maxInfluences = 0;
1194 for (vert=M->_vert_tab.begin(); vert != M->_vert_tab.end(); ++vert) {
1195 if ((int)(vert->_weights.size()) > maxInfluences) {
1196 maxInfluences = vert->_weights.size();
1197 }
1198 for (unsigned int i=0; i<vert->_weights.size(); i++) {
1199 MayaEggJoint *joint = FindJoint(vert->_weights[i].second);
1200 if (joint && !joint->_inskin) {
1201 joint->_inskin = true;
1202 joint->_index = joints.size();
1203 joints.push_back(joint);
1204 /*
1205 if (mayaloader_cat.is_spam()) {
1206 mayaloader_cat.spam() << joints[i]->_egg_joint->get_name() << ": adding to skin\n";
1207 }
1208 */
1209 }
1210 }
1211 }
1212 cmd += maxInfluences;
1213
1214 /*
1215 if (mayaloader_cat.is_spam()) {
1216 mayaloader_cat.spam() << joints.size() << " joints have weights on " << M->_pool->get_name() << endl;
1217 }
1218 */
1219 if (joints.size() == 0) {
1220 // no need to cluster; there are no weights
1221 return;
1222 }
1223
1224 for (unsigned int i=0; i<joints.size(); i++) {
1225 MFnDependencyNode joint(joints[i]->_joint);
1226 cmd = cmd + " ";
1227 cmd = cmd + joint.name();
1228 }
1229
1230 MFnDependencyNode shape(M->_shapeNode);
1231 cmd = cmd + " ";
1232 cmd = cmd + shape.name();
1233
1234 MStatus status;
1235 MDGModifier dgmod;
1236 if (mayaloader_cat.is_spam()) {
1237 mayaloader_cat.spam() << cmd.asChar() << endl;
1238 string spamCmd = M->_pool->get_name();
1239 for (unsigned int i=0; i<joints.size(); i++) {
1240 spamCmd = spamCmd + " ";
1241 spamCmd = spamCmd + joints[i]->_egg_joint->get_name();
1242 }
1243 mayaloader_cat.spam() << spamCmd << ": total = " << joints.size() << endl;
1244 }
1245 status = dgmod.commandToExecute(cmd);
1246 if (status != MStatus::kSuccess) {
1247 perror("skinCluster commandToExecute");
1248 return;
1249 }
1250 status = dgmod.doIt();
1251 if (status != MStatus::kSuccess) {
1252 perror("skinCluster doIt");
1253 return;
1254 }
1255
1256 MPlugArray oldplugs;
1257 MPlug inPlug;
1258 if (shape.typeName() == "mesh") {
1259 inPlug = shape.findPlug("inMesh");
1260 } else if (shape.typeName() == "nurbsSurface") {
1261 inPlug = shape.findPlug("create");
1262 } else {
1263 // we only support mesh and nurbsSurface
1264 return;
1265 }
1266
1267 if ((!inPlug.connectedTo(oldplugs,true,false))||(oldplugs.length() != 1)) {
1268 cerr << "skinCluster command failed";
1269 return;
1270 }
1271 MFnSkinCluster skinCluster(oldplugs[0].node());
1272 MIntArray influenceIndices;
1273 MFnSingleIndexedComponent component;
1274 component.create(MFn::kMeshVertComponent); // [gjeon] Interestingly, we can use MFn::kMeshVertComponent for NURBS surface, too
1275 component.setCompleteData(M->_vert_count);
1276 for (unsigned int i=0; i<joints.size(); i++) {
1277 unsigned int index = skinCluster.indexForInfluenceObject(joints[i]->_joint_dag_path, &status);
1278 if (status != MStatus::kSuccess) {
1279 perror("skinCluster index");
1280 return;
1281 }
1282 influenceIndices.append((int)index);
1283 }
1284
1285 MDagPathArray paths;
1286 unsigned infcount = skinCluster.influenceObjects(paths, &status);
1287 if (status != MStatus::kSuccess) {
1288 perror("influenceObjects");
1289 return;
1290 }
1291 for (unsigned int i=0; i<infcount; i++) {
1292 unsigned int index = skinCluster.indexForInfluenceObject(paths[i], &status);
1293 if (status != MStatus::kSuccess) {
1294 perror("skinCluster index");
1295 return;
1296 }
1297 skinCluster.setWeights(M->_shape_dag_path, component.object(), index, 0.0, false, nullptr);
1298 }
1299
1300 MFloatArray values;
1301 int tot = M->_vert_count * joints.size();
1302 values.setLength(tot);
1303 for (int i=0; i<tot; i++) {
1304 values[i] = 0.0;
1305 }
1306 for (vert=M->_vert_tab.begin(); vert != M->_vert_tab.end(); ++vert) {
1307 for (unsigned int i=0; i<vert->_weights.size(); i++) {
1308 double strength = vert->_weights[i].first / vert->_sumWeights; // [gjeon] nomalizing weights
1309 MayaEggJoint *joint = FindJoint(vert->_weights[i].second);
1310 values[vert->_index * joints.size() + joint->_index] = (PN_stdfloat)strength;
1311 }
1312 }
1313 skinCluster.setWeights(M->_shape_dag_path, component.object(), influenceIndices, values, false, nullptr);
1314
1315 for (unsigned int i=0; i<joints.size(); i++) {
1316 /*
1317 if (mayaloader_cat.is_spam()) {
1318 mayaloader_cat.spam() << joints[i]->_egg_joint->get_name() << ": clearing skin\n";
1319 }
1320 */
1321 joints[i]->_inskin = false;
1322 joints[i]->_index = -1;
1323 }
1324}
1325
1326// TraverseEggData We have an EggData in memory, and now we're going to copy
1327// that over into the maya scene graph.
1328
1329void MayaEggLoader::TraverseEggNode(EggNode *node, EggGroup *context, string delim)
1330{
1331 vector<int> vertIndices;
1332 vector<int> tvertIndices;
1333 vector<int> cvertIndices;
1334
1335 string delstring = " ";
1336
1337 if (node->is_of_type(EggPolygon::get_class_type())) {
1338 /*
1339 if (mayaloader_cat.is_debug()) {
1340 mayaloader_cat.debug() << delim+delstring << "found an EggMesh: " << node->get_name() << endl;
1341 }
1342 */
1343 EggPolygon *poly = DCAST(EggPolygon, node);
1344 if (poly->empty()) {
1345 return;
1346 }
1347 poly->cleanup();
1348
1349 MayaEggTex *tex = 0;
1350 LMatrix3d uvtrans = LMatrix3d::ident_mat();
1351
1352 if (poly->has_texture()) {
1353 EggTexture *etex = poly->get_texture(0);
1354 if (mayaloader_cat.is_spam()) {
1355 mayaloader_cat.spam() << "Texture format : " << etex->get_format() << endl;
1356 }
1357 tex = GetTex(etex);
1358 if (etex->has_transform())
1359 uvtrans = etex->get_transform2d();
1360 } else {
1361 tex = GetTex(nullptr);
1362 }
1363
1364 EggPolygon::const_iterator ci;
1365 MayaEggMesh *mesh = GetMesh(poly->get_pool(), context);
1366 if (mayaloader_cat.is_spam()) {
1367 mayaloader_cat.spam() << "traverse mesh pointer " << mesh << "\n";
1368 }
1369 vertIndices.clear();
1370 tvertIndices.clear();
1371 cvertIndices.clear();
1372 int numVertices = 0;
1373 for (ci = poly->begin(); ci != poly->end(); ++ci) {
1374 EggVertex *vtx = (*ci);
1375 LTexCoordd uv(0,0);
1376 if (vtx->has_uv()) {
1377 uv = vtx->get_uv();
1378 }
1379 vertIndices.push_back(mesh->GetVert(vtx, context));
1380 tvertIndices.push_back(mesh->GetTVert(uv * uvtrans));
1381 cvertIndices.push_back(mesh->GetCVert(vtx->get_color()));
1382 numVertices++;
1383 }
1384 if (mayaloader_cat.is_spam()) {
1385 mayaloader_cat.spam() << "num vertices: " << vertIndices.size() << "\n";
1386 }
1387
1388 if (numVertices < 3)
1389 return;
1390
1391 MIntArray mvertIndices;
1392 MIntArray mtvertIndices;
1393 for (int i = 0; i < numVertices; i++) {
1394 mvertIndices.append(vertIndices[i]);
1395 mtvertIndices.append(tvertIndices[i]);
1396 }
1397 if (poly->has_color()) {
1398 if (mayaloader_cat.is_spam()) {
1399 mayaloader_cat.spam() << "found a face color of " << poly->get_color() << endl;
1400 }
1401 mesh->_faceIndices.append(mesh->_face_count);
1402 mesh->_faceColorArray.append(MakeMayaColor(poly->get_color()));
1403 }
1404 mesh->AddFace(numVertices, mvertIndices, mtvertIndices, tex);
1405
1406 // [gjeon] to handle double-sided flag
1407 if (poly->get_bface_flag()) {
1408 mesh->AddEggFlag("double-sided");
1409 }
1410
1411 // [gjeon] to handle model flag
1412 if (context->get_model_flag()) {
1413 mesh->AddEggFlag("model");
1414 }
1415
1416 // [gjeon] to handle billboard flag
1417 switch (context->get_billboard_type()) {
1418 case EggGroup::BT_axis:
1419 mesh->AddEggFlag("billboard");
1420 break;
1421
1422 case EggGroup::BT_point_camera_relative:
1423 mesh->AddEggFlag("billboard-point");
1424 break;
1425
1426 default:
1427 ;
1428 }
1429
1430 // [gjeon] to handle other flags
1431 for (int i = 0; i < context->get_num_object_types(); i++) {
1432 mesh->AddEggFlag(MString(context->get_object_type(i).c_str()));
1433 }
1434
1435 } else if (node->is_of_type(EggNurbsSurface::get_class_type())) {
1436 // [gjeon] to convert nurbsSurface
1437 EggNurbsSurface *eggNurbsSurface = DCAST(EggNurbsSurface, node);
1438
1439 EggNurbsSurface::const_iterator ci;
1440 EggVertexPool *pool = eggNurbsSurface->get_pool();
1441 MayaEggNurbsSurface *surface = GetSurface(pool, context);
1442
1443 for (ci = eggNurbsSurface->begin(); ci != eggNurbsSurface->end(); ++ci) {
1444 EggVertex *vtx = (*ci);
1445 surface->GetVert(vtx, context);
1446 }
1447
1448 // [gjeon] finding textures
1449 MayaEggTex *tex = 0;
1450 LMatrix3d uvtrans = LMatrix3d::ident_mat();
1451
1452 if (eggNurbsSurface->has_texture()) {
1453 EggTexture *etex = eggNurbsSurface->get_texture(0);
1454 tex = GetTex(etex);
1455 if (etex->has_transform())
1456 {
1457 mayaloader_cat.debug() << "uvtrans?" << endl;
1458 uvtrans = etex->get_transform2d();
1459 }
1460 } else {
1461 tex = GetTex(nullptr);
1462 }
1463
1464 surface->_tex = tex;
1465 surface->_uNumCvs = eggNurbsSurface->get_num_u_cvs();
1466 surface->_vNumCvs = eggNurbsSurface->get_num_v_cvs();
1467
1468 // [gjeon] building cvArray
1469 for (uint ui = 0; ui < surface->_uNumCvs; ui++) {
1470 for (uint vi = 0; vi < surface->_vNumCvs; vi++) {
1471 EggVertex *vtx = eggNurbsSurface->get_vertex(eggNurbsSurface->get_vertex_index(ui, vi));
1472 surface->_cvArray.append(MakeMPoint(vtx->get_pos3()));
1473 }
1474 }
1475
1476 // [gjeon] building u knotArray
1477 for (int i = 1; i < eggNurbsSurface->get_num_u_knots()-1; i++) {
1478 surface->_uKnotArray.append(eggNurbsSurface->get_u_knot(i));
1479 }
1480
1481 // [gjeon] building v knotArray
1482 for (int i = 1; i < eggNurbsSurface->get_num_v_knots()-1; i++) {
1483 surface->_vKnotArray.append(eggNurbsSurface->get_v_knot(i));
1484 }
1485
1486 surface->_uDegree = eggNurbsSurface->get_u_degree();
1487 surface->_vDegree = eggNurbsSurface->get_v_degree();
1488
1489 if (eggNurbsSurface->is_closed_u()) {
1490 surface->_uForm = MFnNurbsSurface::kClosed;
1491 } else {
1492 surface->_vForm = MFnNurbsSurface::kOpen;
1493 }
1494
1495 if (eggNurbsSurface->is_closed_v()) {
1496 surface->_vForm = MFnNurbsSurface::kClosed;
1497 } else {
1498 surface->_vForm = MFnNurbsSurface::kOpen;
1499 }
1500
1501 // [gjeon] to handle double-sided flag
1502 if (eggNurbsSurface->get_bface_flag()) {
1503 surface->AddEggFlag("double-sided");
1504 }
1505
1506 // [gjeon] to handle model flag
1507 if (context->get_model_flag()) {
1508 surface->AddEggFlag("model");
1509 }
1510
1511 // [gjeon] to handle other flags
1512 for (int i = 0; i < context->get_num_object_types(); i++) {
1513 surface->AddEggFlag(MString(context->get_object_type(i).c_str()));
1514 }
1515
1516 } else if (node->is_of_type(EggComment::get_class_type())) {
1517 string comment = (DCAST(EggComment, node))->get_comment();
1518 if (comment.find("2egg") != string::npos) {
1519 if (mayaloader_cat.is_spam()) {
1520 mayaloader_cat.spam() << delim+delstring << "found an EggComment: " << comment << endl;
1521 }
1522 if (comment.find("chan") != string::npos) {
1523 ParseFrameInfo(comment);
1524 }
1525 }
1526 } else if (node->is_of_type(EggSAnimData::get_class_type())) {
1527 if (mayaloader_cat.is_debug()) {
1528 mayaloader_cat.debug() << delim+delstring << "found an EggSAnimData: " << node->get_name() << endl;
1529 }
1530 // EggSAnimData *anim = DCAST(EggSAnimData, node); MayaAnimData *animData
1531 // = GetAnimData(anim, DCAST(EggXfmSAnim, node->get_parent()));
1532 // animData->PrintData(); if (_end_frame <
1533 // animData->_pool->get_num_rows()) { _end_frame =
1534 // animData->_pool->get_num_rows(); }
1535 } else if (node->is_of_type(EggGroupNode::get_class_type())) {
1536 EggGroupNode *group = DCAST(EggGroupNode, node);
1537 if (node->is_of_type(EggGroup::get_class_type())) {
1538 EggGroup *group = DCAST(EggGroup, node);
1539
1540 if (group->get_name() == "") {
1541 ostringstream stream;
1542 stream << _unnamed_idx;
1543 group->set_name("unnamed" + stream.str());
1544 _unnamed_idx++;
1545 }
1546
1547 string group_name = group->get_name();
1548 size_t found = group_name.find(":");
1549 if (found != string::npos)
1550 group->set_name(group_name.replace(int(found), 1, "_"));
1551
1552 string parent_name = "";
1553 if (context)
1554 parent_name = context->get_name();
1555 if (group->is_joint()) {
1556 if (mayaloader_cat.is_debug()) {
1557 mayaloader_cat.debug() << delim+delstring << group->get_name() << ":" << parent_name << endl;
1558 }
1559 MakeJoint(group, context);
1560 context = group;
1561 } else {
1562 // lets create a group node for it so that it is reflected in Maya
1563 if (mayaloader_cat.is_debug()) {
1564 mayaloader_cat.debug() << delim+delstring << group->get_name() << "@" << parent_name << endl;
1565 }
1566 MakeGroup(group, context);
1567 context = group;
1568 }
1569 } else if (node->is_of_type(EggTable::get_class_type())) {
1570 // EggTable *anim = DCAST(EggTable, node);
1571 if (mayaloader_cat.is_debug()) {
1572 mayaloader_cat.debug() << delim+delstring << "found an EggTable: " << node->get_name() << endl;
1573 }
1574 } else if (node->is_of_type(EggXfmSAnim::get_class_type())) {
1575 // Create a MayaAnim equivalent of the EggXfmSAnim
1576 GetAnim(DCAST(EggXfmSAnim, node));
1577 //anim->PrintData();
1578 if (mayaloader_cat.is_debug()) {
1579 mayaloader_cat.debug() << delim+delstring << "found an EggXfmSAnim: " << node->get_name() << endl;
1580 }
1581 }
1582
1583 EggGroupNode::const_iterator ci;
1584 for (ci = group->begin(); ci != group->end(); ++ci) {
1585 TraverseEggNode(*ci, context, delim+delstring);
1586 }
1587 }
1588}
1589
1590bool MayaEggLoader::ConvertEggData(EggData *data, bool merge, bool model, bool anim, bool respect_normals)
1591{
1592 if (!merge) {
1593 mayaloader_cat.error() << "Currently, only 'merge' mode is implemented.\n";
1594 return false;
1595 }
1596
1597 /*
1598 if ((anim) || (!model)) {
1599 mayaloader_cat.error() << "Currently, only model-loading is implemented.\n";
1600 return false;
1601 }
1602 */
1603
1604 _start_frame = 0;
1605 _end_frame = 0;
1606 _frame_rate = 24;
1607 _timeUnit = MTime::kFilm;
1608 _unnamed_idx = 1;
1609
1610 MeshTable::const_iterator ci;
1611 JointTable::const_iterator ji;
1612 TexTable::const_iterator ti;
1613 SurfaceTable::const_iterator si;
1614 AnimTable::const_iterator ei;
1615
1616 if (MGlobal::isYAxisUp()) {
1617 data->set_coordinate_system(CS_yup_right);
1618 } else {
1619 data->set_coordinate_system(CS_zup_right);
1620 }
1621
1622 if (mayaloader_cat.is_debug()) {
1623 mayaloader_cat.debug() << "root node: " << data->get_type() << endl;
1624 }
1625 TraverseEggNode(data, nullptr, "");
1626
1627 MStatus status;
1628
1629 MFnSet collision_set;
1630 collision_set.create(_collision_nodes, MFnSet::kNone, &status);
1631
1632 if (mayaloader_cat.is_spam()) {
1633 mayaloader_cat.spam() << "num meshes : " << _mesh_tab.size() << endl;
1634 }
1635 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
1636 MayaEggMesh *mesh = (*ci).second;
1637 if (mesh->_face_count==0) {
1638 continue;
1639 }
1640
1641 // MStatus status;
1642 MFnMesh mfn;
1643 MString cset;
1644
1645 MayaEggGroup *parentNode = FindGroup(mesh->_parent);
1646 MObject parent = MObject::kNullObj;
1647 if (parentNode) {
1648 parent = parentNode->_group;
1649 if (mayaloader_cat.is_debug()) {
1650 mayaloader_cat.debug() << "mesh's parent (group) : " << parentNode->_name << endl;
1651 }
1652 } else {
1653 mesh->_renameTrans = true;
1654 if (mayaloader_cat.is_debug()) {
1655 mayaloader_cat.debug() << "mesh's parent (null) : " << endl;
1656 }
1657 }
1658 if (mayaloader_cat.is_spam()) {
1659 mayaloader_cat.spam() << "mesh pointer : " << mesh << " and parent_pointer: " << &parent << endl;
1660 mayaloader_cat.spam() << "mesh vert_count : " << mesh->_vert_count << endl;
1661 mayaloader_cat.spam() << "mesh face_count : " << mesh->_face_count << endl;
1662 mayaloader_cat.spam() << "mesh vertexArray size: " << mesh->_vertexArray.length() << endl;
1663 mayaloader_cat.spam() << "mesh polygonCounts size: " << mesh->_polygonCounts.length() << endl;
1664 mayaloader_cat.spam() << "mesh polygonConnects size: " << mesh->_polygonConnects.length() << endl;
1665 mayaloader_cat.spam() << "mesh uarray size: " << mesh->_uarray.length() << endl;
1666 mayaloader_cat.spam() << "mesh varray size: " << mesh->_varray.length() << endl;
1667 }
1668 mesh->_transNode = mfn.create(mesh->_vert_count, mesh->_face_count,
1669 mesh->_vertexArray, mesh->_polygonCounts, mesh->_polygonConnects,
1670 mesh->_uarray, mesh->_varray,
1671 parent, &status);
1672 if (mayaloader_cat.is_spam()) {
1673 mayaloader_cat.spam() << "transNode created." << endl;
1674 }
1675
1676 if (!mesh->_renameTrans) {
1677 mesh->_transNode = parent;
1678 }
1679
1680 // [gjeon] add eggFlag attributes if any exists
1681 for (unsigned i = 0; i < mesh->_eggObjectTypes.length(); i++) {
1682 MString attrName = "eggObjectTypes";
1683 attrName += (int)(i + 1);
1684 status = create_enum_attribute(mesh->_transNode, attrName, attrName, mesh->_eggObjectTypes, i);
1685 if (status != MStatus::kSuccess) {
1686 status.perror("create_enum_attribute failed!");
1687 }
1688 }
1689
1690 // Check the "Display Colors" box by default, so that vertex colors (if
1691 // any) will be visible.
1692 MPlug displayColors = mfn.findPlug("displayColors");
1693 displayColors.setValue((bool)true);
1694
1695 mesh->_shapeNode = mfn.object();
1696 mfn.getPath(mesh->_shape_dag_path);
1697 mesh->ConnectTextures();
1698
1699 if (mayaloader_cat.is_spam()) {
1700 mayaloader_cat.spam() << "textures connected." << endl;
1701 }
1702
1703 mfn.getCurrentUVSetName(cset);
1704 status = mfn.assignUVs(mesh->_polygonCounts, mesh->_uvIds, &cset);
1705
1706 if (status != MStatus::kSuccess) {
1707 status.perror("assignUVs failed");
1708 if (mayaloader_cat.is_spam()) {
1709 PrintData(mesh);
1710 }
1711 }
1712 else {
1713 if (mayaloader_cat.is_spam()) {
1714 mayaloader_cat.spam() << "uvs assigned." << endl;
1715 }
1716 }
1717
1718 // lets try to set normals per vertex
1719 if (respect_normals) {
1720 status = mfn.setVertexNormals(mesh->_normalArray, mesh->_vertNormalIndices, MSpace::kTransform);
1721 if (status != MStatus::kSuccess) {
1722 status.perror("setVertexNormals failed!");
1723 }
1724 }
1725
1726 if (mayaloader_cat.is_spam()) {
1727 mayaloader_cat.spam() << "vertex normals set." << endl;
1728 }
1729
1730 // lets try to set colors per vertex
1731 /*
1732 MDGModifier dgmod;
1733 status = dgmod.doIt();
1734 if (status != MStatus::kSuccess) {
1735 status.perror("setVertexColors doIt");
1736 }
1737 status = mfn.setVertexColors(mesh->_vertColorArray, mesh->_vertColorIndices, &dgmod);
1738 */
1739 status = mfn.setVertexColors(mesh->_vertColorArray, mesh->_vertColorIndices);
1740 if (status != MStatus::kSuccess) {
1741 status.perror("setVertexColors failed!");
1742 }
1743 status = mfn.setFaceColors(mesh->_faceColorArray, mesh->_faceIndices);
1744 /*
1745 if (status != MStatus::kSuccess) {
1746 status.perror("setFaceColors failed!");
1747 }
1748 */
1749 }
1750
1751 for (si = _surface_tab.begin(); si != _surface_tab.end(); ++si) {
1752 MayaEggNurbsSurface *surface = (*si).second;
1753 if (surface->_cvArray.length()==0) {
1754 continue;
1755 }
1756
1757 // MStatus status;
1758 MFnNurbsSurface mfnNurbsSurface;
1759
1760 MayaEggGroup *parentNode = FindGroup(surface->_parent);
1761 MObject parent = MObject::kNullObj;
1762 if (parentNode) {
1763 parent = parentNode->_group;
1764 if (mayaloader_cat.is_debug()) {
1765 mayaloader_cat.debug() << "surface's parent (group) : " << parentNode->_name << endl;
1766 }
1767 } else {
1768 surface->_renameTrans = true;
1769 if (mayaloader_cat.is_debug()) {
1770 mayaloader_cat.debug() << "surface's parent (null) : " << endl;
1771 }
1772 }
1773
1774 surface->_transNode = mfnNurbsSurface.create(surface->_cvArray, surface->_uKnotArray, surface->_vKnotArray,
1775 surface->_uDegree, surface->_vDegree, surface->_uForm, surface->_vForm,
1776 true, parent, &status);
1777
1778 if (!surface->_renameTrans) {
1779 surface->_transNode = parent;
1780 }
1781
1782 // [gjeon] add eggFlag attributes if any exists
1783 for (unsigned i = 0; i < surface->_eggObjectTypes.length(); i++) {
1784 MString attrName = "eggObjectTypes";
1785 attrName += (int)(i + 1);
1786 status = create_enum_attribute(surface->_transNode, attrName, attrName, surface->_eggObjectTypes, i);
1787 if (status != MStatus::kSuccess) {
1788 status.perror("create_enum_attribute failed!");
1789 }
1790 }
1791 surface->_shapeNode = mfnNurbsSurface.object();
1792 mfnNurbsSurface.getPath(surface->_shape_dag_path);
1793 surface->ConnectTextures();
1794
1795 mayaloader_cat.debug() << status.errorString().asChar() << endl;
1796 }
1797
1798
1799 double thickness = 0.0;
1800 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) {
1801 MayaEggJoint *joint = (*ji).second;
1802 double dfo = (joint->GetPos()).length();
1803 if (dfo > thickness) {
1804 thickness = dfo;
1805 }
1806 }
1807 if (mayaloader_cat.is_spam()) {
1808 mayaloader_cat.spam() << "thickness from joints: " << thickness << endl;
1809 }
1810 thickness = thickness * 0.025;
1811 for (unsigned int i=0; i<_joint_list.size(); i++) {
1812 MayaEggJoint *joint = _joint_list[i];
1813 if (mayaloader_cat.is_spam()) {
1814 mayaloader_cat.spam() << "creating a joint: " << joint->_egg_joint->get_name() << endl;
1815 }
1816 joint->ChooseEndPos(thickness);
1817 joint->CreateMayaBone(FindGroup(joint->_egg_parent));
1818 }
1819 if (mayaloader_cat.is_spam()) {
1820 mayaloader_cat.spam() << "went past all the joints" << endl;
1821 }
1822 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
1823 MayaEggMesh *mesh = (*ci).second;
1824 EggGroup *joint = mesh->GetControlJoint();
1825 if (joint) {
1826 CreateSkinCluster(mesh);
1827 }
1828 }
1829 for (si = _surface_tab.begin(); si != _surface_tab.end(); ++si) {
1830 MayaEggNurbsSurface *surface = (*si).second;
1831 EggGroup *joint = surface->GetControlJoint();
1832 if (joint) {
1833 CreateSkinCluster(surface);
1834 }
1835 }
1836 if (mayaloader_cat.is_spam()) {
1837 mayaloader_cat.spam() << "went past creating skin cluster" << endl;
1838 }
1839 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
1840 (*ci).second->AssignNames();
1841 }
1842 for (si = _surface_tab.begin(); si != _surface_tab.end(); ++si) {
1843 (*si).second->AssignNames();
1844 }
1845 if (mayaloader_cat.is_spam()) {
1846 mayaloader_cat.spam() << "went past mesh AssignNames" << endl;
1847 }
1848 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) {
1849 (*ji).second->AssignNames();
1850 }
1851 if (mayaloader_cat.is_spam()) {
1852 mayaloader_cat.spam() << "went past joint AssignNames" << endl;
1853 }
1854 for (ti = _tex_tab.begin(); ti != _tex_tab.end(); ++ti) {
1855 (*ti).second->AssignNames();
1856 }
1857 if (mayaloader_cat.is_spam()) {
1858 mayaloader_cat.spam() << "went past tex AssignNames" << endl;
1859 }
1860
1861 if (mayaloader_cat.is_debug()) {
1862 mayaloader_cat.debug() << "-fri: " << _frame_rate << " -sf: " << _start_frame
1863 << " -ef: " << _end_frame << endl;
1864 }
1865
1866 // masad: keep track of maximum frames of animation on all these joints
1867 MTime maxFrame(_start_frame - 1, _timeUnit);
1868 MTime minFrame = maxFrame;
1869
1870 for (ei = _anim_tab.begin(); ei != _anim_tab.end(); ++ei) {
1871 MayaAnim *anim = (*ei).second;
1872 MObject node = GetDependencyNode(anim->_joint->get_name());
1873 MFnDagNode mfnNode(node, &status);
1874
1875 MMatrix mMat = mfnNode.transformationMatrix(&status);
1876
1877 MObject attrTX = mfnNode.attribute("translateX", &status);
1878 MObject attrTY = mfnNode.attribute("translateY", &status);
1879 MObject attrTZ = mfnNode.attribute("translateZ", &status);
1880 MObject attrRX = mfnNode.attribute("rotateX", &status);
1881 MObject attrRY = mfnNode.attribute("rotateY", &status);
1882 MObject attrRZ = mfnNode.attribute("rotateZ", &status);
1883 MObject attrSX = mfnNode.attribute("scaleX", &status);
1884 MObject attrSY = mfnNode.attribute("scaleY", &status);
1885 MObject attrSZ = mfnNode.attribute("scaleZ", &status);
1886
1887 MFnAnimCurve mfnAnimCurveTX;
1888 MFnAnimCurve mfnAnimCurveTY;
1889 MFnAnimCurve mfnAnimCurveTZ;
1890 MFnAnimCurve mfnAnimCurveRX;
1891 MFnAnimCurve mfnAnimCurveRY;
1892 MFnAnimCurve mfnAnimCurveRZ;
1893 MFnAnimCurve mfnAnimCurveSX;
1894 MFnAnimCurve mfnAnimCurveSY;
1895 MFnAnimCurve mfnAnimCurveSZ;
1896
1897 mfnAnimCurveTX.create(node, attrTX, MFnAnimCurve::kAnimCurveTL, nullptr, &status);
1898 mfnAnimCurveTY.create(node, attrTY, MFnAnimCurve::kAnimCurveTL, nullptr, &status);
1899 mfnAnimCurveTZ.create(node, attrTZ, MFnAnimCurve::kAnimCurveTL, nullptr, &status);
1900 mfnAnimCurveRX.create(node, attrRX, MFnAnimCurve::kAnimCurveTA, nullptr, &status);
1901 mfnAnimCurveRY.create(node, attrRY, MFnAnimCurve::kAnimCurveTA, nullptr, &status);
1902 mfnAnimCurveRZ.create(node, attrRZ, MFnAnimCurve::kAnimCurveTA, nullptr, &status);
1903 mfnAnimCurveSX.create(node, attrSX, MFnAnimCurve::kAnimCurveTU, nullptr, &status);
1904 mfnAnimCurveSY.create(node, attrSY, MFnAnimCurve::kAnimCurveTU, nullptr, &status);
1905 mfnAnimCurveSZ.create(node, attrSZ, MFnAnimCurve::kAnimCurveTU, nullptr, &status);
1906
1907 MTransformationMatrix matrix( mMat );
1908 MVector trans = matrix.translation(MSpace::kTransform, &status);
1909
1910 double rot[3];
1911 MTransformationMatrix::RotationOrder order = MTransformationMatrix::kXYZ;
1912 status = matrix.getRotation(rot, order);
1913
1914 double scale[3];
1915 status = matrix.getScale(scale, MSpace::kTransform);
1916 MFnAnimCurve::TangentType tangent = MFnAnimCurve::kTangentClamped;
1917 MTime time(_start_frame - 1, _timeUnit);
1918
1919 mfnAnimCurveTX.addKey(time, trans.x, tangent, tangent, nullptr, &status);
1920 mfnAnimCurveTY.addKey(time, trans.y, tangent, tangent, nullptr, &status);
1921 mfnAnimCurveTZ.addKey(time, trans.z, tangent, tangent, nullptr, &status);
1922 mfnAnimCurveRX.addKey(time, rot[0], tangent, tangent, nullptr, &status);
1923 mfnAnimCurveRY.addKey(time, rot[1], tangent, tangent, nullptr, &status);
1924 mfnAnimCurveRZ.addKey(time, rot[2], tangent, tangent, nullptr, &status);
1925 mfnAnimCurveSX.addKey(time, scale[0], tangent, tangent, nullptr, &status);
1926 mfnAnimCurveSY.addKey(time, scale[1], tangent, tangent, nullptr, &status);
1927 mfnAnimCurveSZ.addKey(time, scale[2], tangent, tangent, nullptr, &status);
1928
1929 for (int frame = 0; frame < anim->_pool->get_num_rows(); frame++)
1930 {
1931 LMatrix4d tMat;
1932 anim->_pool->get_value(frame, tMat);
1933
1934 double matData[4][4] = {{tMat.get_cell(0,0), tMat.get_cell(0,1), tMat.get_cell(0,2), tMat.get_cell(0,3)},
1935 {tMat.get_cell(1,0), tMat.get_cell(1,1), tMat.get_cell(1,2), tMat.get_cell(1,3)},
1936 {tMat.get_cell(2,0), tMat.get_cell(2,1), tMat.get_cell(2,2), tMat.get_cell(2,3)},
1937 {tMat.get_cell(3,0), tMat.get_cell(3,1), tMat.get_cell(3,2), tMat.get_cell(3,3)}};
1938 MMatrix mat(matData);
1939
1940 matrix = MTransformationMatrix(mat);
1941 trans = matrix.translation(MSpace::kTransform, &status);
1942 status = matrix.getRotation(rot, order);
1943 status = matrix.getScale(scale, MSpace::kTransform);
1944 time = MTime(frame + _start_frame, _timeUnit);
1945
1946 mfnAnimCurveTX.addKey(time, trans.x, tangent, tangent, nullptr, &status);
1947 mfnAnimCurveTY.addKey(time, trans.y, tangent, tangent, nullptr, &status);
1948 mfnAnimCurveTZ.addKey(time, trans.z, tangent, tangent, nullptr, &status);
1949 mfnAnimCurveRX.addKey(time, rot[0], tangent, tangent, nullptr, &status);
1950 mfnAnimCurveRY.addKey(time, rot[1], tangent, tangent, nullptr, &status);
1951 mfnAnimCurveRZ.addKey(time, rot[2], tangent, tangent, nullptr, &status);
1952 mfnAnimCurveSX.addKey(time, scale[0], tangent, tangent, nullptr, &status);
1953 mfnAnimCurveSY.addKey(time, scale[1], tangent, tangent, nullptr, &status);
1954 mfnAnimCurveSZ.addKey(time, scale[2], tangent, tangent, nullptr, &status);
1955 }
1956 if (maxFrame < time) {
1957 maxFrame = time;
1958 }
1959 }
1960 if (anim) {
1961 // masad: set the control's max time with maxFrame
1962 MAnimControl::setMaxTime(maxFrame);
1963 MAnimControl::setMinTime(minFrame);
1964 }
1965
1966 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
1967 delete (*ci).second;
1968 }
1969 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) {
1970 delete (*ji).second;
1971 }
1972 for (ti = _tex_tab.begin(); ti != _tex_tab.end(); ++ti) {
1973 delete (*ti).second;
1974 }
1975 for (ei = _anim_tab.begin(); ei != _anim_tab.end(); ++ei) {
1976 delete (*ei).second;
1977 }
1978
1979 // ResumeSetKeyMode(); ResumeAnimate();
1980
1981 mayaloader_cat.info() << "Egg import successful\n";
1982 return true;
1983}
1984
1985void MayaEggLoader::PrintData(MayaEggMesh *mesh)
1986{
1987 if (mayaloader_cat.is_spam()) {
1988 mayaloader_cat.spam() << "Mesh: " << mesh->_name << endl;
1989 mayaloader_cat.spam() << "num vertexArray: " << mesh->_vertexArray.length() << endl;
1990 ostringstream stream3;
1991 for (unsigned int i=0; i < mesh->_vertexArray.length(); ++i) {
1992 stream3 << "[" << mesh->_vertexArray[i].x << " " << mesh->_vertexArray[i].y << " " << mesh->_vertexArray[i].z << "]" << endl;
1993 }
1994
1995 mayaloader_cat.spam() << "vertexArray: \n" << stream3.str() << endl;
1996 mayaloader_cat.spam() << "num polygonConnects: " << mesh->_polygonConnects.length() << endl;
1997 mayaloader_cat.spam() << "num uvCounts: " << mesh->_polygonCounts.length() << endl;
1998 mayaloader_cat.spam() << "num uvIds: " << mesh->_uvIds.length() << endl;
1999 ostringstream stream1, stream4;
2000 unsigned int k=0;
2001 for (unsigned int i=0; i < mesh->_polygonCounts.length(); ++i) {
2002 stream1 << mesh->_polygonCounts[i] << ":->";
2003 stream4 << mesh->_polygonCounts[i] << ":->";
2004 for (int j=0; j < mesh->_polygonCounts[i]; ++j, ++k) {
2005 stream1 << mesh->_uvIds[k] << ",";
2006 stream4 << mesh->_polygonConnects[k] << ",";
2007 }
2008 stream1 << endl;
2009 stream4 << endl;
2010 }
2011 mayaloader_cat.spam() << "uvCounts:->uvIds " << endl << stream1.str() << endl;
2012 mayaloader_cat.spam() << "vertexCount:->polygonConnects" << endl << stream4.str() << endl;
2013 }
2014}
2015
2016void MayaEggLoader::ParseFrameInfo(string comment)
2017{
2018 size_t pos, ls, le;
2019
2020 pos = comment.find("-fri");
2021 if (pos != string::npos) {
2022 ls = comment.find(" ", pos+4);
2023 le = comment.find(" ", ls+1);
2024 if (mayaloader_cat.is_debug()) {
2025 mayaloader_cat.debug() << comment.substr(ls+1, le-ls-1) << endl;
2026 }
2027 _frame_rate = atoi(comment.substr(ls+1,le-ls-1).data());
2028 // mayaloader_cat.debug() << "le = " << le << "; and ls = " << ls << ";
2029 // frame_rate = " << _frame_rate << endl;
2030
2031 switch (_frame_rate) {
2032 case 15:
2033 _timeUnit = MTime::kGames;
2034 break;
2035 case 24:
2036 _timeUnit = MTime::kFilm;
2037 break;
2038 case 25:
2039 _timeUnit = MTime::kPALFrame;
2040 break;
2041 case 30:
2042 _timeUnit = MTime::kNTSCFrame;
2043 break;
2044 case 48:
2045 _timeUnit = MTime::kShowScan;
2046 break;
2047 case 50:
2048 _timeUnit = MTime::kPALField;
2049 break;
2050 case 60:
2051 _timeUnit = MTime::kNTSCField;
2052 break;
2053 case 2:
2054 _timeUnit = MTime::k2FPS;
2055 break;
2056 case 3:
2057 _timeUnit = MTime::k3FPS;
2058 break;
2059 case 4:
2060 _timeUnit = MTime::k4FPS;
2061 break;
2062 case 5:
2063 _timeUnit = MTime::k5FPS;
2064 break;
2065 case 6:
2066 _timeUnit = MTime::k6FPS;
2067 break;
2068 case 8:
2069 _timeUnit = MTime::k8FPS;
2070 break;
2071 case 10:
2072 _timeUnit = MTime::k10FPS;
2073 break;
2074 case 12:
2075 _timeUnit = MTime::k12FPS;
2076 break;
2077 case 16:
2078 _timeUnit = MTime::k16FPS;
2079 break;
2080 case 20:
2081 _timeUnit = MTime::k20FPS;
2082 break;
2083 case 40:
2084 _timeUnit = MTime::k40FPS;
2085 break;
2086 case 75:
2087 _timeUnit = MTime::k75FPS;
2088 break;
2089 case 80:
2090 _timeUnit = MTime::k80FPS;
2091 break;
2092 case 100:
2093 _timeUnit = MTime::k100FPS;
2094 break;
2095 default:
2096 _timeUnit = MTime::kFilm;
2097 }
2098
2099 }
2100
2101 pos = comment.find("-sf");
2102 if (pos != string::npos) {
2103 ls = comment.find(" ", pos+3);
2104 le = comment.find(" ", ls+1);
2105 if (mayaloader_cat.is_debug()) {
2106 mayaloader_cat.debug() << comment.substr(ls+1, le-ls-1) << endl;
2107 }
2108 if (le == string::npos) {
2109 _start_frame = atoi(comment.substr(ls+1,le).data());
2110 } else {
2111 _start_frame = atoi(comment.substr(ls+1,le-ls-1).data());
2112 }
2113 // mayaloader_cat.debug() << "le = " << le << "; and ls = " << ls << ";
2114 // start_frame = " << _start_frame << endl;
2115 }
2116 pos = comment.find("-ef");
2117 if (pos != string::npos) {
2118 ls = comment.find(" ", pos+3);
2119 le = comment.find(" ", ls+1);
2120 if (mayaloader_cat.is_debug()) {
2121 mayaloader_cat.debug() << comment.substr(ls+1, le-ls-1) << endl;
2122 }
2123 if (le == string::npos) {
2124 _end_frame = atoi(comment.substr(ls+1,le).data());
2125 } else {
2126 _end_frame = atoi(comment.substr(ls+1,le-ls-1).data());
2127 }
2128 // mayaloader_cat.debug() << "le = " << le << "; and ls = " << ls << ";
2129 // end_frame = " << _end_frame << endl;
2130 }
2131
2132
2133}
2134
2135bool MayaEggLoader::ConvertEggFile(const char *name, bool merge, bool model, bool anim, bool respect_normals)
2136{
2137 EggData data;
2138 Filename datafn = Filename::from_os_specific(name);
2139 if (!data.read(datafn)) {
2140 mayaloader_cat.error() << "Cannot read Egg file for import\n";
2141 return false;
2142 }
2143 return ConvertEggData(&data, merge, model, anim, respect_normals);
2144}
2145
2146MObject MayaEggLoader::GetDependencyNode(string givenName)
2147{
2148 MObject node = MObject::kNullObj;
2149 size_t pos;
2150 string name;
2151
2152 pos = givenName.find(":");
2153 if (pos != string::npos) {
2154 name = givenName.substr(pos+1);
2155 } else
2156 name = givenName;
2157
2158 /*
2159 // masad: I do not think you want to return a mesh node because keyframes
2160 // should only apply to joint nodes.
2161 MeshTable::const_iterator ci;
2162 for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
2163 MayaEggMesh *mesh = (*ci).second;
2164
2165 string meshName = mesh->_pool->get_name();
2166 int nsize = meshName.size();
2167 if ((nsize > 6) && (meshName.rfind(".verts")==(nsize-6))) {
2168 meshName.resize(nsize-6);
2169 }
2170 if (meshName == name)
2171 {
2172 node = mesh->_transNode;
2173 cerr << "foo get dependency node returning a mesh's transNode? why? : " << givenName << endl;
2174 return node;
2175 }
2176 }
2177 */
2178
2179 JointTable::const_iterator ji;
2180 for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) {
2181 MayaEggJoint *joint = (*ji).second;
2182 if (mayaloader_cat.is_spam()) {
2183 mayaloader_cat.spam() << "traversing a joint: " << joint->_egg_joint->get_name() << endl;
2184 }
2185 string jointName = joint->_egg_joint->get_name();
2186 if (jointName == name)
2187 {
2188 node = joint->_joint;
2189 return node;
2190 }
2191 }
2192
2193 return node;
2194}
2195
2196// The two global functions that form the API of this module.
2197
2198bool MayaLoadEggData(EggData *data, bool merge, bool model, bool anim, bool respect_normals)
2199{
2200 MayaEggLoader loader;
2201 bool temp = loader.ConvertEggData(data, merge, model, anim, respect_normals);
2202 return temp;
2203}
2204
2205bool MayaLoadEggFile(const char *name, bool merge, bool model, bool anim, bool respect_normals)
2206{
2207 MayaEggLoader loader;
2208 return loader.ConvertEggFile(name, merge, model, anim, respect_normals);
2209}
LColor get_color() const
Returns the color set on this particular attribute.
A comment that appears in an egg file within a <Comment> entry.
Definition eggComment.h:24
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition eggData.h:37
const Filename & get_fullpath() const
Returns the full pathname to the file, if it is known; otherwise, returns the same thing as get_filen...
A base class for nodes in the hierarchy that are not leaf nodes.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition eggGroup.h:34
virtual bool is_joint() const
Returns true if this particular node represents a <Joint> entry or not.
Definition eggGroup.cxx:468
double get_vertex_membership(const EggVertex *vert) const
Returns the amount of membership of the indicated vertex in this group.
Definition eggGroup.cxx:677
A base class for things that may be directly added into the egg hierarchy.
Definition eggNode.h:36
const LMatrix4d & get_vertex_to_node() const
Returns the transformation matrix suitable for converting the vertices as read from the egg file into...
Definition eggNode.I:166
A parametric NURBS surface.
bool is_closed_u() const
Returns true if the surface appears to be closed in the U direction.
bool is_closed_v() const
Returns true if the surface appears to be closed in the V direction.
get_num_u_knots
Returns the number of knots in the U direction.
int get_vertex_index(int ui, int vi) const
Returns the index number within the EggPrimitive's list of the control vertex at position ui,...
int get_v_degree() const
Returns the degree of the surface in the V direction.
get_v_knot
Returns the nth knot value defined in the V direction.
int get_num_v_cvs() const
Returns the number of control vertices that should be present in the V direction.
int get_u_degree() const
Returns the degree of the surface in the U direction.
get_u_knot
Returns the nth knot value defined in the U direction.
int get_num_u_cvs() const
Returns the number of control vertices that should be present in the U direction.
get_num_v_knots
Returns the number of knots in the V direction.
A single polygon.
Definition eggPolygon.h:24
virtual bool cleanup() override
Cleans up modeling errors in whatever context this makes sense.
get_pool
Returns the vertex pool associated with the vertices of the primitive, or NULL if the primitive has n...
bool has_texture() const
Returns true if the primitive has any textures specified, false otherwise.
get_vertex
Returns a particular index based on its index number.
get_bface_flag
Retrieves the backfacing flag of the polygon.
get_texture
Returns the first texture on the primitive, if any, or NULL if there are no textures on the primitive...
This corresponds to a.
Definition eggTable.h:27
Defines a texture map that may be applied to geometry.
Definition eggTexture.h:30
const LMatrix4d & get_transform3d() const
Returns the overall transform as a 4x4 matrix.
bool has_transform() const
Returns true if the transform is nonempty, false if it is empty (no transform components have been ad...
bool has_transform3d() const
Returns true if the transform is specified as a 3-d transform, e.g.
LMatrix3d get_transform2d() const
Returns the overall transform as a 3x3 matrix.
A collection of vertices.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition eggVertex.h:39
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
Definition eggVertex.I:158
int get_index() const
Returns the index number of the vertex within its pool.
Definition eggVertex.I:277
LTexCoordd get_uv() const
Returns the unnamed UV coordinate pair on the vertex.
Definition eggVertex.I:179
GroupRef::const_iterator gref_end() const
Returns an iterator that can, in conjunction with gref_begin(), be used to traverse the entire set of...
GroupRef::const_iterator gref_begin() const
Returns an iterator that can, in conjunction with gref_end(), be used to traverse the entire set of g...
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
Definition eggVertex.I:131
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine entries that specify...
Definition eggXfmSAnim.h:28
virtual void write(std::ostream &out, int indent_level) const
Writes the data to the indicated output stream in Egg format.
int get_num_rows() const
Returns the effective number of rows in the table.
void get_value(int row, LMatrix4d &mat) const
Returns the value of the aggregate row of the table as a matrix.
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition filename.cxx:328
Specifies parameters that may be passed to the loader.
static Texture * load_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads the given filename up into a texture, if it has not already been loaded, and returns the new te...
Definition texturePool.I:70
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition texture.h:72
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.