1
0
forked from 0ad/0ad

Renaming new PMDExp

This was SVN commit r2388.
This commit is contained in:
Ykkrosh 2005-06-14 20:42:41 +00:00
parent 982bcf268d
commit 79b92f8a16
56 changed files with 6356 additions and 0 deletions

View File

@ -0,0 +1,34 @@
/DllEntry.cpp/1.2/Mon Jun 21 06:19:06 2004//
/ExpUtil.cpp/1.2/Mon Jun 21 06:19:06 2004//
/ExpUtil.h/1.2/Mon Jun 21 06:19:06 2004//
/MaxInc.h/1.2/Mon Jun 21 06:19:06 2004//
/PMDExp.dsw/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp.h/1.2/Mon Jun 21 06:19:06 2004//
/PMDExp.opt/1.1/Mon Jun 21 06:19:06 2004/-kb/
/PMDExp.pchs/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp.rc/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp5.def/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp5.dsp/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp6.def/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp6.dsp/1.1/Mon Jun 21 06:19:06 2004//
/PSAExp.h/1.2/Mon Jun 21 06:19:06 2004//
/PSProp.cpp/1.2/Mon Jun 21 06:19:06 2004//
/PSProp.h/1.2/Mon Jun 21 06:19:06 2004//
/Tree.h/1.2/Mon Jun 21 06:19:06 2004//
/VertexTree.h/1.2/Mon Jun 21 06:19:06 2004//
/mssccprj.scc/1.1/Mon Jun 21 06:19:06 2004//
/pmdexp.smp/1.1/Mon Jun 21 06:19:06 2004/-kb/
/resource.h/1.2/Mon Jun 21 06:19:06 2004//
/vssver.scc/1.1/Mon Jun 21 06:19:06 2004/-kb/
/VNormal.cpp/1.2/Thu Aug 5 05:23:00 2004//
/VNormal.h/1.2/Thu Aug 5 05:22:30 2004//
/ExpMesh.cpp/1.2/Mon Nov 22 00:36:42 2004//
/ExpMesh.h/1.2/Mon Nov 22 00:36:42 2004//
/ExpProp.cpp/1.2/Mon Nov 22 00:36:42 2004//
/ExpProp.h/1.2/Mon Nov 22 00:36:42 2004//
/ExpSkeleton.cpp/1.2/Mon Nov 22 00:36:42 2004//
/ExpSkeleton.h/1.2/Mon Nov 22 00:36:42 2004//
/ExpVertex.h/1.2/Mon Nov 22 00:36:42 2004//
/PMDExp.cpp/1.2/Mon Nov 22 00:36:42 2004//
/PSAExp.cpp/1.2/Mon Nov 22 00:36:42 2004//
D

View File

@ -0,0 +1,33 @@
/DllEntry.cpp////
/ExpUtil.cpp////
/ExpUtil.h////
/MaxInc.h////
/PMDExp.dsw////
/PMDExp.h////
/PMDExp.opt////
/PMDExp.pchs////
/PMDExp.rc////
/PMDExp5.def////
/PMDExp5.dsp////
/PMDExp6.def////
/PMDExp6.dsp////
/PSAExp.h////
/PSProp.cpp////
/PSProp.h////
/Tree.h////
/VertexTree.h////
/mssccprj.scc////
/pmdexp.smp////
/resource.h////
/vssver.scc////
/VNormal.cpp////
/VNormal.h////
/ExpMesh.cpp////
/ExpMesh.h////
/ExpProp.cpp////
/ExpProp.h////
/ExpSkeleton.cpp////
/ExpSkeleton.h////
/ExpVertex.h////
/PMDExp.cpp////
/PSAExp.cpp////

View File

@ -0,0 +1,33 @@
/DllEntry.cpp////
/ExpUtil.cpp////
/ExpUtil.h////
/MaxInc.h////
/PMDExp.dsw////
/PMDExp.h////
/PMDExp.opt////
/PMDExp.pchs////
/PMDExp.rc////
/PMDExp5.def////
/PMDExp5.dsp////
/PMDExp6.def////
/PMDExp6.dsp////
/PSAExp.h////
/PSProp.cpp////
/PSProp.h////
/Tree.h////
/VertexTree.h////
/mssccprj.scc////
/pmdexp.smp////
/resource.h////
/vssver.scc////
/VNormal.cpp////
/VNormal.h////
/ExpMesh.cpp////
/ExpMesh.h////
/ExpProp.cpp////
/ExpProp.h////
/ExpSkeleton.cpp////
/ExpSkeleton.h////
/ExpVertex.h////
/PMDExp.cpp////
/PSAExp.cpp////

View File

@ -0,0 +1,34 @@
/DllEntry.cpp/1.2/Mon Jun 21 06:19:06 2004//
/ExpUtil.cpp/1.2/Mon Jun 21 06:19:06 2004//
/ExpUtil.h/1.2/Mon Jun 21 06:19:06 2004//
/MaxInc.h/1.2/Mon Jun 21 06:19:06 2004//
/PMDExp.dsw/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp.h/1.2/Mon Jun 21 06:19:06 2004//
/PMDExp.opt/1.1/Mon Jun 21 06:19:06 2004/-kb/
/PMDExp.pchs/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp.rc/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp5.def/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp5.dsp/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp6.def/1.1/Mon Jun 21 06:19:06 2004//
/PMDExp6.dsp/1.1/Mon Jun 21 06:19:06 2004//
/PSAExp.h/1.2/Mon Jun 21 06:19:06 2004//
/PSProp.cpp/1.2/Mon Jun 21 06:19:06 2004//
/PSProp.h/1.2/Mon Jun 21 06:19:06 2004//
/Tree.h/1.2/Mon Jun 21 06:19:06 2004//
/VertexTree.h/1.2/Mon Jun 21 06:19:06 2004//
/mssccprj.scc/1.1/Mon Jun 21 06:19:06 2004//
/pmdexp.smp/1.1/Mon Jun 21 06:19:06 2004/-kb/
/resource.h/1.2/Mon Jun 21 06:19:06 2004//
/vssver.scc/1.1/Mon Jun 21 06:19:06 2004/-kb/
/VNormal.cpp/1.2/Thu Aug 5 05:23:00 2004//
/VNormal.h/1.2/Thu Aug 5 05:22:30 2004//
/ExpMesh.cpp/1.2/Wed Sep 15 01:09:02 2004//
/ExpMesh.h/1.2/Wed Sep 15 01:09:02 2004//
/ExpProp.cpp/1.2/Wed Sep 15 01:09:02 2004//
/ExpProp.h/1.2/Wed Sep 15 01:09:02 2004//
/ExpSkeleton.cpp/1.2/Wed Sep 15 01:09:02 2004//
/ExpSkeleton.h/1.2/Wed Sep 15 01:09:02 2004//
/ExpVertex.h/1.2/Wed Sep 15 01:09:02 2004//
/PMDExp.cpp/1.2/Wed Sep 15 01:09:02 2004//
/PSAExp.cpp/1.2/Wed Sep 15 01:09:02 2004//
D

View File

@ -0,0 +1 @@
source/tools/pmdexp

View File

@ -0,0 +1 @@
:pserver:notpete@wfg.serveftp.com:/cvs/wfg

View File

@ -0,0 +1,2 @@
DirStatus=In CVS
DirStatusRecursive=In CVS

View File

