Browse Source

Finished: Meshes & Bones. Unfinished: Materials, Skin Mod, Tex Matrix, Anim.

Josh Yelon 20 years ago
parent
commit
b34260896c
1 changed files with 209 additions and 23 deletions
  1. 209 23
      pandatool/src/maxeggimport/maxEggImport.cxx

+ 209 - 23
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<EggVertexPool *, MaxEggMesh *> MeshTable;
+  // Import-related fields:
+  typedef phash_map<EggVertexPool *, MaxEggMesh *> MeshTable;
   typedef second_of_pair_iterator<MeshTable::const_iterator> MeshIterator;
+  typedef phash_map<EggGroup *, MaxEggJoint *> JointTable;
+  typedef second_of_pair_iterator<JointTable::const_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 <MaxEggJoint *> _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; i<blk->NumParams(); 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);
 }