|
|
@@ -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);
|
|
|
}
|
|
|
|