@ -0,0 +1,125 @@
/**********************************************************************
*<
FILE: DllEntry.cpp
DESCRIPTION: Contains the Dll Entry stuff
CREATED BY:
HISTORY:
*> Copyright (c) 2000, All Rights Reserved.
**********************************************************************/
#include "PMDExp.h"
#include "PSAExp.h"
#include "PSProp.h"
#include "MaxInc.h"
#define PMDEXP_CLASS_ID Class_ID(0x71d92656, 0x136330c5)
#define PSAEXP_CLASS_ID Class_ID(0x6cf86c73, 0x54e0844)
HINSTANCE hInstance;
static int controlsInit = FALSE;
TCHAR* GetString(int id)
{
static TCHAR buf[256];
if (hInstance) {
if (!LoadString(hInstance, id, buf, sizeof(buf))) {
return NULL;
}
return buf;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////////////////
// PMDExpClassDesc: required class to expose PMDExp to MAX
class PMDExpClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void * Create(BOOL loading = FALSE) { return new PMDExp(); }
const TCHAR * ClassName() { return GetString(IDS_PSA_CLASS_NAME); }
SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
Class_ID ClassID() { return PMDEXP_CLASS_ID; }
const TCHAR* Category() { return GetString(IDS_CATEGORY); }
const TCHAR* InternalName() { return _T("PMDExp"); }
HINSTANCE HInstance() { return hInstance; }
};
static PMDExpClassDesc PMDExpDesc;
ClassDesc2* GetPMDExpDesc() { return &PMDExpDesc; }
//////////////////////////////////////////////////////////////////////////////////////
// PSAExpClassDesc: required class to expose PSAExp to MAX
class PSAExpClassDesc : public ClassDesc2
{
public:
int IsPublic() { return TRUE; }
void * Create(BOOL loading = FALSE) { return new PSAExp(); }
const TCHAR * ClassName() { return GetString(IDS_PSA_CLASS_NAME); }
SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
Class_ID ClassID() { return PSAEXP_CLASS_ID; }
const TCHAR* Category() { return GetString(IDS_CATEGORY); }
const TCHAR* InternalName() { return _T("PSAExp"); }
HINSTANCE HInstance() { return hInstance; }
};
static PSAExpClassDesc PSAExpDesc;
ClassDesc2* GetPSAExpDesc() { return &PSAExpDesc; }
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
{
hInstance = hinstDLL; // Hang on to this DLL's instance handle.
if (!controlsInit) {
controlsInit = TRUE;
InitCustomControls(hInstance); // Initialize MAX's custom controls
InitCommonControls(); // Initialize Win95 controls
}
return (TRUE);
}
__declspec(dllexport) const TCHAR* LibDescription()
{
return GetString(IDS_LIBDESCRIPTION);
}
__declspec(dllexport) int LibNumberClasses()
{
return 3;
}
__declspec(dllexport) ClassDesc* LibClassDesc(int i)
{
switch(i) {
case 0: return GetPMDExpDesc();
case 1: return GetPSAExpDesc();
case 2: return GetPSPropDesc();
default: return 0;
}
}
__declspec(dllexport) ULONG LibVersion()
{
return VERSION_3DSMAX;
}
__declspec( dllexport ) ULONG CanAutoDefer()
{
return 1;
}

View File

@ -0,0 +1,463 @@
#include "ExpMesh.h"
#include "ExpUtil.h"
#include "ExpSkeleton.h"
#include "VertexTree.h"
#include "VNormal.h"
#include "phyexp.h"
////////////////////////////////////////////////////////////////////////////////
// TMNegParity: return whether the given matrix has a negative scale or not
inline bool TMNegParity(Matrix3 &Mat)
{
return (DotProd(CrossProd(Mat.GetRow(0),Mat.GetRow(1)),Mat.GetRow(2)) < 0.0) ? 1 : 0;
}
////////////////////////////////////////////////////////////////////////////////
// GetTriObjectFromNode: return a pointer to a TriObject
// given an INode or return NULL if the node cannot be converted
// to a TriObject
static TriObject* GetTriObjectFromNode(INode* node,bool& deleteIt)
{
deleteIt = false;
Object* obj=node->EvalWorldState(0).obj;
if (obj) {
if (obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) {
TriObject *tri=(TriObject*) obj->ConvertToType(0,Class_ID(TRIOBJ_CLASS_ID,0));
// note that the TriObject should only be deleted if the pointer to it is
// not equal to the object pointer that called ConvertToType()
if (obj != tri) {
deleteIt = true;
}
return tri;
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// GetPhysiqueFromNode: return a pointer to a Physique modifier found
// in the modifier stack of the given INode, or return NULL is no Physique
// modifier can be found
static Modifier* GetPhysiqueFromNode(INode* node)
{
// Get object from node. Abort if no object.
Object* object=node->GetObjectRef();
if (!object) return 0;
// ss derived object?
if (object->SuperClassID()==GEN_DERIVOB_CLASS_ID) {
// yes -> cast
IDerivedObject* derivedObj=static_cast<IDerivedObject*>(object);
// iterate over all entries of the modifier stack
int modStackIndex=0;
while (modStackIndex<derivedObj->NumModifiers()) {
// get current modifier
Modifier* modifier=derivedObj->GetModifier(modStackIndex);
Class_ID clsid=modifier->ClassID();
// check if it's a Physique
if (modifier->ClassID()==Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B)) {
// yes -> return it
return modifier;
}
// advance to next modifier stack entry
modStackIndex++;
}
}
// not found ..
return 0;
}
PMDExpMesh::PMDExpMesh(INode* node,const ExpSkeleton* skeleton)
: m_Node(node), m_Skeleton(skeleton)
{
}
bool PMDExpMesh::IsMesh(Object* obj)
{
assert(obj);
if (obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) {
return true;
} else {
return false;
}
}
////////////////////////////////////////////////////////////////////////////////
// InsertBlend: insert the given bone/weight blend into the given blend set
void PMDExpMesh::InsertBlend(unsigned char bone,float weight,SVertexBlend& blend)
{
// get position where this blend should be inserted
int i=0;
while (weight<blend.m_Weight[i]) i++;
if (i>=SVertexBlend::SIZE) {
// all other blends carry greater weight; reject this blend
return;
}
for (int j=SVertexBlend::SIZE-2;j>=i;j--) {
blend.m_Bone[j+1]=blend.m_Bone[j];
blend.m_Weight[j+1]=blend.m_Weight[j];
}
blend.m_Bone[i]=bone;
blend.m_Weight[i]=weight;
}
void PMDExpMesh::BuildVertexBlends(Mesh& mesh,VBlendList& blends)
{
// allocate blends
int numVerts=mesh.getNumVerts();
blends.resize(mesh.getNumVerts());
// set all blends to null
for (int i=0;i<numVerts;i++) {
memset(blends[i].m_Bone,0xff,sizeof(blends[i].m_Bone));
memset(blends[i].m_Weight,0,sizeof(blends[i].m_Weight));
}
// query presence of physique modifier first
Modifier* physique=GetPhysiqueFromNode(m_Node);
if (!physique) {
// no Physique, no blends: no support for Skin at present
// LogError("No physique export");
return;
}
// get physique export interface
IPhysiqueExport *phyExport=(IPhysiqueExport*) physique->GetInterface(I_PHYINTERFACE);
if(phyExport) {
// get ModContext interface from export interface for this INode
IPhyContextExport *contextExport=(IPhyContextExport*) phyExport->GetContextInterface(m_Node);
if(contextExport) {
// export all the vertices as if they are rigid ..
contextExport->ConvertToRigid(TRUE);
// .. and disable blending
contextExport->AllowBlending(FALSE);
// check number of vertices assigned to physique matches mesh total
if (contextExport->GetNumberVertices()!=mesh.getNumVerts()) {
// LogError("vtx mismatch!\n");
return;
}
for (int i=0;i<numVerts;i++) {
SVertexBlend& blend=blends[i];
// get export interface for this vertex
IPhyVertexExport* vertexexport=contextExport->GetVertexInterface(i);
if (vertexexport) {
// get type of vertex
int type=vertexexport->GetVertexType();
if (type==RIGID_TYPE) {
IPhyRigidVertex* rigidVertex=(IPhyRigidVertex*) vertexexport;
// get attached bone
INode* boneNode=rigidVertex->GetNode();
if (boneNode) {
// store blend
blend.m_Bone[0]=m_Skeleton->FindBoneByNode(boneNode);
if (blend.m_Bone[0]==0xff) {
// LogError("Failed to find bonenode %s (0x%p)\n",boneNode->GetName(),boneNode);
}
blend.m_Weight[0]=1.0f;
}
} else {
// must be RIGID_BLENDED_TYPE vertex
IPhyBlendedRigidVertex* blendedVertex=(IPhyBlendedRigidVertex*) vertexexport;
// get number of nodes affecting vertex; clamp to SVertexBlend::SIZE
int numBones=blendedVertex->GetNumberNodes();
for (int boneindex=0;boneindex<numBones;boneindex++) {
// get weight of boneindex'th bone
float boneWeight=blendedVertex->GetWeight(boneindex);
if (boneWeight>0.001f) {
// get boneindex'th bone
INode* boneNode=blendedVertex->GetNode(boneindex);
// store blend - (need to check for prior bones using same bone?)
unsigned char bone=m_Skeleton->FindBoneByNode(boneNode);
if (bone==0xff) {
//LogError("Failed to find bonenode %s (0x%p)\n",boneNode->GetName(),boneNode);
} else {
InsertBlend(bone,boneWeight,blend);
}
}
}
#if 0
if (blend.m_Bone[0]==0xff) {
// ugh - all bones must have zero weight .. use the root bone with a weight of 1?
blend.m_Bone[0]=0;
blend.m_Weight[0]=1;
}
#else
if (blend.m_Bone[0]==0xff) {
// ugh - all bones must have zero weight .. try again and assign all bones equal weight
// TODO, RC 13/03/04 - log warning for this; most likely user error in enveloping/bone assignment
for (boneindex=0;boneindex<numBones;boneindex++) {
float boneWeight=1.0f;
// get boneindex'th bone
INode* boneNode=blendedVertex->GetNode(boneindex);
// store blend - (need to check for prior bones using same bone?)
unsigned char bone=m_Skeleton->FindBoneByNode(boneNode);
if (bone==0xff) {
//LogError("Failed to find bonenode %s (0x%p)\n",boneNode->GetName(),boneNode);
} else {
InsertBlend(bone,boneWeight,blend);
}
}
}
#endif
// normalise bone weights of this blend such that they sum to 1
int j;
float totalweight=0;
for (j=0;j<SVertexBlend::SIZE && blend.m_Bone[j]!=0xff;j++) {
totalweight+=blend.m_Weight[j];
}
for (j=0;j<SVertexBlend::SIZE && blend.m_Bone[j]!=0xff;j++) {
blend.m_Weight[j]/=totalweight;
}
}
// done with this vertex
contextExport->ReleaseVertexInterface(vertexexport);
} else {
//LogError("No vertexexport interface!\n");
}
}
} else {
//LogError("No contextexport interface!\n");
}
}
}
static CVector3D SkinVertex(const ExpSkeleton* skeleton,const CVector3D& pos,const SVertexBlend& blend)
{
CVector3D result(0,0,0);
for (int i=0;i<SVertexBlend::SIZE && blend.m_Bone[i]!=0xff;i++) {
const CMatrix3D& m=skeleton->m_Bones[blend.m_Bone[i]]->m_Transform;
CVector3D tmp=m.Transform(pos);
result+=tmp*blend.m_Weight[i];
}
return result;
}
static CVector3D SkinNormal(const ExpSkeleton* skeleton,const CVector3D& pos,const SVertexBlend& blend)
{
CMatrix3D minv,minvtrans;
CVector3D result(0,0,0);
for (int i=0;i<SVertexBlend::SIZE && blend.m_Bone[i]!=0xff;i++) {
const CMatrix3D& m=skeleton->m_Bones[blend.m_Bone[i]]->m_Transform;
m.GetInverse(minv);
minv.GetTranspose(minvtrans);
CVector3D tmp=minvtrans.Transform(pos);
result+=tmp*blend.m_Weight[i];
}
return result;
}
static CVector3D UnskinPoint(const ExpSkeleton* skeleton,const CVector3D& pos,const SVertexBlend& blend)
{
CMatrix3D m,minv;
m.SetZero();
for (int i=0;i<SVertexBlend::SIZE && blend.m_Bone[i]!=0xff;i++) {
const CMatrix3D& m2=skeleton->m_Bones[blend.m_Bone[i]]->m_Transform;
m+=m2*blend.m_Weight[i];
}
m.GetInverse(minv);
return minv.Transform(pos);
}
static CVector3D UnskinNormal(const ExpSkeleton* skeleton,const CVector3D& nrm,const SVertexBlend& blend)
{
CMatrix3D m,minv,minvtrans;
m.SetZero();
for (int i=0;i<SVertexBlend::SIZE && blend.m_Bone[i]!=0xff;i++) {
const CMatrix3D& m2=skeleton->m_Bones[blend.m_Bone[i]]->m_Transform;
m+=m2*blend.m_Weight[i];
}
m.GetInverse(minv);
minv.GetTranspose(minvtrans);
minvtrans.GetInverse(m);
return m.Rotate(nrm);
}
CVector3D* PMDExpMesh::BuildVertexPoints(Mesh& mesh,VBlendList& vblends)
{
// get transform to world space
Matrix3 tm=m_Node->GetObjectTM(0);
bool negScale=TMNegParity(tm);
int numverts=mesh.getNumVerts();
CVector3D* transPts=new CVector3D[numverts];
// transform each vertex and store in output array
for (int i=0;i<numverts;i++) {
Point3 maxpos=mesh.getVert(i)*tm;
transPts[i]=CVector3D(maxpos.x,maxpos.z,maxpos.y);
}
if (m_Skeleton) {
BuildVertexBlends(mesh,vblends);
for (i=0;i<numverts;i++) {
transPts[i]=UnskinPoint(m_Skeleton,transPts[i],vblends[i]);
}
}
return transPts;
}
VNormal* PMDExpMesh::BuildVertexNormals(Mesh& mesh,VBlendList& vblends)
{
// get transform to world space
Matrix3 tm=m_Node->GetObjectTM(0);
bool negScale=TMNegParity(tm);
// allocate basis vectors for dot product lighting
VNormal* vnormals=new VNormal[mesh.getNumVerts()];
for (u32 i=0;i<mesh.getNumFaces();++i) {
// build face normal
Point3 P0=mesh.getVert(mesh.faces[i].v[0])*tm;
Point3 P1=mesh.getVert(mesh.faces[i].v[1])*tm;
Point3 P2=mesh.getVert(mesh.faces[i].v[2])*tm;
Point3 e0=P1-P0;
Point3 e1=P2-P0;
Point3 faceNormal=e0^e1;
if (negScale) faceNormal*=-1;
CVector3D N(faceNormal.x,faceNormal.z,faceNormal.y);
N.Normalize();
// accumulate normal
vnormals[mesh.faces[i].v[0]].add(N,mesh.faces[i].smGroup);
vnormals[mesh.faces[i].v[1]].add(N,mesh.faces[i].smGroup);
vnormals[mesh.faces[i].v[2]].add(N,mesh.faces[i].smGroup);
}
for (i=0;i<mesh.getNumVerts();i++) {
if (m_Skeleton) {
VNormal* vnorm=&vnormals[i];
vnorm->normalize();
while (vnorm) {
vnorm->_normal=UnskinNormal(m_Skeleton,vnorm->_normal,vblends[i]);
vnorm=vnorm->next;
}
}
vnormals[i].normalize();
}
// .. and return them
return vnormals;
}
void PMDExpMesh::BuildVerticesAndFaces(Mesh& mesh,VertexList& vertices,CVector3D* vpoints,VBlendList& vblends,VNormal* vnormals,FaceList& faces)
{
// assume worst case and reserve enough space up front ..
u32 numFaces=mesh.getNumFaces();
vertices.reserve(numFaces*3);
// initialise outgoing face array
faces.resize(numFaces);
// create a vertex tree setup to fill unique vertices into outgoing array
VertexTree<UniqueVertexCmp> vtxtree(vertices);
// get transform to world space
Matrix3 tm=m_Node->GetObjectTM(0);
bool negScale=TMNegParity(tm);
// iterate through faces
for (u32 i=0;i<numFaces;++i) {
for (int k=0;k<3;++k) {
ExpVertex vtx;
vtx.m_Index=mesh.faces[i].v[k];
// get position
vtx.m_Pos=vpoints[vtx.m_Index];
// get UVs
if (mesh.getNumTVerts()) {
const TVFace& tvface=mesh.tvFace[i];
const UVVert& uv=mesh.getTVert(tvface.t[k]);
vtx.m_UVs[0]=uv.x;
vtx.m_UVs[1]=uv.y;
} else {
vtx.m_UVs[0]=0;
vtx.m_UVs[1]=0;
}
VNormal* vnrm=vnormals[mesh.faces[i].v[k]].get(mesh.faces[i].smGroup);
vtx.m_Normal=vnrm ? vnrm->_normal : CVector3D(0,0,0);
faces[i].m_V[k]=vtxtree.insert(vtx);
}
if (negScale) {
int t=faces[i].m_V[1];
faces[i].m_V[1]=faces[i].m_V[2];
faces[i].m_V[2]=t;
}
faces[i].m_MAXindex=i;
faces[i].m_Smooth=mesh.faces[i].smGroup;
}
}
ExpMesh* PMDExpMesh::Build()
{
// get mesh from node
bool delTriObj;
TriObject* triObj=GetTriObjectFromNode(m_Node,delTriObj);
Mesh& mesh=triObj->mesh;
ExpMesh* expmesh=new ExpMesh;
// build vertex positions/blends from given mesh data
CVector3D* vpoints=BuildVertexPoints(mesh,expmesh->m_Blends);
// build vertex normals from mesh data and vertex positions
VNormal* vnormals=BuildVertexNormals(mesh,expmesh->m_Blends);
// build face and vertex lists
BuildVerticesAndFaces(mesh,expmesh->m_Vertices,vpoints,expmesh->m_Blends,vnormals,expmesh->m_Faces);
// clean up ..
delete[] vnormals;
delete[] vpoints;
if (delTriObj) {
triObj->DeleteThis();
}
return expmesh;
}

View File

@ -0,0 +1,81 @@
#ifndef __EXPMESH_H
#define __EXPMESH_H
#include <vector>
#include "MaxInc.h"
#include "lib\types.h"
#include "Vector3D.h"
#include "ExpVertex.h"
class VNormal;
class ExpSkeleton;
////////////////////////////////////////////////////////////////////////
// ExpFace: face declaration used in building mesh geometry
struct ExpFace {
// vertex indices
u32 m_V[3];
// index of this face in max's face list (necessary, since extra
// faces may be created in fixing t-junctions, but it's still
// necessary to map back to MAX for eg. getting material on face)
u32 m_MAXindex;
// smoothing group
u32 m_Smooth;
// face normal
CVector3D m_Normal;
// face area
float m_Area;
};
// handy typedefs
typedef std::vector<u32> IndexList;
typedef std::vector<CVector3D> PointList;
typedef std::vector<ExpFace> FaceList;
typedef std::vector<ExpVertex> VertexList;
typedef std::vector<SVertexBlend> VBlendList;
////////////////////////////////////////////////////////////////////////
// ExpMesh: mesh type used in building mesh geometry
class ExpMesh
{
public:
// list of faces in mesh
FaceList m_Faces;
// list of vertices used by mesh
VertexList m_Vertices;
// list of vertex blends used by mesh
VBlendList m_Blends;
};
////////////////////////////////////////////////////////////////////////
// PMDExpMesh: class used for building output meshes
class PMDExpMesh
{
public:
PMDExpMesh(INode* node,const ExpSkeleton* skeleton);
static bool IsMesh(Object* obj);
ExpMesh* Build();
private:
// the node we're constructing the mesh from
INode* m_Node;
// the skeleton attached to the mesh, if any
const ExpSkeleton* m_Skeleton;
// construct list of vertices and faces used by mesh
void BuildVerticesAndFaces(Mesh& mesh,VertexList& vertices,CVector3D* vpoints,VBlendList& vblends,VNormal* vnormals,FaceList& faces);
// build and return vertex normals, accounting for smoothing groups
VNormal* BuildVertexNormals(Mesh& mesh,VBlendList& vblends);
// build and return vertex blends (determined by Physique), if any
void BuildVertexBlends(Mesh& mesh,VBlendList& blends);
// insert the given bone/weight blend into the given blend set
void InsertBlend(unsigned char bone,float weight,SVertexBlend& blend);
CVector3D* BuildVertexPoints(Mesh& mesh,VBlendList& vblends);
};
#endif

View File

@ -0,0 +1,44 @@
#include "PSProp.h"
#include "ExpProp.h"
#include "ExpUtil.h"
#include "decomp.h"
PMDExpProp::PMDExpProp(INode* node) : m_Node(node)
{
}
bool PMDExpProp::IsProp(Object* obj)
{
return obj->ClassID()==PSPROP_CLASS_ID ? true : false;
}
ExpProp* PMDExpProp::Build()
{
ExpProp* prop=new ExpProp;
prop->m_Name=m_Node->GetName();
prop->m_Parent=m_Node->GetParentNode();
// build local transformation matrix
INode *parent;
Matrix3 parentTM, nodeTM, localTM;
nodeTM = m_Node->GetNodeTM(0);
parent = m_Node->GetParentNode();
parentTM = parent->GetNodeTM(0);
localTM = nodeTM*Inverse(parentTM);
// decompose it to get translation and rotation
AffineParts parts;
decomp_affine(localTM,&parts);
// get translation from affine parts
MAXtoGL(parts.t);
prop->m_Position=CVector3D(parts.t.x,parts.t.y,parts.t.z);
// get rotation from affine parts
prop->m_Rotation.m_V.X=parts.q.x;
prop->m_Rotation.m_V.Y=parts.q.z;
prop->m_Rotation.m_V.Z=parts.q.y;
prop->m_Rotation.m_W=parts.q.w;
return prop;
}

View File

@ -0,0 +1,38 @@
#ifndef _EXPPROP_H
#define _EXPPROP_H
#include <string>
#include "Vector3D.h"
#include "Quaternion.h"
////////////////////////////////////////////////////////////////////////
// ExpProp: prop object used on export
class ExpProp
{
public:
// name of prop
std::string m_Name;
// position relative to parent
CVector3D m_Position;
// rotation relative to parent
CQuaternion m_Rotation;
// parent node
INode* m_Parent;
};
////////////////////////////////////////////////////////////////////////
// PMDExpProp: class used for building output props
class PMDExpProp
{
public:
PMDExpProp(INode* node);
static bool IsProp(Object* obj);
ExpProp* Build();
private:
// the node we're constructing the prop from
INode* m_Node;
};
#endif

View File

@ -0,0 +1,173 @@
#include "ExpSkeleton.h"
#include "ExpUtil.h"
#include "bipexp.h"
#include "decomp.h"
#include "ModelDef.h"
#include "SkeletonAnimDef.h"
/////////////////////////////////////////////////////////////////////////////////
// ExpSkeleton constructor
ExpSkeleton::ExpSkeleton()
{
}
/////////////////////////////////////////////////////////////////////////////////
// ExpSkeleton destructor
ExpSkeleton::~ExpSkeleton()
{
for (int i=0;i<m_Bones.size();i++) {
delete m_Bones[i];
}
}
/////////////////////////////////////////////////////////////////////////////////
// IsFootprints: return true if given node is biped footprints, else false
bool ExpSkeleton::IsFootprints(INode* node)
{
// get nodes transform control
Control* c=node->GetTMController();
// check classID for footprints
return (c && (c->ClassID()==FOOTPRINT_CLASS_ID)) ? true : false;
}
/////////////////////////////////////////////////////////////////////////////////
// IsBone: return true if given node is a skeletal biped bone, else false
bool ExpSkeleton::IsBone(INode* node)
{
// get nodes transform control
Control* c=node->GetTMController();
// check classID for either a root or a child bone
return (c && (c->ClassID()==BIPSLAVE_CONTROL_CLASS_ID || c->ClassID()==BIPBODY_CONTROL_CLASS_ID)) ? true : false;
}
/////////////////////////////////////////////////////////////////////////////////
// IsSkeleton: return true if given node is the root of a skeleton, else false
bool ExpSkeleton::IsSkeletonRoot(INode* node)
{
// get nodes transform control
Control* c=node->GetTMController();
// check for biped root
return (c && c->ClassID()==BIPBODY_CONTROL_CLASS_ID) ? true : false;
}
/////////////////////////////////////////////////////////////////////////////////
// BuildSkeletons: build all skeletons from given root node
void ExpSkeleton::BuildSkeletons(INode* node,std::vector<ExpSkeleton*>& skeletons)
{
if (IsSkeletonRoot(node)) {
// build skeleton from this node - Build traverses all children
// of given node
ExpSkeleton* skeleton=new ExpSkeleton;
skeleton->Build(node,0);
skeletons.push_back(skeleton);
} else {
// traverse into children as this object wasn't a skeleton root
for (int i=0;i<node->NumberOfChildren();i++) {
BuildSkeletons(node->GetChildNode(i),skeletons);
}
}
}
////////////////////////////////////////////////////////////////////////////////
// FindBoneByNode: search skeleton looking for matching bone using given node;
// return index of given node in the skeleton, 0xff if not found
u8 ExpSkeleton::FindBoneByNode(INode* boneNode) const
{
if (!boneNode) return 0xff;
for (int j=0;j<m_Bones.size();j++) {
ExpBone* bone=m_Bones[j];
if (bone->m_Node==boneNode) return j;
}
return 0xff;
}
/////////////////////////////////////////////////////////////////////////////////
// Build: traverse node heirachy adding bones to skeleton
void ExpSkeleton::Build(INode* node,ExpBone* parent)
{
if (IsBone(node)) {
// build bone
ExpBone* bone=new ExpBone;
bone->m_Node=node;
bone->m_Parent=parent;
// get bone's translation and rotation relative to root at time 0
GetBoneTransformComponents(node,0,bone->m_Translation,bone->m_Rotation);
// build transform from bone to object space
CMatrix3D m;
bone->m_Transform.SetIdentity();
bone->m_Transform.Rotate(bone->m_Rotation);
bone->m_Transform.Translate(bone->m_Translation);
// add bone to parent's list of children and complete bone list
if (parent) parent->m_Children.push_back(bone);
m_Bones.push_back(bone);
char buf[256];
sprintf(buf,"bonenode 0x%p (%s) added\n",node,node->GetName());
OutputDebugString(buf);
for (int i=0;i<node->NumberOfChildren();i++) {
Build(node->GetChildNode(i),bone);
}
}
}
/////////////////////////////////////////////////////////////////////////////////
// BuildAnimation: build and return a complete animation for this skeleton over
// given time range
CSkeletonAnimDef* ExpSkeleton::BuildAnimation(TimeValue start,TimeValue end,float rate)
{
CSkeletonAnimDef* anim=new CSkeletonAnimDef;
strcpy(anim->m_Name,"God Knows");
anim->m_NumFrames=1+(end-start)/rate;
anim->m_NumKeys=m_Bones.size();
anim->m_FrameTime=rate;
anim->m_Keys=new CSkeletonAnimDef::Key[anim->m_NumFrames*anim->m_NumKeys];
u32 counter=0;
TimeValue t=start;
while (t<end) {
for (int i=0;i<m_Bones.size();i++) {
CSkeletonAnimDef::Key& key=anim->m_Keys[counter++];
GetBoneTransformComponents(m_Bones[i]->m_Node,t,key.m_Translation,key.m_Rotation);
}
t+=rate;
}
return anim;
}
///////////////////////////////////////////////////////////////////////////////////////
// GetBoneTransformComponents: calculate the translation and rotation
// values of the given bone, relative to the root bone, at the given time
void ExpSkeleton::GetBoneTransformComponents(INode* node,TimeValue t,
CVector3D& trans,CQuaternion& rot)
{
Matrix3 nodeTM=node->GetNodeTM(t);
nodeTM.NoScale();
// decompose it to get translation and rotation
AffineParts parts;
decomp_affine(nodeTM,&parts);
// get translation from affine parts
MAXtoGL(parts.t);
trans=CVector3D(parts.t.x,parts.t.y,parts.t.z);
// get rotation from affine parts
rot.m_V.X=parts.q.x;
rot.m_V.Y=parts.q.z;
rot.m_V.Z=parts.q.y;
rot.m_W=parts.q.w;
}

View File

@ -0,0 +1,74 @@
#ifndef __EXPSKELETON_H
#define __EXPSKELETON_H
#include <vector>
#include "MaxInc.h"
#include "Matrix3D.h"
#include "Vector3D.h"
#include "Quaternion.h"
#include "lib/types.h"
class CSkeleton;
class CSkeletonAnimDef;
////////////////////////////////////////////////////////////////////////
// ExpBone: bone type used during export
class ExpBone
{
public:
// MAX bone node
INode* m_Node;
// transform from object to this bones space at time 0
CMatrix3D m_Transform;
// translation relative to root bone at time 0
CVector3D m_Translation;
// rotation relative to root bone at time 0
CQuaternion m_Rotation;
// parent of this bone; 0 for root bone
ExpBone* m_Parent;
// children of this bone
std::vector<ExpBone*> m_Children;
};
////////////////////////////////////////////////////////////////////////
// ExpSkeleton:
class ExpSkeleton
{
public:
////////////////////////////////////////////////////////////////////////
// static methods for skeleton creation, destruction and type queries:
// build all skeletons from given root node
static void BuildSkeletons(INode* node,std::vector<ExpSkeleton*>& skeletons);
// return true if given node is a skeletal biped bone, else false
static bool IsBone(INode* node);
// return true if given node is biped footprints, else false
static bool IsFootprints(INode* node);
// return true if given node is the root of a skeleton, else false
static bool IsSkeletonRoot(INode* node);
public:
// constructor, destructor
ExpSkeleton();
~ExpSkeleton();
// search skeleton looking for matching bone using given node;
// return index of given node in the skeleton, 0xff if not found
u8 FindBoneByNode(INode* boneNode) const;
// build and return a complete animation for this skeleton over given time range
CSkeletonAnimDef* BuildAnimation(TimeValue start,TimeValue end,float rate);
private:
// traverse node heirachy adding bones to skeleton
void Build(INode* node,ExpBone* parent=0);
// calculate the translation and rotation values of the given bone,
// relative to the root bone, at the given time
void GetBoneTransformComponents(INode* node,TimeValue t,CVector3D& trans,CQuaternion& rot);
public:
// list of bones in skeleton; root bone is m_Bones[0]
std::vector<ExpBone*> m_Bones;
};
#endif

View File

@ -0,0 +1,12 @@
#include "MaxInc.h"
#include "ExpUtil.h"
//////////////////////////////////////////////////////////////////////
// MAXtoGL: convert point from MAX's coordinate system to that used
// within the engine
void MAXtoGL(Point3 &pnt)
{
float tmp = pnt.y;
pnt.y = pnt.z;
pnt.z = tmp;
}

View File

@ -0,0 +1,9 @@
#ifndef _EXPUTIL_H
#define _EXPUTIL_H
class Point3;
extern void MAXtoGL(Point3 &pnt);
#endif

View File

@ -0,0 +1,22 @@
#ifndef __EXPVERTEX_H
#define __EXPVERTEX_H
#include "lib\types.h"
#include "Vector3D.h"
#include "ModelDef.h"
////////////////////////////////////////////////////////////////////////
// ExpVertex: vertex type used in building mesh geometry
struct ExpVertex {
// index into original meshes point list
unsigned int m_Index;
// object space position
CVector3D m_Pos;
// object space normal
CVector3D m_Normal;
// uv coordinates
float m_UVs[2];
};
#endif

View File

@ -0,0 +1,77 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: FilePacker.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "pmdexp_types.h"
#include "FilePacker.h"
#include <stdio.h>
////////////////////////////////////////////////////////////////////////////////////////
// CFilePacker constructor
CFilePacker::CFilePacker()
{
}
////////////////////////////////////////////////////////////////////////////////////////
// Write: write out any packed data to file, using given version and magic bits
void CFilePacker::Write(const char* filename,u32 version,const char magicstr[4])
{
FILE* fp=fopen(filename,"wb");
if (!fp) {
throw CFileOpenError();
}
// write magic bits
if (fwrite(magicstr,sizeof(char)*4,1,fp)!=1) {
fclose(fp);
throw CFileWriteError();
}
// write version
if (fwrite(&version,sizeof(version),1,fp)!=1) {
fclose(fp);
throw CFileWriteError();
}
// get size of data
u32 datasize=(u32)m_Data.size();
if (fwrite(&datasize,sizeof(datasize),1,fp)!=1) {
fclose(fp);
throw CFileWriteError();
}
// write out one big chunk of data
if (fwrite(&m_Data[0],datasize,1,fp)!=1) {
fclose(fp);
throw CFileWriteError();
}
// all done
fclose(fp);
}
////////////////////////////////////////////////////////////////////////////////////////
// PackRaw: pack given number of bytes onto the end of the data stream
void CFilePacker::PackRaw(const void* rawdata,u32 rawdatalen)
{
u32 start=(u32)m_Data.size();
m_Data.resize(m_Data.size()+rawdatalen);
memcpy(&m_Data[start],rawdata,rawdatalen);
}
////////////////////////////////////////////////////////////////////////////////////////
// PackString: pack a string onto the end of the data stream
void CFilePacker::PackString(const char* str)
{
u32 len=(u32)strlen(str);
PackRaw(&len,sizeof(len));
PackRaw((const char*) str,len);
}

View File

@ -0,0 +1,41 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: FilePacker.h
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _FILEPACKER_H
#define _FILEPACKER_H
#include <vector>
////////////////////////////////////////////////////////////////////////////////////////
// CFilePacker: class to assist in writing of binary files
class CFilePacker
{
public:
// CFilePacker exceptions
class CError { };
class CFileOpenError : public CError { };
class CFileWriteError : public CError { };
public:
// constructor
CFilePacker();
// Write: write out any packed data to file, using given version and magic bits
void Write(const char* filename,u32 version,const char magicstr[4]);
// PackRaw: pack given number of bytes onto the end of the data stream
void PackRaw(const void* rawdata,u32 rawdatalen);
// PackString: pack a string onto the end of the data stream
void PackString(const char* str);
private:
// the output data stream built during pack operations
std::vector<u8> m_Data;
};
#endif

View File

@ -0,0 +1,224 @@
#ifndef MATH_UTIL_H
#define MATH_UTIL_H
#ifndef PI
#define PI 3.14159265358979323846f
#endif
#define DEGTORAD(a) ((a) * (PI/180.0f))
#define RADTODEG(a) ((a) * (180.0f/PI))
#define SQR(x) ((x) * (x))
#define MAX3(a,b,c) ( MAX (MAX(a,b), c) )
#define ABS(a) ((a > 0) ? (a) : (-a))
template <typename T>
T Interpolate( T& a, T& b, float l )
{
return( a + ( b - a ) * l );
}
#if 0
/*
Math utility functions
by Michael Reiland
recondite_phreak@yahool.com
--Overview--
Contains common math functions like Abs, Sign, Max, Min, etc.
--More info--
TODO: actually write corresponding documentation
http://wildfiregames.com/0ad/codepit/TDD/math_utils.html
*/
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------
#include "Prometheus.h" // Standard Engine Include
#include <math.h> // Needed for fmod()
//--------------------------------------------------------
// Error declarations
//--------------------------------------------------------
// MathUtil Errors
DECLARE_ERROR(ERRONEOUS_BOUND_ERROR);
//--------------------------------------------------------
// Declarations
//--------------------------------------------------------
namespace MathUtil
{
const double PI = 3.14159265358932384;
const double FL_FP_TOLERANCE = .000000001;
//--------------------------------------------------------
// Template functions
//--------------------------------------------------------
//--------------------------------------------------------
// Declarations
//--------------------------------------------------------
//////////////////////////////////////////////////////////
// NAME: Abs
// PURPOSE: Calculates the Absolute value
//
template <typename T>
T Abs(const T &num)
{
if( num < 0)
return -1*num;
return num;
}
//////////////////////////////////////////////////////////
// NAME: Clamp
// PURPOSE: Forces num to be between lowerBound and upperBound
//
template <typename T>
T Clamp(T &num, const int &lowerBound,const int &upperBound)
{
if(num <= lowerBound)
num = static_cast<T>(lowerBound);
else if( num >= upperBound)
num = static_cast<T>(upperBound);
}
//////////////////////////////////////////////////////////
// NAME: Max
// PURPOSE: Returns the largest number.
//
template <typename T>
T Max(const T &num1, const T &num2)
{
if( num1 > num2)
return num1;
else
return num2;
}
//////////////////////////////////////////////////////////
// NAME: Min
// PURPOSE: Returns the smallest number.
//
template <typename T>
T Min(const T &num1, const T &num2)
{
if( num1 < num2)
return num1;
else
return num2;
}
//////////////////////////////////////////////////////////
// NAME: Sign
// PURPOSE: Returns 1 if the number is > 0, -1 if it's < 0,
// otherwise returns 0.
//
template <typename T>
int Sign(const T &num)
{
if( num > 0 )
return 1;
else if( num < 0 )
return -1;
else
return 0;
}
//////////////////////////////////////////////////////////
// NAME: Square
// PURPOSE: Returns the square of a number
// NOTES: Num should be less than the square root of the
// maximum representable number for the data type.
//
template <typename T>
inline double Square(const T &num)
{
return num*num;
}
//////////////////////////////////////////////////////////
// NAME: Swap
// PURPOSE: Swaps two numbers
//
template <typename T>
void Swap(T *num1, T *num2)
{
T temp = num1;
num1 = num2;
num2 = temp;
}
//////////////////////////////////////////////////////////
// NAME: Wrap
// PURPOSE: Wraps num between lowerBound and upperBound.
//
template <typename T>
int Wrap(T *num,const T &lowerBound, const T &upperBound)
{
if(lowerBound >= upperBound)
return -1;
else
{
// translate to range 0 to n-1, find the modulus, then
// translate back to range lowerBound to upperBound.
num -= lowerBound;
num = SignedModulus( num, Abs(upperBound - lowerBound) );
num += lowerBound;
}
return 0;
}
//--------------------------------------------------------
// Non-template functions
//--------------------------------------------------------
int Ceiling(const float &num);
int Ceiling(const double &num);
bool CompareFloat(const double &, const double &);
int Floor(const float &num);
int Floor(const double &num);
inline double RadiansToDegrees(const double &num);
inline double DegreesToRadians(const double &num);
float Random(const float &, const float &);
int Random(const int &,const int &);
int Round(const float &num);
int Round(const double &num);
int SignedModulus(const int &num, const int &n);
long SignedModulus(const long &num, const long &n);
float SignedModulus(const float &num, const float &n);
double SignedModulus(const double &num, const double &n);
}
#endif
#endif

View File

@ -0,0 +1,539 @@
//***********************************************************
//
// Name: Matrix3D.Cpp
// Last Update: 31/1/02
// Author: Poya Manouchehri
//
// Description: A Matrix class used for holding and
// manipulating transformation info.
//
//***********************************************************
#include "Matrix3D.h"
#include "Quaternion.h"
CMatrix3D::CMatrix3D ()
{
}
CMatrix3D::CMatrix3D(float a11,float a12,float a13,float a14,float a21,float a22,float a23,float a24,
float a31,float a32,float a33,float a34,float a41,float a42,float a43,float a44)
{
_11=a11;
_12=a12;
_13=a13;
_14=a14;
_21=a21;
_22=a22;
_23=a23;
_24=a24;
_31=a31;
_32=a32;
_33=a33;
_34=a34;
_41=a41;
_42=a42;
_43=a43;
_44=a44;
}
//Matrix multiplication
CMatrix3D CMatrix3D::operator*(const CMatrix3D& matrix) const
{
CMatrix3D Temp;
Temp._11 = _11*matrix._11 +
_12*matrix._21 +
_13*matrix._31 +
_14*matrix._41;
Temp._12 = _11*matrix._12 +
_12*matrix._22 +
_13*matrix._32 +
_14*matrix._42;
Temp._13 = _11*matrix._13 +
_12*matrix._23 +
_13*matrix._33 +
_14*matrix._43;
Temp._14 = _11*matrix._14 +
_12*matrix._24 +
_13*matrix._34 +
_14*matrix._44;
Temp._21 = _21*matrix._11 +
_22*matrix._21 +
_23*matrix._31 +
_24*matrix._41;
Temp._22 = _21*matrix._12 +
_22*matrix._22 +
_23*matrix._32 +
_24*matrix._42;
Temp._23 = _21*matrix._13 +
_22*matrix._23 +
_23*matrix._33 +
_24*matrix._43;
Temp._24 = _21*matrix._14 +
_22*matrix._24 +
_23*matrix._34 +
_24*matrix._44;
Temp._31 = _31*matrix._11 +
_32*matrix._21 +
_33*matrix._31 +
_34*matrix._41;
Temp._32 = _31*matrix._12 +
_32*matrix._22 +
_33*matrix._32 +
_34*matrix._42;
Temp._33 = _31*matrix._13 +
_32*matrix._23 +
_33*matrix._33 +
_34*matrix._43;
Temp._34 = _31*matrix._14 +
_32*matrix._24 +
_33*matrix._34 +
_34*matrix._44;
Temp._41 = _41*matrix._11 +
_42*matrix._21 +
_43*matrix._31 +
_44*matrix._41;
Temp._42 = _41*matrix._12 +
_42*matrix._22 +
_43*matrix._32 +
_44*matrix._42;
Temp._43 = _41*matrix._13 +
_42*matrix._23 +
_43*matrix._33 +
_44*matrix._43;
Temp._44 = _41*matrix._14 +
_42*matrix._24 +
_43*matrix._34 +
_44*matrix._44;
return Temp;
}
//Matrix multiplication/assignment
CMatrix3D& CMatrix3D::operator*=(const CMatrix3D& matrix)
{
Concatenate(matrix);
return *this;
}
//Matrix scaling
CMatrix3D CMatrix3D::operator*(float f) const
{
CMatrix3D tmp;
for (int i=0;i<16;i++) {
tmp._data[i]=_data[i]*f;
}
return tmp;
}
//Matrix scaling/assignment
CMatrix3D& CMatrix3D::operator*=(float f)
{
for (int i=0;i<16;i++) {
_data[i]*=f;
}
return *this;
}
//Matrix addition
CMatrix3D CMatrix3D::operator+(const CMatrix3D& m) const
{
CMatrix3D tmp;
for (int i=0;i<16;i++) {
tmp._data[i]=_data[i]+m._data[i];
}
return tmp;
}
//Matrix addition/assignment
CMatrix3D& CMatrix3D::operator+=(const CMatrix3D& m)
{
for (int i=0;i<16;i++) {
_data[i]+=m._data[i];
}
return *this;
}
//Sets the identity matrix
void CMatrix3D::SetIdentity ()
{
_11=1.0f; _12=0.0f; _13=0.0f; _14=0.0f;
_21=0.0f; _22=1.0f; _23=0.0f; _24=0.0f;
_31=0.0f; _32=0.0f; _33=1.0f; _34=0.0f;
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
}
//Sets the zero matrix
void CMatrix3D::SetZero ()
{
_11=0.0f; _12=0.0f; _13=0.0f; _14=0.0f;
_21=0.0f; _22=0.0f; _23=0.0f; _24=0.0f;
_31=0.0f; _32=0.0f; _33=0.0f; _34=0.0f;
_41=0.0f; _42=0.0f; _43=0.0f; _44=0.0f;
}
//The following clear the matrix and set the
//rotation of each of the 3 axes
void CMatrix3D::SetXRotation (float angle)
{
float Cos = cosf (angle);
float Sin = sinf (angle);
_11=1.0f; _12=0.0f; _13=0.0f; _14=0.0f;
_21=0.0f; _22=Cos; _23=-Sin; _24=0.0f;
_31=0.0f; _32=Sin; _33=Cos; _34=0.0f;
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
}
void CMatrix3D::SetYRotation (float angle)
{
float Cos = cosf (angle);
float Sin = sinf (angle);
_11=Cos; _12=0.0f; _13=Sin; _14=0.0f;
_21=0.0f; _22=1.0f; _23=0.0f; _24=0.0f;
_31=-Sin; _32=0.0f; _33=Cos; _34=0.0f;
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
}
void CMatrix3D::SetZRotation (float angle)
{
float Cos = cosf (angle);
float Sin = sinf (angle);
_11=Cos; _12=-Sin; _13=0.0f; _14=0.0f;
_21=Sin; _22=Cos; _23=0.0f; _24=0.0f;
_31=0.0f; _32=0.0f; _33=1.0f; _34=0.0f;
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
}
//The following apply a rotation to the matrix
//about each of the axes;
void CMatrix3D::RotateX (float angle)
{
CMatrix3D Temp;
Temp.SetXRotation (angle);
Concatenate(Temp);
}
void CMatrix3D::RotateY (float angle)
{
CMatrix3D Temp;
Temp.SetYRotation (angle);
Concatenate(Temp);
}
void CMatrix3D::RotateZ (float angle)
{
CMatrix3D Temp;
Temp.SetZRotation(angle);
Concatenate(Temp);
}
//Sets the translation of the matrix
void CMatrix3D::SetTranslation (float x, float y, float z)
{
_11=1.0f; _12=0.0f; _13=0.0f; _14=x;
_21=0.0f; _22=1.0f; _23=0.0f; _24=y;
_31=0.0f; _32=0.0f; _33=1.0f; _34=z;
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
}
void CMatrix3D::SetTranslation(const CVector3D& vector)
{
SetTranslation(vector.X, vector.Y, vector.Z);
}
//Applies a translation to the matrix
void CMatrix3D::Translate(float x, float y, float z)
{
CMatrix3D Temp;
Temp.SetTranslation(x,y,z);
Concatenate(Temp);
}
void CMatrix3D::Translate(const CVector3D &vector)
{
Translate(vector.X,vector.Y,vector.Z);
}
void CMatrix3D::Concatenate(const CMatrix3D& m)
{
(*this)=m*(*this);
}
CVector3D CMatrix3D::GetTranslation() const
{
CVector3D Temp;
Temp.X = _14;
Temp.Y = _24;
Temp.Z = _34;
return Temp;
}
//Clears and sets the scaling of the matrix
void CMatrix3D::SetScaling (float x_scale, float y_scale, float z_scale)
{
_11=x_scale; _12=0.0f; _13=0.0f; _14=0.0f;
_21=0.0f; _22=y_scale; _23=0.0f; _24=0.0f;
_31=0.0f; _32=0.0f; _33=z_scale; _34=0.0f;
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
}
//Scales the matrix
void CMatrix3D::Scale (float x_scale, float y_scale, float z_scale)
{
CMatrix3D Temp;
Temp.SetScaling(x_scale,y_scale,z_scale);
Concatenate(Temp);
}
//Returns the transpose of the matrix. For orthonormal
//matrices, this is the same is the inverse matrix
void CMatrix3D::GetTranspose(CMatrix3D& result) const
{
result._11 = _11;
result._21 = _12;
result._31 = _13;
result._41 = _14;
result._12 = _21;
result._22 = _22;
result._32 = _23;
result._42 = _24;
result._13 = _31;
result._23 = _32;
result._33 = _33;
result._43 = _34;
result._14 = _41;
result._24 = _42;
result._34 = _43;
result._44 = _44;
}
//Get a vector which points to the left of the matrix
CVector3D CMatrix3D::GetLeft () const
{
CVector3D Temp;
Temp.X = -_11;
Temp.Y = -_21;
Temp.Z = -_31;
return Temp;
}
//Get a vector which points up from the matrix
CVector3D CMatrix3D::GetUp () const
{
CVector3D Temp;
Temp.X = _12;
Temp.Y = _22;
Temp.Z = _32;
return Temp;
}
//Get a vector which points to front of the matrix
CVector3D CMatrix3D::GetIn () const
{
CVector3D Temp;
Temp.X = _13;
Temp.Y = _23;
Temp.Z = _33;
return Temp;
}
//Transform a vector by this matrix
CVector3D CMatrix3D::Transform (const CVector3D &vector) const
{
CVector3D result;
Transform(vector,result);
return result;
}
void CMatrix3D::Transform(const CVector3D& vector,CVector3D& result) const
{
result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14;
result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24;
result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34;
}
//Transform a vector by this matrix
CVector4D CMatrix3D::Transform(const CVector4D &vector) const
{
CVector4D result;
Transform(vector,result);
return result;
}
void CMatrix3D::Transform(const CVector4D& vector,CVector4D& result) const
{
result[0] = _11*vector[0] + _12*vector[1] + _13*vector[2] + _14*vector[3];
result[1] = _21*vector[0] + _22*vector[1] + _23*vector[2] + _24*vector[3];
result[2] = _31*vector[0] + _32*vector[1] + _33*vector[2] + _34*vector[3];
result[3] = _41*vector[0] + _42*vector[1] + _43*vector[2] + _44*vector[3];
}
//Only rotate (not translate) a vector by this matrix
CVector3D CMatrix3D::Rotate(const CVector3D& vector) const
{
CVector3D result;
Rotate(vector,result);
return result;
}
void CMatrix3D::Rotate(const CVector3D& vector,CVector3D& result) const
{
result.X = _11*vector.X + _12*vector.Y + _13*vector.Z;
result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z;
result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z;
}
///////////////////////////////////////////////////////////////////////////////
// RotateTransposed: rotate a vector by the transpose of this matrix
CVector3D CMatrix3D::RotateTransposed(const CVector3D& vector) const
{
CVector3D result;
RotateTransposed(vector,result);
return result;
}
///////////////////////////////////////////////////////////////////////////////
// RotateTransposed: rotate a vector by the transpose of this matrix
void CMatrix3D::RotateTransposed(const CVector3D& vector,CVector3D& result) const
{
result.X = _11*vector.X + _21*vector.Y + _31*vector.Z;
result.Y = _12*vector.X + _22*vector.Y + _32*vector.Z;
result.Z = _13*vector.X + _23*vector.Y + _33*vector.Z;
}
void CMatrix3D::GetInverse(CMatrix3D& dst) const
{
float tmp[12]; // temp array for pairs
float src[16]; // array of transpose source matrix
float det; // determinant
// transpose matrix
for (int i = 0; i < 4; ++i) {
src[i] = _data[i*4];
src[i + 4] = _data[i*4 + 1];
src[i + 8] = _data[i*4 + 2];
src[i + 12] = _data[i*4 + 3];
}
// calculate pairs for first 8 elements (cofactors)
tmp[0] = src[10] * src[15];
tmp[1] = src[11] * src[14];
tmp[2] = src[9] * src[15];
tmp[3] = src[11] * src[13];
tmp[4] = src[9] * src[14];
tmp[5] = src[10] * src[13];
tmp[6] = src[8] * src[15];
tmp[7] = src[11] * src[12];
tmp[8] = src[8] * src[14];
tmp[9] = src[10] * src[12];
tmp[10] = src[8] * src[13];
tmp[11] = src[9] * src[12];
// calculate first 8 elements (cofactors)
dst._data[0] = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
dst._data[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
dst._data[1] = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
dst._data[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
dst._data[2] = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
dst._data[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
dst._data[3] = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
dst._data[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
dst._data[4] = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
dst._data[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
dst._data[5] = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
dst._data[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
dst._data[6] = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
dst._data[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
dst._data[7] = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
dst._data[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
// calculate pairs for second 8 elements (cofactors)
tmp[0] = src[2]*src[7];
tmp[1] = src[3]*src[6];
tmp[2] = src[1]*src[7];
tmp[3] = src[3]*src[5];
tmp[4] = src[1]*src[6];
tmp[5] = src[2]*src[5];
tmp[6] = src[0]*src[7];
tmp[7] = src[3]*src[4];
tmp[8] = src[0]*src[6];
tmp[9] = src[2]*src[4];
tmp[10] = src[0]*src[5];
tmp[11] = src[1]*src[4];
// calculate second 8 elements (cofactors)
dst._data[8] = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
dst._data[8] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
dst._data[9] = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
dst._data[9] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
dst._data[10] = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
dst._data[10]-= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
dst._data[11] = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
dst._data[11]-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
dst._data[12] = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
dst._data[12]-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
dst._data[13] = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
dst._data[13]-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
dst._data[14] = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
dst._data[14]-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
dst._data[15] = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
dst._data[15]-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
// calculate matrix inverse
det=src[0]*dst._data[0]+src[1]*dst._data[1]+src[2]*dst._data[2]+src[3]*dst._data[3];
det = 1/det;
for ( int j = 0; j < 16; j++) {
dst._data[j] *= det;
}
}
void CMatrix3D::Rotate(const CQuaternion& quat)
{
CMatrix3D rotationMatrix=quat.ToMatrix();
Concatenate(rotationMatrix);
}
void CMatrix3D::SetRotation(const CQuaternion& quat)
{
quat.ToMatrix(*this);
}

View File

@ -0,0 +1,123 @@
#ifndef __MATRIX3D_H
#define __MATRIX3D_H
#include <math.h>
#include "Vector3D.h"
#include "Vector4D.h"
class CQuaternion;
/////////////////////////////////////////////////////////////////////////
// CMatrix3D: a 4x4 matrix class for common operations in 3D
class CMatrix3D
{
public:
// the matrix data itself - accessible as either longhand names
// or via a flat array
union {
struct {
float _11, _21, _31, _41;
float _12, _22, _32, _42;
float _13, _23, _33, _43;
float _14, _24, _34, _44;
};
float _data[16];
};
public:
// constructors
CMatrix3D();
CMatrix3D(float a11,float a12,float a13,float a14,float a21,float a22,float a23,float a24,
float a31,float a32,float a33,float a34,float a41,float a42,float a43,float a44);
// accessors to individual elements of matrix
float& operator()(int col,int row) {
return _data[row*4+col];
}
const float& operator()(int col,int row) const {
return _data[row*4+col];
}
// matrix multiplication
CMatrix3D operator*(const CMatrix3D &matrix) const;
// matrix multiplication/assignment
CMatrix3D& operator*=(const CMatrix3D &matrix);
// matrix scaling
CMatrix3D operator*(float f) const;
// matrix scaling/assignment
CMatrix3D& operator*=(float f);
// matrix addition
CMatrix3D operator+(const CMatrix3D &matrix) const;
// matrix addition/assignment
CMatrix3D& operator+=(const CMatrix3D &matrix);
// set this matrix to the identity matrix
void SetIdentity();
// set this matrix to the zero matrix
void SetZero();
// concatenate arbitrary matrix onto this matrix
void Concatenate(const CMatrix3D& m);
// set this matrix to a rotation matrix for a rotation about X axis of given angle
void SetXRotation(float angle);
// set this matrix to a rotation matrix for a rotation about Y axis of given angle
void SetYRotation(float angle);
// set this matrix to a rotation matrix for a rotation about Z axis of given angle
void SetZRotation(float angle);
// set this matrix to a rotation described by given quaternion
void SetRotation(const CQuaternion& quat);
// concatentate a rotation about the X axis onto this matrix
void RotateX(float angle);
// concatentate a rotation about the Y axis onto this matrix
void RotateY(float angle);
// concatentate a rotation about the Z axis onto this matrix
void RotateZ(float angle);
// concatentate a rotation described by given quaternion
void Rotate(const CQuaternion& quat);
// set this matrix to given translation
void SetTranslation(float x, float y, float z);
void SetTranslation(const CVector3D& vector);
// concatenate given translation onto this matrix
void Translate(float x, float y, float z);
void Translate(const CVector3D& vector);
// set this matrix to the given scaling matrix
void SetScaling(float x_scale, float y_scale, float z_scale);
// concatentate given scaling matrix onto this matrix
void Scale(float x_scale, float y_scale, float z_scale);
// calculate the inverse of this matrix, store in dst
void GetInverse(CMatrix3D& dst) const;
// calculate the transpose of this matrix, store in dst
void GetTranspose(CMatrix3D& dst) const;
// return the translation component of this matrix
CVector3D GetTranslation() const;
// return left vector, derived from rotation
CVector3D GetLeft() const;
// return up vector, derived from rotation
CVector3D GetUp() const;
// return forward vector, derived from rotation
CVector3D GetIn() const;
// transform a 3D vector by this matrix
void Transform(const CVector3D &vector,CVector3D& result) const;
CVector3D Transform(const CVector3D &vector) const;
// transform a 4D vector by this matrix
void Transform(const CVector4D &vector,CVector4D& result) const;
CVector4D Transform(const CVector4D &vector) const;
// rotate a vector by this matrix
void Rotate(const CVector3D& vector,CVector3D& result) const;
CVector3D Rotate(const CVector3D& vector) const;
// rotate a vector by the transpose of this matrix
void RotateTransposed(const CVector3D& vector,CVector3D& result) const;
CVector3D RotateTransposed(const CVector3D& vector) const;
};
#endif

View File

@ -0,0 +1,15 @@
#ifndef _MAXINC_H
#define _MAXINC_H
#define timeval MAX_timeval
//#define ERROR MAX_ERROR
#include "Max.h"
#include "iparamb2.h"
#include "iparamm2.h"
#include "istdplug.h"
#include "resource.h"
#undef timeval
#endif

View File

@ -0,0 +1,77 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: ModelDef.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "pmdexp_types.h"
#include "ModelDef.h"
#include "FilePacker.h"
///////////////////////////////////////////////////////////////////////////////
// CModelDef Constructor
CModelDef::CModelDef()
: m_pVertices(0), m_NumVertices(0), m_pFaces(0), m_NumFaces(0), m_Bones(0), m_NumBones(0),
m_NumPropPoints(0), m_PropPoints(0)
{
}
///////////////////////////////////////////////////////////////////////////////
// CModelDef Destructor
CModelDef::~CModelDef()
{
delete[] m_pVertices;
delete[] m_pFaces;
delete[] m_Bones;
delete[] m_PropPoints;
}
///////////////////////////////////////////////////////////////////////////////
// FindPropPoint: find and return pointer to prop point matching given name;
// return null if no match (case insensitive search)
SPropPoint* CModelDef::FindPropPoint(const char* name) const
{
for (uint i=0;i<m_NumPropPoints;i++) {
if (stricmp(name,m_PropPoints[i].m_Name)==0) {
return &m_PropPoints[i];
}
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// Save: write the given CModelDef to the given file
void CModelDef::Save(const char* filename,const CModelDef* mdef)
{
CFilePacker packer;
// pack everything up
u32 numVertices=mdef->GetNumVertices();
packer.PackRaw(&numVertices,sizeof(numVertices));
packer.PackRaw(mdef->GetVertices(),sizeof(SModelVertex)*numVertices);
u32 numFaces=mdef->GetNumFaces();
packer.PackRaw(&numFaces,sizeof(numFaces));
packer.PackRaw(mdef->GetFaces(),sizeof(SModelFace)*numFaces);
packer.PackRaw(&mdef->m_NumBones,sizeof(mdef->m_NumBones));
if (mdef->m_NumBones) {
packer.PackRaw(mdef->m_Bones,sizeof(CBoneState)*mdef->m_NumBones);
}
packer.PackRaw(&mdef->m_NumPropPoints,sizeof(mdef->m_NumPropPoints));
for (u32 i=0;i<mdef->m_NumPropPoints;i++) {
packer.PackString(mdef->m_PropPoints[i].m_Name);
packer.PackRaw(&mdef->m_PropPoints[i].m_Position.X,sizeof(mdef->m_PropPoints[i].m_Position));
packer.PackRaw(&mdef->m_PropPoints[i].m_Rotation.m_V.X,sizeof(mdef->m_PropPoints[i].m_Rotation));
packer.PackRaw(&mdef->m_PropPoints[i].m_BoneIndex,sizeof(mdef->m_PropPoints[i].m_BoneIndex));
}
// flush everything out to file
packer.Write(filename,FILE_VERSION,"PSMD");
}

View File

@ -0,0 +1,128 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: ModelDef.h
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MODELDEF_H
#define _MODELDEF_H
#include "Vector3D.h"
#include "SkeletonAnimDef.h"
#include <vector>
///////////////////////////////////////////////////////////////////////////////
// SPropPoint: structure describing a prop point
struct SPropPoint
{
// name of the prop point
char m_Name[128];
// position of the point
CVector3D m_Position;
// rotation of the point
CQuaternion m_Rotation;
// object to parent space transformation
CMatrix3D m_Transform;
// index of parent bone; 0xff if unboned
u8 m_BoneIndex;
};
///////////////////////////////////////////////////////////////////////////////
// SVertexBlend: structure containing the necessary data for blending vertices
// with multiple bones
struct SVertexBlend
{
enum { SIZE = 4 };
// index of the influencing bone, or 0xff if none
u8 m_Bone[SIZE];
// weight of the influence; all weights sum to 1
float m_Weight[SIZE];
};
///////////////////////////////////////////////////////////////////////////////
// SModelVertex: structure containing per-vertex data
struct SModelVertex
{
// vertex position
CVector3D m_Coords;
// vertex normal
CVector3D m_Norm;
// vertex UVs
float m_U, m_V;
// vertex blend data
SVertexBlend m_Blend;
};
///////////////////////////////////////////////////////////////////////////////
// SModelFace: structure containing per-face data
struct SModelFace
{
// indices of the 3 vertices on this face
u16 m_Verts[3];
};
////////////////////////////////////////////////////////////////////////////////////////
// CModelDef: a raw 3D model; describes the vertices, faces, skinning and skeletal
// information of a model
class CModelDef
{
public:
// current file version given to saved animations
enum { FILE_VERSION = 2 };
// supported file read version - files with a version less than this will be rejected
enum { FILE_READ_VERSION = 1 };
public:
// constructor
CModelDef();
// destructor
virtual ~CModelDef();
// shutdown memory-freer
static void Shutdown();
// model I/O functions
static CModelDef* Load(const char* filename);
static void Save(const char* filename,const CModelDef* mdef);
public:
// accessor: get vertex data
int GetNumVertices() const { return m_NumVertices; }
SModelVertex *GetVertices() const { return m_pVertices; }
// accessor: get face data
int GetNumFaces() const { return m_NumFaces; }
SModelFace *GetFaces() const { return m_pFaces; }
// accessor: get bone data
int GetNumBones() const { return m_NumBones; }
CBoneState *GetBones() const { return m_Bones; }
// find and return pointer to prop point matching given name; return
// null if no match (case insensitive search)
SPropPoint* FindPropPoint(const char* name) const;
public:
// vertex data
u32 m_NumVertices;
SModelVertex* m_pVertices;
// face data
u32 m_NumFaces;
SModelFace* m_pFaces;
// bone data - default model pose
u32 m_NumBones;
CBoneState* m_Bones;
// prop point data
u32 m_NumPropPoints;
SPropPoint* m_PropPoints;
// all loaded models, to be freed on shutdown
static std::vector<CModelDef*> m_LoadedModelDefs;
};
#endif

View File

@ -0,0 +1,276 @@
#include "PMDExp.h"
#include "ExpMesh.h"
#include "ExpProp.h"
#include "ExpSkeleton.h"
#undef PI
#include "ModelDef.h"
//////////////////////////////////////////////////////////////////////
// PMDExp constructor
PMDExp::PMDExp()
{
}
//////////////////////////////////////////////////////////////////////
// PMDExp destructor
PMDExp::~PMDExp()
{
}
//////////////////////////////////////////////////////////////////////
// ExtCount: return the number of file name extensions supported
// by the plug-in.
int PMDExp::ExtCount()
{
return 1;
}
//////////////////////////////////////////////////////////////////////
// Ext: return the ith file name extension
const TCHAR* PMDExp::Ext(int n)
{
return _T("pmd");
}
//////////////////////////////////////////////////////////////////////
// LongDesc: return long ASCII description
const TCHAR* PMDExp::LongDesc()
{
return _T("Prometheus Model Data");
}
//////////////////////////////////////////////////////////////////////
// ShortDesc: return short ASCII description
const TCHAR* PMDExp::ShortDesc()
{
return _T("Prometheus Model");
}
//////////////////////////////////////////////////////////////////////
// AuthorName: return author name
const TCHAR* PMDExp::AuthorName()
{
return _T("Rich Cross");
}
//////////////////////////////////////////////////////////////////////
// CopyrightMessage: return copyright message
const TCHAR* PMDExp::CopyrightMessage()
{
return _T("(c) Wildfire Games 2004");
}
//////////////////////////////////////////////////////////////////////
// OtherMessage1: return some other message (or don't, in this case)
const TCHAR* PMDExp::OtherMessage1()
{
return _T("");
}
//////////////////////////////////////////////////////////////////////
// OtherMessage2: return some other message (or don't, in this case)
const TCHAR* PMDExp::OtherMessage2()
{
return _T("");
}
//////////////////////////////////////////////////////////////////////
// Version: return version number * 100 (i.e. v3.01 = 301)
unsigned int PMDExp::Version()
{
return 1;
}
//////////////////////////////////////////////////////////////////////
// ShowAbout: show an about box (or don't, in this case)
void PMDExp::ShowAbout(HWND hWnd)
{
}
//////////////////////////////////////////////////////////////////////
// SupportsOptions: return true for each option supported by each
// extension the exporter supports
BOOL PMDExp::SupportsOptions(int ext, DWORD options)
{
// return TRUE to indicate export selected supported
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// DoExport: actually perform the export to the given filename
int PMDExp::DoExport(const TCHAR *name,ExpInterface *ei,Interface *ip, BOOL suppressPrompts, DWORD options)
{
// result of the export: assume we'll fail somewhere along the way
BOOL res=FALSE;
// save off the interface ptr
m_IP=ip;
// save off the options
m_Options=options;
// build any skeletons in MAXs heirarchy before going any further
std::vector<ExpSkeleton*> skeletons;
ExpSkeleton::BuildSkeletons(m_IP->GetRootNode(),skeletons);
if (skeletons.size()>1) {
MessageBox(GetActiveWindow(),"Found more than one skeleton in scene","Error",MB_OK);
} else {
// build list of meshes and props from nodes in MAXs heirarchy
std::vector<ExpMesh*> meshes;
std::vector<ExpProp*> props;
ExpSkeleton* skeleton=skeletons.size()>0 ? skeletons[0] : 0;
BuildOutputList(m_IP->GetRootNode(),skeleton,meshes,props);
if (meshes.size()==0) {
// hmm .. nothing there?
MessageBox(GetActiveWindow(),"Failed to find any meshes to export","Error",MB_OK);
} else {
// build a model from the node tree and any skeleton in scene
CModelDef* model=BuildModel(meshes,props,skeleton);
if (!model) {
MessageBox(GetActiveWindow(),"Failed to create model","Error",MB_OK);
} else {
try {
CModelDef::Save(name,model);
res=TRUE;
} catch (...) {
res=FALSE;
}
MessageBox(GetActiveWindow(),res ? "Export Complete" : "Error saving model",res ? "Info" : "Error",MB_OK);
}
for (int i=0;i<meshes.size();i++) {
delete meshes[i];
}
}
}
// clean up
for (int i=0;i<skeletons.size();i++) {
delete skeletons[i];
}
// return result
return res;
}
/////////////////////////////////////////////////////////////////////////////////
// BuildOutputList: traverse heirarchy collecting meshes/props
void PMDExp::BuildOutputList(INode* node,ExpSkeleton* skeleton,
std::vector<ExpMesh*>& meshes,std::vector<ExpProp*>& props)
{
// get object attached to node
ObjectState os=node->EvalWorldState(0);
if (os.obj) {
// handle export selected
if ((m_Options & SCENE_EXPORT_SELECTED) && !node->Selected()) {
// ignore ..
} else {
// mesh?
bool isMesh=true; // assume so
if (isMesh && !PMDExpMesh::IsMesh(os.obj)) isMesh=false;
if (isMesh && ExpSkeleton::IsBone(node)) isMesh=false;
if (isMesh && ExpSkeleton::IsFootprints(node)) isMesh=false;
if (isMesh) {
PMDExpMesh meshbuilder(node,skeleton);
ExpMesh* mesh=meshbuilder.Build();
meshes.push_back(mesh);
} else {
// not a mesh - a prop?
if (PMDExpProp::IsProp(os.obj)) {
PMDExpProp propbuilder(node);
ExpProp* prop=propbuilder.Build();
props.push_back(prop);
}
}
}
}
// traverse into children
for (int i=0;i<node->NumberOfChildren();i++) {
BuildOutputList(node->GetChildNode(i),skeleton,meshes,props);
}
}
/////////////////////////////////////////////////////////////////////////////////
// BuildModel: weld together given list of meshes, and attach props; return
// result as a CModelDef
CModelDef* PMDExp::BuildModel(std::vector<ExpMesh*>& meshes,std::vector<ExpProp*>& props,
ExpSkeleton* skeleton)
{
SVertexBlend nullBlend;
memset(nullBlend.m_Bone,0xff,sizeof(nullBlend.m_Bone));
memset(nullBlend.m_Weight,0,sizeof(nullBlend.m_Weight));
// sum up total number of vertices and faces
u32 totalVerts=0,totalFaces=0;
for (int i=0;i<meshes.size();i++) {
totalVerts+=meshes[i]->m_Vertices.size();
totalFaces+=meshes[i]->m_Faces.size();
}
CModelDef* mdl=new CModelDef;
mdl->m_NumVertices=totalVerts;
mdl->m_pVertices=new SModelVertex[totalVerts];
mdl->m_NumFaces=totalFaces;
mdl->m_pFaces=new SModelFace[totalFaces];
mdl->m_NumBones=skeleton ? skeleton->m_Bones.size() : 0;
mdl->m_Bones=new CBoneState[mdl->m_NumBones];
// build vertices
int vcount=0;
for (i=0;i<meshes.size();i++) {
const VertexList& verts=meshes[i]->m_Vertices;
const VBlendList& blends=meshes[i]->m_Blends;
for (int j=0;j<verts.size();j++) {
mdl->m_pVertices[vcount].m_Coords=verts[j].m_Pos;
mdl->m_pVertices[vcount].m_Norm=verts[j].m_Normal;
mdl->m_pVertices[vcount].m_U=verts[j].m_UVs[0];
mdl->m_pVertices[vcount].m_V=verts[j].m_UVs[1];
mdl->m_pVertices[vcount].m_Blend=blends.size()>0 ? blends[verts[j].m_Index] : nullBlend;
vcount++;
}
}
// build faces
int fcount=0;
int offset=0;
for (i=0;i<meshes.size();i++) {
const FaceList& faces=meshes[i]->m_Faces;
for (int j=0;j<faces.size();j++) {
mdl->m_pFaces[fcount].m_Verts[0]=faces[j].m_V[0]+offset;
mdl->m_pFaces[fcount].m_Verts[1]=faces[j].m_V[1]+offset;
mdl->m_pFaces[fcount].m_Verts[2]=faces[j].m_V[2]+offset;
fcount++;
}
offset+=meshes[i]->m_Vertices.size();
}
// build bones
for (i=0;i<mdl->m_NumBones;i++) {
mdl->m_Bones[i].m_Translation=skeleton->m_Bones[i]->m_Translation;
mdl->m_Bones[i].m_Rotation=skeleton->m_Bones[i]->m_Rotation;
}
// attach props
mdl->m_NumPropPoints=props.size();
mdl->m_PropPoints=new SPropPoint[mdl->m_NumPropPoints];
for (i=0;i<mdl->m_NumPropPoints;i++) {
strcpy(mdl->m_PropPoints[i].m_Name,props[i]->m_Name.c_str());
mdl->m_PropPoints[i].m_Position=props[i]->m_Position;
mdl->m_PropPoints[i].m_Rotation=props[i]->m_Rotation;
mdl->m_PropPoints[i].m_BoneIndex=skeleton ? skeleton->FindBoneByNode(props[i]->m_Parent) : 0xff;
}
// all done
return mdl;
}

View File

@ -0,0 +1,144 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "DyMaxLight"=..\dymaxlight\DyMaxLight.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/dev/src/tools/max/dymaxlight", ZVAAAAAA
..\dymaxlight
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "arbvp_c"=..\..\arbvp_c\arbvp_c.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/dev/src/tools/arbvp_c", LRBAAAAA
..\..\arbvp_c
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "common"=..\..\..\common\common.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/dev/src/common", LVAAAAAA
..\..\..\common
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "dy"=..\..\..\dy\dy.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/dev/src/dy", NVAAAAAA
..\..\..\dy
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "dyexp"=.\dyexp.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/dev/src/tools/max/dyexp", YVAAAAAA
.
end source code control
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name dy
End Project Dependency
Begin Project Dependency
Project_Dep_Name DyMaxLight
End Project Dependency
Begin Project Dependency
Project_Dep_Name common
End Project Dependency
Begin Project Dependency
Project_Dep_Name filesys
End Project Dependency
Begin Project Dependency
Project_Dep_Name luacore
End Project Dependency
}}}
###############################################################################
Project: "filesys"=..\..\..\filesys\filesys.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/dev/src/filesys", RSBAAAAA
..\..\..\filesys
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "luacore"=..\..\..\lua\luacore\luacore.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/dev/src/lua/luacore", RVBAAAAA
..\..\..\lua\luacore
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@ -0,0 +1,53 @@
#ifndef __PMDEXP_H
#define __PMDEXP_H
// necessary includes
#include "MaxInc.h"
#include <vector>
// necessary declarations
class ExpMesh;
class ExpProp;
class ExpSkeleton;
class CModelDef;
/////////////////////////////////////////////////////////////////
// PMDExp:
class PMDExp : public SceneExport
{
public:
PMDExp();
~PMDExp();
// standard stuff that Max requires
int ExtCount(); // Number of extensions supported
const TCHAR* Ext(int n); // Extension #n (i.e. "3DS")
const TCHAR* LongDesc(); // Long ASCII description (i.e. "Autodesk 3D Studio File")
const TCHAR* ShortDesc(); // Short ASCII description (i.e. "3D Studio")
const TCHAR* AuthorName(); // ASCII Author name
const TCHAR* CopyrightMessage(); // ASCII Copyright message
const TCHAR* OtherMessage1(); // Other message #1
const TCHAR* OtherMessage2(); // Other message #2
unsigned int Version(); // Version number * 100 (i.e. v3.01 = 301)
void ShowAbout(HWND hWnd); // Show DLL's "About..." box
BOOL SupportsOptions(int ext, DWORD options);
int DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts=FALSE, DWORD options=0);
private:
// BuildOutputList: traverse heirarchy collecting meshes/props
void BuildOutputList(INode* node,ExpSkeleton* skeleton,
std::vector<ExpMesh*>& meshes,std::vector<ExpProp*>& props);
// WeldMeshes: weld together given list of meshes; return result as a CModelDef
CModelDef* BuildModel(std::vector<ExpMesh*>& meshes,std::vector<ExpProp*>& props,ExpSkeleton* skeleton);
// pointer to MAXs Interface object
Interface* m_IP;
// handle to the export parameters window
HWND m_Params;
// export options
DWORD m_Options;
};
#endif

View File

@ -0,0 +1 @@
35

View File

@ -0,0 +1,168 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_NEW_POINTPARAM DIALOG DISCARDABLE 0, 0, 108, 110
STYLE WS_CHILD | WS_VISIBLE
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "Axis Tripod",IDC_POINT_AXIS,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,12,24,53,10
CONTROL "",IDC_POINT_SIZE,"CustEdit",WS_TABSTOP,49,63,28,10
RTEXT "Size:",IDC_STATIC,19,63,27,8
CONTROL "",IDC_POINT_SIZESPIN,"SpinnerControl",0x0,78,63,7,10
CONTROL "Center Marker",IDC_POINT_MARKER,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,12,12,63,10
CONTROL "Cross",IDC_POINT_CROSS,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,12,36,33,10
CONTROL "Box",IDC_POINT_BOX,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,12,48,33,10
GROUPBOX "Display:",IDC_STATIC,5,1,98,105
CONTROL "Constant Screen Size",IDC_POINT_SCREENSIZE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,12,78,84,10
CONTROL "Draw On Top",IDC_POINT_DRAWONTOP,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,12,91,59,10
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 5,0,0,0
PRODUCTVERSION 5,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "TECH: \0"
VALUE "CompanyName", "\0"
VALUE "FileDescription", "PMD File Export\0"
VALUE "FileVersion", "5.0.0.0\0"
VALUE "InternalName", "PMDExp\0"
VALUE "LegalCopyright", "\0"
VALUE "LegalTrademarks", "3D Studio MAX, Biped, Character Studio, Heidi, Kinetix and Physique are registered trademarks and 3ds max, combustion, Discreet, DWG Unplugged, DXF, FLI and FLC are trademarks of Autodesk, Inc.\0"
VALUE "OriginalFilename", "PMDExp.dle\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "3ds max\0"
VALUE "ProductVersion", "5.0.0.0\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // !_MAC
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDS_LIBDESCRIPTION "Prometheus Export Tools"
IDS_CATEGORY "Exporters"
IDS_PMD_CLASS_NAME "PMDExp"
IDS_PARAMS "Parameters"
IDS_PSA_CLASS_NAME "PSAExp"
IDS_DB_POINT "PSProp"
IDS_DB_POINTHELPER_CLASS "Prop Point"
IDS_DB_POINT_CLASS "Prop Point"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_POINT_PARAMS "Parameters"
IDS_POINT_SIZE "Size"
IDS_POINT_CENTERMARKER "Center Marker"
IDS_POINT_AXISTRIPOD "Axis Tripod"
IDS_POINT_CROSS "Cross"
IDS_POINT_BOX "Box"
IDS_POINT_SCREENSIZE "Constant Screen Size"
IDS_POINT_HELPER_NAME "PSProp"
IDS_POINT_DRAWONTOP "Draw On Top"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,8 @@
LIBRARY pmdexp5
EXPORTS
LibDescription @1
LibNumberClasses @2
LibClassDesc @3
LibVersion @4
SECTIONS
.data READ WRITE

View File

@ -0,0 +1,189 @@
# Microsoft Developer Studio Project File - Name="PMDExp5" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=PMDExp5 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "PMDExp5.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "PMDExp5.mak" CFG="PMDExp5 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "PMDExp5 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "PMDExp5 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""$/dev/dylan/plugins/PMDExp", YVAAAAAA"
# PROP Scc_LocalPath "."
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "PMDExp5 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "ReleaseR5"
# PROP Intermediate_Dir "ReleaseR5"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
# ADD CPP /nologo /G5 /MT /W3 /GX /I "d:\3dsmax5\maxsdk\include" /I "..\\" /I "..\lib" /I "..\ps" /I "..\simulation" /I "..\terrain" /D "NDEBUG" /D "_USRDLL" /D "_3DSMAX_" /D "_WINDOWS" /D "WIN32" /D "_NO_WINMAIN_" /FD /LD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 pslib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib /nologo /base:"0x50810000" /subsystem:windows /dll /machine:I386 /out:"d:\3dsmax5\plugins\pmdexp5.dle" /libpath:"d:\3dsmax5\maxsdk\lib" /libpath:"..\libs" /release
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "PMDExp5 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "DebugR5"
# PROP Intermediate_Dir "DebugR5"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
# ADD CPP /nologo /G6 /MTd /W3 /GX /ZI /Od /I "d:\3dsmax5\maxsdk\include" /I "..\\" /I "..\lib" /I "..\ps" /I "..\simulation" /I "..\terrain" /D "_DEBUG" /D "_USRDLL" /D "_3DSMAX_" /D "_WINDOWS" /D "WIN32" /D "_NO_WINMAIN_" /FD /LD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 pslib_d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib /nologo /base:"0x50810000" /subsystem:windows /dll /map /debug /machine:I386 /out:"d:\3dsmax5\plugins\pmdexp5.dle" /pdbtype:sept /libpath:"d:\3dsmax5\maxsdk\lib" /libpath:"..\libs"
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "PMDExp5 - Win32 Release"
# Name "PMDExp5 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\DllEntry.cpp
# End Source File
# Begin Source File
SOURCE=.\ExpMesh.cpp
# End Source File
# Begin Source File
SOURCE=.\ExpSkeleton.cpp
# End Source File
# Begin Source File
SOURCE=.\ExpUtil.cpp
# End Source File
# Begin Source File
SOURCE=.\PMDExp.cpp
# End Source File
# Begin Source File
SOURCE=.\PMDExp.rc
# End Source File
# Begin Source File
SOURCE=.\PMDExp5.def
# End Source File
# Begin Source File
SOURCE=.\PSAExp.cpp
# End Source File
# Begin Source File
SOURCE=.\PSProp.cpp
# End Source File
# Begin Source File
SOURCE=.\VNormal.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\ExpMesh.h
# End Source File
# Begin Source File
SOURCE=.\ExpSkeleton.h
# End Source File
# Begin Source File
SOURCE=.\ExpUtil.h
# End Source File
# Begin Source File
SOURCE=.\ExpVertex.h
# End Source File
# Begin Source File
SOURCE=.\PMDExp.h
# End Source File
# Begin Source File
SOURCE=.\PSAExp.h
# End Source File
# Begin Source File
SOURCE=.\PSProp.h
# End Source File
# Begin Source File
SOURCE=.\resource.h
# End Source File
# Begin Source File
SOURCE=.\Tree.h
# End Source File
# Begin Source File
SOURCE=.\VertexTree.h
# End Source File
# Begin Source File
SOURCE=.\VNormal.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@ -0,0 +1,8 @@
LIBRARY pmdexp6
EXPORTS
LibDescription @1
LibNumberClasses @2
LibClassDesc @3
LibVersion @4
SECTIONS
.data READ WRITE

View File

@ -0,0 +1,193 @@
# Microsoft Developer Studio Project File - Name="PMDExp6" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=PMDExp6 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "PMDExp6.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "PMDExp6.mak" CFG="PMDExp6 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "PMDExp6 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "PMDExp6 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""$/dev/dylan/plugins/PMDExp", YVAAAAAA"
# PROP Scc_LocalPath "."
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "PMDExp6 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "ReleaseR6"
# PROP Intermediate_Dir "ReleaseR6"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
# ADD CPP /nologo /G5 /MT /W3 /GX /I "d:\3dsmax6\maxsdk\include" /I "..\\" /I "..\lib" /I "..\ps" /I "..\simulation" /I "..\terrain" /D "NDEBUG" /D "_USRDLL" /D "_3DSMAX_" /D "_WINDOWS" /D "WIN32" /D "_NO_WINMAIN_" /FD /LD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 pslib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib /nologo /base:"0x50810000" /entry:"" /subsystem:windows /dll /machine:I386 /out:"d:\3dsmax6\plugins\pmdexp6.dle" /libpath:"d:\3dsmax6\maxsdk\lib" /libpath:"..\libs" /release
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "PMDExp6 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "DebugR6"
# PROP Intermediate_Dir "DebugR6"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /I "d:\3dsmax6\maxsdk\include" /I "..\\" /I "..\lib" /I "..\ps" /I "..\simulation" /I "..\terrain" /D "_DEBUG" /D "_USRDLL" /D "_3DSMAX_" /D "_WINDOWS" /D "WIN32" /D "_NO_WINMAIN_" /FD /LD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 pslib_d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib /nologo /base:"0x50810000" /subsystem:windows /dll /debug /machine:I386 /out:"d:\3dsmax6\plugins\pmdexp6.dle" /pdbtype:sept /libpath:"d:\3dsmax6\maxsdk\lib" /libpath:"..\libs"
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "PMDExp6 - Win32 Release"
# Name "PMDExp6 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\DllEntry.cpp
# End Source File
# Begin Source File
SOURCE=.\ExpMesh.cpp
# End Source File
# Begin Source File
SOURCE=.\ExpProp.cpp
# End Source File
# Begin Source File
SOURCE=.\ExpSkeleton.cpp
# End Source File
# Begin Source File
SOURCE=.\ExpUtil.cpp
# End Source File
# Begin Source File
SOURCE=.\PMDExp.cpp
# End Source File
# Begin Source File
SOURCE=.\PMDExp.rc
# End Source File
# Begin Source File
SOURCE=.\PMDExp6.def
# End Source File
# Begin Source File
SOURCE=.\PSAExp.cpp
# End Source File
# Begin Source File
SOURCE=.\PSProp.cpp
# End Source File
# Begin Source File
SOURCE=.\VNormal.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\ExpMesh.h
# End Source File
# Begin Source File
SOURCE=.\ExpProp.h
# End Source File
# Begin Source File
SOURCE=.\ExpSkeleton.h
# End Source File
# Begin Source File
SOURCE=.\ExpUtil.h
# End Source File
# Begin Source File
SOURCE=.\ExpVertex.h
# End Source File
# Begin Source File
SOURCE=.\MaxInc.h
# End Source File
# Begin Source File
SOURCE=.\PMDExp.h
# End Source File
# Begin Source File
SOURCE=.\resource.h
# End Source File
# Begin Source File
SOURCE=.\Tree.h
# End Source File
# Begin Source File
SOURCE=.\VertexTree.h
# End Source File
# Begin Source File
SOURCE=.\VNormal.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PMDExp6", "PMDExp6.vcproj", "{DC12B42A-5BD3-4767-9947-059DF94BA502}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
Testing = Testing
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{DC12B42A-5BD3-4767-9947-059DF94BA502}.Debug.ActiveCfg = Debug|Win32
{DC12B42A-5BD3-4767-9947-059DF94BA502}.Debug.Build.0 = Debug|Win32
{DC12B42A-5BD3-4767-9947-059DF94BA502}.Release.ActiveCfg = Release|Win32
{DC12B42A-5BD3-4767-9947-059DF94BA502}.Release.Build.0 = Release|Win32
{DC12B42A-5BD3-4767-9947-059DF94BA502}.Testing.ActiveCfg = Release|Win32
{DC12B42A-5BD3-4767-9947-059DF94BA502}.Testing.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,414 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="PMDExp6"
ProjectGUID="{DC12B42A-5BD3-4767-9947-059DF94BA502}"
SccProjectName="&quot;$/dev/dylan/plugins/PMDExp&quot;, YVAAAAAA"
SccLocalPath=".">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\DebugR6"
IntermediateDirectory=".\DebugR6"
ConfigurationType="2"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/LD "
Optimization="0"
OptimizeForProcessor="2"
AdditionalIncludeDirectories="d:\3dsmax6\maxsdk\include,d:\3dsmax6\maxsdk\cssdk\include,..\..,..\..\lib,..\..\ps,..\..\simulation,..\..\terrain"
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\DebugR6/PMDExp6.pch"
AssemblerListingLocation=".\DebugR6/"
ObjectFile=".\DebugR6/"
ProgramDataBaseFileName=".\DebugR6/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib"
OutputFile="d:\3dsmax6\plugins\pmdexp6.dle"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="d:\3dsmax6\maxsdk\lib,..\libs"
ModuleDefinitionFile=".\PMDExp6.def"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile=".\DebugR6/pmdexp6.pdb"
SubSystem="2"
BaseAddress="0x50810000"
ImportLibrary=".\DebugR6/pmdexp6.lib"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="TRUE"
SuppressStartupBanner="TRUE"
TargetEnvironment="1"
TypeLibraryName=".\DebugR6/PMDExp6.tlb"
HeaderFileName=""/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2057"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\ReleaseR6"
IntermediateDirectory=".\ReleaseR6"
ConfigurationType="2"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/LD "
Optimization="4"
OptimizeForProcessor="1"
AdditionalIncludeDirectories="d:\3dsmax6\maxsdk\include,d:\3dsmax6\maxsdk\cssdk\include,..\..,..\..\lib,..\..\ps,..\..\simulation,..\..\terrain"
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_"
RuntimeLibrary="0"
PrecompiledHeaderFile=".\ReleaseR6/PMDExp6.pch"
AssemblerListingLocation=".\ReleaseR6/"
ObjectFile=".\ReleaseR6/"
ProgramDataBaseFileName=".\ReleaseR6/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib"
OutputFile="d:\3dsmax6\plugins\pmdexp6.dle"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="d:\3dsmax6\maxsdk\lib,..\libs"
ModuleDefinitionFile=".\PMDExp6.def"
ProgramDatabaseFile=".\ReleaseR6/pmdexp6.pdb"
SubSystem="2"
SetChecksum="TRUE"
BaseAddress="0x50810000"
ImportLibrary=".\ReleaseR6/pmdexp6.lib"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="TRUE"
SuppressStartupBanner="TRUE"
TargetEnvironment="1"
TypeLibraryName=".\ReleaseR6/PMDExp6.tlb"
HeaderFileName=""/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2057"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
<File
RelativePath="DllEntry.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
</File>
<File
RelativePath="ExpMesh.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
</File>
<File
RelativePath="ExpProp.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
</File>
<File
RelativePath="ExpSkeleton.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
</File>
<File
RelativePath="ExpUtil.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
</File>
<File
RelativePath=".\FilePacker.cpp">
</File>
<File
RelativePath=".\Matrix3D.cpp">
</File>
<File
RelativePath=".\ModelDef.cpp">
</File>
<File
RelativePath="PMDExp.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
</File>
<File
RelativePath="PMDExp.rc">
</File>
<File
RelativePath="PMDExp6.def">
</File>
<File
RelativePath="PSAExp.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
</File>
<File
RelativePath="PSProp.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
</File>
<File
RelativePath=".\Quaternion.cpp">
</File>
<File
RelativePath=".\SkeletonAnimDef.cpp">
</File>
<File
RelativePath=".\Vector3D.cpp">
</File>
<File
RelativePath="VNormal.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_DEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG;_USRDLL;_3DSMAX_;_WINDOWS;WIN32;_NO_WINMAIN_;$(NoInherit)"/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl">
<File
RelativePath="ExpMesh.h">
</File>
<File
RelativePath="ExpProp.h">
</File>
<File
RelativePath="ExpSkeleton.h">
</File>
<File
RelativePath="ExpUtil.h">
</File>
<File
RelativePath="ExpVertex.h">
</File>
<File
RelativePath=".\FilePacker.h">
</File>
<File
RelativePath=".\MathUtil.h">
</File>
<File
RelativePath=".\Matrix3D.h">
</File>
<File
RelativePath="MaxInc.h">
</File>
<File
RelativePath=".\ModelDef.h">
</File>
<File
RelativePath="PMDExp.h">
</File>
<File
RelativePath=".\pmdexp_types.h">
</File>
<File
RelativePath=".\PSAExp.h">
</File>
<File
RelativePath="resource.h">
</File>
<File
RelativePath=".\SkeletonAnimDef.h">
</File>
<File
RelativePath="Tree.h">
</File>
<File
RelativePath=".\Vector3D.h">
</File>
<File
RelativePath=".\Vector4D.h">
</File>
<File
RelativePath="VertexTree.h">
</File>
<File
RelativePath="VNormal.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,143 @@
#include "PSAExp.h"
#include "ExpMesh.h"
#include "ExpSkeleton.h"
#undef PI
#include "ModelDef.h"
//#include "SkeletonAnim.h"
//////////////////////////////////////////////////////////////////////
// PSAExp constructor
PSAExp::PSAExp()
{
}
//////////////////////////////////////////////////////////////////////
// PSAExp destructor
PSAExp::~PSAExp()
{
}
//////////////////////////////////////////////////////////////////////
// ExtCount: return the number of file name extensions supported
// by the plug-in.
int PSAExp::ExtCount()
{
return 1;
}
//////////////////////////////////////////////////////////////////////
// Ext: return the ith file name extension
const TCHAR* PSAExp::Ext(int n)
{
return _T("psa");
}
//////////////////////////////////////////////////////////////////////
// LongDesc: return long ASCII description
const TCHAR* PSAExp::LongDesc()
{
return _T("Prometheus Skeleton Anim");
}
//////////////////////////////////////////////////////////////////////
// ShortDesc: return short ASCII description
const TCHAR* PSAExp::ShortDesc()
{
return _T("Prometheus Anim");
}
//////////////////////////////////////////////////////////////////////
// AuthorName: return author name
const TCHAR* PSAExp::AuthorName()
{
return _T("Rich Cross");
}
//////////////////////////////////////////////////////////////////////
// CopyrightMessage: return copyright message
const TCHAR* PSAExp::CopyrightMessage()
{
return _T("(c) Wildfire Games 2004");
}
//////////////////////////////////////////////////////////////////////
// OtherMessage1: return some other message (or don't, in this case)
const TCHAR* PSAExp::OtherMessage1()
{
return _T("");
}
//////////////////////////////////////////////////////////////////////
// OtherMessage2: return some other message (or don't, in this case)
const TCHAR* PSAExp::OtherMessage2()
{
return _T("");
}
//////////////////////////////////////////////////////////////////////
// Version: return version number * 100 (i.e. v3.01 = 301)
unsigned int PSAExp::Version()
{
return 1;
}
//////////////////////////////////////////////////////////////////////
// ShowAbout: show an about box (or don't, in this case)
void PSAExp::ShowAbout(HWND hWnd)
{
}
//////////////////////////////////////////////////////////////////////
// SupportsOptions: return true for each option supported by each
// extension the exporter supports
BOOL PSAExp::SupportsOptions(int ext, DWORD options)
{
// return TRUE to indicate export selected supported
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// DoExport: actually perform the export to the given filename
int PSAExp::DoExport(const TCHAR *name,ExpInterface *ei,Interface *ip, BOOL suppressPrompts, DWORD options)
{
// result of the export: assume we'll fail somewhere along the way
BOOL res=FALSE;
// save off the interface ptr
m_IP=ip;
// save off the options
m_Options=options;
// build any skeletons in MAXs heirarchy before going any further
std::vector<ExpSkeleton*> skeletons;
ExpSkeleton::BuildSkeletons(m_IP->GetRootNode(),skeletons);
if (skeletons.size()>1) {
MessageBox(GetActiveWindow(),"Found more than one skeleton in scene","Error",MB_OK);
} else if (skeletons.size()==0) {
MessageBox(GetActiveWindow(),"No skeletons found in scene","Error",MB_OK);
} else {
// build an animation from first skeleton
ExpSkeleton* skeleton=skeletons[0];
Interval interval=m_IP->GetAnimRange();
CSkeletonAnimDef* anim=skeleton->BuildAnimation(interval.Start(),interval.End(),1000/30);
try {
CSkeletonAnimDef::Save(name,anim);
res=TRUE;
} catch (...) {
res=FALSE;
}
MessageBox(GetActiveWindow(),res ? "Export Complete" : "Error saving model",res ? "Info" : "Error",MB_OK);
}
// clean up
for (int i=0;i<skeletons.size();i++) {
delete skeletons[i];
}
// return result
return res;
}

View File

@ -0,0 +1,49 @@
#ifndef __PSAEXP_H
#define __PSAEXP_H
// necessary includes
#include "MaxInc.h"
#include <vector>
// necessary declarations
class ExpMesh;
class ExpSkeleton;
class CModelDef;
class CSkeleton;
/////////////////////////////////////////////////////////////////
// PSAExp:
class PSAExp : public SceneExport
{
public:
PSAExp();
~PSAExp();
// standard stuff that Max requires
int ExtCount(); // Number of extensions supported
const TCHAR* Ext(int n); // Extension #n (i.e. "3DS")
const TCHAR* LongDesc(); // Long ASCII description (i.e. "Autodesk 3D Studio File")
const TCHAR* ShortDesc(); // Short ASCII description (i.e. "3D Studio")
const TCHAR* AuthorName(); // ASCII Author name
const TCHAR* CopyrightMessage(); // ASCII Copyright message
const TCHAR* OtherMessage1(); // Other message #1
const TCHAR* OtherMessage2(); // Other message #2
unsigned int Version(); // Version number * 100 (i.e. v3.01 = 301)
void ShowAbout(HWND hWnd); // Show DLL's "About..." box
BOOL SupportsOptions(int ext, DWORD options);
int DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts=FALSE, DWORD options=0);
private:
// pointer to MAXs Interface object
Interface* m_IP;
// handle to the export parameters window
HWND m_Params;
// export options
DWORD m_Options;
// list of all skeletons found in scene
std::vector<ExpSkeleton*> m_Skeletons;
};
#endif

View File

@ -0,0 +1,924 @@
/**********************************************************************
*<
FILE: pthelp.cpp
DESCRIPTION: A point helper implementation
CREATED BY:
HISTORY: created 14 July 1995
*> Copyright (c) 1995, All Rights Reserved.
**********************************************************************/
#include "PSProp.h"
//------------------------------------------------------
// in prim.cpp - The dll instance handle
extern HINSTANCE hInstance;
#define AXIS_LENGTH 20.0f
#define ZFACT (float).005;
void AxisViewportRect(ViewExp *vpt, const Matrix3 &tm, float length, Rect *rect);
void DrawAxis(ViewExp *vpt, const Matrix3 &tm, float length, BOOL screenSize);
Box3 GetAxisBox(ViewExp *vpt, const Matrix3 &tm,float length,int resetTM);
//////////////////////////////////////////////////////////////////////////////////////
// PSPropClassDesc : required class to expose PSProp to MAX
class PSPropClassDesc : public ClassDesc2
{
public:
int IsPublic() { return 1; }
void * Create(BOOL loading = FALSE) { return new PSPropObject; }
const TCHAR * ClassName() { return GetString(IDS_DB_POINT_CLASS); }
SClass_ID SuperClassID() { return HELPER_CLASS_ID; }
Class_ID ClassID() { return PSPROP_CLASS_ID; }
const TCHAR* Category() { return _T("PS Helpers"); }
const TCHAR* InternalName() {return _T("PSProp");}
HINSTANCE HInstance() {return hInstance;}
};
PSPropClassDesc pointHelpObjDesc;
ClassDesc* GetPSPropDesc() { return &pointHelpObjDesc; }
// class variable for point class.
IObjParam *PSPropObject::ip = NULL;
PSPropObject *PSPropObject::editOb = NULL;
//HWND PSPropObject::hParams = NULL;
//IObjParam *PSPropObject::iObjParams;
//int PSPropObject::dlgShowAxis = TRUE;
//float PSPropObject::dlgAxisLength = AXIS_LENGTH;
void resetPointParams()
{
//PSPropObject::dlgShowAxis = TRUE;
//PSPropObject::dlgAxisLength = AXIS_LENGTH;
}
#define PBLOCK_REF_NO 0
// The following two enums are transfered to the istdplug.h by AG: 01/20/2002
// in order to access the parameters for use in Spline IK Control modifier
// and the Spline IK Solver
// block IDs
//enum { pointobj_params, };
// pointobj_params IDs
// enum {
// pointobj_size, pointobj_centermarker, pointobj_axistripod,
// pointobj_cross, pointobj_box, pointobj_screensize, pointobj_drawontop };
// per instance block
static ParamBlockDesc2 pointobj_param_blk(
pointobj_params, _T("PointObjectParameters"), 0, &pointHelpObjDesc, P_AUTO_CONSTRUCT+P_AUTO_UI, PBLOCK_REF_NO,
//rollout
IDD_NEW_POINTPARAM, IDS_POINT_PARAMS, 0, 0, NULL,
// params
pointobj_size, _T("size"), TYPE_FLOAT, P_ANIMATABLE, IDS_POINT_SIZE,
p_default, 20.0,
p_ms_default, 20.0,
p_range, 0.0f, float(1.0E30),
p_ui, TYPE_SPINNER, EDITTYPE_UNIVERSE, IDC_POINT_SIZE, IDC_POINT_SIZESPIN, SPIN_AUTOSCALE,
end,
pointobj_centermarker, _T("centermarker"), TYPE_BOOL, P_ANIMATABLE, IDS_POINT_CENTERMARKER,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_POINT_MARKER,
end,
pointobj_axistripod, _T("axistripod"), TYPE_BOOL, P_ANIMATABLE, IDS_POINT_AXISTRIPOD,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_POINT_AXIS,
end,
pointobj_cross, _T("cross"), TYPE_BOOL, P_ANIMATABLE, IDS_POINT_CROSS,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_POINT_CROSS,
end,
pointobj_box, _T("box"), TYPE_BOOL, P_ANIMATABLE, IDS_POINT_BOX,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_POINT_BOX,
end,
pointobj_screensize, _T("constantscreensize"), TYPE_BOOL, P_ANIMATABLE, IDS_POINT_SCREENSIZE,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_POINT_SCREENSIZE,
end,
pointobj_drawontop, _T("drawontop"), TYPE_BOOL, P_ANIMATABLE, IDS_POINT_DRAWONTOP,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_POINT_DRAWONTOP,
end,
end
);
/*
INT_PTR CALLBACK PointParamProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
PSPropObject *po = (PSPropObject*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
if (!po && msg!=WM_INITDIALOG) return FALSE;
switch (msg) {
case WM_INITDIALOG: {
po = (PSPropObject*)lParam;
SetWindowLongPtr(hWnd,GWLP_USERDATA,lParam);
CheckDlgButton(hWnd,IDC_SHOWAXIS,po->showAxis);
ISpinnerControl *spin =
GetISpinner(GetDlgItem(hWnd,IDC_AXISLENGHSPIN));
spin->SetLimits(10,1000,FALSE);
spin->SetScale(0.1f);
spin->SetValue(po->axisLength,FALSE);
spin->LinkToEdit(GetDlgItem(hWnd,IDC_AXISLENGTH),EDITTYPE_FLOAT);
ReleaseISpinner(spin);
return FALSE;
}
case CC_SPINNER_CHANGE: {
ISpinnerControl *spin = (ISpinnerControl*)lParam;
po->axisLength = spin->GetFVal();
po->NotifyDependents(FOREVER,PART_OBJ,REFMSG_CHANGE);
po->iObjParams->RedrawViews(po->iObjParams->GetTime());
break;
}
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_SHOWAXIS:
po->showAxis = IsDlgButtonChecked(hWnd,IDC_SHOWAXIS);
po->NotifyDependents(FOREVER,PART_OBJ,REFMSG_CHANGE);
po->iObjParams->RedrawViews(po->iObjParams->GetTime());
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
*/
void PSPropObject::BeginEditParams(
IObjParam *ip, ULONG flags,Animatable *prev)
{
this->ip = ip;
editOb = this;
pointHelpObjDesc.BeginEditParams(ip, this, flags, prev);
/*
iObjParams = ip;
if (!hParams) {
hParams = ip->AddRollupPage(
hInstance,
MAKEINTRESOURCE(IDD_POINTPARAM),
PointParamProc,
GetString(IDS_DB_PARAMETERS),
(LPARAM)this );
ip->RegisterDlgWnd(hParams);
} else {
SetWindowLongPtr(hParams,GWLP_USERDATA,(LONG_PTR)this);
CheckDlgButton(hParams,IDC_SHOWAXIS,showAxis);
ISpinnerControl *spin =
GetISpinner(GetDlgItem(hParams,IDC_AXISLENGHSPIN));
spin->SetValue(axisLength,FALSE);
ReleaseISpinner(spin);
}
*/
}
void PSPropObject::EndEditParams(
IObjParam *ip, ULONG flags,Animatable *next)
{
editOb = NULL;
this->ip = NULL;
pointHelpObjDesc.EndEditParams(ip, this, flags, next);
ClearAFlag(A_OBJ_CREATING);
/*
dlgShowAxis = IsDlgButtonChecked(hParams, IDC_SHOWAXIS );
ISpinnerControl *spin = GetISpinner(GetDlgItem(hParams,IDC_AXISLENGHSPIN));
dlgAxisLength = spin->GetFVal();
ReleaseISpinner(spin);
if (flags&END_EDIT_REMOVEUI) {
ip->UnRegisterDlgWnd(hParams);
ip->DeleteRollupPage(hParams);
hParams = NULL;
} else {
SetWindowLongPtr(hParams,GWLP_USERDATA,0);
}
iObjParams = NULL;
*/
}
PSPropObject::PSPropObject()
{
pointHelpObjDesc.MakeAutoParamBlocks(this);
showAxis = TRUE; //dlgShowAxis;
axisLength = 10.0f; //dlgAxisLength;
suspendSnap = FALSE;
SetAFlag(A_OBJ_CREATING);
}
PSPropObject::~PSPropObject()
{
DeleteAllRefsFromMe();
}
IParamArray *PSPropObject::GetParamBlock()
{
return (IParamArray*)pblock2;
}
int PSPropObject::GetParamBlockIndex(int id)
{
if (pblock2 && id>=0 && id<pblock2->NumParams()) return id;
else return -1;
}
class PointHelpObjCreateCallBack: public CreateMouseCallBack {
PSPropObject *ob;
public:
int proc( ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat );
void SetObj(PSPropObject *obj) { ob = obj; }
};
int PointHelpObjCreateCallBack::proc(ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat ) {
#ifdef _OSNAP
if (msg == MOUSE_FREEMOVE)
{
#ifdef _3D_CREATE
vpt->SnapPreview(m,m,NULL, SNAP_IN_3D);
#else
vpt->SnapPreview(m,m,NULL, SNAP_IN_PLANE);
#endif
}
#endif
if (msg==MOUSE_POINT||msg==MOUSE_MOVE) {
switch(point) {
case 0: {
// Find the node and plug in the wire color
ULONG handle;
ob->NotifyDependents(FOREVER, (PartID)&handle, REFMSG_GET_NODE_HANDLE);
INode *node;
node = GetCOREInterface()->GetINodeByHandle(handle);
if (node) {
Point3 color(0,0,1);// = GetUIColor(COLOR_POINT_OBJ);
node->SetWireColor(RGB(color.x*255.0f, color.y*255.0f, color.z*255.0f));
}
ob->suspendSnap = TRUE;
#ifdef _3D_CREATE
mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_3D));
#else
mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE));
#endif
break;
}
case 1:
#ifdef _3D_CREATE
mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_3D));
#else
mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE));
#endif
if (msg==MOUSE_POINT) {
ob->suspendSnap = FALSE;
return 0;
}
break;
}
} else
if (msg == MOUSE_ABORT) {
return CREATE_ABORT;
}
return 1;
}
static PointHelpObjCreateCallBack pointHelpCreateCB;
CreateMouseCallBack* PSPropObject::GetCreateMouseCallBack() {
pointHelpCreateCB.SetObj(this);
return(&pointHelpCreateCB);
}
void PSPropObject::SetExtendedDisplay(int flags)
{
extDispFlags = flags;
}
void PSPropObject::GetLocalBoundBox(
TimeValue t, INode* inode, ViewExp* vpt, Box3& box )
{
Matrix3 tm = inode->GetObjectTM(t);
float size;
int screenSize;
pblock2->GetValue(pointobj_size, t, size, FOREVER);
pblock2->GetValue(pointobj_screensize, t, screenSize, FOREVER);
float zoom = 1.0f;
if (screenSize) {
zoom = vpt->GetScreenScaleFactor(tm.GetTrans())*ZFACT;
}
if (zoom==0.0f) zoom = 1.0f;
size *= zoom;
box = Box3(Point3(0,0,0), Point3(0,0,0));
box += Point3(size*0.5f, 0.0f, 0.0f);
box += Point3( 0.0f, size*0.5f, 0.0f);
box += Point3( 0.0f, 0.0f, size*0.5f);
box += Point3(-size*0.5f, 0.0f, 0.0f);
box += Point3( 0.0f, -size*0.5f, 0.0f);
box += Point3( 0.0f, 0.0f, -size*0.5f);
box.EnlargeBy(10.0f/zoom);
/*
if (showAxis)
box = GetAxisBox(vpt,tm,showAxis?axisLength:0.0f, TRUE);
else
box = Box3(Point3(0,0,0), Point3(0,0,0));
*/
}
void PSPropObject::GetWorldBoundBox(
TimeValue t, INode* inode, ViewExp* vpt, Box3& box )
{
Matrix3 tm;
tm = inode->GetObjectTM(t);
Box3 lbox;
GetLocalBoundBox(t, inode, vpt, lbox);
box = Box3(tm.GetTrans(), tm.GetTrans());
for (int i=0; i<8; i++) {
box += lbox * tm;
}
/*
if(!(extDispFlags & EXT_DISP_ZOOM_EXT) && showAxis)
box = GetAxisBox(vpt,tm,showAxis?axisLength:0.0f, FALSE);
else
box = Box3(tm.GetTrans(), tm.GetTrans());
*/
}
void PSPropObject::Snap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt)
{
if(suspendSnap)
return;
Matrix3 tm = inode->GetObjectTM(t);
GraphicsWindow *gw = vpt->getGW();
gw->setTransform(tm);
Matrix3 invPlane = Inverse(snap->plane);
// Make sure the vertex priority is active and at least as important as the best snap so far
if(snap->vertPriority > 0 && snap->vertPriority <= snap->priority) {
Point2 fp = Point2((float)p->x, (float)p->y);
Point2 screen2;
IPoint3 pt3;
Point3 thePoint(0,0,0);
// If constrained to the plane, make sure this point is in it!
if(snap->snapType == SNAP_2D || snap->flags & SNAP_IN_PLANE) {
Point3 test = thePoint * tm * invPlane;
if(fabs(test.z) > 0.0001) // Is it in the plane (within reason)?
return;
}
gw->wTransPoint(&thePoint,&pt3);
screen2.x = (float)pt3.x;
screen2.y = (float)pt3.y;
// Are we within the snap radius?
int len = (int)Length(screen2 - fp);
if(len <= snap->strength) {
// Is this priority better than the best so far?
if(snap->vertPriority < snap->priority) {
snap->priority = snap->vertPriority;
snap->bestWorld = thePoint * tm;
snap->bestScreen = screen2;
snap->bestDist = len;
}
else
if(len < snap->bestDist) {
snap->priority = snap->vertPriority;
snap->bestWorld = thePoint * tm;
snap->bestScreen = screen2;
snap->bestDist = len;
}
}
}
}
int PSPropObject::DrawAndHit(TimeValue t, INode *inode, ViewExp *vpt)
{
float size;
int centerMarker, axisTripod, cross, box, screenSize, drawOnTop;
// Color color = inode->GetWireColor();
Interval ivalid = FOREVER;
pblock2->GetValue(pointobj_size, t, size, ivalid);
pblock2->GetValue(pointobj_centermarker, t, centerMarker, ivalid);
pblock2->GetValue(pointobj_axistripod, t, axisTripod, ivalid);
pblock2->GetValue(pointobj_cross, t, cross, ivalid);
pblock2->GetValue(pointobj_box, t, box, ivalid);
pblock2->GetValue(pointobj_screensize, t, screenSize, ivalid);
pblock2->GetValue(pointobj_drawontop, t, drawOnTop, ivalid);
Matrix3 tm(1);
Point3 pt(0,0,0);
Point3 pts[5];
vpt->getGW()->setTransform(tm);
tm = inode->GetObjectTM(t);
int limits = vpt->getGW()->getRndLimits();
if (drawOnTop) vpt->getGW()->setRndLimits(limits & ~GW_Z_BUFFER);
if (inode->Selected()) {
vpt->getGW()->setColor( TEXT_COLOR, GetUIColor(COLOR_SELECTION) );
vpt->getGW()->setColor( LINE_COLOR, GetUIColor(COLOR_SELECTION) );
} else if (!inode->IsFrozen() && !inode->Dependent()) {
//vpt->getGW()->setColor( TEXT_COLOR, GetUIColor(COLOR_POINT_AXES) );
//vpt->getGW()->setColor( LINE_COLOR, GetUIColor(COLOR_POINT_AXES) );
vpt->getGW()->setColor( TEXT_COLOR, Color(0,0,1));
vpt->getGW()->setColor( LINE_COLOR, Color(0,0,1));
}
if (axisTripod) {
DrawAxis(vpt, tm, size, screenSize);
}
size *= 0.5f;
float zoom = vpt->GetScreenScaleFactor(tm.GetTrans())*ZFACT;
if (screenSize) {
tm.Scale(Point3(zoom,zoom,zoom));
}
vpt->getGW()->setTransform(tm);
if (!inode->IsFrozen() && !inode->Dependent() && !inode->Selected()) {
//vpt->getGW()->setColor(LINE_COLOR, GetUIColor(COLOR_POINT_OBJ));
vpt->getGW()->setColor( LINE_COLOR, Color(0,0,1));
}
if (centerMarker) {
vpt->getGW()->marker(&pt,X_MRKR);
}
if (cross) {
// X
pts[0] = Point3(-size, 0.0f, 0.0f); pts[1] = Point3(size, 0.0f, 0.0f);
vpt->getGW()->polyline(2, pts, NULL, NULL, FALSE, NULL);
// Y
pts[0] = Point3(0.0f, -size, 0.0f); pts[1] = Point3(0.0f, size, 0.0f);
vpt->getGW()->polyline(2, pts, NULL, NULL, FALSE, NULL);
// Z
pts[0] = Point3(0.0f, 0.0f, -size); pts[1] = Point3(0.0f, 0.0f, size);
vpt->getGW()->polyline(2, pts, NULL, NULL, FALSE, NULL);
}
if (box) {
// Make the box half the size
size = size * 0.5f;
// Bottom
pts[0] = Point3(-size, -size, -size);
pts[1] = Point3(-size, size, -size);
pts[2] = Point3( size, size, -size);
pts[3] = Point3( size, -size, -size);
vpt->getGW()->polyline(4, pts, NULL, NULL, TRUE, NULL);
// Top
pts[0] = Point3(-size, -size, size);
pts[1] = Point3(-size, size, size);
pts[2] = Point3( size, size, size);
pts[3] = Point3( size, -size, size);
vpt->getGW()->polyline(4, pts, NULL, NULL, TRUE, NULL);
// Sides
pts[0] = Point3(-size, -size, -size);
pts[1] = Point3(-size, -size, size);
vpt->getGW()->polyline(2, pts, NULL, NULL, FALSE, NULL);
pts[0] = Point3(-size, size, -size);
pts[1] = Point3(-size, size, size);
vpt->getGW()->polyline(2, pts, NULL, NULL, FALSE, NULL);
pts[0] = Point3( size, size, -size);
pts[1] = Point3( size, size, size);
vpt->getGW()->polyline(2, pts, NULL, NULL, FALSE, NULL);
pts[0] = Point3( size, -size, -size);
pts[1] = Point3( size, -size, size);
vpt->getGW()->polyline(2, pts, NULL, NULL, FALSE, NULL);
}
vpt->getGW()->setRndLimits(limits);
return 1;
}
int PSPropObject::HitTest(
TimeValue t, INode *inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt)
{
Matrix3 tm(1);
HitRegion hitRegion;
DWORD savedLimits;
Point3 pt(0,0,0);
vpt->getGW()->setTransform(tm);
GraphicsWindow *gw = vpt->getGW();
Material *mtl = gw->getMaterial();
tm = inode->GetObjectTM(t);
MakeHitRegion(hitRegion, type, crossing, 4, p);
gw->setRndLimits(((savedLimits = gw->getRndLimits())|GW_PICK)&~GW_ILLUM);
gw->setHitRegion(&hitRegion);
gw->clearHitCode();
DrawAndHit(t, inode, vpt);
/*
if (showAxis) {
DrawAxis(vpt,tm,axisLength,screenSize);
}
vpt->getGW()->setTransform(tm);
vpt->getGW()->marker(&pt,X_MRKR);
*/
gw->setRndLimits(savedLimits);
if((hitRegion.type != POINT_RGN) && !hitRegion.crossing)
return TRUE;
return gw->checkHitCode();
}
int PSPropObject::Display(
TimeValue t, INode* inode, ViewExp *vpt, int flags)
{
DrawAndHit(t, inode, vpt);
/*
Matrix3 tm(1);
Point3 pt(0,0,0);
vpt->getGW()->setTransform(tm);
tm = inode->GetObjectTM(t);
if (showAxis) {
DrawAxis(vpt,tm,axisLength,inode->Selected(),inode->IsFrozen());
}
vpt->getGW()->setTransform(tm);
if(!inode->IsFrozen())
vpt->getGW()->setColor(LINE_COLOR,GetUIColor(COLOR_POINT_OBJ));
vpt->getGW()->marker(&pt,X_MRKR);
*/
return(0);
}
//
// Reference Managment:
//
// This is only called if the object MAKES references to other things.
RefResult PSPropObject::NotifyRefChanged(
Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message )
{
switch (message) {
case REFMSG_CHANGE:
if (editOb==this) InvalidateUI();
break;
}
return(REF_SUCCEED);
}
void PSPropObject::InvalidateUI()
{
pointobj_param_blk.InvalidateUI(pblock2->LastNotifyParamID());
}
Interval PSPropObject::ObjectValidity(TimeValue t)
{
float size;
int centerMarker, axisTripod, cross, box, screenSize, drawOnTop;
Interval ivalid = FOREVER;
pblock2->GetValue(pointobj_size, t, size, ivalid);
pblock2->GetValue(pointobj_centermarker, t, centerMarker, ivalid);
pblock2->GetValue(pointobj_axistripod, t, axisTripod, ivalid);
pblock2->GetValue(pointobj_cross, t, cross, ivalid);
pblock2->GetValue(pointobj_box, t, box, ivalid);
pblock2->GetValue(pointobj_screensize, t, screenSize, ivalid);
pblock2->GetValue(pointobj_drawontop, t, drawOnTop, ivalid);
return ivalid;
}
ObjectState PSPropObject::Eval(TimeValue t)
{
return ObjectState(this);
}
RefTargetHandle PSPropObject::Clone(RemapDir& remap)
{
PSPropObject* newob = new PSPropObject();
newob->showAxis = showAxis;
newob->axisLength = axisLength;
newob->ReplaceReference(0, pblock2->Clone(remap));
BaseClone(this, newob, remap);
return(newob);
}
void PSPropObject::UpdateParamblockFromVars()
{
SuspendAnimate();
AnimateOff();
pblock2->SetValue(pointobj_size, TimeValue(0), axisLength);
pblock2->SetValue(pointobj_centermarker, TimeValue(0), TRUE);
pblock2->SetValue(pointobj_axistripod, TimeValue(0), showAxis);
pblock2->SetValue(pointobj_cross, TimeValue(0), FALSE);
pblock2->SetValue(pointobj_box, TimeValue(0), FALSE);
pblock2->SetValue(pointobj_screensize, TimeValue(0), TRUE);
ResumeAnimate();
}
class PointHelperPostLoadCallback : public PostLoadCallback {
public:
PSPropObject *pobj;
PointHelperPostLoadCallback(PSPropObject *p) {pobj=p;}
void proc(ILoad *iload) {
pobj->UpdateParamblockFromVars();
}
};
#define SHOW_AXIS_CHUNK 0x0100
#define AXIS_LENGTH_CHUNK 0x0110
#define POINT_HELPER_R4_CHUNKID 0x0120 // new version of point helper for R4 (updated to use PB2)
IOResult PSPropObject::Load(ILoad *iload)
{
ULONG nb;
IOResult res = IO_OK;
BOOL oldVersion = TRUE;
while (IO_OK==(res=iload->OpenChunk())) {
switch (iload->CurChunkID()) {
case SHOW_AXIS_CHUNK:
res = iload->Read(&showAxis,sizeof(showAxis),&nb);
break;
case AXIS_LENGTH_CHUNK:
res = iload->Read(&axisLength,sizeof(axisLength),&nb);
break;
case POINT_HELPER_R4_CHUNKID:
oldVersion = FALSE;
break;
}
res = iload->CloseChunk();
if (res!=IO_OK) return res;
}
if (oldVersion) {
iload->RegisterPostLoadCallback(new PointHelperPostLoadCallback(this));
}
return IO_OK;
}
IOResult PSPropObject::Save(ISave *isave)
{
/*
isave->BeginChunk(SHOW_AXIS_CHUNK);
isave->Write(&showAxis,sizeof(showAxis),&nb);
isave->EndChunk();
isave->BeginChunk(AXIS_LENGTH_CHUNK);
isave->Write(&axisLength,sizeof(axisLength),&nb);
isave->EndChunk();
*/
isave->BeginChunk(POINT_HELPER_R4_CHUNKID);
isave->EndChunk();
return IO_OK;
}
/*--------------------------------------------------------------------*/
//
// Stole this from scene.cpp
// Probably couldn't hurt to make an API...
//
//
void Text( ViewExp *vpt, TCHAR *str, Point3 &pt )
{
vpt->getGW()->text( &pt, str );
}
static void DrawAnAxis( ViewExp *vpt, Point3 axis )
{
Point3 v1, v2, v[3];
v1 = axis * (float)0.9;
if ( axis.x != 0.0 || axis.y != 0.0 ) {
v2 = Point3( axis.y, -axis.x, axis.z ) * (float)0.1;
} else {
v2 = Point3( axis.x, axis.z, -axis.y ) * (float)0.1;
}
v[0] = Point3(0.0,0.0,0.0);
v[1] = axis;
vpt->getGW()->polyline( 2, v, NULL, NULL, FALSE, NULL );
v[0] = axis;
v[1] = v1+v2;
vpt->getGW()->polyline( 2, v, NULL, NULL, FALSE, NULL );
v[0] = axis;
v[1] = v1-v2;
vpt->getGW()->polyline( 2, v, NULL, NULL, FALSE, NULL );
}
void DrawAxis(ViewExp *vpt, const Matrix3 &tm, float length, BOOL screenSize)
{
Matrix3 tmn = tm;
float zoom;
// Get width of viewport in world units: --DS
zoom = vpt->GetScreenScaleFactor(tmn.GetTrans())*ZFACT;
if (screenSize) {
tmn.Scale( Point3(zoom,zoom,zoom) );
}
vpt->getGW()->setTransform( tmn );
Text( vpt, _T("x"), Point3(length,0.0f,0.0f) );
DrawAnAxis( vpt, Point3(length,0.0f,0.0f) );
Text( vpt, _T("y"), Point3(0.0f,length,0.0f) );
DrawAnAxis( vpt, Point3(0.0f,length,0.0f) );
Text( vpt, _T("z"), Point3(0.0f,0.0f,length) );
DrawAnAxis( vpt, Point3(0.0f,0.0f,length) );
}
//--- RB 7/17/2000: the code below seems to be unused ---------------------------------------------------
Box3 GetAxisBox(ViewExp *vpt, const Matrix3 &tm,float length,int resetTM)
{
Matrix3 tmn = tm;
Box3 box;
float zoom;
// Get width of viewport in world units: --DS
zoom = vpt->GetScreenScaleFactor(tmn.GetTrans())*ZFACT;
if (zoom==0.0f) zoom = 1.0f;
// tmn.Scale(Point3(zoom,zoom,zoom));
length *= zoom;
if(resetTM)
tmn.IdentityMatrix();
box += Point3(0.0f,0.0f,0.0f) * tmn;
box += Point3(length,0.0f,0.0f) * tmn;
box += Point3(0.0f,length,0.0f) * tmn;
box += Point3(0.0f,0.0f,length) * tmn;
box += Point3(-length/5.f,0.0f,0.0f) * tmn;
box += Point3(0.0f,-length/5.f,0.0f) * tmn;
box += Point3(0.0f,0.0f,-length/5.0f) * tmn;
box.EnlargeBy(10.0f/zoom);
return box;
}
inline void EnlargeRectIPoint3( RECT *rect, IPoint3& pt )
{
if ( pt.x < rect->left ) rect->left = pt.x;
if ( pt.x > rect->right ) rect->right = pt.x;
if ( pt.y < rect->top ) rect->top = pt.y;
if ( pt.y > rect->bottom ) rect->bottom = pt.y;
}
// This is a guess - need to find real w/h.
#define FONT_HEIGHT 11
#define FONT_WIDTH 9
static void AxisRect( GraphicsWindow *gw, Point3 axis, Rect *rect )
{
Point3 v1, v2, v;
IPoint3 iv;
v1 = axis * (float)0.9;
if ( axis.x != 0.0 || axis.y != 0.0 ) {
v2 = Point3( axis.y, -axis.x, axis.z ) * (float)0.1;
} else {
v2 = Point3( axis.x, axis.z, -axis.y ) * (float)0.1;
}
v = axis;
gw->wTransPoint( &v, &iv );
EnlargeRectIPoint3( rect, iv);
iv.x += FONT_WIDTH;
iv.y -= FONT_HEIGHT;
EnlargeRectIPoint3( rect, iv);
v = v1+v2;
gw->wTransPoint( &v, &iv );
EnlargeRectIPoint3( rect, iv);
v = v1-v2;
gw->wTransPoint( &v, &iv );
EnlargeRectIPoint3( rect, iv);
}
void AxisViewportRect(ViewExp *vpt, const Matrix3 &tm, float length, Rect *rect)
{
Matrix3 tmn = tm;
float zoom;
IPoint3 wpt;
Point3 pt;
GraphicsWindow *gw = vpt->getGW();
// Get width of viewport in world units: --DS
zoom = vpt->GetScreenScaleFactor(tmn.GetTrans())*ZFACT;
tmn.Scale( Point3(zoom,zoom,zoom) );
gw->setTransform( tmn );
pt = Point3(0.0f, 0.0f, 0.0f);
gw->wTransPoint( &pt, &wpt );
rect->left = rect->right = wpt.x;
rect->top = rect->bottom = wpt.y;
AxisRect( gw, Point3(length,0.0f,0.0f),rect );
AxisRect( gw, Point3(0.0f,length,0.0f),rect );
AxisRect( gw, Point3(0.0f,0.0f,length),rect );
rect->right += 2;
rect->bottom += 2;
rect->left -= 2;
rect->top -= 2;
}

View File

@ -0,0 +1,95 @@
#ifndef _PSPROP_H
#define _PSPROP_H
#include "MaxInc.h"
TCHAR *GetString(int id);
#define PSPROP_CLASS_ID Class_ID(0x353f201d, 0x3d01408d)
extern ClassDesc* GetPSPropDesc();
class PSPropObject : public HelperObject
{
public:
static IObjParam *ip;
static PSPropObject *editOb;
IParamBlock2 *pblock2;
// Class vars
/*
static HWND hParams;
static IObjParam *iObjParams;
static int dlgShowAxis;
static float dlgAxisLength;
*/
// Snap suspension flag (TRUE during creation only)
BOOL suspendSnap;
// Old params... these are for loading old files only. Params are now stored in pb2.
BOOL showAxis;
float axisLength;
// For use by display system
int extDispFlags;
// inherited virtual methods for Reference-management
RefResult NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message );
PSPropObject();
~PSPropObject();
// From BaseObject
int HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt);
void Snap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt);
void SetExtendedDisplay(int flags);
int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags);
CreateMouseCallBack* GetCreateMouseCallBack();
void BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev);
void EndEditParams( IObjParam *ip, ULONG flags,Animatable *next);
TCHAR *GetObjectName() {return GetString(IDS_POINT_HELPER_NAME);}
// From Object
ObjectState Eval(TimeValue time);
void InitNodeName(TSTR& s) { s = GetString(IDS_DB_POINT); }
ObjectHandle ApplyTransform(Matrix3& matrix) {return this;}
int CanConvertToType(Class_ID obtype) {return FALSE;}
Object* ConvertToType(TimeValue t, Class_ID obtype) {assert(0);return NULL;}
void GetWorldBoundBox(TimeValue t, INode *mat, ViewExp *vpt, Box3& box );
void GetLocalBoundBox(TimeValue t, INode *mat, ViewExp *vpt, Box3& box );
int DoOwnSelectHilite() { return 1; }
Interval ObjectValidity(TimeValue t);
int UsesWireColor() {return TRUE;}
// Animatable methods
void DeleteThis() { delete this; }
Class_ID ClassID() { return PSPROP_CLASS_ID; }
void GetClassName(TSTR& s) { s = TSTR(GetString(IDS_DB_POINTHELPER_CLASS)); }
int IsKeyable(){ return 0;}
int NumSubs() { return 1; }
Animatable* SubAnim(int i) { return pblock2; }
TSTR SubAnimName(int i) { return TSTR(_T("Parameters"));}
IParamArray *GetParamBlock();
int GetParamBlockIndex(int id);
int NumParamBlocks() { return 1; }
IParamBlock2* GetParamBlock(int i) { return pblock2; }
IParamBlock2* GetParamBlockByID(short id) { return pblock2; }
// From ref
RefTargetHandle Clone(RemapDir& remap = NoRemap());
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
int NumRefs() {return 1;}
RefTargetHandle GetReference(int i) {return pblock2;}
void SetReference(int i, RefTargetHandle rtarg) {pblock2=(IParamBlock2*)rtarg;}
// Local methods
void InvalidateUI();
void UpdateParamblockFromVars();
int DrawAndHit(TimeValue t, INode *inode, ViewExp *vpt);
};
#endif

