From b34260896c3c1c3a6836e9067b50a9b2faba8904 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Tue, 12 Jul 2005 20:48:25 +0000 Subject: [PATCH] Finished: Meshes & Bones. Unfinished: Materials, Skin Mod, Tex Matrix, Anim. --- pandatool/src/maxeggimport/maxEggImport.cxx | 232 ++++++++++++++++++-- 1 file changed, 209 insertions(+), 23 deletions(-) diff --git a/pandatool/src/maxeggimport/maxEggImport.cxx b/pandatool/src/maxeggimport/maxEggImport.cxx index 788c8d4dc0..7e76f3f03d 100755 --- a/pandatool/src/maxeggimport/maxEggImport.cxx +++ b/pandatool/src/maxeggimport/maxEggImport.cxx @@ -10,8 +10,8 @@ #include "stdmat.h" #include "decomp.h" #include "shape.h" -#include "splshape.h" -#include "dummy.h" +#include "simpobj.h" +#include "iparamb2.h" #include "eggData.h" #include "eggVertexPool.h" @@ -33,10 +33,13 @@ static FILE *lgfile; //////////////////////////////////////////////////////////////////////////////////////////////////// class MaxEggMesh; +class MaxEggJoint; +class BoneFunctions; class MaxEggImporter : public SceneImport { public: + // GUI-related methods MaxEggImporter(); ~MaxEggImporter(); int ExtCount(); // Number of extensions supported @@ -50,23 +53,35 @@ public: unsigned int Version(); // Version number * 100 (i.e. v3.01 = 301) void ShowAbout(HWND hWnd); // Show DLL's "About..." box int DoImport(const TCHAR *name,ImpInterface *ei,Interface *i, BOOL suppressPrompts); - MaxEggMesh *GetMesh(EggVertexPool *pool); + +public: + // GUI-related fields + static Interface *_ip; + static ImpInterface *_impip; + static BOOL _merge; + static BOOL _importmodel; + static BOOL _importanim; + +public: + // Import-related methods: void TraverseEggData(EggData *data); void TraverseEggNode(EggNode *node, EggGroup *context); + MaxEggMesh *GetMesh(EggVertexPool *pool); + MaxEggJoint *FindJoint(EggGroup *joint); + MaxEggJoint *MakeJoint(EggGroup *joint, EggGroup *context); public: - Interface *_ip; - ImpInterface *_impip; - static BOOL _merge; - static BOOL _importmodel; - static BOOL _importanim; - - typedef pmap MeshTable; + // Import-related fields: + typedef phash_map MeshTable; typedef second_of_pair_iterator MeshIterator; + typedef phash_map JointTable; + typedef second_of_pair_iterator JointIterator; MeshTable _mesh_tab; + JointTable _joint_tab; }; - +Interface *MaxEggImporter::_ip; +ImpInterface *MaxEggImporter::_impip; BOOL MaxEggImporter::_merge = TRUE; BOOL MaxEggImporter::_importmodel = TRUE; BOOL MaxEggImporter::_importanim = TRUE; @@ -146,13 +161,15 @@ static BOOL CALLBACK AboutBoxDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM return FALSE; } return TRUE; -} +} void MaxEggImporter::ShowAbout(HWND hWnd) { - DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutBoxDlgProc, 0); + DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), + hWnd, AboutBoxDlgProc, 0); } + static BOOL CALLBACK ImportDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { MaxEggImporter *imp = (MaxEggImporter*)GetWindowLong(hWnd,GWL_USERDATA); @@ -240,17 +257,8 @@ public: int GetTVert(TexCoordd uv); int GetCVert(Colorf col); int AddFace(int v0, int v1, int v2, int tv0, int tv1, int tv2, int cv0, int cv1, int cv2); - void LogData(void); }; -void MaxEggMesh::LogData(void) -{ - fprintf(lgfile,"Mesh %08x faces: %d\n",_mesh,_mesh->numFaces); - for (int i=0; i<_mesh->numFaces; i++) { - fprintf(lgfile," -- %d %d %d\n",_mesh->tvFace[i].t[0],_mesh->tvFace[i].t[1],_mesh->tvFace[i].t[2]); - } -} - int MaxEggMesh::GetVert(Vertexd pos, Normald norm, EggGroup *context) { VertexContext key = VertexContext(VertexPos(pos,norm),context); @@ -337,6 +345,158 @@ int MaxEggMesh::AddFace(int v0, int v1, int v2, int tv0, int tv1, int tv2, int c return idx; } +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// MaxEggJoint +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class MaxEggJoint +{ +public: + Point3 _xv,_yv,_zv; + Point3 _pos; + Point3 _endpos; + Point3 _zaxis; + double _thickness; + bool _anyvertex; + SimpleObject2 *_bone; + INode *_node; + EggGroup *_egg_joint; + MaxEggJoint *_parent; + vector _children; + +public: + MaxEggJoint *ChooseBestChild(Point3 dir); + void ChooseEndPos(double thickness); + void CreateMaxBone(void); +}; + +MaxEggJoint *MaxEggImporter::FindJoint(EggGroup *joint) +{ + if (joint==0) return 0; + return _joint_tab[joint]; +} + +MaxEggJoint *MaxEggImporter::MakeJoint(EggGroup *joint, EggGroup *context) +{ + MaxEggJoint *parent = FindJoint(context); + MaxEggJoint *result = new MaxEggJoint; + LMatrix4d t = joint->get_transform(); + if (parent) { + result->_xv = parent->_xv*((float)t(0,0)) + parent->_yv*((float)t(0,1)) + parent->_zv*((float)t(0,2)); + result->_yv = parent->_xv*((float)t(1,0)) + parent->_yv*((float)t(1,1)) + parent->_zv*((float)t(1,2)); + result->_zv = parent->_xv*((float)t(2,0)) + parent->_yv*((float)t(2,1)) + parent->_zv*((float)t(2,2)); + result->_pos = parent->_xv*((float)t(3,0)) + parent->_yv*((float)t(3,1)) + parent->_zv*((float)t(3,2)) + parent->_pos; + } else { + result->_xv = Point3(((float)t(0,0)), ((float)t(0,1)), ((float)t(0,2))); + result->_yv = Point3(((float)t(1,0)), ((float)t(1,1)), ((float)t(1,2))); + result->_zv = Point3(((float)t(2,0)), ((float)t(2,1)), ((float)t(2,2))); + result->_pos = Point3(((float)t(3,0)), ((float)t(3,1)), ((float)t(3,2))); + } + result->_endpos = Point3(0,0,0); + result->_zaxis = Point3(0,0,0); + result->_thickness = 0.0; + result->_anyvertex = false; + result->_bone = 0; + result->_node = 0; + result->_egg_joint = joint; + result->_parent = parent; + if (parent) parent->_children.push_back(result); + _joint_tab[joint] = result; + return result; +} + +MaxEggJoint *MaxEggJoint::ChooseBestChild(Point3 dir) +{ + if (dir.Length() < 0.001) return 0; + dir = dir.Normalize(); + double firstbest = -1000; + MaxEggJoint *firstchild = 0; + Point3 firstpos = _pos; + double secondbest = 0; + for (int i=0; i<_children.size(); i++) { + MaxEggJoint *child = _children[i]; + Point3 tryfwd = child->_pos - _pos; + if ((child->_pos != firstpos) && (tryfwd.Length() > 0.001)) { + Point3 trydir = tryfwd.Normalize(); + double quality = trydir % dir; + if (quality > firstbest) { + secondbest = firstbest; + firstbest = quality; + firstpos = child->_pos; + firstchild = child; + } else if (quality > secondbest) { + secondbest = quality; + } + } + } + if (firstbest > secondbest + 0.1) + return firstchild; + return 0; +} + +void MaxEggJoint::ChooseEndPos(double thickness) +{ + Point3 parentpos(0,0,0); + Point3 parentendpos(0,0,1); + if (_parent) { + parentpos = _parent->_pos; + parentendpos = _parent->_endpos; + } + Point3 fwd = _pos - parentpos; + if (fwd.Length() < 0.001) { + fwd = parentendpos - parentpos; + } + fwd = fwd.Normalize(); + MaxEggJoint *child = ChooseBestChild(fwd); + if (child == 0) { + _endpos = fwd * ((float)(thickness * 0.8)) + _pos; + _thickness = thickness * 0.8; + } else { + _endpos = child->_pos; + _thickness = (_endpos - _pos).Length(); + if (_thickness > thickness) _thickness = thickness; + } + Point3 orient = (_endpos - _pos).Normalize(); + Point3 altaxis = orient ^ Point3(0,-1,0); + if (altaxis.Length() < 0.001) altaxis = orient ^ Point3(0,0,1); + _zaxis = (altaxis ^ orient).Normalize(); +} + +void MaxEggJoint::CreateMaxBone(void) +{ + Point3 fwd = _endpos - _pos; + double len = fwd.Length(); + Point3 txv = fwd * ((float)(1.0/len)); + Point3 tzv = _zaxis; + Point3 tyv = tzv ^ txv; + Point3 row1 = Point3(txv % _xv, txv % _yv, txv % _zv); + Point3 row2 = Point3(tyv % _xv, tyv % _yv, tyv % _zv); + Point3 row3 = Point3(tzv % _xv, tzv % _yv, tzv % _zv); + _bone = (SimpleObject2*)CreateInstance(GEOMOBJECT_CLASS_ID, BONE_OBJ_CLASSID); + _node = (MaxEggImporter::_ip)->CreateObjectNode(_bone); + if (_parent) { + _node->Detach(0, 1); + _parent->_node->AttachChild(_node, 1); + } + _node->SetNodeTM(0, Matrix3(_xv, _yv, _zv, _pos)); + _node->SetObjOffsetRot(Quat(Matrix3(row1, row2, row3, Point3(0,0,0)))); + IParamBlock2 *blk = _bone->pblock2; + for (int i=0; iNumParams(); i++) { + TSTR n = blk->GetLocalName(i); + if (strcmp(n, "Length")==0) blk->SetValue(i,0,(float)len); + else if (strcmp(n, "Width")==0) blk->SetValue(i,0,(float)_thickness); + else if (strcmp(n, "Height")==0) blk->SetValue(i,0,(float)_thickness); + } + Point3 boneColor = GetUIColor(COLOR_BONES); + _node->SetWireColor(RGB(int(boneColor.x*255.0f), int(boneColor.y*255.0f), int(boneColor.z*255.0f) )); + _node->SetBoneNodeOnOff(TRUE, 0); + _node->SetRenderable(FALSE); + _node->SetName((TCHAR*)(_egg_joint->get_name().c_str())); +} + + //////////////////////////////////////////////////////////////////////////////////////////////////// // // TraverseEggData @@ -375,7 +535,10 @@ void MaxEggImporter::TraverseEggNode(EggNode *node, EggGroup *context) EggGroupNode *group = DCAST(EggGroupNode, node); if (node->is_of_type(EggGroup::get_class_type())) { EggGroup *group = DCAST(EggGroup, node); - if (group->is_joint()) context = group; + if (group->is_joint()) { + MakeJoint(group, context); + context = group; + } } EggGroupNode::const_iterator ci; for (ci = group->begin(); ci != group->end(); ++ci) { @@ -387,7 +550,13 @@ void MaxEggImporter::TraverseEggNode(EggNode *node, EggGroup *context) void MaxEggImporter::TraverseEggData(EggData *data) { lgfile = fopen("MaxEggImporter.log","w"); + + SuspendAnimate(); + SuspendSetKeyMode(); + AnimateOff(); + TraverseEggNode(data, NULL); + MeshIterator ci; for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) { MaxEggMesh *mesh = (*ci); @@ -401,6 +570,23 @@ void MaxEggImporter::TraverseEggData(EggData *data) mesh->_mesh->InvalidateGeomCache(); mesh->_mesh->buildNormals(); } + + double thickness = 0.0; + JointIterator ji; + for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) { + double dfo = ((*ji)->_pos).Length(); + if (dfo > thickness) thickness = dfo; + } + thickness = thickness * 0.025; + for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) { + MaxEggJoint *joint = *ji; + joint->ChooseEndPos(thickness); + joint->CreateMaxBone(); + } + + ResumeSetKeyMode(); + ResumeAnimate(); + if (lgfile) fclose(lgfile); }