View File

@ -0,0 +1,202 @@
/************************************************************
*
* File Name: Quaternion.Cpp
*
* Description:
*
************************************************************/
#include "Quaternion.h"
const float EPSILON=0.0001f;
CQuaternion::CQuaternion()
{
m_V.Clear ();
m_W = 0;
}
//quaternion addition
CQuaternion CQuaternion::operator + (CQuaternion &quat)
{
CQuaternion Temp;
Temp.m_W = m_W + quat.m_W;
Temp.m_V = m_V + quat.m_V;
return Temp;
}
//quaternion addition/assignment
CQuaternion &CQuaternion::operator += (CQuaternion &quat)
{
m_W += quat.m_W;
m_V += quat.m_V;
return (*this);
}
//quaternion multiplication
CQuaternion CQuaternion::operator * (CQuaternion &quat)
{
CQuaternion Temp;
Temp.m_W = (m_W * quat.m_W) - (m_V.Dot(quat.m_V));
Temp.m_V = (m_V.Cross(quat.m_V)) + (quat.m_V * m_W) + (m_V * quat.m_W);
return Temp;
}
//quaternion multiplication/assignment
CQuaternion &CQuaternion::operator *= (CQuaternion &quat)
{
(*this) = (*this) * quat;
return (*this);
}
void CQuaternion::FromEularAngles (float x, float y, float z)
{
float cr, cp, cy;
float sr, sp, sy;
CQuaternion QRoll, QPitch, QYaw;
cr = cosf(x * 0.5f);
cp = cosf(y * 0.5f);
cy = cosf(z * 0.5f);
sr = sinf(x * 0.5f);
sp = sinf(y * 0.5f);
sy = sinf(z * 0.5f);
QRoll.m_V.Set (sr,0,0);
QRoll.m_W = cr;
QPitch.m_V.Set (0,sp,0);
QPitch.m_W = cp;
QYaw.m_V.Set (0,0,sy);
QYaw.m_W = cy;
(*this) = QYaw * QPitch * QRoll;
}
CMatrix3D CQuaternion::ToMatrix () const
{
CMatrix3D result;
ToMatrix(result);
return result;
}
void CQuaternion::ToMatrix(CMatrix3D& result) const
{
float x2, y2, z2;
float wx, wy, wz, xx, xy, xz, yy, yz, zz;
// calculate coefficients
x2 = m_V.X + m_V.X;
y2 = m_V.Y + m_V.Y;
z2 = m_V.Z + m_V.Z;
xx = m_V.X * x2;
xy = m_V.X * y2;
xz = m_V.X * z2;
yy = m_V.Y * y2;
yz = m_V.Y * z2;
zz = m_V.Z * z2;
wx = m_W * x2;
wy = m_W * y2;
wz = m_W * z2;
result._11 = 1.0f - (yy + zz);
result._12 = xy - wz;
result._13 = xz + wy;
result._14 = 0;
result._21 = xy + wz;
result._22 = 1.0f - (xx + zz);
result._23 = yz - wx;
result._24 = 0;
result._31 = xz - wy;
result._32 = yz + wx;
result._33 = 1.0f - (xx + yy);
result._34 = 0;
result._41 = 0;
result._42 = 0;
result._43 = 0;
result._44 = 1;
}
void CQuaternion::Slerp(const CQuaternion& from,const CQuaternion& to, float ratio)
{
float to1[4];
float omega, cosom, sinom, scale0, scale1;
// calc cosine
cosom = from.m_V.X * to.m_V.X +
from.m_V.Y * to.m_V.Y +
from.m_V.Z * to.m_V.Z +
from.m_W * to.m_W;
// adjust signs (if necessary)
if (cosom < 0.0)
{
cosom = -cosom;
to1[0] = -to.m_V.X;
to1[1] = -to.m_V.Y;
to1[2] = -to.m_V.Z;
to1[3] = -to.m_W;
}
else
{
to1[0] = to.m_V.X;
to1[1] = to.m_V.Y;
to1[2] = to.m_V.Z;
to1[3] = to.m_W;
}
// calculate coefficients
if ((1.0f - cosom) > EPSILON)
{
// standard case (slerp)
omega = acosf(cosom);
sinom = sinf(omega);
scale0 = sinf((1.0f - ratio) * omega) / sinom;
scale1 = sinf(ratio * omega) / sinom;
}
else
{
// "from" and "to" quaternions are very close
// ... so we can do a linear interpolation
scale0 = 1.0f - ratio;
scale1 = ratio;
}
// calculate final values
m_V.X = scale0 * from.m_V.X + scale1 * to1[0];
m_V.Y = scale0 * from.m_V.Y + scale1 * to1[1];
m_V.Z = scale0 * from.m_V.Z + scale1 * to1[2];
m_W = scale0 * from.m_W + scale1 * to1[3];
}
///////////////////////////////////////////////////////////////////////////////////////////////
// FromAxisAngle: create a quaternion from axis/angle representation of a rotation
void CQuaternion::FromAxisAngle(const CVector3D& axis,float angle)
{
float sinHalfTheta=(float) sin(angle/2);
float cosHalfTheta=(float) cos(angle/2);
m_V.X=axis.X*sinHalfTheta;
m_V.Y=axis.Y*sinHalfTheta;
m_V.Z=axis.Z*sinHalfTheta;
m_W=cosHalfTheta;
}

View File

@ -0,0 +1,47 @@
/************************************************************
*
* File Name: Quaternion.H
*
* Description:
*
************************************************************/
#ifndef QUATERNION_H
#define QUATERNION_H
#include "Matrix3D.h"
class CQuaternion
{
public:
CVector3D m_V;
float m_W;
public:
CQuaternion();
//quaternion addition
CQuaternion operator + (CQuaternion &quat);
//quaternion addition/assignment
CQuaternion &operator += (CQuaternion &quat);
//quaternion multiplication
CQuaternion operator * (CQuaternion &quat);
//quaternion multiplication/assignment
CQuaternion &operator *= (CQuaternion &quat);
void FromEularAngles (float x, float y, float z);
//convert the quaternion to matrix
CMatrix3D ToMatrix() const;
void ToMatrix(CMatrix3D& result) const;
//sphere interpolation
void Slerp(const CQuaternion& from,const CQuaternion& to, float ratio);
// create a quaternion from axis/angle representation of a rotation
void FromAxisAngle(const CVector3D& axis,float angle);
};
#endif

View File

@ -0,0 +1,72 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: SkeletonAnimDef.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "pmdexp_types.h"
#include "SkeletonAnimDef.h"
#include "FilePacker.h"
///////////////////////////////////////////////////////////////////////////////////////////
// CSkeletonAnimDef constructor
CSkeletonAnimDef::CSkeletonAnimDef() : m_Keys(0), m_NumKeys(0), m_NumFrames(0), m_FrameTime(0)
{
}
///////////////////////////////////////////////////////////////////////////////////////////
// CSkeletonAnimDef destructor
CSkeletonAnimDef::~CSkeletonAnimDef()
{
delete[] m_Keys;
}
///////////////////////////////////////////////////////////////////////////////////////////
// BuildBoneMatrices: build matrices for all bones at the given time (in MS) in this
// animation
void CSkeletonAnimDef::BuildBoneMatrices(float time,CMatrix3D* matrices) const
{
float fstartframe=time/m_FrameTime;
u32 startframe=u32(time/m_FrameTime);
float deltatime=fstartframe-startframe;
startframe%=m_NumFrames;
u32 endframe=startframe+1;
endframe%=m_NumFrames;
u32 i;
for (i=0;i<m_NumKeys;i++) {
const Key& startkey=GetKey(startframe,i);
const Key& endkey=GetKey(endframe,i);
CVector3D trans=startkey.m_Translation*(1-deltatime)+endkey.m_Translation*deltatime;
CQuaternion rot;
rot.Slerp(startkey.m_Rotation,endkey.m_Rotation,deltatime);
matrices[i].SetIdentity();
matrices[i].Rotate(rot);
matrices[i].Translate(trans);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Save: try to save anim to file
void CSkeletonAnimDef::Save(const char* filename,const CSkeletonAnimDef* anim)
{
CFilePacker packer;
// pack up all the data
packer.PackString(anim->m_Name);
packer.PackRaw(&anim->m_FrameTime,sizeof(anim->m_FrameTime));
packer.PackRaw(&anim->m_NumKeys,sizeof(anim->m_NumKeys));
packer.PackRaw(&anim->m_NumFrames,sizeof(anim->m_NumFrames));
packer.PackRaw(anim->m_Keys,anim->m_NumKeys*anim->m_NumFrames*sizeof(Key));
// now write it
packer.Write(filename,FILE_VERSION,"PSSA");
}

View File

@ -0,0 +1,83 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: SkeletonAnimDef.h
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _SKELETONANIMDEF_H
#define _SKELETONANIMDEF_H
#include "Vector3D.h"
#include "Quaternion.h"
////////////////////////////////////////////////////////////////////////////////////////
// CBoneState: structure describing state of a bone at some point
class CBoneState
{
public:
// translation of bone relative to root
CVector3D m_Translation;
// rotation of bone relative to root
CQuaternion m_Rotation;
};
////////////////////////////////////////////////////////////////////////////////////////
// CSkeletonAnimDef: raw description - eg bonestates - of an animation that plays upon
// a skeleton
class CSkeletonAnimDef
{
public:
// current file version given to saved animations
enum { FILE_VERSION = 1 };
// supported file read version - files with a version less than this will be rejected
enum { FILE_READ_VERSION = 1 };
public:
// Key: description of a single key in a skeleton animation
typedef CBoneState Key;
public:
// CSkeletonAnimDef constructor + destructor
CSkeletonAnimDef();
~CSkeletonAnimDef();
// return the number of keys in this animation
u32 GetNumKeys() const { return m_NumKeys; }
// accessors: get a key for given bone at given time
Key& GetKey(u32 frame,u32 bone) { return m_Keys[frame*m_NumKeys+bone]; }
const Key& GetKey(u32 frame,u32 bone) const { return m_Keys[frame*m_NumKeys+bone]; }
// get duration of this anim, in ms
float GetDuration() const { return m_NumFrames*m_FrameTime; }
// return length of each frame, in ms
float GetFrameTime() const { return m_FrameTime; }
// return number of frames in animation
u32 GetNumFrames() const { return m_NumFrames; }
// build matrices for all bones at the given time (in MS) in this animation
void BuildBoneMatrices(float time,CMatrix3D* matrices) const;
// anim I/O functions
static CSkeletonAnimDef* Load(const char* filename);
static void Save(const char* filename,const CSkeletonAnimDef* anim);
public:
// name of the animation
char m_Name[128];
// frame time - time between successive frames, in ms
float m_FrameTime;
// number of keys in each frame - should match number of bones in the skeleton
u32 m_NumKeys;
// number of frames in the animation
u32 m_NumFrames;
// animation data - m_NumKeys*m_NumFrames total keys
Key* m_Keys;
};
#endif

212
source/tools/pmdexp/Tree.h Normal file
View File

@ -0,0 +1,212 @@
#ifndef __TREE_H
#define __TREE_H
//////////////////////////////////////////////////////////////////////////////
// Tree: template class to build a binary tree of elements of class T
template <class T,class Cmp>
class Tree
{
public:
template <class T>
class Node {
public:
Node<T>* _Next;
public:
Node() : _Left(0), _Right(0) {}
int _Index;
T _Element;
Node<T>* _Left;
Node<T>* _Right;
};
public:
Tree();
~Tree();
void Clear();
int Find(T& element);
int Find(Node<T>* _node,T& _vtx);
int Add(T& element);
int Add(Node<T>* _node,T& _vtx,int _index);
// total nodes currently in tree
int Entries() { return _Size; }
void Reserve(int count) { _AllocatedNodes.reserve(count); }
T& operator[](int index) { return _AllocatedNodes[index]->_Element; }
private:
// the root node of the tree
Node<T>* _Root;
// all allocated nodes in tree
std::vector<Node<T>*> _AllocatedNodes;
// size of tree
int _Size;
// the comparison function used to compare two elements in the tree
Cmp _Cmp;
};
//***************************************************************************
// Default Tree constructor - create tree with no allocated nodes
//***************************************************************************
template <class T,class Cmp>
Tree<T,Cmp>::Tree()
{
_Root=0;
_Size=0;
}
//***************************************************************************
// Tree destructor
//***************************************************************************
template <class T,class Cmp>
Tree<T,Cmp>::~Tree()
{
Clear();
}
template <class T,class Cmp>
void Tree<T,Cmp>::Clear()
{
for (int i=0;i<_AllocatedNodes.Entries();i++) {
_NodePile.Release(_AllocatedNodes[i]);
}
_AllocatedNodes.SetSize(0);
_Root=0;
_Size=0;
}
//***************************************************************************
// Add : insert an element into the tree; return the index of the treenode
// at which the element was added, or, if an identical element was already
// in the tree, return it's index
//***************************************************************************
template <class T,class Cmp>
int Tree<T,Cmp>::Add(T& element)
{
if (_Root) {
int index=Add(_Root,element,_Size);
if (index==_Size) {
// element added to tree
_Size++;
} else {
// element not added
}
return index;
} else {
_Root=_NodePile.Allocate();
_AllocatedNodes.Add(_Root);
_Root->_Element=element;
_Root->_Index=0;
_Root->_Left=0;
_Root->_Right=0;
_Size++;
return 0;
}
}
//***************************************************************************
// Add : insert an element into the given node; return the index of the
// treenode at which the element was added, or, if an identical element was
// already in the tree, return it's index
//***************************************************************************
template <class T,class Cmp>
int Tree<T,Cmp>::Add(Node<T>* _node,T& element,int _index)
{
// compare given element with element at given node
int cmp=_Cmp.compare(_node->_Element,element);
if (cmp==0) {
// identical - return index of this node
return _node->_Index;
} else {
if (cmp==-1) {
// this node less than new node
if (_node->_Left) {
// send down left tree
return Add(_node->_Left,element,_index);
} else {
// no left node - create one
_node->_Left=_NodePile.Allocate();
_AllocatedNodes.Add(_node->_Left);
_node->_Left->_Element=element;
_node->_Left->_Index=_index;
_node->_Left->_Left=0;
_node->_Left->_Right=0;
return _index;
}
} else {
// this node greater than new node
if (_node->_Right) {
// send down right tree
return Add(_node->_Right,element,_index);
} else {
// no right node - create one
_node->_Right=_NodePile.Allocate();
_AllocatedNodes.Add(_node->_Right);
_node->_Right->_Element=element;
_node->_Right->_Index=_index;
_node->_Right->_Left=0;
_node->_Right->_Right=0;
return _index;
}
}
}
}
//***************************************************************************
// Find: try and find a matching element in the tree; return the index of the
// treenode at which a match was found, or -1 if no match found
//***************************************************************************
template <class T,class Cmp>
int Tree<T,Cmp>::Find(T& element)
{
return _Root ? Find(_Root,element) : -1;
}
//***************************************************************************
// Find: try and find a matching element in the given node; return the index
// of the treenode at which a match was found, or -1 if no match found
//***************************************************************************
template <class T,class Cmp>
int Tree<T,Cmp>::Find(Node<T>* _node,T& element)
{
// compare given element with element at given node
int cmp=_Cmp.compare(_node->_Element,element);
if (cmp==0) {
// identical - return index of this node
return _node->_Index;
} else {
if (cmp==-1) {
// this node less than new node
if (_node->_Left) {
// send down left tree
return Find(_node->_Left,element);
} else {
// no left node - no match on this subtree
return -1;
}
} else {
// this node greater than new node
if (_node->_Right) {
// send down right tree
return Find(_node->_Right,element);
} else {
// no left node - no match on this subtree
return -1;
}
}
}
}
#endif

View File

@ -0,0 +1,56 @@
#include "MaxInc.h"
#include "VNormal.h"
void VNormal::add(CVector3D& n,unsigned int s)
{
if (!(s&smooth) && init) {
if (next) {
next->add(n,s);
} else {
next=new VNormal(n,s);
}
} else {
_normal+=n;
smooth|=s;
init=true;
}
}
VNormal* VNormal::get(unsigned int s)
{
if (smooth&s || !next) {
return this;
} else {
return next->get(s);
}
}
void VNormal::get(unsigned int s,CVector3D& normal)
{
if (smooth&s || !next) {
normal=_normal;
} else {
next->get(s,normal);
}
}
void VNormal::normalize()
{
VNormal *ptr = next, *prev = this;
while (ptr) {
if (ptr->smooth&smooth) {
_normal += ptr->_normal;
prev->next = ptr->next;
delete ptr;
ptr = prev->next;
} else {
prev = ptr;
ptr = ptr->next;
}
}
_normal.Normalize();
if (next) next->normalize();
}

View File

@ -0,0 +1,36 @@
#ifndef __VNORMAL_H
#define __VNORMAL_H
#include "Vector3D.h"
class VNormal
{
public:
CVector3D _normal;
unsigned int smooth;
VNormal *next;
bool init;
VNormal() {
smooth=0;
next=0;
init=false;
_normal=CVector3D(0,0,0);
}
VNormal(CVector3D& n,unsigned int s) {
next=0;
init=true;
_normal=n;
smooth=s;
}
~VNormal() {delete next;}
void add(CVector3D &n,unsigned int s);
VNormal* get(unsigned int s);
void get(unsigned int s,CVector3D& normal);
void normalize();
};
#endif

View File

@ -0,0 +1,153 @@
//***********************************************************
//
// Name: Vector3D.Cpp
// Last Update: 28/1/02
// Author: Poya Manouchehri
//
// Description: Provides an interface for a vector in R3 and
// allows vector and scalar operations on it
//
//***********************************************************
#include "Vector3D.h"
CVector3D::CVector3D (float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
int CVector3D::operator ! () const
{
if (X != 0.0f ||
Y != 0.0f ||
Z != 0.0f)
return 0;
return 1;
}
//vector addition
CVector3D CVector3D::operator + (const CVector3D &vector) const
{
CVector3D Temp;
Temp.X = X + vector.X;
Temp.Y = Y + vector.Y;
Temp.Z = Z + vector.Z;
return Temp;
}
//vector addition/assignment
CVector3D &CVector3D::operator += (const CVector3D &vector)
{
X += vector.X;
Y += vector.Y;
Z += vector.Z;
return *this;
}
//vector subtraction
CVector3D CVector3D::operator - (const CVector3D &vector) const
{
CVector3D Temp;
Temp.X = X - vector.X;
Temp.Y = Y - vector.Y;
Temp.Z = Z - vector.Z;
return Temp;
}
//vector negation
CVector3D CVector3D::operator-() const
{
CVector3D Temp;
Temp.X = -X;
Temp.Y = -Y;
Temp.Z = -Z;
return Temp;
}
//vector subtrcation/assignment
CVector3D &CVector3D::operator -= (const CVector3D &vector)
{
X -= vector.X;
Y -= vector.Y;
Z -= vector.Z;
return *this;
}
//scalar multiplication
CVector3D CVector3D::operator * (float value) const
{
CVector3D Temp;
Temp.X = X * value;
Temp.Y = Y * value;
Temp.Z = Z * value;
return Temp;
}
//scalar multiplication/assignment
CVector3D& CVector3D::operator *= (float value)
{
X *= value;
Y *= value;
Z *= value;
return *this;
}
void CVector3D::Set (float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
void CVector3D::Clear ()
{
X = Y = Z = 0.0f;
}
//Dot product
float CVector3D::Dot (const CVector3D &vector) const
{
return ( X * vector.X +
Y * vector.Y +
Z * vector.Z );
}
//Cross product
CVector3D CVector3D::Cross (const CVector3D &vector) const
{
CVector3D Temp;
Temp.X = (Y * vector.Z) - (Z * vector.Y);
Temp.Y = (Z * vector.X) - (X * vector.Z);
Temp.Z = (X * vector.Y) - (Y * vector.X);
return Temp;
}
float CVector3D::GetLength () const
{
return sqrtf ( SQR(X) + SQR(Y) + SQR(Z) );
}
void CVector3D::Normalize ()
{
float scale = 1.0f/GetLength ();
X *= scale;
Y *= scale;
Z *= scale;
}

View File

@ -0,0 +1,66 @@
//***********************************************************
//
// Name: Vector3D.H
// Last Update: 28/1/02
// Author: Poya Manouchehri
//
// Description: Provides an interface for a vector in R3 and
// allows vector and scalar operations on it
//
//***********************************************************
#ifndef VECTOR3D_H
#define VECTOR3D_H
#include <math.h>
#include "MathUtil.h"
class CVector3D
{
public:
float X, Y, Z;
public:
CVector3D () { X = 0.0f; Y = 0.0f; Z = 0.0f; }
CVector3D (float x, float y, float z);
int operator ! () const ;
float& operator[](int index) { return *((&X)+index); }
const float& operator[](int index) const { return *((&X)+index); }
//vector addition
CVector3D operator + (const CVector3D &vector) const ;
//vector addition/assignment
CVector3D &operator += (const CVector3D &vector);
//vector subtraction
CVector3D operator - (const CVector3D &vector) const ;
//vector subtraction/assignment
CVector3D &operator -= (const CVector3D &vector);
//scalar multiplication
CVector3D operator * (float value) const ;
//scalar multiplication/assignment
CVector3D& operator *= (float value);
// negation
CVector3D operator-() const;
public:
void Set (float x, float y, float z);
void Clear ();
//Dot product
float Dot (const CVector3D &vector) const;
//Cross product
CVector3D Cross (const CVector3D &vector) const;
//Returns length of the vector
float GetLength () const;
void Normalize ();
};
#endif

View File

@ -0,0 +1,110 @@
//***********************************************************
//
// Name: CVector4D.h
// Last Update: 02/11/03
// Author: Rich Cross
//
// Description: Provides an interface for a vector in R4 and
// allows vector and scalar operations on it
//
//***********************************************************
#ifndef _VECTOR4D_H
#define _VECTOR4D_H
#include <math.h>
///////////////////////////////////////////////////////////////////////////////
// CVector4D:
class CVector4D
{
public:
CVector4D() {}
CVector4D(const float f[4]) { m_X=f[0]; m_Y=f[1]; m_Z=f[2]; m_W=f[3]; }
CVector4D(float x,float y,float z,float w) { m_X=x; m_Y=y; m_Z=z; m_W=w; }
CVector4D(const CVector4D& p) { m_X=p.m_X; m_Y=p.m_Y; m_Z=p.m_Z; m_W=p.m_W; }
operator float*() {
return &m_X;
}
operator const float*() const {
return &m_X;
}
CVector4D operator-() const {
return CVector4D(-m_X,-m_Y,-m_Z,-m_W);
}
CVector4D operator+(const CVector4D& t) const {
return CVector4D(m_X+t.m_X,m_Y+t.m_Y,m_Z+t.m_Z,m_W+t.m_W);
}
CVector4D operator-(const CVector4D& t) const {
return CVector4D(m_X-t.m_X,m_Y-t.m_Y,m_Z-t.m_Z,m_W-t.m_W);
}
CVector4D operator*(const CVector4D& t) const {
return CVector4D(m_X*t.m_X,m_Y*t.m_Y,m_Z*t.m_Z,m_W*t.m_W);
}
CVector4D operator*(float f) const {
return CVector4D(m_X*f,m_Y*f,m_Z*f,m_W*f);
}
CVector4D operator/(float f) const {
float inv=1.0f/f;
return CVector4D(m_X*inv,m_Y*inv,m_Z*inv,m_W*inv);
}
CVector4D& operator+=(const CVector4D& t) {
m_X+=t.m_X; m_Y+=t.m_Y; m_Z+=t.m_Z; m_W+=t.m_W;
return *this;
}
CVector4D& operator-=(const CVector4D& t) {
m_X-=t.m_X; m_Y-=t.m_Y; m_Z-=t.m_Z; m_W-=t.m_W;
return *this;
}
CVector4D& operator*=(const CVector4D& t) {
m_X*=t.m_X; m_Y*=t.m_Y; m_Z*=t.m_Z; m_W*=t.m_W;
return *this;
}
CVector4D& operator*=(float f) {
m_X*=f; m_Y*=f; m_Z*=f; m_W*=f;
return *this;
}
CVector4D& operator/=(float f) {
float invf=1.0f/f;
m_X*=invf; m_Y*=invf; m_Z*=invf; m_W*=invf;
return *this;
}
float dot(const CVector4D& a) const {
return m_X*a.m_X+m_Y*a.m_Y+m_Z*a.m_Z+m_W*a.m_W;
}
float lengthSquared() const {
return SQR(m_X)+SQR(m_Y)+SQR(m_Z)+SQR(m_W);
}
float length() const {
return (float) sqrt(lengthSquared());
}
void normalize() {
float mag=length();
m_X/=mag; m_Y/=mag; m_Z/=mag; m_W/=mag;
}
public:
float m_X,m_Y,m_Z,m_W;
};
//////////////////////////////////////////////////////////////////////////////////
#endif

View File

@ -0,0 +1,158 @@
#ifndef __VERTEXTREE_H
#define __VERTEXTREE_H
// necessary includes
#include "ExpVertex.h"
////////////////////////////////////////////////////////////////////////////////////////////
// VertexTree: template tree class for building unique vertices in varying fashions; the
// template parameter Cmp specifies a function which compares (and possibly modifies)
// two vertices
// FIXME: ugh .. modifying a vertex already in the tree may cause it to be in the
// wrong position in the tree
template <class Cmp>
class VertexTree
{
private:
struct Node {
Node(int index,ExpVertex& vtx) : _index(index), _vertex(vtx), _left(0), _right(0) {}
// index into the output _vertices array
int _index;
// reference to actual vertex on the node (vertex itself in _vertices array)
ExpVertex& _vertex;
// children
Node* _left;
Node* _right;
};
public:
VertexTree(VertexList& vertices) : _vertices(vertices), _treeroot(0) {}
int insert(const ExpVertex& vtx) {
// copy incoming vertex in case the comparison function wants to modify
// it before storing it ..
ExpVertex copy=vtx;
if (_treeroot) {
return insert(_treeroot,copy);
} else {
_vertices.push_back(copy);
_treeroot=new Node(0,_vertices.back());
return 0;
}
}
int insert(Node* node,ExpVertex& vtx) {
// compare given element with element at given node
Cmp compareFn;
int cmp=compareFn(node->_vertex,vtx);
if (cmp==0) {
// matching vertex found
return node->_index;
} else {
if (cmp==-1) {
// this node less than new node
if (node->_left) {
// send down left tree
return insert(node->_left,vtx);
} else {
// no left node - create one
_vertices.push_back(vtx);
node->_left=new Node(_vertices.size()-1,_vertices.back());
return _vertices.size()-1;
}
} else {
// this node greater than new node
if (node->_right) {
// send down right tree
return insert(node->_right,vtx);
} else {
// no right node - create one
_vertices.push_back(vtx);
node->_right=new Node(_vertices.size()-1,_vertices.back());
return _vertices.size()-1;
}
}
}
}
private:
Node* _treeroot;
VertexList& _vertices;
};
class UniqueVertexCmp {
public:
int operator()(ExpVertex& left,ExpVertex& right) {
// check distance between two vertices ..
CVector3D vec3=left.m_Pos-right.m_Pos;
if (vec3.GetLength()>0.0001f) {
// vertices too far apart to weld .. sort on x,y,z
if (left.m_Pos[0]<right.m_Pos[0]) {
return -1;
} else if (left.m_Pos[0]>right.m_Pos[0]) {
return 1;
} else {
if (left.m_Pos[1]<right.m_Pos[1]) {
return -1;
} else if (left.m_Pos[1]>right.m_Pos[1]) {
return 1;
} else {
if (left.m_Pos[2]<right.m_Pos[2]) {
return -1;
} else {
return 1;
}
}
}
} else {
// weld two points together ..
right.m_Pos=left.m_Pos;
// .. and now compare by texcoords
CVector3D vec2(left.m_UVs[0]-right.m_UVs[0],left.m_UVs[1]-right.m_UVs[1],0);
if (vec2.GetLength()>0.0001f) {
// uvs too far apart to weld .. sort on u,v
if (left.m_UVs[0]<right.m_UVs[0]) {
return -1;
} else if (left.m_UVs[0]>right.m_UVs[0]) {
return 1;
} else {
if (left.m_UVs[1]<right.m_UVs[1]) {
return -1;
} else {
return 1;
}
}
} else {
// weld uvs
right.m_UVs[0]=left.m_UVs[0];
right.m_UVs[1]=left.m_UVs[1];
// compare normals
if (left.m_Normal[0]<right.m_Normal[0]) {
return -1;
} else if (left.m_Normal[0]>right.m_Normal[0]) {
return 1;
} else {
if (left.m_Normal[1]<right.m_Normal[1]) {
return -1;
} else if (left.m_Normal[1]>right.m_Normal[1]) {
return 1;
} else {
if (left.m_Normal[2]<right.m_Normal[2]) {
return -1;
} else if (left.m_Normal[2]>right.m_Normal[2]) {
return 1;
} else {
return 0;
}
}
}
}
}
}
};
#endif

View File

@ -0,0 +1,5 @@
SCC = This is a Source Code Control file
[dyexp.dsp]
SCC_Aux_Path = "D:\Program Files\Microsoft Visual Studio\Common\VSS\data"
SCC_Project_Name = "$/dev/src/tools/max/dyexp", YVAAAAAA

Binary file not shown.

View File

@ -0,0 +1,10 @@
#ifndef _PMDEXP_TYPES_H
#define _PMDEXP_TYPES_H
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned int uint;
#endif

View File

@ -0,0 +1,54 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by PMDExp.rc
//
#define IDS_LIBDESCRIPTION 1
#define IDS_CATEGORY 2
#define IDS_CLASS_NAME 3
#define IDS_PMD_CLASS_NAME 3
#define IDS_PARAMS 4
#define IDS_SPIN 5
#define IDS_PSA_CLASS_NAME 6
#define IDD_PANEL 101
#define IDC_CLOSEBUTTON 1000
#define IDC_DOSTUFF 1000
#define IDC_COLOR 1456
#define IDC_EDIT 1490
#define IDC_SPIN 1496
#define IDD_NEW_POINTPARAM 118
#define IDC_POINT_SIZE 1059
#define IDC_POINT_SIZESPIN 1060
#define IDC_POINT_AXIS 1061
#define IDC_POINT_MARKER 1062
#define IDC_POINT_CROSS 1063
#define IDC_POINT_BOX 1064
#define IDC_POINT_SCREENSIZE 1065
#define IDC_POINT_DRAWONTOP 1066
#define IDS_DB_POINT 8
#define IDS_DB_POINTHELPER 9
#define IDS_DB_POINTHELPER_CLASS 10
#define IDS_DB_POINT_CLASS 11
#define IDS_POINT_PARAMS 18
#define IDS_POINT_SIZE 19
#define IDS_POINT_CENTERMARKER 20
#define IDS_POINT_AXISTRIPOD 21
#define IDS_POINT_CROSS 22
#define IDS_POINT_BOX 23
#define IDS_POINT_SCREENSIZE 24
#define IDS_POINT_HELPER_NAME 25
#define IDS_POINT_DRAWONTOP 26
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

Binary file not shown.