added everything
This commit is contained in:
1698
tools/max2dtsExporter/NvTriStripObjects.cc
Executable file
1698
tools/max2dtsExporter/NvTriStripObjects.cc
Executable file
File diff suppressed because it is too large
Load Diff
237
tools/max2dtsExporter/NvTriStripObjects.h
Executable file
237
tools/max2dtsExporter/NvTriStripObjects.h
Executable file
@ -0,0 +1,237 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef NV_TRISTRIP_OBJECTS_H
|
||||
#define NV_TRISTRIP_OBJECTS_H
|
||||
|
||||
//#include <assert.h>
|
||||
//#include <windows.h>
|
||||
//#include <vector>
|
||||
//#include <list>
|
||||
|
||||
#ifndef _NVVERTEXCACHE_H_
|
||||
#include "max2dtsExporter/NvVertexCache.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "Core/tVector.h"
|
||||
#endif
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
|
||||
//#define int S32
|
||||
#define UINT U32
|
||||
//#define float F32
|
||||
#define WORD U16
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Types defined for stripification
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct MyVertex {
|
||||
float x, y, z;
|
||||
float nx, ny, nz;
|
||||
};
|
||||
|
||||
typedef MyVertex MyVector;
|
||||
|
||||
struct MyFace {
|
||||
int v1, v2, v3;
|
||||
float nx, ny, nz;
|
||||
};
|
||||
|
||||
|
||||
class NvFaceInfo {
|
||||
public:
|
||||
|
||||
// vertex indices
|
||||
NvFaceInfo(int v0, int v1, int v2){
|
||||
m_v0 = v0; m_v1 = v1; m_v2 = v2;
|
||||
m_stripId = -1;
|
||||
m_testStripId = -1;
|
||||
m_experimentId = -1;
|
||||
}
|
||||
|
||||
// data members are left public
|
||||
int m_v0, m_v1, m_v2;
|
||||
int m_stripId; // real strip Id
|
||||
int m_testStripId; // strip Id in an experiment
|
||||
int m_experimentId; // in what experiment was it given an experiment Id?
|
||||
};
|
||||
|
||||
// nice and dumb edge class that points knows its
|
||||
// indices, the two faces, and the next edge using
|
||||
// the lesser of the indices
|
||||
class NvEdgeInfo {
|
||||
public:
|
||||
|
||||
// constructor puts 1 ref on us
|
||||
NvEdgeInfo (int v0, int v1){
|
||||
m_v0 = v0;
|
||||
m_v1 = v1;
|
||||
m_face0 = NULL;
|
||||
m_face1 = NULL;
|
||||
m_nextV0 = NULL;
|
||||
m_nextV1 = NULL;
|
||||
|
||||
// we will appear in 2 lists. this is a good
|
||||
// way to make sure we delete it the second time
|
||||
// we hit it in the edge infos
|
||||
m_refCount = 2;
|
||||
|
||||
}
|
||||
|
||||
// ref and unref
|
||||
void Unref () { if (--m_refCount == 0) delete this; }
|
||||
|
||||
// data members are left public
|
||||
UINT m_refCount;
|
||||
NvFaceInfo *m_face0, *m_face1;
|
||||
int m_v0, m_v1;
|
||||
NvEdgeInfo *m_nextV0, *m_nextV1;
|
||||
};
|
||||
|
||||
|
||||
// This class is a quick summary of parameters used
|
||||
// to begin a triangle strip. Some operations may
|
||||
// want to create lists of such items, so they were
|
||||
// pulled out into a class
|
||||
class NvStripStartInfo {
|
||||
public:
|
||||
NvStripStartInfo(NvFaceInfo *startFace, NvEdgeInfo *startEdge, bool toV1){
|
||||
m_startFace = startFace;
|
||||
m_startEdge = startEdge;
|
||||
m_toV1 = toV1;
|
||||
}
|
||||
NvFaceInfo *m_startFace;
|
||||
NvEdgeInfo *m_startEdge;
|
||||
bool m_toV1;
|
||||
};
|
||||
|
||||
|
||||
typedef Vector<NvFaceInfo*> NvFaceInfoVec;
|
||||
typedef Vector<NvFaceInfo*> NvFaceInfoList;
|
||||
typedef Vector<NvFaceInfoVec*> NvStripList;
|
||||
typedef Vector<NvEdgeInfo*> NvEdgeInfoVec;
|
||||
|
||||
typedef Vector<WORD> WordVec;
|
||||
typedef Vector<MyVertex> MyVertexVec;
|
||||
typedef Vector<MyFace> MyFaceVec;
|
||||
|
||||
// This is a summary of a strip that has been built
|
||||
class NvStripInfo {
|
||||
public:
|
||||
|
||||
// A little information about the creation of the triangle strips
|
||||
NvStripInfo(const NvStripStartInfo &startInfo, int stripId, int experimentId = -1) :
|
||||
m_startInfo(startInfo)
|
||||
{
|
||||
m_stripId = stripId;
|
||||
m_experimentId = experimentId;
|
||||
visited = false;
|
||||
}
|
||||
|
||||
// This is an experiment if the experiment id is >= 0
|
||||
inline bool IsExperiment () const { return m_experimentId >= 0; }
|
||||
|
||||
inline bool IsInStrip (const NvFaceInfo *faceInfo) const
|
||||
{
|
||||
if(faceInfo == NULL)
|
||||
return false;
|
||||
|
||||
return (m_experimentId >= 0 ? faceInfo->m_testStripId == m_stripId : faceInfo->m_stripId == m_stripId);
|
||||
}
|
||||
|
||||
bool SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos);
|
||||
|
||||
// take the given forward and backward strips and combine them together
|
||||
void Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward);
|
||||
|
||||
//returns true if the face is "unique", i.e. has a vertex which doesn't exist in the faceVec
|
||||
bool Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face);
|
||||
|
||||
// mark the triangle as taken by this strip
|
||||
bool IsMarked (NvFaceInfo *faceInfo);
|
||||
void MarkTriangle(NvFaceInfo *faceInfo);
|
||||
|
||||
// build the strip
|
||||
void Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos);
|
||||
|
||||
// public data members
|
||||
NvStripStartInfo m_startInfo;
|
||||
NvFaceInfoVec m_faces;
|
||||
int m_stripId;
|
||||
int m_experimentId;
|
||||
|
||||
bool visited;
|
||||
};
|
||||
|
||||
typedef Vector<NvStripInfo*> NvStripInfoVec;
|
||||
|
||||
|
||||
//The actual stripifier
|
||||
class NvStripifier {
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
NvStripifier();
|
||||
~NvStripifier();
|
||||
|
||||
//the target vertex cache size, the structure to place the strips in, and the input indices
|
||||
void Stripify(const WordVec &in_indices, const int in_cacheSize, const int in_minStripLength,
|
||||
NvStripInfoVec &allStrips, NvFaceInfoVec &allFaces);
|
||||
|
||||
static int GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB);
|
||||
static int GetSharedVertex(NvFaceInfo *faceA, NvFaceInfo *faceB);
|
||||
|
||||
protected:
|
||||
|
||||
WordVec indices;
|
||||
int cacheSize;
|
||||
int minStripLength;
|
||||
float meshJump;
|
||||
bool bFirstTimeResetPoint;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Big mess of functions called during stripification
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int GetNextIndex(const WordVec &indices, NvFaceInfo *face);
|
||||
static NvEdgeInfo *FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1);
|
||||
static NvFaceInfo *FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo);
|
||||
NvFaceInfo *FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
|
||||
|
||||
void FindAllStrips(NvStripInfoVec &allStrips, NvFaceInfoVec &allFaceInfos, NvEdgeInfoVec &allEdgeInfos, int numSamples);
|
||||
void SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList);
|
||||
void RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList);
|
||||
|
||||
bool FindTraversal(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, NvStripInfo *strip, NvStripStartInfo &startInfo);
|
||||
int CountRemainingTris(Vector<NvStripInfo*>::iterator iter, Vector<NvStripInfo*>::iterator end);
|
||||
|
||||
void CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips);
|
||||
|
||||
float AvgStripSize(const NvStripInfoVec &strips);
|
||||
int FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
|
||||
|
||||
void UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip);
|
||||
void UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face);
|
||||
float CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip);
|
||||
int CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face);
|
||||
int NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec);
|
||||
|
||||
void BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
|
||||
bool AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos);
|
||||
|
||||
// let our strip info classes and the other classes get
|
||||
// to these protected stripificaton methods if they want
|
||||
friend NvStripInfo;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
57
tools/max2dtsExporter/NvVertexCache.cc
Executable file
57
tools/max2dtsExporter/NvVertexCache.cc
Executable file
@ -0,0 +1,57 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "max2dtsExporter/NvVertexCache.h"
|
||||
|
||||
VertexCache::VertexCache()
|
||||
{
|
||||
VertexCache(16);
|
||||
}
|
||||
|
||||
|
||||
VertexCache::VertexCache(int size)
|
||||
{
|
||||
numEntries = size;
|
||||
|
||||
entries = new int[numEntries];
|
||||
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
entries[i] = -1;
|
||||
}
|
||||
|
||||
|
||||
VertexCache::~VertexCache()
|
||||
{
|
||||
delete[] entries;
|
||||
}
|
||||
|
||||
|
||||
int VertexCache::At(int index)
|
||||
{
|
||||
return entries[index];
|
||||
}
|
||||
|
||||
|
||||
void VertexCache::Set(int index, int value)
|
||||
{
|
||||
entries[index] = value;
|
||||
}
|
||||
|
||||
|
||||
void VertexCache::Clear()
|
||||
{
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
entries[i] = -1;
|
||||
}
|
||||
|
||||
void VertexCache::Copy(VertexCache* inVcache)
|
||||
{
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
{
|
||||
inVcache->Set(i, entries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
71
tools/max2dtsExporter/NvVertexCache.h
Executable file
71
tools/max2dtsExporter/NvVertexCache.h
Executable file
@ -0,0 +1,71 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if !defined(VERTEX_CACHE_H)
|
||||
|
||||
#define VERTEX_CACHE_H
|
||||
|
||||
class VertexCache
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
VertexCache(int size);
|
||||
VertexCache();
|
||||
~VertexCache();
|
||||
|
||||
bool InCache(int entry);
|
||||
int AddEntry(int entry);
|
||||
void Clear();
|
||||
|
||||
void Copy(VertexCache* inVcache);
|
||||
int At(int index);
|
||||
void Set(int index, int value);
|
||||
|
||||
private:
|
||||
|
||||
int *entries;
|
||||
int numEntries;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline bool VertexCache::InCache(int entry)
|
||||
{
|
||||
bool returnVal = false;
|
||||
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
{
|
||||
if(entries[i] == entry)
|
||||
{
|
||||
returnVal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
|
||||
inline int VertexCache::AddEntry(int entry)
|
||||
{
|
||||
int removed;
|
||||
|
||||
removed = entries[numEntries - 1];
|
||||
|
||||
//push everything right one
|
||||
for(int i = numEntries - 2; i >= 0; i--)
|
||||
{
|
||||
entries[i + 1] = entries[i];
|
||||
}
|
||||
|
||||
entries[0] = entry;
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
1007
tools/max2dtsExporter/SceneEnum.cc
Executable file
1007
tools/max2dtsExporter/SceneEnum.cc
Executable file
File diff suppressed because it is too large
Load Diff
126
tools/max2dtsExporter/SceneEnum.h
Executable file
126
tools/max2dtsExporter/SceneEnum.h
Executable file
@ -0,0 +1,126 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SCENEENUM_H_
|
||||
#define SCENEENUM_H_
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <max.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
#include "max2dtsExporter/shapeMimic.h"
|
||||
#include "ts/tsShape.h"
|
||||
#include "platform/platform.h"
|
||||
#include "core/tvector.h"
|
||||
#include "core/filestream.h"
|
||||
|
||||
class SceneEnumProc : public ITreeEnumProc
|
||||
{
|
||||
static FileStream file;
|
||||
|
||||
Vector<INode*> meshNodes;
|
||||
Vector<INode*> skinNodes;
|
||||
Vector<INode*> subTrees;
|
||||
Vector<INode*> sequences;
|
||||
INode *boundsNode;
|
||||
INode *viconNode;
|
||||
|
||||
ShapeMimic shapeMimic;
|
||||
TSShape * pShape;
|
||||
|
||||
bool exportError;
|
||||
char * exportErrorStr;
|
||||
|
||||
S32 getSequence( INode *pNode );
|
||||
|
||||
static void clearExportConfig();
|
||||
|
||||
void getPolyCount(S32 & polyCount, F32 & minVolPerPoly, F32 & maxVolPerPoly);
|
||||
void getPolyCountSubtree(INode *, S32 &, F32 & minVolPerPoly, F32 & maxVolPerPoly);
|
||||
|
||||
public:
|
||||
SceneEnumProc();
|
||||
~SceneEnumProc();
|
||||
|
||||
static Vector<char *> alwaysExport;
|
||||
static Vector<char *> neverExport;
|
||||
static Vector<char *> neverAnimate;
|
||||
|
||||
static char exportType;
|
||||
|
||||
static const char * readConfigFile(const char * filename);
|
||||
static void writeConfigFile(const char * filename);
|
||||
static void setInitialDefaults();
|
||||
|
||||
static bool dumpShape(const char * filename);
|
||||
|
||||
void exportTextFile(Stream * file);
|
||||
|
||||
static bool isDummy(INode *pNode);
|
||||
static bool isBounds(INode *pNode);
|
||||
static bool isVICON(INode *pNode);
|
||||
static bool isCamera(INode *pNode);
|
||||
static bool isSubtree(INode *pNode);
|
||||
static bool isBillboard(INode * pNode);
|
||||
static bool isBillboardZAxis(INode * pNode);
|
||||
static bool isSortedObject(INode * pNode);
|
||||
static bool isDecal(INode * pNode);
|
||||
static void tweakName(const char ** nodeName); // can only take from front at this point...
|
||||
|
||||
static void printDump(U32 mask, const char *);
|
||||
void startDump(const TCHAR * filename, const TCHAR * maxFile);
|
||||
|
||||
void setExportError(const char * errStr) { dFree(exportErrorStr); exportErrorStr = dStrdup(errStr); exportError = true; }
|
||||
void clearExportError() { exportError = false; dFree(exportErrorStr); exportErrorStr = NULL; }
|
||||
bool isExportError() { return exportError; }
|
||||
const char * getExportError() { return exportErrorStr; }
|
||||
|
||||
TSShape * getShape() { return pShape; }
|
||||
|
||||
TSShape * regenShape(); // for testing purposes only...
|
||||
|
||||
bool isEmpty();
|
||||
S32 callback( INode *node );
|
||||
|
||||
void processScene();
|
||||
void enumScene(IScene *);
|
||||
};
|
||||
|
||||
// enum for printDump
|
||||
enum
|
||||
{
|
||||
PDPass1 = 1 << 0, // collect useful nodes
|
||||
PDPass2 = 1 << 1, // put together shape structure
|
||||
PDPass3 = 1 << 2, // cull un-needed nodes
|
||||
PDObjectOffsets = 1 << 3, // display object offset transform during 2nd pass
|
||||
PDNodeStates = 1 << 4, // display as added
|
||||
PDObjectStates = 1 << 5, // ""
|
||||
PDNodeStateDetails = 1 << 6, // details of above
|
||||
PDObjectStateDetails = 1 << 7, // ""
|
||||
PDSequences = 1 << 8,
|
||||
PDShapeHierarchy = 1 << 9,
|
||||
PDAlways = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
// parameters of export...
|
||||
extern U32 dumpMask;
|
||||
extern U32 allowEmptySubtrees;
|
||||
extern U32 allowCrossedDetails;
|
||||
extern U32 allowUnusedMeshes;
|
||||
extern U32 transformCollapse;
|
||||
extern U32 viconNeeded;
|
||||
extern U32 enableSequences;
|
||||
extern U32 allowOldSequences;
|
||||
extern U32 enableTwoSidedMaterials;
|
||||
extern F32 animationDelta;
|
||||
extern F32 maxFrameRate;
|
||||
extern S32 weightsPerVertex;
|
||||
extern F32 weightThreshhold;
|
||||
extern char baseTexturePath[256];
|
||||
extern S32 t2AutoDetail;
|
||||
|
||||
extern void setBaseTexturePath(const char *);
|
||||
//--------------------------------------------------------------
|
||||
#endif
|
192
tools/max2dtsExporter/Sequence.h
Executable file
192
tools/max2dtsExporter/Sequence.h
Executable file
@ -0,0 +1,192 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _SEQUENCE_H_
|
||||
#define _SEQUENCE_H_
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <MAX.H>
|
||||
#include <dummy.h>
|
||||
#include <iparamm.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
|
||||
#define SEQUENCE_CLASS_ID Class_ID(0x63a64197, 0xfd72a55)
|
||||
|
||||
#define PB_SEQ_BEGIN_END 0
|
||||
|
||||
#define PB_SEQ_CYCLIC 1
|
||||
#define PB_SEQ_BLEND 2
|
||||
|
||||
#define PB_SEQ_LAST_FIRST_FRAME_SAME 3 // only valid if cyclic
|
||||
|
||||
#define PB_SEQ_USE_FRAME_RATE 4 // if this
|
||||
#define PB_SEQ_FRAME_RATE 5 // then this
|
||||
#define PB_SEQ_NUM_FRAMES 6 // else this
|
||||
|
||||
#define PB_SEQ_IGNORE_GROUND_TRANSFORM 7
|
||||
#define PB_SEQ_USE_GROUND_FRAME_RATE 8 // if this
|
||||
#define PB_SEQ_GROUND_FRAME_RATE 9 // then use this
|
||||
#define PB_SEQ_NUM_GROUND_FRAMES 10// else use this
|
||||
|
||||
#define PB_SEQ_ENABLE_MORPH_ANIMATION 11
|
||||
#define PB_SEQ_ENABLE_VIS_ANIMATION 12
|
||||
#define PB_SEQ_ENABLE_TRANSFORM_ANIMATION 13
|
||||
|
||||
#define PB_SEQ_FORCE_MORPH_ANIMATION 14
|
||||
#define PB_SEQ_FORCE_VIS_ANIMATION 15
|
||||
#define PB_SEQ_FORCE_TRANSFORM_ANIMATION 16
|
||||
|
||||
#define PB_SEQ_DEFAULT_PRIORITY 17
|
||||
|
||||
#define PB_SEQ_BLEND_REFERENCE_TIME 18
|
||||
|
||||
#define PB_SEQ_ENABLE_TEXTURE_ANIMATION 19
|
||||
#define PB_SEQ_ENABLE_IFL_ANIMATION 20
|
||||
#define PB_SEQ_FORCE_TEXTURE_ANIMATION 21
|
||||
|
||||
#define PB_SEQ_TRIGGERS 22
|
||||
|
||||
#define PB_SEQ_ENABLE_DECAL_ANIMATION 23
|
||||
#define PB_SEQ_ENABLE_DECAL_FRAME_ANIMATION 24
|
||||
#define PB_SEQ_FORCE_DECAL_ANIMATION 25
|
||||
|
||||
#define PB_SEQ_OVERRIDE_DURATION 26
|
||||
#define PB_SEQ_DURATION 27
|
||||
|
||||
#define PB_SEQ_ENABLE_UNIFORM_SCALE_ANIMATION 28
|
||||
#define PB_SEQ_ENABLE_ARBITRARY_SCALE_ANIMATION 29
|
||||
#define PB_SEQ_FORCE_SCALE_ANIMATION 30
|
||||
|
||||
// Class ID for old sequence class -- id for exporter used
|
||||
// in starsiege, tribes 1, and other games around that time
|
||||
// You know, games from the previous millenium.
|
||||
#define OLD_SEQUENCE_CLASS_ID Class_ID(0x09923023,0)
|
||||
|
||||
// param block constants for old sequence class
|
||||
#define PB_OLD_SEQ_ONESHOT 3
|
||||
#define PB_OLD_SEQ_FORCEVIS 4
|
||||
#define PB_OLD_SEQ_VISONLY 5
|
||||
#define PB_OLD_SEQ_NOCOLLAPSE 6
|
||||
#define PB_OLD_SEQ_USECELRATE 7
|
||||
|
||||
extern ClassDesc * GetSequenceDesc();
|
||||
|
||||
extern bool getBoolSequenceDefault(S32 index);
|
||||
extern F32 getFloatSequenceDefault(S32 index);
|
||||
extern S32 getIntSequenceDefault(S32 index);
|
||||
extern void resetSequenceDefaults();
|
||||
|
||||
|
||||
class SequenceObject: public DummyObject
|
||||
{
|
||||
public:
|
||||
|
||||
static U32 defaultCyclic;
|
||||
static U32 defaultBlend;
|
||||
static U32 defaultFirstLastFrameSame;
|
||||
|
||||
static U32 defaultUseFrameRate;
|
||||
static F32 defaultFrameRate;
|
||||
static S32 defaultNumFrames;
|
||||
|
||||
static U32 defaultIgnoreGroundTransform;
|
||||
static U32 defaultUseGroundFrameRate;
|
||||
static F32 defaultGroundFrameRate;
|
||||
static S32 defaultNumGroundFrames;
|
||||
|
||||
static U32 defaultEnableMorphAnimation;
|
||||
static U32 defaultEnableVisAnimation;
|
||||
static U32 defaultEnableTransformAnimation;
|
||||
|
||||
static U32 defaultForceMorphAnimation;
|
||||
static U32 defaultForceVisAnimation;
|
||||
static U32 defaultForceTransformAnimation;
|
||||
|
||||
static S32 defaultDefaultSequencePriority;
|
||||
|
||||
static S32 defaultBlendReferenceTime;
|
||||
|
||||
static U32 defaultEnableTextureAnimation;
|
||||
static U32 defaultEnableIflAnimation;
|
||||
static U32 defaultForceTextureAnimation;
|
||||
|
||||
static U32 defaultEnableDecalAnimation;
|
||||
static U32 defaultEnableDecalFrameAnimation;
|
||||
static U32 defaultForceDecalAnimation;
|
||||
|
||||
static U32 defaultOverrideDuration;
|
||||
static F32 defaultDuration;
|
||||
|
||||
static U32 defaultEnableUniformScaleAnimation;
|
||||
static U32 defaultEnableArbitraryScaleAnimation;
|
||||
static U32 defaultForceScaleAnimation;
|
||||
|
||||
// Class vars
|
||||
IParamBlock *pblock;
|
||||
Interval ivalid;
|
||||
|
||||
//
|
||||
static IParamMap *pmapParam1;
|
||||
static IParamMap *pmapParam2;
|
||||
static IParamMap *pmapParam3;
|
||||
static SequenceObject *editOb;
|
||||
|
||||
SequenceObject();
|
||||
~SequenceObject();
|
||||
|
||||
// inherited virtual methods for Reference-management
|
||||
RefResult NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget,
|
||||
PartID& partID, RefMessage message );
|
||||
|
||||
// From BaseObject
|
||||
void BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev);
|
||||
void EndEditParams( IObjParam *ip, ULONG flags,Animatable *next);
|
||||
RefTargetHandle Clone(RemapDir& remap = NoRemap());
|
||||
|
||||
// From Object
|
||||
virtual TCHAR *GetObjectName() { return _T("Sequence II"); }
|
||||
void InitNodeName(TSTR& s);
|
||||
Interval ObjectValidity(TimeValue t);
|
||||
// unimplemented methods from Object class:
|
||||
// ObjectState Eval(TimeValue time);
|
||||
// ObjectHandle ApplyTransform(Matrix3& matrix) {return this;}
|
||||
// Interval ObjectValidity(TimeValue t) {return FOREVER;}
|
||||
// S32 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 );
|
||||
// S32 DoOwnSelectHilite() { return 1; }
|
||||
|
||||
// Animatable methods
|
||||
void FreeCaches();
|
||||
S32 NumSubs() { return 1; }
|
||||
Animatable* SubAnim(S32 i) { return pblock; }
|
||||
TSTR SubAnimName(S32 i);
|
||||
void DeleteThis() { delete this; }
|
||||
Class_ID ClassID() { return SEQUENCE_CLASS_ID; }
|
||||
void GetClassName(TSTR& s);
|
||||
// S32 IsKeyable(){ return 0;}
|
||||
|
||||
// From ref
|
||||
S32 NumRefs() {return 1;}
|
||||
RefTargetHandle GetReference(S32 i) {return pblock;}
|
||||
void SetReference(S32 i, RefTargetHandle rtarg) {pblock=(IParamBlock*)rtarg;}
|
||||
IOResult Load(ILoad *iload);
|
||||
//IOResult Save(ISave *isave);
|
||||
//RefTargetHandle Clone(RemapDir& remap = NoRemap());
|
||||
|
||||
// where do these come from?
|
||||
virtual void InvalidateUI();
|
||||
IParamArray *GetParamBlock();
|
||||
S32 GetParamBlockIndex(S32 id);
|
||||
virtual ParamDimension *GetParameterDim(S32 pbIndex);
|
||||
virtual TSTR GetParameterName(S32 pbIndex);
|
||||
};
|
||||
|
||||
#endif
|
8819
tools/max2dtsExporter/ShapeMimic.cc
Executable file
8819
tools/max2dtsExporter/ShapeMimic.cc
Executable file
File diff suppressed because it is too large
Load Diff
461
tools/max2dtsExporter/ShapeMimic.h
Executable file
461
tools/max2dtsExporter/ShapeMimic.h
Executable file
@ -0,0 +1,461 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SHAPEMIMIC_H_
|
||||
#define SHAPEMIMIC_H_
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <max.h>
|
||||
#include <stdmat.h>
|
||||
#include <decomp.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifndef _TSSHAPE_H_
|
||||
#include "ts/tsShape.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/tVector.h"
|
||||
#endif
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
|
||||
struct ExporterSequenceData;
|
||||
|
||||
struct SkinMimic
|
||||
{
|
||||
typedef Vector<F32> WeightList;
|
||||
|
||||
INode * skinNode;
|
||||
TSSkinMesh * skinMesh;
|
||||
S32 detailSize;
|
||||
S32 skinNum;
|
||||
S32 meshNum;
|
||||
|
||||
F32 multiResPercent;
|
||||
|
||||
Vector<TSDrawPrimitive> faces;
|
||||
Vector<Point3> verts;
|
||||
Vector<Point3F> normals;
|
||||
Vector<Point3> tverts;
|
||||
Vector<U16> indices;
|
||||
Vector<U16> mergeIndices;
|
||||
Vector<U32> smoothingGroups;
|
||||
Vector<U32> vertId;
|
||||
|
||||
Vector<INode *> bones;
|
||||
Vector<WeightList*> weights;
|
||||
|
||||
~SkinMimic() { for (S32 i=0;i<weights.size(); i++) delete weights[i]; }
|
||||
};
|
||||
|
||||
struct IflMimic
|
||||
{
|
||||
char * fileName;
|
||||
char * fullFileName;
|
||||
S32 materialSlot;
|
||||
~IflMimic() { dFree(fileName); dFree(fullFileName); }
|
||||
};
|
||||
|
||||
struct MeshMimic
|
||||
{
|
||||
INode * pNode;
|
||||
TSMesh * tsMesh;
|
||||
SkinMimic * skinMimic;
|
||||
bool billboard; // i.e., face camera
|
||||
bool sortedObject;
|
||||
S32 numVerts; // number of unique vertices
|
||||
S32 meshNum;
|
||||
Vector<U32> smoothingGroups;
|
||||
Vector<U32> remap;
|
||||
Vector<U32> vertId;
|
||||
|
||||
Matrix3 objectOffset; // NOTE: not valid till late in the game
|
||||
|
||||
F32 multiResPercent;
|
||||
|
||||
MeshMimic(INode * meshNode) { pNode = meshNode; skinMimic = NULL; tsMesh = NULL; }
|
||||
};
|
||||
|
||||
struct MultiResMimic
|
||||
{
|
||||
INode * pNode;
|
||||
INode * multiResNode;
|
||||
S32 totalVerts;
|
||||
// record off order of vertex merging (we'll figure out tverts later)
|
||||
Vector<Point3F> mergeFrom;
|
||||
Vector<Point3F> mergeTo;
|
||||
MultiResMimic(INode * pn, INode * mrn) { pNode = pn; multiResNode = mrn; }
|
||||
};
|
||||
|
||||
struct ObjectMimic
|
||||
{
|
||||
enum { MaxDetails=20 };
|
||||
struct Detail
|
||||
{
|
||||
S32 size;
|
||||
MeshMimic * mesh;
|
||||
};
|
||||
|
||||
// my object has a name...I'm Jimmy.
|
||||
const char * name;
|
||||
const char * fullName; // name of object in tree
|
||||
|
||||
// each object has several meshes attached
|
||||
S32 numDetails;
|
||||
Detail details[MaxDetails];
|
||||
|
||||
// we'll check the object against this list in the end
|
||||
Vector<S32> * pValidDetails;
|
||||
INode * inTreeNode; // this is the node that sits in the shape's node hierrarchy
|
||||
|
||||
// The next two items are used for sorting objects
|
||||
// objects are sorted by subTreeNum first, and then
|
||||
// priority (smallest to highest in both cases).
|
||||
S32 subtreeNum;
|
||||
U32 priority;
|
||||
|
||||
// all verts in the meshes get multiplied by this matrix
|
||||
// before being added to ts shape
|
||||
Matrix3 objectOffset;
|
||||
|
||||
// The max node this object hangs on (i.e., the one in the shape not
|
||||
// the loose objects that make up the detail levels).
|
||||
INode * maxParent;
|
||||
// Similar to above: the max node that corresponds to tsNode that will
|
||||
// be our parent. Starts out the same as maxParent, but is revised
|
||||
// as we prune unwanted nodes from the tree structure.
|
||||
INode * maxTSParent;
|
||||
|
||||
// ts node index we hang off
|
||||
S32 tsNodeIndex;
|
||||
S32 tsObjectIndex;
|
||||
|
||||
// This is the eventual payoff
|
||||
TSObject * tsObject;
|
||||
|
||||
//
|
||||
bool isBone;
|
||||
bool isSkin;
|
||||
|
||||
~ObjectMimic()
|
||||
{
|
||||
dFree((char*)name);
|
||||
dFree((char*)fullName);
|
||||
for (S32 i=0;i<numDetails;i++)
|
||||
delete details[i].mesh;
|
||||
}
|
||||
};
|
||||
|
||||
struct DecalMeshMimic
|
||||
{
|
||||
MeshMimic * targetMesh;
|
||||
TSDecalMesh * tsMesh;
|
||||
|
||||
DecalMeshMimic(MeshMimic * target) { targetMesh = target; tsMesh = NULL; }
|
||||
};
|
||||
|
||||
struct DecalObjectMimic
|
||||
{
|
||||
enum { MaxDetails=20 };
|
||||
struct Detail
|
||||
{
|
||||
DecalMeshMimic * decalMesh;
|
||||
};
|
||||
|
||||
// each object has several meshes attached
|
||||
S32 numDetails;
|
||||
Detail details[MaxDetails];
|
||||
|
||||
// The next two items are used for sorting decal objects.
|
||||
// See ObjectMimic for more info.
|
||||
S32 subtreeNum;
|
||||
U32 priority;
|
||||
|
||||
// The object used to map the decal onto the object
|
||||
INode * decalNode;
|
||||
|
||||
// This is the object we decal
|
||||
ObjectMimic * targetObject;
|
||||
|
||||
// This is the eventual payoff
|
||||
TSDecal * tsDecal;
|
||||
|
||||
~DecalObjectMimic()
|
||||
{
|
||||
for (S32 i=0;i<numDetails;i++)
|
||||
delete details[i].decalMesh;
|
||||
}
|
||||
};
|
||||
|
||||
struct NodeMimic
|
||||
{
|
||||
// our twin in the max world:
|
||||
INode * maxNode;
|
||||
|
||||
// our neighbors in the mimic world:
|
||||
NodeMimic * parent;
|
||||
NodeMimic * child;
|
||||
NodeMimic * sibling;
|
||||
|
||||
// transforms at default time
|
||||
AffineParts child0;
|
||||
AffineParts parent0;
|
||||
|
||||
// index of our ts version
|
||||
S32 number;
|
||||
|
||||
// our mimic object
|
||||
Vector<ObjectMimic*> objects;
|
||||
};
|
||||
|
||||
struct CropInfo
|
||||
{
|
||||
bool hasTVerts;
|
||||
Matrix3 uvTransform;
|
||||
|
||||
bool uWrap;
|
||||
bool vWrap;
|
||||
|
||||
bool crop;
|
||||
bool place;
|
||||
|
||||
F32 uOffset;
|
||||
F32 vOffset;
|
||||
F32 uWidth;
|
||||
F32 vHeight;
|
||||
|
||||
// only valid if crop==true
|
||||
bool cropLeft;
|
||||
bool cropRight;
|
||||
bool cropTop;
|
||||
bool cropBottom;
|
||||
|
||||
bool twoSided;
|
||||
};
|
||||
|
||||
class ShapeMimic
|
||||
{
|
||||
friend class SceneEnumProc;
|
||||
|
||||
struct Subtree
|
||||
{
|
||||
Vector<S32> validDetails;
|
||||
Vector<const char*> detailNames;
|
||||
Vector<INode*> detailNodes;
|
||||
NodeMimic start;
|
||||
};
|
||||
|
||||
Vector<Subtree*> subtrees;
|
||||
Vector<ObjectMimic*> objectList;
|
||||
Vector<DecalObjectMimic*> decalObjectList;
|
||||
Vector<SkinMimic*> skins;
|
||||
Vector<MultiResMimic*> multiResList;
|
||||
Vector<IflMimic*> iflList;
|
||||
Vector<INode*> sequences;
|
||||
Vector<char*> materials;
|
||||
Vector<U32> materialFlags;
|
||||
Vector<U32> materialReflectionMaps;
|
||||
Vector<U32> materialBumpMaps;
|
||||
Vector<U32> materialDetailMaps;
|
||||
Vector<F32> materialDetailScales;
|
||||
Vector<F32> materialEmapAmounts;
|
||||
INode * boundsNode;
|
||||
|
||||
// this gets filled in late in the game
|
||||
// it holds the nodes that actually go into the shape
|
||||
// in the order they appear in the shape
|
||||
Vector<NodeMimic*> nodes;
|
||||
|
||||
// error control
|
||||
char * errorStr;
|
||||
void setExportError(const char * str);
|
||||
|
||||
// called by generateShape
|
||||
void generateBounds(TSShape * pShape);
|
||||
void generateDetails(TSShape * pShape);
|
||||
void generateSubtrees(TSShape * pShape);
|
||||
void generateObjects(TSShape * pShape);
|
||||
void generateDecals(TSShape * pShape);
|
||||
void generateDefaultStates(TSShape * pShape);
|
||||
void generateIflMaterials(TSShape * pShape);
|
||||
void generateSequences(TSShape * pShape);
|
||||
void generateMaterialList(TSShape * pShape);
|
||||
void generateSkins(TSShape * pShape);
|
||||
void optimizeMeshes(TSShape * pShape);
|
||||
void convertSortObjects(TSShape * pShape);
|
||||
|
||||
void generateObjectState(ObjectMimic*,S32 time,TSShape *, bool addFrame, bool addMatFrame);
|
||||
void generateDecalState(DecalObjectMimic*,S32 time,TSShape *, bool multipleFrames);
|
||||
void generateFrame(ObjectMimic*,S32 time, bool addFrame, bool addMatFrame);
|
||||
void generateFaces(INode * meshNode, Mesh & maxMesh, Matrix3 & objectOffset,
|
||||
Vector<TSDrawPrimitive> & faces, Vector<Point3F> & normals,
|
||||
Vector<Point3> & verts, Vector<Point3> & tverts, Vector<U16> & indices,
|
||||
Vector<U32> & smooth, Vector<U32> * vertId = NULL);
|
||||
S32 getMultiResVerts(INode * meshNode, F32 multiResPercent);
|
||||
void generateNodeTransform(NodeMimic*,S32 time,TSShape *, bool blend, S32 blendReferenceTime, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale);
|
||||
|
||||
void addNodeRotation(NodeMimic*,S32 time,TSShape *, bool blend, Quat16 & rot, bool defaultVal=false);
|
||||
void addNodeTranslation(NodeMimic*,S32 time,TSShape *, bool blend, Point3F & trans, bool defaultVal=false);
|
||||
void addNodeUniformScale(NodeMimic*,S32 time,TSShape *, bool blend, F32 scale);
|
||||
void addNodeAlignedScale(NodeMimic*,S32 time,TSShape *, bool blend, Point3F & scale);
|
||||
void addNodeArbitraryScale(NodeMimic*,S32 time,TSShape *, bool blend, Quat16 & srot, Point3F & scale);
|
||||
|
||||
void computeNormals(Vector<TSDrawPrimitive> &, Vector<U16> & indices, Vector<Point3F> & verts, Vector<Point3F> & norms, Vector<U32> & smooth, S32 vertsPerFrame, S32 numFrames, Vector<U16> * mergeIndices);
|
||||
void computeNormals(Vector<TSDrawPrimitive> &, Vector<U16> & indices, Vector<Point3> & verts, Vector<Point3F> & norms, Vector<U32> & smooth, S32 vertsPerFrame, S32 numFrames);
|
||||
|
||||
void generateNodeAnimation(TSShape * pShape, Interval & range, ExporterSequenceData &);
|
||||
void generateObjectAnimation(TSShape * pShape, Interval & range, ExporterSequenceData &);
|
||||
void generateDecalAnimation(TSShape * pShape, Interval & range, ExporterSequenceData &);
|
||||
void generateGroundAnimation(TSShape * pShape, Interval & range, ExporterSequenceData &);
|
||||
void generateFrameTriggers(TSShape *, Interval &, ExporterSequenceData &, IParamBlock *);
|
||||
void addTriggersInOrder(IKeyControl *, F32 duration, TSShape *, U32 & offTriggers);
|
||||
|
||||
void setNodeMembership(TSShape *, Interval & range, ExporterSequenceData &, S32 &, S32 &, S32 &, S32 &, S32 &);
|
||||
S32 setObjectMembership(TSShape::Sequence &, Interval & range, ExporterSequenceData &);
|
||||
S32 setDecalMembership(TSShape::Sequence &, Interval & range, ExporterSequenceData &);
|
||||
S32 setIflMembership(TSShape::Sequence &, Interval & range, ExporterSequenceData &);
|
||||
|
||||
S32 setRotationMembership(TSShape *, TSSequence &, ExporterSequenceData &, S32 numFrames);
|
||||
S32 setTranslationMembership(TSShape *, TSSequence &, ExporterSequenceData &, S32 numFrames);
|
||||
S32 setUniformScaleMembership(TSShape *, TSSequence &, ExporterSequenceData &, S32 numFrames);
|
||||
S32 setAlignedScaleMembership(TSShape *, TSSequence &, ExporterSequenceData &, S32 numFrames);
|
||||
S32 setArbitraryScaleMembership(TSShape *, TSSequence &, ExporterSequenceData &, S32 numFrames);
|
||||
|
||||
bool animatesAlignedScale(ExporterSequenceData &, S32 numFrames);
|
||||
bool animatesArbitraryScale(ExporterSequenceData &, S32 numFrames);
|
||||
|
||||
void setObjectPriorities(Vector<ObjectMimic*> &);
|
||||
void setDecalObjectPriorities(Vector<DecalObjectMimic*> &);
|
||||
|
||||
bool testCutNodes(Interval & range, ExporterSequenceData &);
|
||||
|
||||
// methods used to optimize meshes
|
||||
void collapseVertices(TSMesh*, Vector<U32> & smooth, Vector<U32> & remap, Vector<U32> * vertId = NULL);
|
||||
void shareVerts(ObjectMimic *, S32 dl, TSShape *);
|
||||
void shareVerts(SkinMimic *, Vector<U32> & originalRemap, TSShape *);
|
||||
void shareBones(SkinMimic *, TSShape *);
|
||||
bool vertexSame(Point3F &, Point3F &, Point2F &, Point2F &, U32 smooth1, U32 smooth2, U32 idx1, U32 idx2, Vector<U32> * vertId);
|
||||
void stripify(Vector<TSDrawPrimitive> &, Vector<U16> & indices);
|
||||
|
||||
// add a name to the shape and return the index
|
||||
S32 addName(const char *, TSShape *);
|
||||
|
||||
// adds a mesh node to the mesh list and returns the mesh it hangs off
|
||||
ObjectMimic * getObject(INode *, char * name, S32 size, S32 * detailNum, F32 multiResPercent = -1.0f, bool matchFullName = true, bool isBone=false, bool isSkin=false);
|
||||
ObjectMimic * addObject(INode *, Vector<S32> *pValidDetails);
|
||||
ObjectMimic * addObject(INode *, Vector<S32> *pValidDetails, bool multiRes, S32 multiResSize = -1, F32 multiResPercent = -1.0f);
|
||||
ObjectMimic * addBoneObject(INode * bone, S32 subtreeNum);
|
||||
MeshMimic * addSkinObject(SkinMimic * skinMimic);
|
||||
void addDecalObject(INode *, ObjectMimic *);
|
||||
|
||||
// functions for adding decals
|
||||
bool decalOn(DecalObjectMimic*,S32 time);
|
||||
void interpolateTVert(Point3F v0, Point3F v1, Point3F v2, Point3F planeNormal, Point3F & p, Point3 tv0, Point3 tv1, Point3 tv2, Point3 & tv);
|
||||
S32 generateDecalFrame(DecalObjectMimic*,S32 time);
|
||||
void findDecalTexGen(MatrixF &, Point4F &, Point4F &);
|
||||
S32 findLastDecalFrameNumber(DecalObjectMimic*);
|
||||
bool prepareDecal(INode * decalNode, S32 time);
|
||||
void generateDecalFrame(DecalObjectMimic*, S32 time, S32 dl);
|
||||
bool getDecalTVert(U32 decalType, Point3 vert, Point3F normal, Point3 & tv);
|
||||
bool getPlaneDecalTVSpecial(Point3 & vert, const Point3F & normal, Point3 & tv);
|
||||
void findNonOrthogonalComponents(const Point3F & v1, const Point3F & v2, const Point3F & p, F32 & t1, F32 & t2);
|
||||
bool getDecalProjPoint(U32 decalType, Point3 vert, Point3F & normal, U32 decalFaceIdx, Point3F & p);
|
||||
bool checkDecalFilter(Point3 v0, Point3 v1, Point3 v2);
|
||||
bool checkDecalFace(Point3 tv0, Point3 tv1, Point3 tv2);
|
||||
|
||||
// utility function for traversing tree in depth first order
|
||||
// returns NULL when we get back to the top
|
||||
NodeMimic * findNextNode(NodeMimic * cur);
|
||||
|
||||
// utility function called by collapseTransform removes
|
||||
// the node from the mimic tree structure, taking care
|
||||
// to otherwise maintain the integrity of the shape tree
|
||||
void snip(NodeMimic *);
|
||||
|
||||
// should we cut this node?
|
||||
bool cut(NodeMimic *);
|
||||
|
||||
// is this node on the never animate list?
|
||||
bool neverAnimateNode(NodeMimic *);
|
||||
|
||||
void splitFaceX(TSDrawPrimitive & face, TSDrawPrimitive & faceA, TSDrawPrimitive & faceB,
|
||||
Vector<Point3> & verts, Vector<Point3> & tverts, Vector<U16> & indices,
|
||||
Vector<bool> & flipX, Vector<bool> & flipY,
|
||||
F32 splitAt,
|
||||
Vector<U32> & smooth, Vector<U32> * vertId);
|
||||
void splitFaceY(TSDrawPrimitive & face, TSDrawPrimitive & faceA, TSDrawPrimitive & faceB,
|
||||
Vector<Point3> & verts, Vector<Point3> & tverts, Vector<U16> & indices,
|
||||
Vector<bool> & flipX, Vector<bool> & flipY,
|
||||
F32 splitAt,
|
||||
Vector<U32> & smooth, Vector<U32> * vertId);
|
||||
void handleCropAndPlace(Point3 &, CropInfo &);
|
||||
|
||||
public:
|
||||
ShapeMimic();
|
||||
~ShapeMimic();
|
||||
|
||||
// check for errors
|
||||
bool isError();
|
||||
const char * getError();
|
||||
|
||||
//
|
||||
void setGlobals(INode * pNode, S32 polyCount, F32 minVolPerPoly, F32 maxVolPerPoly);
|
||||
|
||||
void recordMergeOrder(IParamBlock *, MultiResMimic *);
|
||||
void collapseEdge(Vector<Face> & faces, S32 fromA, S32 toB);
|
||||
void getMultiResData(INode * pNode, Vector<S32> & multiResSize, Vector<F32> & multiResPercent);
|
||||
void addMultiRes(INode * pNode, INode * multiResNode);
|
||||
MultiResMimic * getMultiRes(INode * pNode);
|
||||
void remapWeights(Vector<SkinMimic::WeightList*> &, INode * skinNode, INode * multiResNode);
|
||||
void copyWeightsToVerts(SkinMimic *);
|
||||
|
||||
void fixupT2AutoDetail();
|
||||
void applyAutoDetail(Vector<S32> &, Vector<const char*> &, Vector<INode*> &);
|
||||
|
||||
// find which vertices merge with which vertices
|
||||
void findMergeIndices(MeshMimic *, Matrix3 & objectOffset, const Vector<TSDrawPrimitive> &,
|
||||
Vector<Point3F> &, Vector<Point3F> &, Vector<Point2F> &,
|
||||
const Vector<U16> & indices, Vector<U16> & mergeIndices,
|
||||
Vector<U32> & smooth, Vector<U32> & vertId, S32 numChildVerts);
|
||||
// very specialized function used by above
|
||||
void addMergeTargetAndMerge(Vector<TSDrawPrimitive> & faces, S32 & faceNum, S32 & v,
|
||||
Vector<U16> & indices, Vector<U16> & mergeIndices,
|
||||
Vector<Point3F> & verts, Vector<Point2F> & tverts, Vector<Point3F> & norms,
|
||||
Vector<U32> & smooth, Vector<U32> & vertId,
|
||||
Vector<S32> & mergeOrder, Vector<S32> & mergeID, Vector<Point3F> & mergeTarget);
|
||||
// called in optimizeMeshes
|
||||
void fixupMergeIndices(TSShape *);
|
||||
// called after adding first frame to non-skin objects
|
||||
void generateMergeIndices(ObjectMimic*);
|
||||
void testMerge(TSShape *, ObjectMimic *, S32 dl, S32 numChildVerts);
|
||||
|
||||
// parts added to mimic using these methods...order unimportant
|
||||
void addBounds(INode * pNode);
|
||||
void addSubtree(INode * pNode);
|
||||
void addNode(NodeMimic *,INode *, Vector<S32> &,bool);
|
||||
void addMesh(INode * pNode) { addObject(pNode,NULL); }
|
||||
void addSkin(INode * pNode);
|
||||
void addSkin(INode * pNode, S32 multiResSize, F32 multiResPercent);
|
||||
void addSequence(INode * pNode);
|
||||
S32 addMaterial(INode * pNode, S32 materialIndex, CropInfo *);
|
||||
S32 findMaterial(const char * name, const char * fullName, U32 flags, S32,S32,S32,F32 dscale = 1.0f,F32 emapAmount=1.0f); // finds, and adds if not there
|
||||
void appendMaterialList(const char * name, U32 flags, S32,S32,S32,F32 dscale = 1.0f,F32 emapAmount=1.0f); // adds to the end
|
||||
const char * getBaseTextureName(const char *);
|
||||
|
||||
// can optionally get rid of nodes with no mesh
|
||||
void collapseTransforms();
|
||||
void clearCollapseTransforms();
|
||||
|
||||
F32 findMaxDistance(TSMesh * loMesh, TSMesh * hiMesh, F32 & total, S32 & count);
|
||||
|
||||
// the payoff...call after adding all of the above
|
||||
TSShape * generateShape();
|
||||
void initShape(TSShape*);
|
||||
void destroyShape(TSShape*);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
657
tools/max2dtsExporter/exportUtil.cc
Executable file
657
tools/max2dtsExporter/exportUtil.cc
Executable file
@ -0,0 +1,657 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <MAX.H>
|
||||
#include <istdplug.h>
|
||||
#include <utilapi.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
#include "max2dtsExporter/SceneEnum.h"
|
||||
#include "max2dtsExporter/maxUtil.h"
|
||||
|
||||
#include "Platform/platform.h"
|
||||
#include "Platform/platformAssert.h"
|
||||
#include "max2dtsExporter/exportUtil.h"
|
||||
#include "max2dtsExporter/exporter.h"
|
||||
|
||||
extern HINSTANCE hInstance;
|
||||
extern TCHAR *GetString(S32);
|
||||
extern const char * GetVersionString();
|
||||
|
||||
#define EditBoxesToo 0x80000000
|
||||
|
||||
class ExportUtil : public UtilityObj
|
||||
{
|
||||
public:
|
||||
|
||||
IUtil *iu;
|
||||
Interface *ip;
|
||||
HWND hPanel1;
|
||||
HWND hPanel1b;
|
||||
HWND hPanel2;
|
||||
HWND hPanel3;
|
||||
HWND hPanel4;
|
||||
HWND hPanel5;
|
||||
|
||||
//Constructor/Destructor
|
||||
ExportUtil();
|
||||
~ExportUtil();
|
||||
|
||||
void BeginEditParams(Interface *ip, IUtil *iu);
|
||||
void EndEditParams(Interface *ip, IUtil *iu);
|
||||
void DeleteThis() {}
|
||||
|
||||
void Init(HWND hWnd);
|
||||
void Destroy(HWND hWnd);
|
||||
|
||||
void initializePanels(S32 mask = -1);
|
||||
};
|
||||
|
||||
|
||||
static ExportUtil exportUtil;
|
||||
|
||||
// This is the Class Descriptor for the U plug-in
|
||||
class ExportUtilClassDesc:public ClassDesc
|
||||
{
|
||||
public:
|
||||
S32 IsPublic() {return 1;}
|
||||
void * Create(BOOL loading = FALSE) { loading; return &exportUtil;}
|
||||
const TCHAR * ClassName() {return "DTS Exporter Utility";}
|
||||
SClass_ID SuperClassID() {return UTILITY_CLASS_ID;}
|
||||
Class_ID ClassID() {return ExportUtil_CLASS_ID;}
|
||||
const TCHAR* Category() {return "Exporter Utility";}
|
||||
void ResetClassParams (BOOL fileReset);
|
||||
};
|
||||
|
||||
static ExportUtilClassDesc exportUtilDesc;
|
||||
|
||||
ClassDesc * GetExportUtilDesc() {return &exportUtilDesc;}
|
||||
Interface * GetMaxInterface() { return exportUtil.ip; }
|
||||
|
||||
//TODO: Should implement this method to reset the plugin params when Max is reset
|
||||
void ExportUtilClassDesc::ResetClassParams (BOOL fileReset)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#define MAX_FILENAME_LEN 128
|
||||
char filenameBuffer[MAX_FILENAME_LEN];
|
||||
|
||||
void findFiles(const char * filePattern, Vector<char *> & matches)
|
||||
{
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE searchHandle = FindFirstFile(filePattern,&findData);
|
||||
if (searchHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
matches.push_back(dStrdup(findData.cFileName));
|
||||
while (FindNextFile(searchHandle,&findData))
|
||||
matches.push_back(dStrdup(findData.cFileName));
|
||||
}
|
||||
}
|
||||
|
||||
void clearFindFiles(Vector<char*> & matches)
|
||||
{
|
||||
for (S32 i=0; i<matches.size(); i++)
|
||||
dFree(matches[i]);
|
||||
matches.clear();
|
||||
}
|
||||
|
||||
void initOFN(OPENFILENAME & ofn, char * filter, char * ext, char * title, const char * dir)
|
||||
{
|
||||
memset(filenameBuffer,0,MAX_FILENAME_LEN);
|
||||
memset(&ofn,0,sizeof(OPENFILENAME));
|
||||
|
||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||
ofn.hwndOwner = NULL;
|
||||
ofn.hInstance = hInstance;
|
||||
ofn.lpstrFilter = filter;
|
||||
ofn.lpstrCustomFilter = NULL;
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = filenameBuffer;
|
||||
ofn.nMaxFile = MAX_FILENAME_LEN;
|
||||
filenameBuffer[0] = '\0';
|
||||
ofn.lpstrFileTitle = NULL;
|
||||
ofn.nMaxFileTitle = 0;
|
||||
ofn.lpstrInitialDir = dir;
|
||||
ofn.lpstrTitle = title;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_EXPLORER;
|
||||
ofn.lpstrDefExt = ext;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ExportUtilDlgProc1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
exportUtil.Init(hWnd);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
exportUtil.Destroy(hWnd);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
exportUtil.ip->RollupMouseMessage(hWnd,msg,wParam,lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK RenumberDlgFunc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd,-99);
|
||||
break;
|
||||
case IDOK:
|
||||
char buffer[128];
|
||||
if (GetDlgItemText(hWnd,IDC_EDIT,buffer,128)>0)
|
||||
{
|
||||
int newSize = dAtoi(buffer);
|
||||
EndDialog(hWnd,newSize);
|
||||
}
|
||||
else
|
||||
EndDialog(hWnd,-99);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ExportUtilDlgProc1b(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
exportUtil.Init(hWnd);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
exportUtil.Destroy(hWnd);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_EXPORT_WHOLE :
|
||||
initOFN(ofn,"Torque 3Space Shape File (*.dts)\0*.dts\0","dts","Export DTS",exportUtil.ip->GetDir(APP_EXPORT_DIR));
|
||||
if (GetSaveFileName(&ofn))
|
||||
exportUtil.ip->ExportToFile(ofn.lpstrFile);
|
||||
break;
|
||||
case IDC_EXPORT_SEQUENCES :
|
||||
initOFN(ofn,"Torque 3Space Sequence File (*.dsq)\0*.dsq\0","dsq","Export DSQ",exportUtil.ip->GetDir(APP_EXPORT_DIR));
|
||||
if (GetSaveFileName(&ofn))
|
||||
exportUtil.ip->ExportToFile(ofn.lpstrFile);
|
||||
break;
|
||||
case IDC_EXPORT_TEXT:
|
||||
initOFN(ofn,"Torque 3Space Scene Text Export (*.txt)\0*.txt\0","txt","Scene Text Export",exportUtil.ip->GetDir(APP_EXPORT_DIR));
|
||||
if (GetSaveFileName(&ofn))
|
||||
exportUtil.ip->ExportToFile(ofn.lpstrFile);
|
||||
break;
|
||||
case IDC_RENUMBER:
|
||||
{
|
||||
S32 newNumber = DialogBox(hInstance,MAKEINTRESOURCE(IDD_RENUMBER),hWnd,RenumberDlgFunc);
|
||||
if (newNumber >=0 && exportUtil.ip)
|
||||
renumberNodes(exportUtil.ip,newNumber);
|
||||
break;
|
||||
}
|
||||
case IDC_REGISTER_DETAILS:
|
||||
registerDetails(exportUtil.ip);
|
||||
break;
|
||||
case IDC_EMBED:
|
||||
embedSubtree(exportUtil.ip);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
exportUtil.ip->RollupMouseMessage(hWnd,msg,wParam,lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ExportUtilDlgProc2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
exportUtil.Init(hWnd);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
exportUtil.Destroy(hWnd);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_COLLAPSE : transformCollapse = !transformCollapse; break;
|
||||
case IDC_ENABLE_SEQUENCES : enableSequences = !enableSequences; break;
|
||||
case IDC_ENABLE_TWO_SIDED : enableTwoSidedMaterials = !enableTwoSidedMaterials; break;
|
||||
case IDC_ANIMATION_DELTA:
|
||||
if (HIWORD(wParam)==EN_CHANGE)
|
||||
{
|
||||
ICustEdit * edit = GetICustEdit( GetDlgItem(exportUtil.hPanel2,IDC_ANIMATION_DELTA) );
|
||||
if (!edit->GotReturn())
|
||||
return TRUE;
|
||||
F32 tmp = edit->GetFloat();
|
||||
if (tmp > 10E-12f)
|
||||
animationDelta = tmp;
|
||||
ReleaseICustEdit(edit);
|
||||
exportUtil.initializePanels(2 + EditBoxesToo);
|
||||
}
|
||||
break;
|
||||
case IDC_BASE_TEXTURE_PATH:
|
||||
if (HIWORD(wParam)==EN_CHANGE)
|
||||
{
|
||||
ICustEdit * edit = GetICustEdit( GetDlgItem(exportUtil.hPanel2,IDC_BASE_TEXTURE_PATH) );
|
||||
if (!edit->GotReturn())
|
||||
return TRUE;
|
||||
char buffer[256];
|
||||
edit->GetText(buffer,sizeof(buffer));
|
||||
setBaseTexturePath(buffer);
|
||||
ReleaseICustEdit(edit);
|
||||
exportUtil.initializePanels(2 + EditBoxesToo);
|
||||
}
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
exportUtil.initializePanels(2);
|
||||
break;
|
||||
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
exportUtil.ip->RollupMouseMessage(hWnd,msg,wParam,lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ExportUtilDlgProc3(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
exportUtil.Init(hWnd);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
exportUtil.Destroy(hWnd);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_ALLOW_EMPTY : allowEmptySubtrees = !allowEmptySubtrees; break;
|
||||
case IDC_ALLOW_CROSSED : allowCrossedDetails = !allowCrossedDetails; break;
|
||||
case IDC_ALLOW_UNUSED : allowUnusedMeshes = !allowUnusedMeshes; break;
|
||||
case IDC_ALLOW_OLD : allowOldSequences = !allowOldSequences; break;
|
||||
case IDC_REQUIRE_VICON : viconNeeded = !viconNeeded; break;
|
||||
}
|
||||
exportUtil.initializePanels(4);
|
||||
break;
|
||||
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
exportUtil.ip->RollupMouseMessage(hWnd,msg,wParam,lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ExportUtilDlgProc4(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
exportUtil.Init(hWnd);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
exportUtil.Destroy(hWnd);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_PASS1 : dumpMask ^= PDPass1; break;
|
||||
case IDC_PASS2 : dumpMask ^= PDPass2; break;
|
||||
case IDC_PASS3 : dumpMask ^= PDPass3; break;
|
||||
case IDC_NODE_STATES : dumpMask ^= PDNodeStates; break;
|
||||
case IDC_OBJECT_STATES : dumpMask ^= PDObjectStates; break;
|
||||
case IDC_NODE_STATE_DETAILS : dumpMask ^= PDNodeStateDetails; break;
|
||||
case IDC_OBJECT_STATE_DETAILS : dumpMask ^= PDObjectStateDetails; break;
|
||||
case IDC_OBJECT_OFFSETS : dumpMask ^= PDObjectOffsets; break;
|
||||
case IDC_SEQUENCE_DETAILS : dumpMask ^= PDSequences; break;
|
||||
case IDC_SHAPE_HIERARCHY : dumpMask ^= PDShapeHierarchy; break;
|
||||
}
|
||||
exportUtil.initializePanels(8);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
exportUtil.ip->RollupMouseMessage(hWnd,msg,wParam,lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ok,ok, so this should probably be in a header somewhere...so sue me
|
||||
extern char globalConfig[270];
|
||||
|
||||
static BOOL CALLBACK ExportUtilDlgProc5(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
exportUtil.Init(hWnd);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
exportUtil.Destroy(hWnd);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_CONFIG_LOAD_DEFAULT :
|
||||
SceneEnumProc::readConfigFile(globalConfig);
|
||||
break;
|
||||
case IDC_CONFIG_SAVE_DEFAULT :
|
||||
SceneEnumProc::writeConfigFile(globalConfig);
|
||||
break;
|
||||
case IDC_CONFIG_LOAD :
|
||||
initOFN(ofn,"Exporter Configuration File (*.cfg)\0*.cfg\0","cfg","Load Configuration File",NULL);
|
||||
if (GetOpenFileName(&ofn))
|
||||
SceneEnumProc::readConfigFile(ofn.lpstrFile);
|
||||
break;
|
||||
case IDC_CONFIG_SAVE :
|
||||
initOFN(ofn,"Exporter Configuration File (*.cfg)\0*.cfg\0","dsq","Save Configuration File",NULL);
|
||||
if (GetSaveFileName(&ofn))
|
||||
SceneEnumProc::writeConfigFile(ofn.lpstrFile);
|
||||
break;
|
||||
}
|
||||
exportUtil.initializePanels();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
exportUtil.ip->RollupMouseMessage(hWnd,msg,wParam,lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ExportUtil::ExportUtil()
|
||||
{
|
||||
iu = NULL;
|
||||
ip = NULL;
|
||||
hPanel1 = NULL;
|
||||
hPanel1b = NULL;
|
||||
hPanel2 = NULL;
|
||||
hPanel3 = NULL;
|
||||
hPanel4 = NULL;
|
||||
hPanel5 = NULL;
|
||||
}
|
||||
|
||||
ExportUtil::~ExportUtil()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ExportUtil::BeginEditParams(Interface *ip, IUtil *iu)
|
||||
{
|
||||
this->iu = iu;
|
||||
this->ip = ip;
|
||||
hPanel1 = ip->AddRollupPage(
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_UTIL_PANEL1),
|
||||
ExportUtilDlgProc1,
|
||||
"About",
|
||||
0,
|
||||
APPENDROLL_CLOSED);
|
||||
|
||||
hPanel1b = ip->AddRollupPage(
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_UTIL_PANEL1B),
|
||||
ExportUtilDlgProc1b,
|
||||
"Utilities",
|
||||
0);
|
||||
|
||||
hPanel2 = ip->AddRollupPage(
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_UTIL_PANEL2),
|
||||
ExportUtilDlgProc2,
|
||||
"Parameters",
|
||||
0,
|
||||
APPENDROLL_CLOSED);
|
||||
|
||||
hPanel3 = ip->AddRollupPage(
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_UTIL_PANEL3),
|
||||
ExportUtilDlgProc3,
|
||||
"Error Control",
|
||||
0,
|
||||
APPENDROLL_CLOSED);
|
||||
|
||||
hPanel4 = ip->AddRollupPage(
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_UTIL_PANEL4),
|
||||
ExportUtilDlgProc4,
|
||||
"Dump File Control",
|
||||
0,
|
||||
APPENDROLL_CLOSED);
|
||||
|
||||
hPanel5 = ip->AddRollupPage(
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_UTIL_PANEL5),
|
||||
ExportUtilDlgProc5,
|
||||
"Configuration Control",
|
||||
0,
|
||||
APPENDROLL_CLOSED);
|
||||
|
||||
initializePanels();
|
||||
}
|
||||
|
||||
void ExportUtil::EndEditParams(Interface *ip, IUtil *iu)
|
||||
{
|
||||
this->iu = NULL;
|
||||
this->ip = NULL;
|
||||
|
||||
ip->DeleteRollupPage(hPanel1);
|
||||
hPanel1 = NULL;
|
||||
|
||||
ip->DeleteRollupPage(hPanel1b);
|
||||
hPanel1b = NULL;
|
||||
|
||||
ip->DeleteRollupPage(hPanel2);
|
||||
hPanel2 = NULL;
|
||||
|
||||
ip->DeleteRollupPage(hPanel3);
|
||||
hPanel3 = NULL;
|
||||
|
||||
ip->DeleteRollupPage(hPanel4);
|
||||
hPanel4 = NULL;
|
||||
|
||||
ip->DeleteRollupPage(hPanel5);
|
||||
hPanel5 = NULL;
|
||||
}
|
||||
|
||||
void ExportUtil::Init(HWND hWnd)
|
||||
{
|
||||
}
|
||||
|
||||
void ExportUtil::Destroy(HWND hWnd)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ExportUtil::initializePanels(S32 mask)
|
||||
{
|
||||
|
||||
ICustButton * button;
|
||||
ICustEdit * edit;
|
||||
char buffer[255];
|
||||
|
||||
// Panel 1 -- about panel
|
||||
if (mask & 1)
|
||||
{
|
||||
// add text to about panel
|
||||
dStrcpy(buffer,avar("Torque DTS Exporter\n%s\nCompiled %s\n%s",GetVersionString(),__DATE__,__TIME__));
|
||||
SetDlgItemText(hPanel1,IDC_STATIC_ABOUT,buffer);
|
||||
}
|
||||
|
||||
// Panel 2 -- Parameters
|
||||
if (mask&2)
|
||||
{
|
||||
CheckDlgButton(hPanel2,IDC_COLLAPSE,transformCollapse);
|
||||
CheckDlgButton(hPanel2,IDC_ENABLE_SEQUENCES,enableSequences);
|
||||
CheckDlgButton(hPanel2,IDC_ENABLE_TWO_SIDED,enableTwoSidedMaterials);
|
||||
if (mask & EditBoxesToo)
|
||||
{
|
||||
edit = GetICustEdit(GetDlgItem(hPanel2,IDC_ANIMATION_DELTA));
|
||||
dStrcpy(buffer,avar("%f",animationDelta));
|
||||
if (edit) // may already be locked
|
||||
{
|
||||
edit->SetText( buffer );
|
||||
edit->WantReturn(true);
|
||||
ReleaseICustEdit(edit);
|
||||
}
|
||||
edit = GetICustEdit(GetDlgItem(hPanel2,IDC_BASE_TEXTURE_PATH));
|
||||
dStrcpy(buffer,baseTexturePath);
|
||||
if (edit)
|
||||
{
|
||||
edit->SetText( buffer );
|
||||
edit->WantReturn(true);
|
||||
ReleaseICustEdit(edit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Panel 3 -- Error Control
|
||||
if (mask & 4)
|
||||
{
|
||||
CheckDlgButton(hPanel3,IDC_ALLOW_EMPTY,allowEmptySubtrees);
|
||||
CheckDlgButton(hPanel3,IDC_ALLOW_CROSSED,allowCrossedDetails);
|
||||
CheckDlgButton(hPanel3,IDC_ALLOW_UNUSED,allowUnusedMeshes);
|
||||
CheckDlgButton(hPanel3,IDC_ALLOW_OLD,allowOldSequences);
|
||||
CheckDlgButton(hPanel3,IDC_REQUIRE_VICON,viconNeeded);
|
||||
}
|
||||
|
||||
// Panel 4 -- Dump file control
|
||||
if (mask & 8)
|
||||
{
|
||||
CheckDlgButton(hPanel4,IDC_PASS1,dumpMask & PDPass1);
|
||||
CheckDlgButton(hPanel4,IDC_PASS2,dumpMask & PDPass2);
|
||||
CheckDlgButton(hPanel4,IDC_PASS3,dumpMask & PDPass3);
|
||||
CheckDlgButton(hPanel4,IDC_NODE_STATES,dumpMask & PDNodeStates);
|
||||
CheckDlgButton(hPanel4,IDC_OBJECT_STATES,dumpMask & PDObjectStates);
|
||||
CheckDlgButton(hPanel4,IDC_NODE_STATE_DETAILS,dumpMask & PDNodeStateDetails);
|
||||
CheckDlgButton(hPanel4,IDC_OBJECT_STATE_DETAILS,dumpMask & PDObjectStateDetails);
|
||||
CheckDlgButton(hPanel4,IDC_OBJECT_OFFSETS,dumpMask & PDObjectOffsets);
|
||||
CheckDlgButton(hPanel4,IDC_SEQUENCE_DETAILS,dumpMask & PDSequences);
|
||||
CheckDlgButton(hPanel4,IDC_SHAPE_HIERARCHY,dumpMask & PDShapeHierarchy);
|
||||
}
|
||||
|
||||
// Panel 5 -- Configuration control
|
||||
if (mask & 16)
|
||||
{
|
||||
// make buttons push buttons rather than check buttons...
|
||||
button = GetICustButton(GetDlgItem(hPanel5,IDC_CONFIG_LOAD_DEFAULT));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
button = GetICustButton(GetDlgItem(hPanel5,IDC_CONFIG_SAVE_DEFAULT));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
button = GetICustButton(GetDlgItem(hPanel5,IDC_CONFIG_LOAD));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
button = GetICustButton(GetDlgItem(hPanel5,IDC_CONFIG_SAVE));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
}
|
||||
|
||||
// Panel 1b -- Utility panel
|
||||
if (mask & 32)
|
||||
{
|
||||
// make buttons push buttons rather than check buttons...
|
||||
button = GetICustButton(GetDlgItem(hPanel1b,IDC_EXPORT_WHOLE));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
button = GetICustButton(GetDlgItem(hPanel1b,IDC_EXPORT_SEQUENCES));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
button = GetICustButton(GetDlgItem(hPanel1b,IDC_EXPORT_TEXT));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
button = GetICustButton(GetDlgItem(hPanel1b,IDC_RENUMBER));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
button = GetICustButton(GetDlgItem(hPanel1b,IDC_EMBED));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
button = GetICustButton(GetDlgItem(hPanel1b,IDC_REGISTER_DETAILS));
|
||||
button->SetType(CBT_PUSH);
|
||||
ReleaseICustButton(button);
|
||||
}
|
||||
}
|
17
tools/max2dtsExporter/exportUtil.h
Executable file
17
tools/max2dtsExporter/exportUtil.h
Executable file
@ -0,0 +1,17 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _EXPORT_UTIL_H_
|
||||
#define _EXPORT_UTIL_H_
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <MAX.H>
|
||||
#pragma pack(pop)
|
||||
|
||||
#define ExportUtil_CLASS_ID Class_ID(0x5959933e, 0x7673c15a)
|
||||
extern ClassDesc * GetExportUtilDesc();
|
||||
extern Interface * GetMaxInterface();
|
||||
|
||||
#endif // _EXPORT_UTIL_H_
|
7
tools/max2dtsExporter/exporter.def
Executable file
7
tools/max2dtsExporter/exporter.def
Executable file
@ -0,0 +1,7 @@
|
||||
EXPORTS
|
||||
LibDescription @1
|
||||
LibNumberClasses @2
|
||||
LibClassDesc @3
|
||||
LibVersion @4
|
||||
SECTIONS
|
||||
.data READ WRITE
|
114
tools/max2dtsExporter/exporter.h
Executable file
114
tools/max2dtsExporter/exporter.h
Executable file
@ -0,0 +1,114 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define IDD_DTSEXP_UI 101
|
||||
#define IDD_SEQUENCE_PARAMS 102
|
||||
#define IDD_SEQUENCE_PARAMS2 103
|
||||
#define IDD_SEQUENCE_PARAMS3 105
|
||||
#define IDD_UTIL_PANEL1 106
|
||||
#define IDD_UTIL_PANEL2 107
|
||||
#define IDB_BITMAP1 107
|
||||
#define IDD_UTIL_PANEL3 108
|
||||
#define IDD_UTIL_PANEL4 109
|
||||
#define IDD_UTIL_PANEL5 110
|
||||
#define IDD_UTIL_PANEL1B 111
|
||||
#define IDD_RENUMBER 112
|
||||
#define IDD_SKINHELP_PANEL 113
|
||||
#define IDC_SEQ_CYCLIC 1001
|
||||
#define IDC_SEQ_BLEND 1002
|
||||
#define IDC_SEQ_LAST_FIRST_FRAME_SAME 1003
|
||||
#define IDC_SEQ_USE_FRAME_RATE 1004
|
||||
#define IDC_SEQ_FRAME_RATE 1005
|
||||
#define IDC_SEQ_NUM_FRAMES 1006
|
||||
#define IDC_SEQ_IGNORE_GROUND_TRANSFORM 1007
|
||||
#define IDC_SEQ_USE_N_FRAMES 1007
|
||||
#define IDC_SEQ_USE_GROUND_FRAME_RATE 1008
|
||||
#define IDC_SEQ_PRIORITY 1008
|
||||
#define IDC_SEQ_GROUND_FRAME_RATE 1009
|
||||
#define IDC_SEQ_DURATION_OVERRIDE 1009
|
||||
#define IDC_SEQ_GROUND_FRAME_RATE_SPINNER 1010
|
||||
#define IDC_SEQ_DURATION 1010
|
||||
#define IDC_SEQ_NUM_GROUND_FRAMES 1011
|
||||
#define IDC_SEQ_NUM_GROUND_FRAMES_SPINNER 1012
|
||||
#define IDC_SEQ_FRAME_RATE_SPINNER 1013
|
||||
#define IDC_SEQ_NUM_FRAMES_SPINNER 1014
|
||||
#define IDC_SEQ_PRIORITY_SPINNER 1015
|
||||
#define IDC_SEQ_DURATION_SPINNER 1016
|
||||
#define IDC_SEQ_ENABLE_MORPH_ANIMATION 1017
|
||||
#define IDC_SEQ_ENABLE_VIS_ANIMATION 1018
|
||||
#define IDC_SEQ_ENABLE_TRANSFORM_ANIMATION 1019
|
||||
#define IDC_SEQ_USE_N_GROUND_FRAMES 1020
|
||||
#define IDC_SEQ_ENABLE_TEXTURE_ANIMATION 1020
|
||||
#define IDC_SEQ_ENABLE_IFL_ANIMATION 1021
|
||||
#define IDC_SEQ_ENABLE_DECAL_ANIMATION 1022
|
||||
#define IDC_SEQ_FORCE_MORPH_ANIMATION 1023
|
||||
#define IDC_SEQ_FORCE_VIS_ANIMATION 1024
|
||||
#define IDC_SEQ_FORCE_TRANSFORM_ANIMATION 1025
|
||||
#define IDC_STATIC_ABOUT 1025
|
||||
#define IDC_EXPORT_WHOLE 1026
|
||||
#define IDC_SEQ_FORCE_TEXTURE_ANIMATION 1026
|
||||
#define IDC_EXPORT_SEQUENCES 1027
|
||||
#define IDC_CONFIG_SAVE_DEFAULT 1027
|
||||
#define IDC_SEQ_ENABLE_DECAL_FRAME_ANIMATION 1027
|
||||
#define IDC_EXPORT_TEXT 1028
|
||||
#define IDC_ANIMATION_DELTA 1028
|
||||
#define IDC_CONFIG_LOAD 1028
|
||||
#define IDC_SEQ_FORCE_DECAL_ANIMATION 1028
|
||||
#define IDC_ALLOW_EMPTY 1029
|
||||
#define IDC_CONFIG_SAVE 1029
|
||||
#define IDC_RENUMBER 1029
|
||||
#define IDC_BASE_TEXTURE_PATH 1029
|
||||
#define IDC_SEQ_ENABLE_UNIFORM_SCALE_ANIMATION 1029
|
||||
#define IDC_ALLOW_CROSSED 1030
|
||||
#define IDC_COLLAPSE 1030
|
||||
#define IDC_EMBED 1030
|
||||
#define IDC_SEQ_ENABLE_ARBITRARY_SCALE_ANIMATION 1030
|
||||
#define IDC_ALLOW_UNUSED 1031
|
||||
#define IDC_ENABLE_SEQUENCES 1031
|
||||
#define IDC_REGISTER_DETAILS 1031
|
||||
#define IDC_SEQ_FORCE_SCALE_ANIMATION 1031
|
||||
#define IDC_ALLOW_OLD 1032
|
||||
#define IDC_REQUIRE_VICON 1033
|
||||
#define IDC_NODE_STATE_DETAILS 1034
|
||||
#define IDC_ENABLE_TWO_SIDED 1034
|
||||
#define IDC_OBJECT_STATE_DETAILS 1035
|
||||
#define IDC_OBJECT_OFFSETS 1036
|
||||
#define IDC_SEQUENCE_DETAILS 1037
|
||||
#define IDC_SHAPE_HIERARCHY 1038
|
||||
#define IDC_PASS1 1039
|
||||
#define IDC_PASS2 1040
|
||||
#define IDC_PASS3 1041
|
||||
#define IDC_NODE_STATES 1042
|
||||
#define IDC_OBJECT_STATES 1043
|
||||
#define IDC_CONFIG_LOAD_DEFAULT 1044
|
||||
#define IDC_EDIT 1045
|
||||
#define IDC_SPIN 1496
|
||||
#define IDS_TH_3SPACE 40216
|
||||
#define IDS_TH_DTSFILE_LONG 40220
|
||||
#define IDS_TH_DTSFILE_SHORT 40221
|
||||
#define IDS_TH_COPYRIGHT_COMPANY 40223
|
||||
#define IDS_TH_DTSEXP 40229
|
||||
#define IDS_TH_SHAPEEXPORT 40231
|
||||
#define IDS_TH_DTSEXPORTDLL 40232
|
||||
#define IDS_TH_NODATATOEXPORT 40233
|
||||
#define IDS_TH_CANTCREATE 40234
|
||||
#define IDS_TH_WRITEERROR 40235
|
||||
#define IDS_OBJ_TOO_LARGE 40236
|
||||
#define IDS_EXPORT_ERROR 40237
|
||||
#define IDS_TH_AUTHOR 40238
|
||||
#define IDS_DB_SEQUENCE 40239
|
||||
#define IDS_DB_GENERAL 40240
|
||||
#define IDS_SKINHELP_PARAMS 40241
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 114
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1046
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
395
tools/max2dtsExporter/exporter.rc
Executable file
395
tools/max2dtsExporter/exporter.rc
Executable file
@ -0,0 +1,395 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "exporter.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "windows.h"
|
||||
#include "winres.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
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"exporter.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
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_SEQUENCE_PARAMS DIALOG DISCARDABLE 0, 0, 108, 185
|
||||
STYLE WS_CHILD | WS_VISIBLE
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CONTROL "",IDC_SEQ_CYCLIC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
61,12,16,8
|
||||
LTEXT "Cyclic sequence:",IDC_STATIC,3,12,55,8
|
||||
LTEXT "Blend Sequence:",IDC_STATIC,3,45,56,8
|
||||
CONTROL "",IDC_SEQ_BLEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
61,46,11,8
|
||||
LTEXT "Complete cycle:",IDC_STATIC,22,25,51,8
|
||||
CONTROL "",IDC_SEQ_LAST_FIRST_FRAME_SAME,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,80,26,12,8
|
||||
LTEXT "Use frame rate:",IDC_STATIC,3,67,49,8
|
||||
CONTROL "",IDC_SEQ_FRAME_RATE,"CustEdit",WS_TABSTOP,28,80,27,10
|
||||
CONTROL "",IDC_SEQ_NUM_FRAMES,"CustEdit",WS_TABSTOP,28,103,27,10
|
||||
CONTROL "",IDC_SEQ_FRAME_RATE_SPINNER,"SpinnerControl",0x0,63,79,
|
||||
6,11
|
||||
CONTROL "",IDC_SEQ_NUM_FRAMES_SPINNER,"SpinnerControl",0x0,63,
|
||||
102,6,11
|
||||
CONTROL "",IDC_SEQ_USE_FRAME_RATE,"Button",BS_AUTORADIOBUTTON,61,
|
||||
67,10,10
|
||||
CONTROL "",IDC_SEQ_USE_N_FRAMES,"Button",BS_AUTORADIOBUTTON,61,
|
||||
92,10,10
|
||||
LTEXT "Use N frames:",IDC_STATIC,3,92,46,8
|
||||
LTEXT "N=",IDC_STATIC,15,104,10,8
|
||||
LTEXT "or,",IDC_STATIC,74,80,12,11
|
||||
CONTROL "",IDC_SEQ_PRIORITY,"CustEdit",WS_TABSTOP,27,167,27,10
|
||||
CONTROL "",IDC_SEQ_PRIORITY_SPINNER,"SpinnerControl",0x0,63,166,
|
||||
6,11
|
||||
LTEXT "Sequence priority:",IDC_STATIC,3,156,58,8
|
||||
LTEXT "Override duration:",IDC_STATIC,4,123,57,8
|
||||
CONTROL "",IDC_SEQ_DURATION_OVERRIDE,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,62,124,11,8
|
||||
CONTROL "",IDC_SEQ_DURATION,"CustEdit",WS_TABSTOP,29,138,27,10
|
||||
CONTROL "",IDC_SEQ_DURATION_SPINNER,"SpinnerControl",0x0,63,137,
|
||||
6,11
|
||||
END
|
||||
|
||||
IDD_SEQUENCE_PARAMS2 DIALOG DISCARDABLE 0, 0, 108, 103
|
||||
STYLE WS_CHILD | WS_VISIBLE
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
LTEXT "Ignore ground transform:",IDC_STATIC,3,13,78,8
|
||||
CONTROL "",IDC_SEQ_IGNORE_GROUND_TRANSFORM,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,88,13,12,8
|
||||
LTEXT "Use frame rate:",IDC_STATIC,3,37,49,8
|
||||
CONTROL "",IDC_SEQ_GROUND_FRAME_RATE,"CustEdit",WS_TABSTOP,34,51,
|
||||
22,10
|
||||
CONTROL "",IDC_SEQ_NUM_GROUND_FRAMES,"CustEdit",WS_TABSTOP,36,77,
|
||||
20,10
|
||||
CONTROL "",IDC_SEQ_GROUND_FRAME_RATE_SPINNER,"SpinnerControl",
|
||||
0x0,59,51,10,10
|
||||
CONTROL "",IDC_SEQ_NUM_GROUND_FRAMES_SPINNER,"SpinnerControl",
|
||||
0x0,60,77,8,10
|
||||
CONTROL "",IDC_SEQ_USE_GROUND_FRAME_RATE,"Button",
|
||||
BS_AUTORADIOBUTTON,58,38,16,8
|
||||
CONTROL "",IDC_SEQ_USE_N_GROUND_FRAMES,"Button",
|
||||
BS_AUTORADIOBUTTON,57,67,16,8
|
||||
LTEXT "Use N frames:",IDC_STATIC,3,66,46,8
|
||||
LTEXT "or,",IDC_STATIC,75,51,17,12
|
||||
LTEXT "N=",IDC_STATIC,20,79,10,8
|
||||
END
|
||||
|
||||
IDD_SEQUENCE_PARAMS3 DIALOG DISCARDABLE 0, 0, 109, 200
|
||||
STYLE WS_CHILD | WS_VISIBLE
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CONTROL "",IDC_SEQ_ENABLE_MORPH_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,18,16,8
|
||||
CONTROL "",IDC_SEQ_ENABLE_VIS_ANIMATION,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,87,29,16,8
|
||||
CONTROL "",IDC_SEQ_ENABLE_TRANSFORM_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,40,16,8
|
||||
LTEXT "Enable:",IDC_STATIC,4,6,25,8
|
||||
LTEXT "Morph animation:",IDC_STATIC,12,18,55,8
|
||||
LTEXT "Visibility animation:",IDC_STATIC,12,29,59,8
|
||||
LTEXT "Transform animation:",IDC_STATIC,12,40,66,8
|
||||
CONTROL "",IDC_SEQ_FORCE_MORPH_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,130,16,8
|
||||
CONTROL "",IDC_SEQ_FORCE_VIS_ANIMATION,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,87,141,16,8
|
||||
CONTROL "",IDC_SEQ_FORCE_TRANSFORM_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,152,16,8
|
||||
LTEXT "Force:",IDC_STATIC,4,119,21,8
|
||||
LTEXT "Morph animation:",IDC_STATIC,12,130,55,8
|
||||
LTEXT "Visibility animation:",IDC_STATIC,12,141,59,8
|
||||
LTEXT "Transform animation:",IDC_STATIC,12,152,66,8
|
||||
CONTROL "",IDC_SEQ_FORCE_TEXTURE_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,174,16,8
|
||||
LTEXT "Texture animation:",IDC_STATIC,12,174,59,8
|
||||
CONTROL "",IDC_SEQ_ENABLE_TEXTURE_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,73,16,8
|
||||
LTEXT "Texture animation:",IDC_STATIC,12,73,59,8
|
||||
CONTROL "",IDC_SEQ_ENABLE_IFL_ANIMATION,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,87,84,16,8
|
||||
LTEXT "IFL animation:",IDC_STATIC,12,84,45,8
|
||||
CONTROL "",IDC_SEQ_ENABLE_DECAL_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,95,16,8
|
||||
LTEXT "Decal animation:",IDC_STATIC,12,95,54,8
|
||||
CONTROL "",IDC_SEQ_ENABLE_DECAL_FRAME_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,106,16,8
|
||||
LTEXT "Decal-frame animation:",IDC_STATIC,12,106,73,8
|
||||
CONTROL "",IDC_SEQ_FORCE_DECAL_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,185,16,8
|
||||
LTEXT "Decal animation:",IDC_STATIC,12,185,54,8
|
||||
CONTROL "",IDC_SEQ_ENABLE_UNIFORM_SCALE_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,51,16,8
|
||||
LTEXT "Uniform scale anim:",IDC_STATIC,12,51,62,8
|
||||
CONTROL "",IDC_SEQ_ENABLE_ARBITRARY_SCALE_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,62,16,8
|
||||
LTEXT "Arbitrary scale anim:",IDC_STATIC,12,62,64,8
|
||||
CONTROL "",IDC_SEQ_FORCE_SCALE_ANIMATION,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,87,163,16,8
|
||||
LTEXT "Scale animation:",IDC_STATIC,12,163,53,8
|
||||
END
|
||||
|
||||
IDD_UTIL_PANEL1 DIALOG DISCARDABLE 0, 0, 108, 51
|
||||
STYLE WS_CHILD
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CTEXT "About text...",IDC_STATIC_ABOUT,11,2,88,40
|
||||
END
|
||||
|
||||
IDD_UTIL_PANEL2 DIALOG DISCARDABLE 0, 0, 108, 91
|
||||
STYLE WS_CHILD
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CONTROL "",IDC_ANIMATION_DELTA,"CustEdit",WS_TABSTOP,57,50,48,9
|
||||
LTEXT "Animation Delta:",IDC_STATIC,2,50,52,8
|
||||
LTEXT "Collapse Transforms",IDC_STATIC,19,7,84,11
|
||||
CONTROL "",IDC_COLLAPSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,
|
||||
7,8,10
|
||||
LTEXT "Enable Sequence Export",IDC_STATIC,19,21,84,11
|
||||
CONTROL "",IDC_ENABLE_SEQUENCES,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,6,21,8,10
|
||||
CONTROL "",IDC_ENABLE_TWO_SIDED,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,6,35,8,9
|
||||
LTEXT "Enable 2-sided materials",IDC_STATIC,19,35,81,12
|
||||
CONTROL "",IDC_BASE_TEXTURE_PATH,"CustEdit",WS_TABSTOP,9,77,91,9
|
||||
LTEXT "Base Texture Path:",IDC_STATIC,2,66,62,8
|
||||
END
|
||||
|
||||
IDD_UTIL_PANEL3 DIALOG DISCARDABLE 0, 0, 108, 96
|
||||
STYLE WS_CHILD
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CONTROL "",IDC_ALLOW_EMPTY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
5,11,8,9
|
||||
LTEXT "Allow Empty Subtrees",IDC_STATIC,16,11,71,11
|
||||
CONTROL "",IDC_ALLOW_CROSSED,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,5,29,8,9
|
||||
LTEXT "Allow Crossed Details",IDC_STATIC,16,29,71,11
|
||||
CONTROL "",IDC_ALLOW_UNUSED,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,5,46,8,9
|
||||
LTEXT "Allow Unused Meshes",IDC_STATIC,16,46,71,11
|
||||
CONTROL "",IDC_ALLOW_OLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,
|
||||
64,8,9
|
||||
LTEXT "Allow Old Style Sequences",IDC_STATIC,16,64,85,12
|
||||
CONTROL "",IDC_REQUIRE_VICON,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,5,80,8,9
|
||||
LTEXT "Require VICON/BIP",IDC_STATIC,16,80,74,12
|
||||
END
|
||||
|
||||
IDD_UTIL_PANEL4 DIALOG DISCARDABLE 0, 0, 108, 178
|
||||
STYLE WS_CHILD
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CONTROL "",IDC_PASS1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,11,
|
||||
8,9
|
||||
LTEXT "Initial Node Collection",IDC_STATIC,16,11,71,11
|
||||
CONTROL "",IDC_PASS2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,27,
|
||||
8,9
|
||||
LTEXT "Initial Shape Construction",IDC_STATIC,16,27,85,11
|
||||
CONTROL "",IDC_PASS3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,44,
|
||||
8,9
|
||||
LTEXT "Node Culling",IDC_STATIC,16,44,71,11
|
||||
CONTROL "",IDC_NODE_STATES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
5,62,8,9
|
||||
LTEXT "Node States",IDC_STATIC,16,62,85,12
|
||||
CONTROL "",IDC_OBJECT_STATES,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,5,78,8,9
|
||||
LTEXT "Object States",IDC_STATIC,16,78,74,12
|
||||
CONTROL "",IDC_NODE_STATE_DETAILS,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,5,93,8,9
|
||||
LTEXT "Node State Details",IDC_STATIC,16,93,71,11
|
||||
CONTROL "",IDC_OBJECT_STATE_DETAILS,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,5,109,8,9
|
||||
LTEXT "Object State Details",IDC_STATIC,16,109,85,11
|
||||
CONTROL "",IDC_OBJECT_OFFSETS,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,5,126,8,9
|
||||
LTEXT "Object Offsets",IDC_STATIC,16,126,71,11
|
||||
CONTROL "",IDC_SEQUENCE_DETAILS,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,5,143,8,9
|
||||
LTEXT "Sequences",IDC_STATIC,16,143,85,12
|
||||
CONTROL "",IDC_SHAPE_HIERARCHY,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,5,159,8,9
|
||||
LTEXT "Shape Hierarchy",IDC_STATIC,16,159,74,12
|
||||
END
|
||||
|
||||
IDD_UTIL_PANEL5 DIALOG DISCARDABLE 0, 0, 107, 85
|
||||
STYLE WS_CHILD
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CONTROL "Load Default Config",IDC_CONFIG_LOAD_DEFAULT,"CustButton",
|
||||
WS_TABSTOP,7,8,94,13
|
||||
CONTROL "Save As Default Config",IDC_CONFIG_SAVE_DEFAULT,
|
||||
"CustButton",WS_TABSTOP,7,27,94,13
|
||||
CONTROL "Load Config...",IDC_CONFIG_LOAD,"CustButton",WS_TABSTOP,
|
||||
7,46,94,13
|
||||
CONTROL "Save Config...",IDC_CONFIG_SAVE,"CustButton",WS_TABSTOP,
|
||||
7,65,94,13
|
||||
END
|
||||
|
||||
IDD_UTIL_PANEL1B DIALOG DISCARDABLE 0, 0, 108, 123
|
||||
STYLE WS_CHILD
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CONTROL "Whole Shape",IDC_EXPORT_WHOLE,"CustButton",WS_TABSTOP,
|
||||
14,16,80,11
|
||||
CONTROL "Sequences",IDC_EXPORT_SEQUENCES,"CustButton",WS_TABSTOP,
|
||||
14,31,80,11
|
||||
CONTROL "Text Description",IDC_EXPORT_TEXT,"CustButton",
|
||||
WS_TABSTOP,14,46,80,11
|
||||
CONTROL " Export:",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP |
|
||||
WS_GROUP,4,4,28,11
|
||||
LTEXT " General:",IDC_STATIC,4,63,30,10
|
||||
CONTROL "Renumber selection...",IDC_RENUMBER,"CustButton",
|
||||
WS_TABSTOP,14,75,80,11
|
||||
CONTROL "Embed Shape",IDC_EMBED,"CustButton",WS_TABSTOP,14,91,80,
|
||||
11
|
||||
CONTROL "Register Details",IDC_REGISTER_DETAILS,"CustButton",
|
||||
WS_TABSTOP,14,107,80,11
|
||||
END
|
||||
|
||||
IDD_RENUMBER DIALOG DISCARDABLE 0, 0, 187, 55
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Renumber"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,130,7,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,130,24,50,14
|
||||
LTEXT "New number:",IDC_STATIC,7,14,53,12
|
||||
EDITTEXT IDC_EDIT,56,13,67,14,ES_AUTOHSCROLL
|
||||
END
|
||||
|
||||
IDD_SKINHELP_PANEL DIALOG DISCARDABLE 0, 0, 108, 156
|
||||
STYLE WS_CHILD | WS_VISIBLE
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CTEXT "Generated by Plugin AppWizard\nCode && design by\nRavi Karra - Kinetix",
|
||||
IDC_STATIC,7,7,94,36
|
||||
CONTROL "",1490,"CustEdit",WS_TABSTOP,29,114,35,10
|
||||
CONTROL "",IDC_SPIN,"SpinnerControl",0x0,65,114,7,10
|
||||
LTEXT "Spinner Cust Control:",IDC_STATIC,20,102,67,8
|
||||
CTEXT "TODO: Place panel controls here.",IDC_STATIC,15,63,78,
|
||||
19
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO DISCARDABLE
|
||||
BEGIN
|
||||
IDD_UTIL_PANEL2, DIALOG
|
||||
BEGIN
|
||||
RIGHTMARGIN, 107
|
||||
END
|
||||
|
||||
IDD_RENUMBER, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 180
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 48
|
||||
END
|
||||
|
||||
IDD_SKINHELP_PANEL, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 101
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 149
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_TH_3SPACE "3Space"
|
||||
IDS_TH_DTSFILE_LONG "V12 3Space (DTS) File"
|
||||
IDS_TH_DTSFILE_SHORT "V12 DTS File"
|
||||
IDS_TH_COPYRIGHT_COMPANY "Copyright 2001 GarageGames.com"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_TH_DTSEXP "max2dtsExporter"
|
||||
IDS_TH_SHAPEEXPORT "Shape Export"
|
||||
IDS_TH_DTSEXPORTDLL "GarageGames V12 3Space DTS File Export DLL"
|
||||
IDS_TH_NODATATOEXPORT "No data to export"
|
||||
IDS_TH_CANTCREATE "Can't create output file"
|
||||
IDS_TH_WRITEERROR "Write error on file"
|
||||
IDS_OBJ_TOO_LARGE "Object %s is too large to export"
|
||||
IDS_EXPORT_ERROR "Export Error"
|
||||
IDS_TH_AUTHOR "Created by Clark Fagot"
|
||||
IDS_DB_SEQUENCE "Sequence"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_DB_GENERAL "General DTS Objects"
|
||||
IDS_SKINHELP_PARAMS "skin help params"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
648
tools/max2dtsExporter/main.cc
Executable file
648
tools/max2dtsExporter/main.cc
Executable file
@ -0,0 +1,648 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <MAX.H>
|
||||
#pragma pack(pop)
|
||||
|
||||
// NOTE:
|
||||
// if you have problems linking this exporter it is likely you are encountering a
|
||||
// bug in Microsofts include\basetsd.h header.
|
||||
//
|
||||
// The problem is that Visual C++ defines INT_PTR to 'long' when it is
|
||||
// supposed to be defined as an 'int' (on ia32 platforms). You can either
|
||||
// use a supported build environment by updating to the platform SDK, or
|
||||
// you can use the unsupported environment by manually fixing the problem
|
||||
// in the header "On or around line 123 of include\basetsd.h change:
|
||||
//
|
||||
// typedef long INT_PTR, *PINT_PTR;
|
||||
// typedef unsigned long UINT_PTR, *PUINT_PTR;
|
||||
// TO
|
||||
// typedef int INT_PTR, *PINT_PTR;
|
||||
// typedef unsigned int UINT_PTR, *PUINT_PTR;
|
||||
|
||||
#include "max2dtsExporter/exporter.h"
|
||||
#include "max2dtsExporter/sceneEnum.h"
|
||||
#include "core/filestream.h"
|
||||
#include "ts/tsShapeInstance.h"
|
||||
#include "max2dtsExporter/sequence.h"
|
||||
#include "max2dtsExporter/exportUtil.h"
|
||||
#include "max2dtsExporter/skinHelper.h"
|
||||
|
||||
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
|
||||
|
||||
#if defined(TORQUE_DEBUG)
|
||||
const char * const gProgramVersion = "0.900d-beta";
|
||||
#else
|
||||
const char * const gProgramVersion = "0.900r-beta";
|
||||
#endif
|
||||
|
||||
HINSTANCE hInstance;
|
||||
|
||||
S32 gSupressUI = 0;
|
||||
TCHAR maxFile[1024];
|
||||
S32 controlsInit = FALSE;
|
||||
char dllPath[256];
|
||||
char globalConfig[270];
|
||||
|
||||
TCHAR *GetString(S32 id)
|
||||
{
|
||||
static TCHAR buf[256];
|
||||
|
||||
if (hInstance)
|
||||
{
|
||||
return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
const char * days[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
|
||||
const char * months[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
|
||||
|
||||
static S32 Alert(const char * s1, const char * s2, S32 option = MB_OK)
|
||||
{
|
||||
if (gSupressUI)
|
||||
{
|
||||
FileStream fs;
|
||||
fs.open(avar("%smax2difExport.error.log",dllPath),FileStream::ReadWrite);
|
||||
if (fs.getStatus() != Stream::Ok)
|
||||
{
|
||||
fs.close();
|
||||
return -1;
|
||||
}
|
||||
fs.setPosition(fs.getStreamSize());
|
||||
|
||||
// what's the time and date?
|
||||
Platform::LocalTime localTime;
|
||||
Platform::getLocalTime(localTime);
|
||||
char timeBuffer[256];
|
||||
dStrcpy(timeBuffer,avar("%i:%i on %s %s %i",localTime.hour,localTime.min,days[localTime.weekday],months[localTime.month],localTime.monthday));
|
||||
|
||||
// write the error to the log file
|
||||
char buffer[1024];
|
||||
dStrcpy(buffer,avar("Error exporting file \"%s\" at %s:\r\n --> %s\r\n\r\n",maxFile,timeBuffer,s1));
|
||||
fs.writeLine((unsigned char*) buffer);
|
||||
fs.close();
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TSTR str1(s1);
|
||||
TSTR str2(s2);
|
||||
return MessageBox(GetActiveWindow(), str1, str2, option);
|
||||
}
|
||||
}
|
||||
|
||||
static S32 Alert(S32 s1, S32 s2 = IDS_TH_DTSEXP, S32 option = MB_OK)
|
||||
{
|
||||
return Alert(GetString(s1),GetString(s2),option);
|
||||
}
|
||||
|
||||
static S32 Alert(const char * s1, S32 s2 = IDS_TH_DTSEXP, S32 option = MB_OK)
|
||||
{
|
||||
return Alert(s1,GetString(s2),option);
|
||||
}
|
||||
|
||||
const char * GetVersionString()
|
||||
{
|
||||
static char versionString[128];
|
||||
dStrcpy(versionString,avar("Version %s (dts v%i.%.2i)",gProgramVersion, DTS_EXPORTER_CURRENT_VERSION/100, DTS_EXPORTER_CURRENT_VERSION%100));
|
||||
return versionString;
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// Our main plugin class:
|
||||
|
||||
class _Exporter : public SceneExport
|
||||
{
|
||||
char extension[10]; // 'DTS' or 'DSQ'
|
||||
|
||||
public:
|
||||
_Exporter(const char *);
|
||||
~_Exporter();
|
||||
|
||||
S32 ExtCount(); // Number of extensions supported
|
||||
const TCHAR *Ext(S32); // Extension #n
|
||||
const TCHAR *LongDesc(); // Long ASCII description
|
||||
const TCHAR *ShortDesc(); // Short ASCII description
|
||||
const TCHAR *AuthorName(); // ASCII Author name
|
||||
const TCHAR *CopyrightMessage(); // ASCII Copyright message
|
||||
const TCHAR *OtherMessage1(); // Other message #1
|
||||
const TCHAR *OtherMessage2(); // Other message #2
|
||||
U32 Version(); // Version number * 100
|
||||
void ShowAbout(HWND); // Show DLL's "About..." box
|
||||
|
||||
S32 DoExport(const TCHAR *, ExpInterface *, Interface *, int, DWORD);
|
||||
};
|
||||
|
||||
//------------------------------------------------------
|
||||
// Jaguar interface code
|
||||
|
||||
extern void mInstallLibrary_C();
|
||||
namespace Memory
|
||||
{
|
||||
extern bool gAlwaysLogLeaks;
|
||||
};
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
|
||||
{
|
||||
hInstance = hinstDLL;
|
||||
|
||||
if (!controlsInit)
|
||||
{
|
||||
controlsInit = TRUE;
|
||||
|
||||
// 3DS custom controls
|
||||
InitCustomControls(hInstance);
|
||||
|
||||
// Initialize common Windows controls
|
||||
InitCommonControls();
|
||||
|
||||
// install math library (set up function pointers)
|
||||
mInstallLibrary_C();
|
||||
|
||||
// set "factory" default parameter values
|
||||
SceneEnumProc::setInitialDefaults();
|
||||
|
||||
// always log memory leaks -- some of them aren't really leaks,
|
||||
// but we want to see them and we don't want the annoying box asking us
|
||||
// about it...
|
||||
Memory::gAlwaysLogLeaks = true;
|
||||
|
||||
// get DLL path
|
||||
GetModuleFileName(hInstance,dllPath,sizeof(dllPath));
|
||||
char * p = dStrrchr(dllPath,'\\');
|
||||
char * p2 = dStrrchr(dllPath,':');
|
||||
if (p && *p=='\\')
|
||||
*(p+1) = '\0';
|
||||
else if(p2 && *p2==':')
|
||||
*(p2+1) = '\0';
|
||||
else
|
||||
dllPath[0] = '\0';
|
||||
|
||||
// load the global config file if we can find it
|
||||
dStrcpy(globalConfig,dllPath);
|
||||
dStrcpy(globalConfig+dStrlen(globalConfig),"dtsGlobal.cfg");
|
||||
SceneEnumProc::readConfigFile(globalConfig);
|
||||
}
|
||||
|
||||
switch(fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
// defines for setting exporter type and description
|
||||
#define _EXPORTER_CLASS_NAME "Torque Shape Exporter"
|
||||
#define _DTS_EXPORTER_CLASS_ID Class_ID(0x296a4787, 0x2ec557fc)
|
||||
#define _DSQ_EXPORTER_CLASS_ID Class_ID(0x65d74e76, 0x10da4a97)
|
||||
#define _TXT_EXPORTER_CLASS_ID Class_ID(0x6bfb02d7, 0x13860666)
|
||||
#define _EXPORTER_CLASS_SDESC "Torque Shape Exporter"
|
||||
|
||||
// more code for interfacing with max
|
||||
class _DTSClassDesc : public ClassDesc
|
||||
{
|
||||
public:
|
||||
S32 IsPublic() { return 1; }
|
||||
void *Create(BOOL loading = FALSE) { return new _Exporter("DTS"); }
|
||||
const TCHAR *ClassName() { return _EXPORTER_CLASS_NAME; }
|
||||
SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
|
||||
Class_ID ClassID() { return _DTS_EXPORTER_CLASS_ID; }
|
||||
const TCHAR *Category() { return GetString(IDS_TH_SHAPEEXPORT); }
|
||||
};
|
||||
|
||||
// more code for interfacing with max
|
||||
class _DSQClassDesc : public ClassDesc
|
||||
{
|
||||
public:
|
||||
S32 IsPublic() { return 1; }
|
||||
void *Create(BOOL loading = FALSE) { return new _Exporter("DSQ"); }
|
||||
const TCHAR *ClassName() { return _EXPORTER_CLASS_NAME; }
|
||||
SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
|
||||
Class_ID ClassID() { return _DSQ_EXPORTER_CLASS_ID; }
|
||||
const TCHAR *Category() { return GetString(IDS_TH_SHAPEEXPORT); }
|
||||
};
|
||||
|
||||
// more code for interfacing with max
|
||||
class _TXTClassDesc : public ClassDesc
|
||||
{
|
||||
public:
|
||||
S32 IsPublic() { return 1; }
|
||||
void *Create(BOOL loading = FALSE) { return new _Exporter("TXT"); }
|
||||
const TCHAR *ClassName() { return _EXPORTER_CLASS_NAME; }
|
||||
SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
|
||||
Class_ID ClassID() { return _TXT_EXPORTER_CLASS_ID; }
|
||||
const TCHAR *Category() { return GetString(IDS_TH_SHAPEEXPORT); }
|
||||
};
|
||||
|
||||
static _DTSClassDesc _DTSDesc;
|
||||
static _DSQClassDesc _DSQDesc;
|
||||
static _TXTClassDesc _TXTDesc;
|
||||
|
||||
DLLEXPORT const TCHAR *LibDescription()
|
||||
{
|
||||
return GetString(IDS_TH_DTSEXPORTDLL);
|
||||
}
|
||||
|
||||
DLLEXPORT S32 LibNumberClasses()
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
DLLEXPORT ClassDesc *LibClassDesc(S32 i)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
return &_DTSDesc;
|
||||
|
||||
case 1:
|
||||
return &_DSQDesc;
|
||||
|
||||
case 2:
|
||||
return &_TXTDesc;
|
||||
|
||||
case 3:
|
||||
return GetSequenceDesc();
|
||||
|
||||
case 4:
|
||||
return GetExportUtilDesc();
|
||||
|
||||
case 5:
|
||||
return GetSkinHelperDesc();
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Return version so can detect obsolete DLLs
|
||||
DLLEXPORT ULONG LibVersion()
|
||||
{
|
||||
return VERSION_3DSMAX;
|
||||
}
|
||||
|
||||
//
|
||||
// ._DTS export module functions follow:
|
||||
//
|
||||
|
||||
_Exporter::_Exporter(const char * _extension)
|
||||
{
|
||||
dStrcpy(extension,_extension);
|
||||
}
|
||||
|
||||
_Exporter::~_Exporter()
|
||||
{
|
||||
}
|
||||
|
||||
S32 _Exporter::ExtCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Extensions supported for import/export modules
|
||||
const TCHAR *_Exporter::Ext(S32 n)
|
||||
{
|
||||
switch(n)
|
||||
{
|
||||
case 0:
|
||||
return _T(extension);
|
||||
|
||||
default:
|
||||
return _T("");
|
||||
}
|
||||
}
|
||||
|
||||
// Long ASCII description (e.g., "Targa 2.0 Image File")
|
||||
const TCHAR *_Exporter::LongDesc()
|
||||
{
|
||||
return GetString(IDS_TH_DTSFILE_LONG);
|
||||
}
|
||||
|
||||
// Short ASCII description (e.g., "Targa")
|
||||
const TCHAR *_Exporter::ShortDesc()
|
||||
{
|
||||
return _EXPORTER_CLASS_SDESC;
|
||||
}
|
||||
|
||||
// ASCII Author name
|
||||
const TCHAR *_Exporter::AuthorName()
|
||||
{
|
||||
return GetString(IDS_TH_AUTHOR);
|
||||
}
|
||||
|
||||
// ASCII Copyright message
|
||||
const TCHAR *_Exporter::CopyrightMessage()
|
||||
{
|
||||
return GetString(IDS_TH_COPYRIGHT_COMPANY);
|
||||
}
|
||||
|
||||
// Other message #1
|
||||
const TCHAR *_Exporter::OtherMessage1()
|
||||
{
|
||||
return _T("");
|
||||
}
|
||||
|
||||
// Other message #2
|
||||
const TCHAR *_Exporter::OtherMessage2()
|
||||
{
|
||||
return _T("");
|
||||
}
|
||||
|
||||
// Version number * 100 (i.e. v3.01 = 301)
|
||||
U32 _Exporter::Version()
|
||||
{
|
||||
return DTS_EXPORTER_CURRENT_VERSION;
|
||||
}
|
||||
|
||||
// Optional
|
||||
void _Exporter::ShowAbout(HWND hWnd)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
// be more thourough about this later...
|
||||
U32 saveDumpMask;
|
||||
bool saveEnableSequences;
|
||||
bool saveCollapse;
|
||||
bool saveAllowEmptySubtrees;
|
||||
bool saveAllowCrossedDetails;
|
||||
bool saveAllowUnusedMeshes;
|
||||
bool saveViconNeeded;
|
||||
bool saveAllowOldSequences;
|
||||
F32 saveAnimationDelta;
|
||||
F32 saveMaxFrameRate;
|
||||
S32 saveT2AutoDetail;
|
||||
|
||||
void saveConfig()
|
||||
{
|
||||
saveDumpMask = dumpMask;
|
||||
saveEnableSequences = enableSequences;
|
||||
saveCollapse = transformCollapse;
|
||||
saveAllowEmptySubtrees = allowEmptySubtrees;
|
||||
saveAllowCrossedDetails = allowCrossedDetails;
|
||||
saveAllowUnusedMeshes = allowUnusedMeshes;
|
||||
saveViconNeeded = viconNeeded;
|
||||
saveAllowOldSequences = allowOldSequences;
|
||||
saveAnimationDelta = animationDelta;
|
||||
saveMaxFrameRate = maxFrameRate;
|
||||
saveT2AutoDetail = t2AutoDetail;
|
||||
}
|
||||
|
||||
void restoreConfig()
|
||||
{
|
||||
dumpMask = saveDumpMask;
|
||||
enableSequences = saveEnableSequences;
|
||||
transformCollapse = saveCollapse;
|
||||
allowEmptySubtrees = saveAllowEmptySubtrees;
|
||||
allowCrossedDetails = saveAllowCrossedDetails;
|
||||
allowUnusedMeshes = saveAllowUnusedMeshes;
|
||||
viconNeeded = saveViconNeeded;
|
||||
allowOldSequences = saveAllowOldSequences;
|
||||
animationDelta = saveAnimationDelta;
|
||||
maxFrameRate = saveMaxFrameRate;
|
||||
t2AutoDetail = saveT2AutoDetail;
|
||||
}
|
||||
|
||||
S32 cheapSemaphore = 0;
|
||||
|
||||
S32 _dts_save(const TCHAR *fname, ExpInterface *ei, Interface *gi)
|
||||
{
|
||||
if (cheapSemaphore)
|
||||
{
|
||||
Alert("One export at a time: Export code not re-entrant.");
|
||||
return 1;
|
||||
}
|
||||
cheapSemaphore = 1;
|
||||
|
||||
char filename[1024];
|
||||
dStrcpy(filename,fname);
|
||||
char * ch = filename;
|
||||
while (*ch!='\0')
|
||||
{
|
||||
*ch = tolower(*ch);
|
||||
ch++;
|
||||
}
|
||||
|
||||
SceneEnumProc myScene;
|
||||
dStrcpy(maxFile,gi->GetCurFilePath());
|
||||
|
||||
//-----------------------------------------------
|
||||
// read in the config file...
|
||||
char configFilename[256];
|
||||
dStrcpy(configFilename,maxFile);
|
||||
char * p = dStrrchr(configFilename,'\\');
|
||||
char * p2 = dStrrchr(configFilename,':');
|
||||
if (p && *p=='\\')
|
||||
dStrcpy(p+1,"*.cfg");
|
||||
else if (p2 && *p2==':')
|
||||
dStrcpy(p2+1,"*.cfg");
|
||||
else
|
||||
dStrcpy(configFilename,"*.cfg");
|
||||
const char * error = myScene.readConfigFile(configFilename);
|
||||
if (error)
|
||||
myScene.setExportError(error);
|
||||
|
||||
//-----------------------------------------------
|
||||
// Error?
|
||||
if (myScene.isExportError())
|
||||
{
|
||||
Alert(myScene.getExportError());
|
||||
cheapSemaphore = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// create dump file...
|
||||
myScene.startDump(filename,maxFile);
|
||||
|
||||
//-----------------------------------------------
|
||||
// read config file again so we have a record of it...
|
||||
myScene.readConfigFile(configFilename);
|
||||
|
||||
//-----------------------------------------------
|
||||
// Error?
|
||||
if (myScene.isExportError())
|
||||
{
|
||||
Alert(myScene.getExportError());
|
||||
cheapSemaphore = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// tweak some parameters depending on export type...
|
||||
if (dStrstr((const char*)filename,".dsq"))
|
||||
{
|
||||
// we're exporting sequences, so turn this on
|
||||
if (!enableSequences)
|
||||
{
|
||||
enableSequences = true;
|
||||
SceneEnumProc::printDump(PDAlways,"\r\nEnabling \"Param::SequenceExport\" (doing *.dsq export).\r\n");
|
||||
}
|
||||
SceneEnumProc::exportType = 's'; // sequence
|
||||
}
|
||||
if (dStrstr((const char*)filename,".txt"))
|
||||
{
|
||||
// doing a text file dump -- export everything
|
||||
if (!enableSequences)
|
||||
{
|
||||
enableSequences = true;
|
||||
SceneEnumProc::printDump(PDAlways,"\r\nEnabling \"Param::SequenceExport\" (doing *.txt export).\r\n");
|
||||
|
||||
}
|
||||
if (transformCollapse)
|
||||
{
|
||||
transformCollapse = false;
|
||||
SceneEnumProc::printDump(PDAlways,"\r\nDisabling \"Param::CollapseTransforms\" (doing *.txt export).\r\n");
|
||||
}
|
||||
SceneEnumProc::exportType = 't'; // text
|
||||
}
|
||||
if (dStrstr((const char*)filename,".dts"))
|
||||
SceneEnumProc::exportType = 'w'; // whole shape
|
||||
|
||||
//-----------------------------------------------
|
||||
// Error?
|
||||
if (myScene.isExportError())
|
||||
{
|
||||
Alert(myScene.getExportError());
|
||||
cheapSemaphore = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// Get the nodes we're interested in!
|
||||
// We also do some checking to make sure everything
|
||||
// we need is present ... if something is missing,
|
||||
// an error will be returned.
|
||||
myScene.enumScene(ei->theScene);
|
||||
|
||||
//-----------------------------------------------
|
||||
// Error?
|
||||
if (myScene.isExportError())
|
||||
{
|
||||
Alert(myScene.getExportError());
|
||||
cheapSemaphore = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// Any useful nodes?
|
||||
if (myScene.isEmpty())
|
||||
{
|
||||
Alert("No data to export");
|
||||
cheapSemaphore = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// make sure we get rid of target file before opening it
|
||||
// otherwise, it'll never shrink
|
||||
File zap;
|
||||
zap.open(filename,File::Write);
|
||||
zap.close();
|
||||
|
||||
//-----------------------------------------------
|
||||
// open a file to save the exported shape to:
|
||||
FileStream file;
|
||||
file.open(filename,FileStream::Write);
|
||||
if( file.getStatus() != Stream::Ok )
|
||||
{
|
||||
Alert(IDS_TH_CANTCREATE);
|
||||
cheapSemaphore = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// actually do the export:
|
||||
myScene.processScene();
|
||||
|
||||
//-----------------------------------------------
|
||||
// Error?
|
||||
if (myScene.isExportError())
|
||||
{
|
||||
Alert(myScene.getExportError());
|
||||
file.close();
|
||||
cheapSemaphore = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// now save the shape
|
||||
TSShape * pShape = myScene.getShape();
|
||||
|
||||
if (dStrstr((const char*)filename,".dts"))
|
||||
pShape->write(&file);
|
||||
else if (dStrstr((const char*)filename,".dsq"))
|
||||
pShape->exportSequences(&file);
|
||||
else if (dStrstr((const char*)filename,".txt"))
|
||||
myScene.exportTextFile(&file);
|
||||
|
||||
//-----------------------------------------------
|
||||
// close the file and report any problems:
|
||||
|
||||
if( file.getStatus() != Stream::Ok )
|
||||
{
|
||||
Alert(IDS_TH_WRITEERROR);
|
||||
file.close();
|
||||
remove(filename);
|
||||
cheapSemaphore = 0;
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
file.close();
|
||||
|
||||
//-----------------------------------------------
|
||||
// write the shape out to dump file
|
||||
if (PDShapeHierarchy & dumpMask && dStrstr((const char*)filename,".dts"))
|
||||
{
|
||||
// write out the structure of the newly created shape
|
||||
// but read it from the file first...
|
||||
if (!SceneEnumProc::dumpShape(filename))
|
||||
{
|
||||
Alert(avar("Error opening created file \"%s\".",filename));
|
||||
file.close();
|
||||
cheapSemaphore = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
cheapSemaphore = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
S32 _Exporter::DoExport(const TCHAR *filename,ExpInterface *ei,Interface *gi, S32 supressUI, DWORD)
|
||||
{
|
||||
gSupressUI = supressUI;
|
||||
|
||||
// so we can go back to defaults when we're done
|
||||
saveConfig();
|
||||
|
||||
S32 status;
|
||||
|
||||
status = _dts_save(filename, ei, gi);
|
||||
|
||||
restoreConfig();
|
||||
|
||||
if(status == 0)
|
||||
return 1; // Dialog cancelled
|
||||
|
||||
if(status < 0)
|
||||
return 0; // Real, honest-to-goodness error
|
||||
|
||||
return status;
|
||||
}
|
748
tools/max2dtsExporter/maxUtil.cc
Executable file
748
tools/max2dtsExporter/maxUtil.cc
Executable file
@ -0,0 +1,748 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "max2dtsExporter/maxUtil.h"
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <decomp.h>
|
||||
#include <dummy.h>
|
||||
#include <ISkin.h>
|
||||
#include <modstack.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
#include "Core/tVector.h"
|
||||
|
||||
// Special for biped stuff -- class id in no header, so we just def it here
|
||||
// NOTE/WARNING: This could change with Character Studio updates
|
||||
#define BipedObjectClassID Class_ID(37157,0)
|
||||
|
||||
Point3F & Point3ToPoint3F(Point3 & p3, Point3F & p3f)
|
||||
{
|
||||
p3f.x = p3.x;
|
||||
p3f.y = p3.y;
|
||||
p3f.z = p3.z;
|
||||
return p3f;
|
||||
}
|
||||
|
||||
void convertToTransform(Matrix3 & mat, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale)
|
||||
{
|
||||
AffineParts parts;
|
||||
decomp_affine(mat,&parts);
|
||||
Point3ToPoint3F(parts.t,trans);
|
||||
rot.set(QuatF(parts.q[0],parts.q[1],parts.q[2],parts.q[3]));
|
||||
srot.set(QuatF(parts.u[0],parts.u[1],parts.u[2],parts.u[3]));
|
||||
Point3ToPoint3F(parts.k,scale);
|
||||
}
|
||||
|
||||
MatrixF & convertToMatrixF(Matrix3 & mat3,MatrixF &matf)
|
||||
{
|
||||
matf.identity();
|
||||
Point3F x,y,z,p;
|
||||
Point3 x3 = mat3 * Point3(1.0f,0.0f,0.0f);
|
||||
Point3 y3 = mat3 * Point3(0.0f,1.0f,0.0f);
|
||||
Point3 z3 = mat3 * Point3(0.0f,0.0f,1.0f);
|
||||
Point3 p3 = mat3 * Point3(0.0f,0.0f,0.0f);
|
||||
x = Point3ToPoint3F(x3,x);
|
||||
y = Point3ToPoint3F(y3,y);
|
||||
z = Point3ToPoint3F(z3,z);
|
||||
p = Point3ToPoint3F(p3,p);
|
||||
x -= p;
|
||||
y -= p;
|
||||
z -= p;
|
||||
matf.setColumn(0,x);
|
||||
matf.setColumn(1,y);
|
||||
matf.setColumn(2,z);
|
||||
matf.setColumn(3,p);
|
||||
return matf;
|
||||
}
|
||||
|
||||
void getNodeTransform(INode *pNode, S32 time, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale)
|
||||
{
|
||||
Matrix3 nodeMat = pNode->GetNodeTM( time );
|
||||
convertToTransform(nodeMat,rot,trans,srot,scale);
|
||||
}
|
||||
|
||||
TriObject * getTriObject( INode *pNode, S32 time, S32 multiResVerts, bool & deleteIt)
|
||||
{
|
||||
TriObject * tri = NULL;
|
||||
IParamBlock * paramBlock = NULL;
|
||||
|
||||
// if we're a multiRes object, dial us down
|
||||
if (multiResVerts>0)
|
||||
{
|
||||
Animatable * obj = (Animatable*)pNode->GetObjectRef();
|
||||
|
||||
for (S32 i=0; i<obj->NumSubs(); i++)
|
||||
{
|
||||
if (!dStrcmp(obj->SubAnimName(i),"MultiRes"))
|
||||
{
|
||||
paramBlock = (IParamBlock*)obj->SubAnim(i)->SubAnim(0);
|
||||
|
||||
Interval range = pNode->GetTimeRange(TIMERANGE_ALL|TIMERANGE_CHILDNODES|TIMERANGE_CHILDANIMS);
|
||||
paramBlock->SetValue(0,time,multiResVerts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the object can't convert to a tri-mesh, eval world state to
|
||||
// get an object that can:
|
||||
const ObjectState &os = pNode->EvalWorldState(time);
|
||||
|
||||
if ( os.obj->CanConvertToType(triObjectClassID) )
|
||||
tri = (TriObject *)os.obj->ConvertToType( time, triObjectClassID );
|
||||
|
||||
deleteIt = (tri && (tri != os.obj));
|
||||
|
||||
return tri;
|
||||
}
|
||||
|
||||
F32 findVolume(INode * pNode, S32 & polyCount)
|
||||
{
|
||||
bool deleteTri;
|
||||
TriObject * tri = getTriObject(pNode,DEFAULT_TIME,-1,deleteTri);
|
||||
if (!tri)
|
||||
{
|
||||
polyCount=0;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
Mesh & mesh = tri->mesh;
|
||||
polyCount = mesh.getNumFaces();
|
||||
Box3F bounds;
|
||||
bounds.min.set( 10E30f, 10E30f, 10E30f);
|
||||
bounds.max.set(-10E30f,-10E30f,-10E30f);
|
||||
for (S32 i=0; i<mesh.numVerts; i++)
|
||||
{
|
||||
Point3F v = Point3ToPoint3F(mesh.verts[i],v);
|
||||
bounds.min.setMin(v);
|
||||
bounds.max.setMax(v);
|
||||
}
|
||||
if (deleteTri)
|
||||
delete tri;
|
||||
return (bounds.max.x-bounds.min.x)*(bounds.max.y-bounds.min.y)*(bounds.max.z-bounds.min.z);
|
||||
}
|
||||
|
||||
void findSkinData(INode * pNode, ISkin **skin, ISkinContextData ** skinData)
|
||||
{
|
||||
// till proven otherwise...
|
||||
*skin = NULL;
|
||||
*skinData = NULL;
|
||||
|
||||
// Get object from node. Abort if no object.
|
||||
Object* obj = pNode->GetObjectRef();
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
Modifier * mod = NULL;
|
||||
|
||||
// Is derived object ?
|
||||
S32 i;
|
||||
while (obj->SuperClassID() == GEN_DERIVOB_CLASS_ID)
|
||||
{
|
||||
IDerivedObject* dobj = (IDerivedObject*) obj;
|
||||
// Iterate over all entries of the modifier stack.
|
||||
for (i=0;i<dobj->NumModifiers();i++)
|
||||
if (dobj->GetModifier(i)->ClassID() == SKIN_CLASSID)
|
||||
break;
|
||||
|
||||
if (i!=dobj->NumModifiers())
|
||||
{
|
||||
mod = dobj->GetModifier(i);
|
||||
break;
|
||||
}
|
||||
obj = dobj->GetObjRef();
|
||||
}
|
||||
if (!mod)
|
||||
return;
|
||||
*skin = (ISkin*) mod->GetInterface(I_SKIN);
|
||||
if (!*skin)
|
||||
return;
|
||||
*skinData = (*skin)->GetContextInterface(pNode);
|
||||
if (!*skinData)
|
||||
*skin=NULL; // return both or neither
|
||||
}
|
||||
|
||||
bool hasSkin(INode * pNode)
|
||||
{
|
||||
ISkin * skin;
|
||||
ISkinContextData * skinData;
|
||||
findSkinData(pNode,&skin,&skinData);
|
||||
return skin != NULL;
|
||||
}
|
||||
|
||||
bool hasMesh(INode * pNode)
|
||||
{
|
||||
ObjectState os = pNode->EvalWorldState(0);
|
||||
return( os.obj->CanConvertToType(triObjectClassID) && !(os.obj->ClassID() == BipedObjectClassID) );
|
||||
}
|
||||
|
||||
void zapScale(Matrix3 & mat)
|
||||
{
|
||||
AffineParts parts;
|
||||
decomp_affine(mat,&parts);
|
||||
|
||||
// now put the matrix back together again without the scale:
|
||||
// mat = mat.rot * mat.pos
|
||||
mat.IdentityMatrix();
|
||||
mat.PreTranslate(parts.t);
|
||||
PreRotateMatrix(mat,parts.q);
|
||||
}
|
||||
|
||||
Matrix3 & getLocalNodeMatrix(INode *pNode, INode *parent, S32 time, Matrix3 & matrix, AffineParts & a10, AffineParts & a20)
|
||||
{
|
||||
// Here's the story: the default transforms have no scale. In order to account for scale, the
|
||||
// scale at the default time is folded into the object offset (which is multiplied into the points
|
||||
// before exporting). Because of this, the local transform at a given time must take into account
|
||||
// the scale of the parent and child node at time 0 in addition to the current time. In particular,
|
||||
// the world transform at a given time is WT(time) = inverse(Tscale(0)) * T(time)
|
||||
// Note: above formula is max style. Torque style would have the order reveresed. :(
|
||||
|
||||
// in order to avoid recomputing matrix at default time over and over, we assume that the first request
|
||||
// for the matrix will be at the default time, and thereafter, we will pass that matrix in and reuse it...
|
||||
Matrix3 m1 = pNode->GetNodeTM(time);
|
||||
Matrix3 m2 = parent ? parent->GetNodeTM(time) : Matrix3(true);
|
||||
if (time==DEFAULT_TIME)
|
||||
{
|
||||
decomp_affine(m1,&a10);
|
||||
decomp_affine(m2,&a20);
|
||||
}
|
||||
|
||||
// build the inverse scale matrices
|
||||
Matrix3 stretchRot10,stretchRot20;
|
||||
Point3 sfactor10, sfactor20;
|
||||
Matrix3 invScale10, invScale20;
|
||||
a10.u.MakeMatrix(stretchRot10);
|
||||
a20.u.MakeMatrix(stretchRot20);
|
||||
sfactor10 = Point3(a10.f/a10.k.x,a10.f/a10.k.y,a10.f/a10.k.z);
|
||||
sfactor20 = Point3(a20.f/a20.k.x,a20.f/a20.k.y,a20.f/a20.k.z);
|
||||
invScale10 = Inverse(stretchRot10) * ScaleMatrix(sfactor10) * stretchRot10;
|
||||
invScale20 = Inverse(stretchRot20) * ScaleMatrix(sfactor20) * stretchRot20;
|
||||
|
||||
// build world transforms
|
||||
m1 = invScale10 * m1;
|
||||
m2 = invScale20 * m2;
|
||||
|
||||
// build local transform
|
||||
matrix = m1 * Inverse(m2);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
void getLocalNodeTransform(INode *pNode, INode *parent, AffineParts & child0, AffineParts & parent0, S32 time, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale)
|
||||
{
|
||||
Matrix3 local;
|
||||
getLocalNodeMatrix(pNode,parent,time,local,parent0,child0);
|
||||
convertToTransform(local,rot,trans,srot,scale);
|
||||
}
|
||||
|
||||
void getBlendNodeTransform(INode *pNode, INode *parent, AffineParts & child0, AffineParts & parent0, S32 time, S32 referenceTime, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale)
|
||||
{
|
||||
Matrix3 m1;
|
||||
Matrix3 m2;
|
||||
|
||||
getLocalNodeMatrix(pNode, parent, referenceTime, m1, child0, parent0);
|
||||
getLocalNodeMatrix(pNode, parent, time, m2, child0, parent0);
|
||||
m1 = Inverse(m1);
|
||||
m2 *= m1;
|
||||
convertToTransform(m2, rot,trans,srot,scale);
|
||||
}
|
||||
|
||||
void computeObjectOffset(INode * pNode, Matrix3 & mat)
|
||||
{
|
||||
// compute the object offset transform...
|
||||
// this will be applied to all the verts of the meshes...
|
||||
// we grab this straight from the node, but we also
|
||||
// multiply in any scaling on the node transform because
|
||||
// the scaling will be stripped out when making a tsshape
|
||||
|
||||
Matrix3 nodeMat = pNode->GetNodeTM(DEFAULT_TIME);
|
||||
zapScale(nodeMat);
|
||||
nodeMat = Inverse(nodeMat);
|
||||
|
||||
mat = pNode->GetObjTMAfterWSM(DEFAULT_TIME);
|
||||
mat *= nodeMat;
|
||||
}
|
||||
|
||||
void getDeltaTransform(INode * pNode, S32 time1, S32 time2, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale)
|
||||
{
|
||||
Matrix3 m1 = pNode->GetNodeTM(time2);
|
||||
Matrix3 m2 = pNode->GetNodeTM(time1);
|
||||
m2 = Inverse(m2);
|
||||
m1 *= m2;
|
||||
convertToTransform(m1,rot,trans,srot,scale);
|
||||
}
|
||||
|
||||
bool isVis(INode * pNode, S32 time)
|
||||
{
|
||||
return pNode->GetVisibility(time) > 0.0000001f;
|
||||
}
|
||||
|
||||
F32 getVisValue(INode * pNode, S32 time)
|
||||
{
|
||||
return pNode->GetVisibility(time);
|
||||
}
|
||||
|
||||
bool animatesVis(INode * pNode, const Interval & range, bool & error)
|
||||
{
|
||||
// running error...exit if already encountered an error
|
||||
if (error)
|
||||
return false;
|
||||
|
||||
F32 startVis = getVisValue(pNode,range.Start());
|
||||
for (S32 i=range.Start()+1; i<=range.End(); i++)
|
||||
if (mFabs(startVis-getVisValue(pNode,i))>0.01f)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool animatesFrame(INode * pNode, const Interval & range, bool & error)
|
||||
{
|
||||
// running error...exit if already encountered an error
|
||||
if (error)
|
||||
return false;
|
||||
|
||||
bool deleteIt;
|
||||
TriObject * tri = getTriObject(pNode,range.Start(),-1,deleteIt);
|
||||
if (!tri)
|
||||
{
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Interval ivalid;
|
||||
ivalid = tri->ChannelValidity(range.Start(), GEOM_CHAN_NUM);
|
||||
|
||||
if (deleteIt)
|
||||
tri->DeleteMe();
|
||||
|
||||
return (ivalid.Start() > range.Start() || ivalid.End() < range.End());
|
||||
}
|
||||
|
||||
bool animatesMatFrame(INode * pNode, const Interval & range, bool & error)
|
||||
{
|
||||
// running error...exit if already encountered an error
|
||||
if (error)
|
||||
return false;
|
||||
|
||||
|
||||
bool deleteIt;
|
||||
TriObject * tri = getTriObject(pNode,range.Start(),-1,deleteIt);
|
||||
if (!tri)
|
||||
{
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Interval ivalid;
|
||||
ivalid = tri->ChannelValidity(range.Start(), TEXMAP_CHAN_NUM);
|
||||
|
||||
if (deleteIt)
|
||||
tri->DeleteMe();
|
||||
|
||||
return (ivalid.Start() > range.Start() || ivalid.End() < range.End());
|
||||
}
|
||||
|
||||
bool isdigit(char ch)
|
||||
{
|
||||
return (ch>='0' && ch<='9');
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// If 's' ends in a number, chopNum returns
|
||||
// a pointer to first digit in this number.
|
||||
// If not, then returns pointer to '\0'
|
||||
// at end of name or first of any trailing
|
||||
// spaces.
|
||||
char * chopNum(char * s)
|
||||
{
|
||||
if (s==NULL)
|
||||
return NULL;
|
||||
|
||||
char * p = s + dStrlen(s);
|
||||
|
||||
if (p==s)
|
||||
return s;
|
||||
p--;
|
||||
|
||||
// trim spaces from the end
|
||||
while (p!=s && *p==' ')
|
||||
p--;
|
||||
|
||||
// back up until we reach a non-digit
|
||||
// gotta be better way than this...
|
||||
if (isdigit(*p))
|
||||
do
|
||||
{
|
||||
if (p--==s)
|
||||
return p+1;
|
||||
} while (isdigit(*p));
|
||||
|
||||
// allow negative numbers
|
||||
if (*p=='-')
|
||||
p--;
|
||||
|
||||
// trim spaces separating name and number
|
||||
while (*p==' ')
|
||||
{
|
||||
p--;
|
||||
if (p==s)
|
||||
return p;
|
||||
}
|
||||
|
||||
// return first space if there was one,
|
||||
// o.w. return first digit
|
||||
return p+1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// separates nodes names into base name
|
||||
// and detail number
|
||||
char * chopTrailingNumber(const char * fullName, S32 & size)
|
||||
{
|
||||
if (!fullName)
|
||||
{
|
||||
size = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * buffer = dStrdup(fullName);
|
||||
char * p = chopNum(buffer);
|
||||
if (*p=='\0')
|
||||
{
|
||||
size = -1;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
size = dAtoi(p);
|
||||
*p='\0'; // terminate string
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// returns a list of detail levels of this shape...grabs meshes off shape
|
||||
// and finds meshes on root level with same name but different trailing
|
||||
// detail number (i.e., head32 on shape, head16 at root, leads to detail
|
||||
// levels 32 and 16).
|
||||
void findDetails(INode * base, INode * root, Vector<S32> & details)
|
||||
{
|
||||
S32 i,j,k;
|
||||
|
||||
// run through all the descendents of this node
|
||||
// and look for numbers indicating detail levels
|
||||
Vector<INode*> nodeStack;
|
||||
nodeStack.push_back(base);
|
||||
while (!nodeStack.empty())
|
||||
{
|
||||
INode * node = nodeStack.last();
|
||||
nodeStack.pop_back();
|
||||
if (hasMesh(node))
|
||||
{
|
||||
// have a mesh...a little obscure below:
|
||||
// add # of this mesh + any mesh w/ same
|
||||
// name on the root level to details vector
|
||||
S32 detailSize;
|
||||
char * baseName = chopTrailingNumber(node->GetName(),detailSize);
|
||||
INode * meshNode = node;
|
||||
for (j=-1;j<root->NumberOfChildren();j++)
|
||||
{
|
||||
if (j>=0)
|
||||
meshNode = root->GetChildNode(j);
|
||||
if (!hasMesh(meshNode))
|
||||
continue;
|
||||
char * meshName = chopTrailingNumber(meshNode->GetName(),detailSize);
|
||||
if (!dStricmp(baseName,meshName))
|
||||
{
|
||||
for (k=0; k<details.size(); k++)
|
||||
if (detailSize==details[k])
|
||||
break;
|
||||
if (k==details.size())
|
||||
details.push_back(detailSize);
|
||||
}
|
||||
dFree(meshName);
|
||||
}
|
||||
dFree(baseName);
|
||||
}
|
||||
for (j=0; j<node->NumberOfChildren();j++)
|
||||
nodeStack.push_back(node->GetChildNode(j));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// find selected subtrees (nodes on root level only) and embed in subtree of
|
||||
// the style the exporter looks for:
|
||||
// Root
|
||||
// |
|
||||
// |-base
|
||||
// |-start
|
||||
// | |
|
||||
// | |-<selected node 1>
|
||||
// | | .
|
||||
// | | .
|
||||
// | |-<selected node N>
|
||||
// |
|
||||
// |-detail 1
|
||||
// | .
|
||||
// | .
|
||||
// |-detail N
|
||||
void embedSubtree(Interface * ip)
|
||||
{
|
||||
S32 i,j,k;
|
||||
|
||||
// make dummy node named baseName
|
||||
TSTR baseName("base");
|
||||
ip->MakeNameUnique(baseName);
|
||||
INode * base = ip->CreateObjectNode(new DummyObject);
|
||||
base->SetName(baseName);
|
||||
|
||||
// make dummy node named startName
|
||||
TSTR startName("start");
|
||||
ip->MakeNameUnique(startName);
|
||||
INode * start = ip->CreateObjectNode(new DummyObject);
|
||||
start->SetName(startName);
|
||||
|
||||
// link later to former
|
||||
base->AttachChild(start);
|
||||
|
||||
Vector<S32> details;
|
||||
|
||||
// loop through selection set, link to start (only if child of root)
|
||||
S32 count = ip->GetSelNodeCount();
|
||||
INode * root = ip->GetRootNode();
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
INode * node = ip->GetSelNode(i);
|
||||
if (!node->GetParentNode()->IsRootNode())
|
||||
continue;
|
||||
start->AttachChild(node);
|
||||
|
||||
findDetails(node,root,details);
|
||||
}
|
||||
|
||||
// now create detail markers
|
||||
for (i=0; i<details.size();i++)
|
||||
{
|
||||
char detailName[20];
|
||||
INode * detailNode = ip->CreateObjectNode(new DummyObject);
|
||||
dSprintf(detailName,20,"detail%i",details[i]);
|
||||
detailNode->SetName(detailName);
|
||||
base->AttachChild(detailNode);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void registerDetails(Interface * ip)
|
||||
{
|
||||
S32 i,j,k;
|
||||
|
||||
// loop through selection set, only care about nodes off root
|
||||
S32 count = ip->GetSelNodeCount();
|
||||
INode * root = ip->GetRootNode();
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
INode * node = ip->GetSelNode(i);
|
||||
if (!node->GetParentNode()->IsRootNode())
|
||||
continue;
|
||||
|
||||
Vector<S32> details;
|
||||
|
||||
// search branches of tree for meshes and find their details
|
||||
for (j=0; j<node->NumberOfChildren(); j++)
|
||||
{
|
||||
INode * child = node->GetChildNode(j);
|
||||
if (child->NumberOfChildren()>0)
|
||||
findDetails(child,root,details);
|
||||
}
|
||||
|
||||
// go through children of base node and cull detail numbers
|
||||
// that don't need to be added (because detail marker already
|
||||
// present)
|
||||
for (j=0; j<node->NumberOfChildren(); j++)
|
||||
{
|
||||
INode * child = node->GetChildNode(j);
|
||||
if (child->NumberOfChildren()==0)
|
||||
{
|
||||
// look for #
|
||||
S32 detailSize;
|
||||
char * baseName = chopTrailingNumber(child->GetName(),detailSize);
|
||||
dFree(baseName);
|
||||
for (k=0;k<details.size();k++)
|
||||
{
|
||||
if (details[k]==detailSize)
|
||||
{
|
||||
// found it
|
||||
details.erase(k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// items left in details list are unique -- add markers
|
||||
for (j=0;j<details.size();j++)
|
||||
{
|
||||
char detailName[20];
|
||||
INode * detailNode = ip->CreateObjectNode(new DummyObject);
|
||||
dSprintf(detailName,20,"detail%i",details[j]);
|
||||
detailNode->SetName(detailName);
|
||||
node->AttachChild(detailNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void renumberNodes(Interface * ip, S32 newSize)
|
||||
{
|
||||
S32 i, count = ip->GetSelNodeCount();
|
||||
char newName[128];
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
INode * node = ip->GetSelNode(i);
|
||||
S32 oldSize;
|
||||
char * baseName = chopTrailingNumber(node->GetName(),oldSize);
|
||||
dSprintf(newName,128,"%s%i",baseName,newSize);
|
||||
node->SetName(newName);
|
||||
dFree(baseName);
|
||||
}
|
||||
}
|
||||
|
||||
// this version of doDot used by m_pointInPoly
|
||||
inline float doDot(F32 v1x, F32 v1y, F32 v2x, F32 v2y, F32 px, F32 py)
|
||||
{
|
||||
return (v1x-px) * (v1y-v2y) +
|
||||
(v1y-py) * (v2x-v1x);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// pointInPoly returns true if point is inside poly defined by verts on plane w/
|
||||
// normal "normal" -- based on m_pointInTriangle.
|
||||
//------------------------------------------------------------------------------------
|
||||
bool pointInPoly(const Point3F & point,
|
||||
const Point3F & normal,
|
||||
const Point3F * verts,
|
||||
U32 n)
|
||||
{
|
||||
F32 thisDot, lastDot=0;
|
||||
U32 i;
|
||||
|
||||
// we can ignore one of the dimensions because all points are on the same plane...
|
||||
if (mFabs(normal.y)>mFabs(normal.x)&&mFabs(normal.y)>mFabs(normal.z))
|
||||
{
|
||||
// drop y coord
|
||||
thisDot = doDot(verts[n-1].x,verts[n-1].z,verts[0].x,verts[0].z,point.x,point.z);
|
||||
if (thisDot*lastDot<0)
|
||||
return false;
|
||||
lastDot = thisDot;
|
||||
|
||||
for (i=0;i<n-1;i++)
|
||||
{
|
||||
thisDot = doDot(verts[i].x,verts[i].z,verts[i+1].x,verts[i+1].z,point.x,point.z);
|
||||
if (thisDot*lastDot<0)
|
||||
return false; // different sign, point outside one of the edges
|
||||
lastDot = thisDot;
|
||||
}
|
||||
}
|
||||
else if (mFabs(normal.x)>mFabs(normal.y)&&mFabs(normal.x)>mFabs(normal.z))
|
||||
{
|
||||
// drop x coord
|
||||
thisDot = doDot(verts[n-1].y,verts[n-1].z,verts[0].y,verts[0].z,point.y,point.z);
|
||||
if (thisDot*lastDot<0)
|
||||
return false;
|
||||
lastDot = thisDot;
|
||||
|
||||
for (i=0;i<n-1;i++)
|
||||
{
|
||||
thisDot = doDot(verts[i].y,verts[i].z,verts[i+1].y,verts[i+1].z,point.y,point.z);
|
||||
if (thisDot*lastDot<0)
|
||||
return false; // different sign, point outside one of the edges
|
||||
lastDot = thisDot;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// drop z coord
|
||||
thisDot = doDot(verts[n-1].x,verts[n-1].y,verts[0].x,verts[0].y,point.x,point.y);
|
||||
if (thisDot*lastDot<0)
|
||||
return false;
|
||||
lastDot = thisDot;
|
||||
|
||||
for (i=0;i<n-1;i++)
|
||||
{
|
||||
thisDot = doDot(verts[i].x,verts[i].y,verts[i+1].x,verts[i+1].y,point.x,point.y);
|
||||
if (thisDot*lastDot<0)
|
||||
return false; // different sign, point outside one of the edges
|
||||
lastDot = thisDot;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// deal with some unresolved externals...
|
||||
#include "platform/event.h"
|
||||
#include "core/bitStream.h"
|
||||
void GamePostEvent(struct Event const &) {}
|
||||
void GameHandleInfoPacket(struct NetAddress const *, BitStream *){}
|
||||
void GameHandleDataPacket(S32, BitStream *){}
|
||||
void GameConnectionAccepted(S32, BitStream *){}
|
||||
void GameConnectionRejected(S32, BitStream *){}
|
||||
void GameConnectionDisconnected(S32, BitStream *){}
|
||||
void GameConnectionRequested(struct NetAddress const *, BitStream *){}
|
||||
void GameConnectionEstablished(S32){}
|
||||
void GameHandleNotify(S32,bool){}
|
||||
void GameConnectionTimedOut(S32){}
|
||||
void GameDeactivate(bool) {}
|
||||
void GameReactivate() {}
|
||||
S32 GameMain(S32,char const * *){ return 0; }
|
||||
U32 getTickCount() { return 0; }
|
||||
void (*terrMipBlit)(U16 *dest, U32 destStride, U32 squareSize, const U8 *sourcePtr, U32 sourceStep, U32 sourceRowAdd);
|
||||
bool gEditingMission;
|
||||
|
||||
class SimGroup;
|
||||
SimGroup * gDataBlockGroup;
|
||||
SimGroup * gActionMapGroup;
|
||||
SimGroup * gClientGroup;
|
||||
SimGroup * gGuiGroup;
|
||||
SimGroup * gGuiDataGroup;
|
||||
SimGroup * gTCPGroup;
|
||||
class SimSet;
|
||||
SimSet * gActiveActionMapSet;
|
||||
SimSet * gGhostAlwaysSet;
|
||||
SimSet * gLightSet;
|
||||
|
||||
//------------------------------------------------------
|
||||
// These routines aren't currently used, but could prove
|
||||
// useful at a later time...
|
||||
//------------------------------------------------------
|
||||
/*
|
||||
|
||||
MatrixF & getNodeMatrix(INode *pNode, S32 time, MatrixF & matrix)
|
||||
{
|
||||
Matrix3 nodeMat = pNode->GetNodeTM( time );
|
||||
convertToMatrixF(nodeMat,matrix);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
MatrixF & getLocalNodeMatrix(INode *pNode, INode *parent, S32 time, MatrixF & matrix)
|
||||
{
|
||||
if (!parent)
|
||||
return getNodeMatrix(pNode,time,matrix);
|
||||
|
||||
MatrixF m1,m2;
|
||||
getNodeMatrix(pNode,time,m1);
|
||||
getNodeMatrix(parent,time ,m2);
|
||||
m2.inverse();
|
||||
matrix.mul(m1,m2);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
*/
|
67
tools/max2dtsExporter/maxUtil.h
Executable file
67
tools/max2dtsExporter/maxUtil.h
Executable file
@ -0,0 +1,67 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _DYN_MAX_UTIL_H
|
||||
#define _DYN_MAX_UTIL_H
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <max.h>
|
||||
#include <iparamb2.h>
|
||||
#include <ISkin.h>
|
||||
#include <decomp.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
#include "math/mMath.h"
|
||||
#include "ts/tsTransform.h"
|
||||
|
||||
#define DEFAULT_TIME 0
|
||||
|
||||
extern Point3F & Point3ToPoint3F(Point3 & p3, Point3F & p3f);
|
||||
|
||||
extern MatrixF & convertToMatrixF(Matrix3 & mat3,MatrixF & matf);
|
||||
|
||||
extern void zapScale(Matrix3 & mat);
|
||||
|
||||
extern TriObject * getTriObject( INode *pNode, S32 time, S32 multiResVerts, bool & deleteIt);
|
||||
|
||||
extern void getLocalNodeTransform(INode *pNode, INode *parent, AffineParts & child0, AffineParts & parent0, S32 time, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale);
|
||||
|
||||
extern void getBlendNodeTransform(INode *pNode, INode *parent, AffineParts & child0, AffineParts & parent0, S32 time, S32 referenceTime, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale);
|
||||
|
||||
extern Matrix3 & getLocalNodeMatrix(INode *pNode, INode *parent, S32 time, Matrix3 & matrix, AffineParts & child0, AffineParts & parent0);
|
||||
|
||||
extern void computeObjectOffset(INode * pNode, Matrix3 & mat);
|
||||
|
||||
extern F32 findVolume(INode * pNode, S32 & polyCount);
|
||||
|
||||
extern void getDeltaTransform(INode * pNode, S32 time1, S32 time2, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale);
|
||||
|
||||
extern bool isVis(INode * pNode, S32 time);
|
||||
|
||||
extern F32 getVisValue(INode * pNode, S32 time);
|
||||
|
||||
extern bool animatesVis(INode * pNode, const Interval & range, bool & error);
|
||||
|
||||
extern bool animatesFrame(INode * pNode, const Interval & range, bool & error);
|
||||
|
||||
extern bool animatesMatFrame(INode * pNode, const Interval & range, bool & error);
|
||||
|
||||
extern void embedSubtree(Interface *);
|
||||
|
||||
extern void renumberNodes(Interface *, S32 newSize);
|
||||
|
||||
extern void registerDetails(Interface * ip);
|
||||
|
||||
extern char * chopTrailingNumber(const char *, S32 & size);
|
||||
|
||||
extern bool hasMesh(INode *pNode);
|
||||
|
||||
extern void findSkinData(INode * pNode, ISkin **skin, ISkinContextData ** skinData);
|
||||
|
||||
extern bool hasSkin(INode * pNode);
|
||||
|
||||
extern bool pointInPoly(const Point3F & point, const Point3F & normal, const Point3F * verts, U32 n);
|
||||
|
||||
#endif // _DYN_MAX_UTIL_H
|
BIN
tools/max2dtsExporter/readme.doc
Executable file
BIN
tools/max2dtsExporter/readme.doc
Executable file
Binary file not shown.
993
tools/max2dtsExporter/sequence.cc
Executable file
993
tools/max2dtsExporter/sequence.cc
Executable file
@ -0,0 +1,993 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "max2dtsExporter/Sequence.h"
|
||||
#include "max2dtsExporter/exporter.h"
|
||||
#include "Platform/platformAssert.h"
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <MAX.H>
|
||||
#include <dummy.h>
|
||||
#include <iparamm.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
// conversion from 1.x to 2.x 3ds Max?
|
||||
//#define TYPE_BOOL TYPE_BOOLEAN
|
||||
|
||||
extern HINSTANCE hInstance;
|
||||
extern TCHAR *GetString(S32);
|
||||
|
||||
//------------------------------------------------------
|
||||
// max data structures used to map between max
|
||||
// user-interface and max parameter blocks...
|
||||
//------------------------------------------------------
|
||||
S32 useFrameRateControls1[] = { IDC_SEQ_USE_FRAME_RATE, IDC_SEQ_USE_N_FRAMES };
|
||||
S32 useFrameRateControls2[] = { IDC_SEQ_USE_GROUND_FRAME_RATE, IDC_SEQ_USE_N_GROUND_FRAMES };
|
||||
S32 tfArray[] = { true, false };
|
||||
|
||||
static ParamUIDesc descParam1[] =
|
||||
{
|
||||
ParamUIDesc(
|
||||
PB_SEQ_CYCLIC,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_CYCLIC ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_BLEND,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_BLEND ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_LAST_FIRST_FRAME_SAME,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_LAST_FIRST_FRAME_SAME ),
|
||||
|
||||
ParamUIDesc(
|
||||
PB_SEQ_USE_FRAME_RATE,
|
||||
TYPE_RADIO,
|
||||
useFrameRateControls1,
|
||||
2,
|
||||
tfArray),
|
||||
|
||||
ParamUIDesc(
|
||||
PB_SEQ_FRAME_RATE,
|
||||
EDITTYPE_FLOAT,
|
||||
IDC_SEQ_FRAME_RATE,IDC_SEQ_FRAME_RATE_SPINNER,
|
||||
0.0001f,100.0f,1.0f),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_NUM_FRAMES,
|
||||
EDITTYPE_INT,
|
||||
IDC_SEQ_NUM_FRAMES,IDC_SEQ_NUM_FRAMES_SPINNER,
|
||||
2.0f,100.0f,1.0f),
|
||||
|
||||
ParamUIDesc(
|
||||
PB_SEQ_OVERRIDE_DURATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_DURATION_OVERRIDE ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_DURATION,
|
||||
EDITTYPE_FLOAT,
|
||||
IDC_SEQ_DURATION,IDC_SEQ_DURATION_SPINNER,
|
||||
0.0001f,1000.0f,1.0f),
|
||||
|
||||
ParamUIDesc(
|
||||
PB_SEQ_DEFAULT_PRIORITY,
|
||||
EDITTYPE_INT,
|
||||
IDC_SEQ_PRIORITY,IDC_SEQ_PRIORITY_SPINNER,
|
||||
0.0f, 1000.0f, 1.0f)
|
||||
};
|
||||
|
||||
static ParamUIDesc descParam2[] =
|
||||
{
|
||||
ParamUIDesc(
|
||||
PB_SEQ_IGNORE_GROUND_TRANSFORM,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_IGNORE_GROUND_TRANSFORM ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_USE_GROUND_FRAME_RATE,
|
||||
TYPE_RADIO,
|
||||
useFrameRateControls2,
|
||||
2,
|
||||
tfArray),
|
||||
|
||||
ParamUIDesc(
|
||||
PB_SEQ_GROUND_FRAME_RATE,
|
||||
EDITTYPE_FLOAT,
|
||||
IDC_SEQ_GROUND_FRAME_RATE,
|
||||
IDC_SEQ_GROUND_FRAME_RATE_SPINNER,
|
||||
0.0001f,100.0f,1.0f),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_NUM_GROUND_FRAMES,
|
||||
EDITTYPE_INT,
|
||||
IDC_SEQ_NUM_GROUND_FRAMES,
|
||||
IDC_SEQ_NUM_GROUND_FRAMES_SPINNER,
|
||||
2.0f,100.0f,1.0f),
|
||||
};
|
||||
|
||||
static ParamUIDesc descParam3[] =
|
||||
{
|
||||
ParamUIDesc(
|
||||
PB_SEQ_ENABLE_MORPH_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_ENABLE_MORPH_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_ENABLE_VIS_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_ENABLE_VIS_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_ENABLE_TRANSFORM_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_ENABLE_TRANSFORM_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_ENABLE_UNIFORM_SCALE_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_ENABLE_UNIFORM_SCALE_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_ENABLE_ARBITRARY_SCALE_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_ENABLE_ARBITRARY_SCALE_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_ENABLE_TEXTURE_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_ENABLE_TEXTURE_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_ENABLE_IFL_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_ENABLE_IFL_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_ENABLE_DECAL_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_ENABLE_DECAL_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_ENABLE_DECAL_FRAME_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_ENABLE_DECAL_FRAME_ANIMATION ),
|
||||
|
||||
ParamUIDesc(
|
||||
PB_SEQ_FORCE_MORPH_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_FORCE_MORPH_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_FORCE_VIS_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_FORCE_VIS_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_FORCE_TRANSFORM_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_FORCE_TRANSFORM_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_FORCE_SCALE_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_FORCE_SCALE_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_FORCE_TEXTURE_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_FORCE_TEXTURE_ANIMATION ),
|
||||
ParamUIDesc(
|
||||
PB_SEQ_FORCE_DECAL_ANIMATION,
|
||||
TYPE_SINGLECHEKBOX,
|
||||
IDC_SEQ_FORCE_DECAL_ANIMATION )
|
||||
};
|
||||
|
||||
#define PARAMDESC1_LENGTH (sizeof( descParam1 ) / sizeof( ParamUIDesc ))
|
||||
#define PARAMDESC2_LENGTH (sizeof( descParam2 ) / sizeof( ParamUIDesc ))
|
||||
#define PARAMDESC3_LENGTH (sizeof( descParam3 ) / sizeof( ParamUIDesc ))
|
||||
|
||||
// This is the current version.
|
||||
static ParamBlockDescID curVer[] =
|
||||
{
|
||||
{ TYPE_BOOL, NULL, TRUE , 0 }, // begin/end
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 1 }, // cyclic
|
||||
{ TYPE_BOOL, NULL, FALSE, 2 }, // blend
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 3 }, // first and last frame same (cyclic seq only)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 4 }, // use frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 5 }, // Frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 6 }, // number of frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 7 }, // ignore ground transform altogether?
|
||||
{ TYPE_BOOL, NULL, FALSE, 8 }, // use ground frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 9 }, // ground frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 10 }, // number of ground frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 11 }, // enable morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 12 }, // enable vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 13 }, // enable transform animation
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 14 }, // force morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 15 }, // force vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 16 }, // force transform animation
|
||||
|
||||
{ TYPE_INT, NULL, FALSE, 17 }, // sequence default priority
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 18 }, // blend sequence reference time (keyframe time determines it, not param value)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 19 }, // enable texture animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 20 }, // enable ifl animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 21 }, // force texture animation
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 22 }, // triggers...keyframes are read to determine trigger times and values
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 23 }, // enable decal animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 24 }, // enable decal frame animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 25 }, // force decal animation
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 26 }, // override sequence duration
|
||||
{ TYPE_FLOAT, NULL, FALSE, 27 }, // sequence duration (if override true)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 28 }, // enable uniform scale animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 29 }, // enable arbitrary scale animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 30 }, // force scale animation
|
||||
};
|
||||
|
||||
static ParamBlockDescID oldVer6[] =
|
||||
{
|
||||
{ TYPE_BOOL, NULL, TRUE , 0 }, // begin/end
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 1 }, // cyclic
|
||||
{ TYPE_BOOL, NULL, FALSE, 2 }, // blend
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 3 }, // first and last frame same (cyclic seq only)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 4 }, // use frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 5 }, // Frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 6 }, // number of frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 7 }, // ignore ground transform altogether?
|
||||
{ TYPE_BOOL, NULL, FALSE, 8 }, // use ground frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 9 }, // ground frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 10 }, // number of ground frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 11 }, // enable morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 12 }, // enable vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 13 }, // enable transform animation
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 14 }, // force morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 15 }, // force vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 16 }, // force transform animation
|
||||
|
||||
{ TYPE_INT, NULL, FALSE, 17 }, // sequence default priority
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 18 }, // blend sequence reference time (keyframe time determines it, not param value)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 19 }, // enable texture animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 20 }, // enable ifl animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 21 }, // force texture animation
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 22 }, // triggers...keyframes are read to determine trigger times and values
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 23 }, // enable decal animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 24 }, // enable decal frame animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 25 }, // force decal animation
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 26 }, // override sequence duration
|
||||
{ TYPE_FLOAT, NULL, FALSE, 27 }, // sequence duration (if override true)
|
||||
};
|
||||
|
||||
static ParamBlockDescID oldVer5[] =
|
||||
{
|
||||
{ TYPE_BOOL, NULL, TRUE , 0 }, // begin/end
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 1 }, // cyclic
|
||||
{ TYPE_BOOL, NULL, FALSE, 2 }, // blend
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 3 }, // first and last frame same (cyclic seq only)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 4 }, // use frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 5 }, // Frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 6 }, // number of frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 7 }, // ignore ground transform altogether?
|
||||
{ TYPE_BOOL, NULL, FALSE, 8 }, // use ground frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 9 }, // ground frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 10 }, // number of ground frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 11 }, // enable morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 12 }, // enable vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 13 }, // enable transform animation
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 14 }, // force morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 15 }, // force vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 16 }, // force transform animation
|
||||
|
||||
{ TYPE_INT, NULL, FALSE, 17 }, // sequence default priority
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 18 }, // blend sequence reference time (keyframe time determines it, not param value)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 19 }, // enable texture animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 20 }, // enable ifl animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 21 }, // force texture animation
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 22 }, // triggers...keyframes are read to determine trigger times and values
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 23 }, // enable decal animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 24 }, // enable decal frame animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 25 } // force decal animation
|
||||
};
|
||||
|
||||
static ParamBlockDescID oldVer4[] =
|
||||
{
|
||||
{ TYPE_BOOL, NULL, TRUE , 0 }, // begin/end
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 1 }, // cyclic
|
||||
{ TYPE_BOOL, NULL, FALSE, 2 }, // blend
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 3 }, // first and last frame same (cyclic seq only)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 4 }, // use frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 5 }, // Frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 6 }, // number of frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 7 }, // ignore ground transform altogether?
|
||||
{ TYPE_BOOL, NULL, FALSE, 8 }, // use ground frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 9 }, // ground frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 10 }, // number of ground frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 11 }, // enable morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 12 }, // enable vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 13 }, // enable transform animation
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 14 }, // force morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 15 }, // force vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 16 }, // force transform animation
|
||||
|
||||
{ TYPE_INT, NULL, FALSE, 17 }, // sequence default priority
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 18 }, // blend sequence reference time (keyframe time determines it, not param value)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 19 }, // enable texture animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 20 }, // enable ifl animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 21 }, // force texture animation
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 22 }, // triggers...keyframes are read to determine trigger times and values
|
||||
};
|
||||
|
||||
// old param block versions
|
||||
static ParamBlockDescID oldVer3[] =
|
||||
{
|
||||
{ TYPE_BOOL, NULL, TRUE , 0 }, // begin/end
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 1 }, // cyclic
|
||||
{ TYPE_BOOL, NULL, FALSE, 2 }, // blend
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 3 }, // first and last frame same (cyclic seq only)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 4 }, // use frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 5 }, // Frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 6 }, // number of frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 7 }, // ignore ground transform altogether?
|
||||
{ TYPE_BOOL, NULL, FALSE, 8 }, // use ground frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 9 }, // ground frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 10 }, // number of ground frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 11 }, // enable morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 12 }, // enable vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 13 }, // enable transform animation
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 14 }, // force morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 15 }, // force vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 16 }, // force transform animation
|
||||
|
||||
{ TYPE_INT, NULL, FALSE, 17 }, // sequence default priority
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 18 }, // blend sequence reference time (keyframe time determines it, not param value)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 19 }, // enable texture animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 20 }, // enable ifl animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 21 } // force texture animation
|
||||
};
|
||||
|
||||
static ParamBlockDescID oldVer2[] =
|
||||
{
|
||||
{ TYPE_BOOL, NULL, TRUE , 0 }, // begin/end
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 1 }, // cyclic
|
||||
{ TYPE_BOOL, NULL, FALSE, 2 }, // blend
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 3 }, // first and last frame same (cyclic seq only)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 4 }, // use frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 5 }, // Frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 6 }, // number of frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 7 }, // ignore ground transform altogether?
|
||||
{ TYPE_BOOL, NULL, FALSE, 8 }, // use ground frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 9 }, // ground frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 10 }, // number of ground frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 11 }, // enable morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 12 }, // enable vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 13 }, // enable transform animation
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 14 }, // force morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 15 }, // force vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 16 }, // force transform animation
|
||||
|
||||
{ TYPE_INT, NULL, FALSE, 17 }, // sequence default priority
|
||||
|
||||
{ TYPE_FLOAT, NULL, TRUE, 18 } // blend sequence reference time (keyframe time determines it, not param value)
|
||||
};
|
||||
|
||||
static ParamBlockDescID oldVer1[] =
|
||||
{
|
||||
{ TYPE_BOOL, NULL, TRUE , 0 }, // begin/end
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 1 }, // cyclic
|
||||
{ TYPE_BOOL, NULL, FALSE, 2 }, // blend
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 3 }, // first and last frame same (cyclic seq only)
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 4 }, // use frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 5 }, // Frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 6 }, // number of frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 7 }, // ignore ground transform altogether?
|
||||
{ TYPE_BOOL, NULL, FALSE, 8 }, // use ground frame rate?
|
||||
{ TYPE_FLOAT, NULL, FALSE, 9 }, // ground frame Rate
|
||||
{ TYPE_INT, NULL, FALSE, 10 }, // number of ground frames
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 11 }, // enable morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 12 }, // enable vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 13 }, // enable transform animation
|
||||
|
||||
{ TYPE_BOOL, NULL, FALSE, 14 }, // force morph animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 15 }, // force vis animation
|
||||
{ TYPE_BOOL, NULL, FALSE, 16 }, // force transform animation
|
||||
|
||||
{ TYPE_INT, NULL, FALSE, 17 } // sequence default priority
|
||||
};
|
||||
|
||||
// Array of old versions
|
||||
static ParamVersionDesc versions[] =
|
||||
{
|
||||
ParamVersionDesc( oldVer1, sizeof(oldVer1)/sizeof(ParamBlockDescID), 0),
|
||||
ParamVersionDesc( oldVer2, sizeof(oldVer2)/sizeof(ParamBlockDescID), 1),
|
||||
ParamVersionDesc( oldVer3, sizeof(oldVer3)/sizeof(ParamBlockDescID), 2),
|
||||
ParamVersionDesc( oldVer4, sizeof(oldVer4)/sizeof(ParamBlockDescID), 3),
|
||||
ParamVersionDesc( oldVer5, sizeof(oldVer5)/sizeof(ParamBlockDescID), 4),
|
||||
ParamVersionDesc( oldVer6, sizeof(oldVer6)/sizeof(ParamBlockDescID), 5)
|
||||
};
|
||||
|
||||
#define NUM_OLDVERSIONS (sizeof(versions) / sizeof(ParamVersionDesc))
|
||||
#define CURRENT_VERSION NUM_OLDVERSIONS
|
||||
|
||||
// Current version
|
||||
#define PBLOCK_LENGTH (sizeof(curVer) / sizeof(ParamBlockDescID))
|
||||
static ParamVersionDesc curVersion( curVer, PBLOCK_LENGTH, CURRENT_VERSION );
|
||||
|
||||
//------------------------------------------------------
|
||||
// sequence class defaults:
|
||||
//------------------------------------------------------
|
||||
U32 SequenceObject::defaultCyclic = true;
|
||||
U32 SequenceObject::defaultBlend = false;
|
||||
U32 SequenceObject::defaultFirstLastFrameSame = false;
|
||||
|
||||
U32 SequenceObject::defaultUseFrameRate = true;
|
||||
F32 SequenceObject::defaultFrameRate = 15.0f;
|
||||
S32 SequenceObject::defaultNumFrames = 2;
|
||||
|
||||
U32 SequenceObject::defaultIgnoreGroundTransform = false;
|
||||
U32 SequenceObject::defaultUseGroundFrameRate = false;
|
||||
F32 SequenceObject::defaultGroundFrameRate = 15.0f;
|
||||
S32 SequenceObject::defaultNumGroundFrames = 2;
|
||||
|
||||
U32 SequenceObject::defaultEnableMorphAnimation = false;
|
||||
U32 SequenceObject::defaultEnableVisAnimation = false;
|
||||
U32 SequenceObject::defaultEnableTransformAnimation = true;
|
||||
U32 SequenceObject::defaultEnableTextureAnimation = false;
|
||||
U32 SequenceObject::defaultEnableIflAnimation = false;
|
||||
U32 SequenceObject::defaultEnableDecalAnimation = false;
|
||||
U32 SequenceObject::defaultEnableDecalFrameAnimation = false;
|
||||
|
||||
U32 SequenceObject::defaultForceMorphAnimation = false;
|
||||
U32 SequenceObject::defaultForceVisAnimation = false;
|
||||
U32 SequenceObject::defaultForceTransformAnimation = false;
|
||||
U32 SequenceObject::defaultForceTextureAnimation = false;
|
||||
U32 SequenceObject::defaultForceDecalAnimation = false;
|
||||
|
||||
S32 SequenceObject::defaultDefaultSequencePriority = 0;
|
||||
|
||||
S32 SequenceObject::defaultBlendReferenceTime = 0; // value not important
|
||||
|
||||
U32 SequenceObject::defaultOverrideDuration = false;
|
||||
F32 SequenceObject::defaultDuration = 1.0f;
|
||||
|
||||
U32 SequenceObject::defaultEnableUniformScaleAnimation = false;
|
||||
U32 SequenceObject::defaultEnableArbitraryScaleAnimation = false;
|
||||
U32 SequenceObject::defaultForceScaleAnimation = false;
|
||||
|
||||
//------------------------------------------------------
|
||||
// Some more statics:
|
||||
//------------------------------------------------------
|
||||
SequenceObject * SequenceObject::editOb = NULL;
|
||||
IParamMap * SequenceObject::pmapParam1 = NULL;
|
||||
IParamMap * SequenceObject::pmapParam2 = NULL;
|
||||
IParamMap * SequenceObject::pmapParam3 = NULL;
|
||||
|
||||
//------------------------------------------------------
|
||||
// Sequence object methods...
|
||||
//------------------------------------------------------
|
||||
|
||||
void SequenceObject::InitNodeName(TSTR& s)
|
||||
{
|
||||
s = GetString(IDS_DB_SEQUENCE);
|
||||
}
|
||||
|
||||
void SequenceObject::GetClassName(TSTR& s)
|
||||
{
|
||||
s = TSTR(GetString(IDS_DB_SEQUENCE));
|
||||
}
|
||||
|
||||
void resetSequenceDefaults()
|
||||
{
|
||||
SequenceObject::defaultCyclic = true;
|
||||
SequenceObject::defaultBlend = false;
|
||||
SequenceObject::defaultFirstLastFrameSame = false;
|
||||
|
||||
SequenceObject::defaultUseFrameRate = true;
|
||||
SequenceObject::defaultFrameRate = 15.0f;
|
||||
SequenceObject::defaultNumFrames = 2;
|
||||
|
||||
SequenceObject::defaultIgnoreGroundTransform = false;
|
||||
SequenceObject::defaultUseGroundFrameRate = false;
|
||||
SequenceObject::defaultGroundFrameRate = 15.0f;
|
||||
SequenceObject::defaultNumGroundFrames = 2;
|
||||
|
||||
SequenceObject::defaultEnableMorphAnimation = false;
|
||||
SequenceObject::defaultEnableVisAnimation = false;
|
||||
SequenceObject::defaultEnableTransformAnimation = true;
|
||||
SequenceObject::defaultEnableTextureAnimation = false;
|
||||
SequenceObject::defaultEnableIflAnimation = false;
|
||||
SequenceObject::defaultEnableDecalAnimation = false;
|
||||
SequenceObject::defaultEnableDecalFrameAnimation = false;
|
||||
|
||||
SequenceObject::defaultForceMorphAnimation = false;
|
||||
SequenceObject::defaultForceVisAnimation = false;
|
||||
SequenceObject::defaultForceTransformAnimation = false;
|
||||
SequenceObject::defaultForceTextureAnimation = false;
|
||||
SequenceObject::defaultForceDecalAnimation = false;
|
||||
|
||||
SequenceObject::defaultDefaultSequencePriority = 0;
|
||||
|
||||
SequenceObject::defaultBlendReferenceTime = 0; // value not important
|
||||
|
||||
SequenceObject::defaultOverrideDuration = false;
|
||||
SequenceObject::defaultDuration = 1.0f;
|
||||
|
||||
SequenceObject::defaultEnableUniformScaleAnimation = false;
|
||||
SequenceObject::defaultEnableArbitraryScaleAnimation = false;
|
||||
SequenceObject::defaultForceScaleAnimation = false;
|
||||
}
|
||||
|
||||
bool getBoolSequenceDefault(S32 index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case PB_SEQ_CYCLIC: return SequenceObject::defaultCyclic;
|
||||
case PB_SEQ_BLEND: return SequenceObject::defaultBlend;
|
||||
case PB_SEQ_LAST_FIRST_FRAME_SAME: return SequenceObject::defaultFirstLastFrameSame;
|
||||
case PB_SEQ_USE_FRAME_RATE: return SequenceObject::defaultUseFrameRate;
|
||||
|
||||
case PB_SEQ_IGNORE_GROUND_TRANSFORM: return SequenceObject::defaultIgnoreGroundTransform;
|
||||
case PB_SEQ_USE_GROUND_FRAME_RATE: return SequenceObject::defaultUseGroundFrameRate;
|
||||
|
||||
case PB_SEQ_ENABLE_MORPH_ANIMATION: return SequenceObject::defaultEnableMorphAnimation;
|
||||
case PB_SEQ_ENABLE_VIS_ANIMATION: return SequenceObject::defaultEnableVisAnimation;
|
||||
case PB_SEQ_ENABLE_TRANSFORM_ANIMATION: return SequenceObject::defaultEnableTransformAnimation;
|
||||
case PB_SEQ_ENABLE_TEXTURE_ANIMATION: return SequenceObject::defaultEnableTextureAnimation;
|
||||
case PB_SEQ_ENABLE_IFL_ANIMATION: return SequenceObject::defaultEnableIflAnimation;
|
||||
case PB_SEQ_ENABLE_DECAL_ANIMATION: return SequenceObject::defaultEnableDecalAnimation;
|
||||
case PB_SEQ_ENABLE_DECAL_FRAME_ANIMATION: return SequenceObject::defaultEnableDecalFrameAnimation;
|
||||
|
||||
case PB_SEQ_FORCE_MORPH_ANIMATION: return SequenceObject::defaultForceMorphAnimation;
|
||||
case PB_SEQ_FORCE_VIS_ANIMATION: return SequenceObject::defaultForceVisAnimation;
|
||||
case PB_SEQ_FORCE_TRANSFORM_ANIMATION: return SequenceObject::defaultForceTransformAnimation;
|
||||
case PB_SEQ_FORCE_TEXTURE_ANIMATION: return SequenceObject::defaultForceTextureAnimation;
|
||||
case PB_SEQ_FORCE_DECAL_ANIMATION: return SequenceObject::defaultForceDecalAnimation;
|
||||
|
||||
case PB_SEQ_OVERRIDE_DURATION: return SequenceObject::defaultOverrideDuration;
|
||||
|
||||
case PB_SEQ_ENABLE_UNIFORM_SCALE_ANIMATION: return SequenceObject::defaultEnableUniformScaleAnimation;
|
||||
case PB_SEQ_ENABLE_ARBITRARY_SCALE_ANIMATION: return SequenceObject::defaultEnableArbitraryScaleAnimation;
|
||||
case PB_SEQ_FORCE_SCALE_ANIMATION: return SequenceObject::defaultForceScaleAnimation;
|
||||
|
||||
// default : AssertFatal(0,"Invalid default when getting sequence default value");
|
||||
// return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
F32 getFloatSequenceDefault(S32 index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case PB_SEQ_FRAME_RATE: return SequenceObject::defaultFrameRate;
|
||||
case PB_SEQ_GROUND_FRAME_RATE: return SequenceObject::defaultGroundFrameRate;
|
||||
case PB_SEQ_DURATION: return SequenceObject::defaultDuration;
|
||||
|
||||
// default : AssertFatal(0,"Invalid default when getting sequence default value");
|
||||
// return 0.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
S32 getIntSequenceDefault(S32 index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case PB_SEQ_NUM_FRAMES: return SequenceObject::defaultNumFrames;
|
||||
case PB_SEQ_NUM_GROUND_FRAMES: return SequenceObject::defaultNumGroundFrames;
|
||||
case PB_SEQ_DEFAULT_PRIORITY: return SequenceObject::defaultDefaultSequencePriority;
|
||||
|
||||
// default : AssertFatal(0,"Invalid default when getting sequence default value");
|
||||
// return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// Sequence object implementation -- not much here
|
||||
//------------------------------------------------------
|
||||
IParamArray *SequenceObject::GetParamBlock()
|
||||
{
|
||||
return pblock;
|
||||
}
|
||||
|
||||
S32 SequenceObject::GetParamBlockIndex(S32 id)
|
||||
{
|
||||
if (pblock && id>=0 && id<pblock->NumParams())
|
||||
return id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SequenceObject::FreeCaches()
|
||||
{
|
||||
ivalid.SetEmpty();
|
||||
}
|
||||
|
||||
RefResult SequenceObject::NotifyRefChanged( Interval changeInt,
|
||||
RefTargetHandle hTarget,
|
||||
PartID& partID,
|
||||
RefMessage message )
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case REFMSG_CHANGE:
|
||||
{
|
||||
if (editOb==this)
|
||||
InvalidateUI();
|
||||
break;
|
||||
}
|
||||
case REFMSG_GET_PARAM_DIM:
|
||||
{
|
||||
GetParamDim *gpd = (GetParamDim*)partID;
|
||||
gpd->dim = GetParameterDim(gpd->index);
|
||||
return REF_STOP;
|
||||
}
|
||||
case REFMSG_GET_PARAM_NAME:
|
||||
{
|
||||
GetParamName *gpn = (GetParamName*)partID;
|
||||
gpn->name = GetParameterName(gpn->index);
|
||||
return REF_STOP;
|
||||
}
|
||||
}
|
||||
return(REF_SUCCEED);
|
||||
}
|
||||
|
||||
Interval SequenceObject::ObjectValidity(TimeValue time)
|
||||
{
|
||||
return ivalid;
|
||||
}
|
||||
|
||||
TSTR SequenceObject::SubAnimName(S32 i)
|
||||
{
|
||||
return _T("Parameters");
|
||||
}
|
||||
|
||||
void SequenceObject::BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev)
|
||||
{
|
||||
// Save the current sequence object
|
||||
editOb = this;
|
||||
|
||||
// we have mutliple parameter maps...make sure one of each is created:
|
||||
|
||||
if (pmapParam1)
|
||||
{
|
||||
// Left over from last sequence ceated
|
||||
pmapParam1->SetParamBlock(pblock);
|
||||
}
|
||||
else
|
||||
{
|
||||
pmapParam1 = CreateCPParamMap(
|
||||
descParam1,
|
||||
PARAMDESC1_LENGTH,
|
||||
pblock,
|
||||
ip,
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_SEQUENCE_PARAMS),
|
||||
_T("General"),
|
||||
0);
|
||||
}
|
||||
|
||||
if (pmapParam2)
|
||||
{
|
||||
// Left over from last sequence ceated
|
||||
pmapParam2->SetParamBlock(pblock);
|
||||
}
|
||||
else
|
||||
{
|
||||
pmapParam2 = CreateCPParamMap(
|
||||
descParam2,
|
||||
PARAMDESC2_LENGTH,
|
||||
pblock,
|
||||
ip,
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_SEQUENCE_PARAMS2),
|
||||
_T("Ground Transform"),
|
||||
APPENDROLL_CLOSED);
|
||||
}
|
||||
|
||||
if (pmapParam3)
|
||||
{
|
||||
// Left over from last sequence ceated
|
||||
pmapParam3->SetParamBlock(pblock);
|
||||
}
|
||||
else
|
||||
{
|
||||
pmapParam3 = CreateCPParamMap(
|
||||
descParam3,
|
||||
PARAMDESC3_LENGTH,
|
||||
pblock,
|
||||
ip,
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_SEQUENCE_PARAMS3),
|
||||
_T("Export Control"),
|
||||
APPENDROLL_CLOSED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SequenceObject::EndEditParams(IObjParam *ip, ULONG flags,Animatable *next)
|
||||
{
|
||||
editOb = NULL;
|
||||
|
||||
ClearAFlag(A_OBJ_CREATING);
|
||||
|
||||
if ( (flags&END_EDIT_REMOVEUI) && pmapParam1 )
|
||||
{
|
||||
// Remove the rollup pages from the command panel.
|
||||
DestroyCPParamMap(pmapParam1);
|
||||
pmapParam1 = NULL;
|
||||
}
|
||||
|
||||
if ( (flags&END_EDIT_REMOVEUI) && pmapParam2 )
|
||||
{
|
||||
// Remove the rollup pages from the command panel.
|
||||
DestroyCPParamMap(pmapParam2);
|
||||
pmapParam2 = NULL;
|
||||
}
|
||||
|
||||
if ( (flags&END_EDIT_REMOVEUI) && pmapParam3 )
|
||||
{
|
||||
// Remove the rollup pages from the command panel.
|
||||
DestroyCPParamMap(pmapParam3);
|
||||
pmapParam3 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This method is called when the user interface controls need to be
|
||||
// updated to reflect new values because of the user moving the time
|
||||
// slider. Here we simply call a method of the parameter map to
|
||||
// handle this for us.
|
||||
void SequenceObject::InvalidateUI()
|
||||
{
|
||||
if (pmapParam1)
|
||||
pmapParam1->Invalidate();
|
||||
|
||||
if (pmapParam2)
|
||||
pmapParam2->Invalidate();
|
||||
|
||||
if (pmapParam3)
|
||||
pmapParam3->Invalidate();
|
||||
}
|
||||
|
||||
// This method returns the dimension of the parameter requested.
|
||||
// This dimension describes the type and magnitude of the value
|
||||
// stored by the parameter.
|
||||
ParamDimension *SequenceObject::GetParameterDim(S32)
|
||||
{
|
||||
return defaultDim; // just store the parameter...ask no questions
|
||||
}
|
||||
|
||||
// This method returns the name of the parameter requested.
|
||||
TSTR SequenceObject::GetParameterName(S32 pbIndex)
|
||||
{
|
||||
switch (pbIndex)
|
||||
{
|
||||
case PB_SEQ_BEGIN_END:
|
||||
return TSTR(_T("Sequence Begin/End"));
|
||||
|
||||
case PB_SEQ_CYCLIC:
|
||||
return TSTR(_T("Cyclic sequence"));
|
||||
case PB_SEQ_BLEND:
|
||||
return TSTR(_T("Blend sequence"));
|
||||
|
||||
case PB_SEQ_LAST_FIRST_FRAME_SAME:
|
||||
return TSTR(_T("Last frame matches first frame"));
|
||||
|
||||
case PB_SEQ_USE_FRAME_RATE:
|
||||
return TSTR(_T("Use frame rate"));
|
||||
case PB_SEQ_FRAME_RATE:
|
||||
return TSTR(_T("Frame rate"));
|
||||
case PB_SEQ_NUM_FRAMES:
|
||||
return TSTR(_T("Number of frames"));
|
||||
|
||||
case PB_SEQ_IGNORE_GROUND_TRANSFORM:
|
||||
return TSTR(_T("Ignore ground transform"));
|
||||
case PB_SEQ_USE_GROUND_FRAME_RATE:
|
||||
return TSTR(_T("Use ground transform frame rate"));
|
||||
case PB_SEQ_GROUND_FRAME_RATE:
|
||||
return TSTR(_T("Ground transform frame rate"));
|
||||
case PB_SEQ_NUM_GROUND_FRAMES:
|
||||
return TSTR(_T("Number of ground transform frames"));
|
||||
|
||||
case PB_SEQ_ENABLE_MORPH_ANIMATION:
|
||||
return TSTR(_T("Enable morph animation"));
|
||||
case PB_SEQ_ENABLE_VIS_ANIMATION:
|
||||
return TSTR(_T("Enable visibility animation"));
|
||||
case PB_SEQ_ENABLE_TRANSFORM_ANIMATION:
|
||||
return TSTR(_T("Enable transform animation"));
|
||||
case PB_SEQ_ENABLE_TEXTURE_ANIMATION:
|
||||
return TSTR(_T("Enable texture animation"));
|
||||
case PB_SEQ_ENABLE_IFL_ANIMATION:
|
||||
return TSTR(_T("Enable IFL animation"));
|
||||
case PB_SEQ_ENABLE_DECAL_ANIMATION:
|
||||
return TSTR(_T("Enable decal animation"));
|
||||
case PB_SEQ_ENABLE_DECAL_FRAME_ANIMATION:
|
||||
return TSTR(_T("Enable decal frame animation"));
|
||||
|
||||
case PB_SEQ_FORCE_MORPH_ANIMATION:
|
||||
return TSTR(_T("Force morph animation"));
|
||||
case PB_SEQ_FORCE_VIS_ANIMATION:
|
||||
return TSTR(_T("Force visibility animation"));
|
||||
case PB_SEQ_FORCE_TRANSFORM_ANIMATION:
|
||||
return TSTR(_T("Force transform animation"));
|
||||
case PB_SEQ_FORCE_TEXTURE_ANIMATION:
|
||||
return TSTR(_T("Force texture animation"));
|
||||
case PB_SEQ_FORCE_DECAL_ANIMATION:
|
||||
return TSTR(_T("Force decal animation"));
|
||||
|
||||
case PB_SEQ_DEFAULT_PRIORITY:
|
||||
return TSTR(_T("Default sequence priority"));
|
||||
|
||||
case PB_SEQ_BLEND_REFERENCE_TIME:
|
||||
return TSTR(_T("Blend Reference Time"));
|
||||
|
||||
case PB_SEQ_TRIGGERS:
|
||||
return TSTR(_T("Triggers"));
|
||||
|
||||
case PB_SEQ_OVERRIDE_DURATION:
|
||||
return TSTR(_T("Override sequence duration"));
|
||||
case PB_SEQ_DURATION:
|
||||
return TSTR(_T("Sequence duration"));
|
||||
|
||||
case PB_SEQ_ENABLE_UNIFORM_SCALE_ANIMATION:
|
||||
return TSTR(_T("Enable uniform scale animation"));
|
||||
case PB_SEQ_ENABLE_ARBITRARY_SCALE_ANIMATION:
|
||||
return TSTR(_T("Enable arbitrary scale animation"));
|
||||
case PB_SEQ_FORCE_SCALE_ANIMATION:
|
||||
return TSTR(_T("Force scale animation"));
|
||||
|
||||
default:
|
||||
return TSTR(_T(""));
|
||||
}
|
||||
}
|
||||
|
||||
RefTargetHandle SequenceObject::Clone(RemapDir& remap)
|
||||
{
|
||||
SequenceObject* newob = new SequenceObject();
|
||||
newob->ReplaceReference(0,pblock->Clone(remap));
|
||||
newob->ivalid.SetEmpty();
|
||||
return newob;
|
||||
}
|
||||
|
||||
SequenceObject::SequenceObject()
|
||||
{
|
||||
ivalid.SetEmpty();
|
||||
pblock = NULL;
|
||||
SetAFlag(A_OBJ_CREATING);
|
||||
|
||||
// Create the parameter block and make a reference to it.
|
||||
MakeRefByID(FOREVER, 0,
|
||||
CreateParameterBlock( curVersion.desc, PBLOCK_LENGTH, CURRENT_VERSION));
|
||||
|
||||
// assert(pblock);
|
||||
|
||||
// if (!pblock)
|
||||
// // need a way to signal an error
|
||||
// return;
|
||||
|
||||
// Initialize the default values.
|
||||
pblock->SetValue(PB_SEQ_BEGIN_END, 0, false);
|
||||
pblock->SetValue(PB_SEQ_CYCLIC, 0, (bool)defaultCyclic);
|
||||
pblock->SetValue(PB_SEQ_BLEND, 0, (bool)defaultBlend);
|
||||
pblock->SetValue(PB_SEQ_LAST_FIRST_FRAME_SAME, 0, (bool)defaultFirstLastFrameSame);
|
||||
pblock->SetValue(PB_SEQ_USE_FRAME_RATE, 0, (bool)defaultUseFrameRate);
|
||||
pblock->SetValue(PB_SEQ_FRAME_RATE, 0, defaultFrameRate);
|
||||
pblock->SetValue(PB_SEQ_NUM_FRAMES, 0, defaultNumFrames);
|
||||
pblock->SetValue(PB_SEQ_IGNORE_GROUND_TRANSFORM, 0, (bool)defaultIgnoreGroundTransform);
|
||||
pblock->SetValue(PB_SEQ_USE_GROUND_FRAME_RATE, 0, (bool)defaultUseGroundFrameRate);
|
||||
pblock->SetValue(PB_SEQ_GROUND_FRAME_RATE, 0, defaultGroundFrameRate);
|
||||
pblock->SetValue(PB_SEQ_NUM_GROUND_FRAMES, 0, defaultNumGroundFrames);
|
||||
pblock->SetValue(PB_SEQ_ENABLE_MORPH_ANIMATION, 0, (bool)defaultEnableMorphAnimation);
|
||||
pblock->SetValue(PB_SEQ_ENABLE_VIS_ANIMATION, 0, (bool)defaultEnableVisAnimation);
|
||||
pblock->SetValue(PB_SEQ_ENABLE_TRANSFORM_ANIMATION, 0, (bool)defaultEnableTransformAnimation);
|
||||
pblock->SetValue(PB_SEQ_ENABLE_TEXTURE_ANIMATION, 0, (bool)defaultEnableTextureAnimation);
|
||||
pblock->SetValue(PB_SEQ_ENABLE_IFL_ANIMATION, 0, (bool)defaultEnableIflAnimation);
|
||||
pblock->SetValue(PB_SEQ_ENABLE_DECAL_ANIMATION, 0, (bool)defaultEnableDecalAnimation);
|
||||
pblock->SetValue(PB_SEQ_ENABLE_DECAL_FRAME_ANIMATION, 0, (bool)defaultEnableDecalFrameAnimation);
|
||||
pblock->SetValue(PB_SEQ_FORCE_MORPH_ANIMATION, 0, (bool)defaultForceMorphAnimation);
|
||||
pblock->SetValue(PB_SEQ_FORCE_VIS_ANIMATION, 0, (bool)defaultForceVisAnimation);
|
||||
pblock->SetValue(PB_SEQ_FORCE_TRANSFORM_ANIMATION, 0, (bool)defaultForceTransformAnimation);
|
||||
pblock->SetValue(PB_SEQ_FORCE_TEXTURE_ANIMATION, 0, (bool)defaultForceTextureAnimation);
|
||||
pblock->SetValue(PB_SEQ_FORCE_DECAL_ANIMATION, 0, (bool)defaultForceDecalAnimation);
|
||||
pblock->SetValue(PB_SEQ_DEFAULT_PRIORITY, 0, defaultDefaultSequencePriority);
|
||||
pblock->SetValue(PB_SEQ_BLEND_REFERENCE_TIME, 0, defaultBlendReferenceTime);
|
||||
pblock->SetValue(PB_SEQ_OVERRIDE_DURATION, 0, (bool)defaultOverrideDuration);
|
||||
pblock->SetValue(PB_SEQ_DURATION, 0, defaultDuration);
|
||||
pblock->SetValue(PB_SEQ_ENABLE_UNIFORM_SCALE_ANIMATION, 0, (bool)defaultEnableUniformScaleAnimation);
|
||||
pblock->SetValue(PB_SEQ_ENABLE_ARBITRARY_SCALE_ANIMATION, 0, (bool)defaultEnableArbitraryScaleAnimation);
|
||||
pblock->SetValue(PB_SEQ_FORCE_SCALE_ANIMATION, 0, (bool)defaultForceScaleAnimation);
|
||||
}
|
||||
|
||||
SequenceObject::~SequenceObject()
|
||||
{
|
||||
DeleteAllRefsFromMe();
|
||||
}
|
||||
|
||||
//
|
||||
// Reference Managment:
|
||||
//
|
||||
|
||||
IOResult SequenceObject::Load(ILoad *iload)
|
||||
{
|
||||
// This is the callback that corrects for any older versions
|
||||
// of the parameter block structure found in the MAX file
|
||||
// being loaded.
|
||||
iload->RegisterPostLoadCallback(new ParamBlockPLCB(versions,NUM_OLDVERSIONS,&curVersion,this,0));
|
||||
return IO_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------
|
||||
// Sequence object descriptor declaration & implementation
|
||||
//------------------------------------------------------
|
||||
class SequenceObjClassDesc:public ClassDesc
|
||||
{
|
||||
public:
|
||||
S32 IsPublic() { return 1; }
|
||||
void * Create(BOOL loading = FALSE) { return new SequenceObject; }
|
||||
const TCHAR * ClassName() { return GetString(IDS_DB_SEQUENCE); }
|
||||
SClass_ID SuperClassID() { return HELPER_CLASS_ID; }
|
||||
Class_ID ClassID() { return SEQUENCE_CLASS_ID; }
|
||||
const TCHAR * Category() { return GetString(IDS_DB_GENERAL); }
|
||||
|
||||
// following functions allow setting of parameter defaults...
|
||||
// worthless unless all 3 are implemented
|
||||
// void ResetClassParams(BOOL fileReset)
|
||||
// {
|
||||
// if(fileReset)
|
||||
// resetSequenceDefaults();
|
||||
// }
|
||||
// HasClassParams?
|
||||
// EditClassParams?
|
||||
};
|
||||
|
||||
static SequenceObjClassDesc sequenceObjDesc;
|
||||
|
||||
ClassDesc * GetSequenceDesc() { return &sequenceObjDesc; }
|
||||
|
289
tools/max2dtsExporter/skinHelper.cc
Executable file
289
tools/max2dtsExporter/skinHelper.cc
Executable file
@ -0,0 +1,289 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "max2dtsExporter/skinHelper.h"
|
||||
#include "max2dtsExporter/sceneEnum.h"
|
||||
#include "max2dtsExporter/exportUtil.h"
|
||||
#include "max2dtsExporter/exporter.h"
|
||||
#include "core/tvector.h"
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <Max.h>
|
||||
#include <decomp.h>
|
||||
#include <dummy.h>
|
||||
#include <ISkin.h>
|
||||
#include <modstack.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
#define printDump SceneEnumProc::printDump
|
||||
|
||||
class SkinHelperClassDesc:public ClassDesc {
|
||||
public:
|
||||
int IsPublic() {return 1;}
|
||||
void * Create(BOOL loading = FALSE) {return new SkinHelper();}
|
||||
const TCHAR * ClassName() {return "Skin Helper";}
|
||||
SClass_ID SuperClassID() {return WSM_CLASS_ID;}
|
||||
Class_ID ClassID() {return SKINHELPER_CLASS_ID;}
|
||||
const TCHAR* Category() {return "General";}
|
||||
void ResetClassParams(BOOL) {}
|
||||
};
|
||||
|
||||
static SkinHelperClassDesc SkinHelperDesc;
|
||||
ClassDesc* GetSkinHelperDesc() {return &SkinHelperDesc;}
|
||||
|
||||
static BOOL CALLBACK SkinHelperDlgProc(
|
||||
HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
SkinHelper *ins = (SkinHelper*)GetWindowLong(hWnd,GWL_USERDATA);
|
||||
if (!ins && msg!=WM_INITDIALOG) return FALSE;
|
||||
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
ins = (SkinHelper*)lParam;
|
||||
SetWindowLong(hWnd,GWL_USERDATA,lParam);
|
||||
ins->hParams = hWnd;
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
ins->ip->RollupMouseMessage(hWnd,msg,wParam,lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
IObjParam *SkinHelper::ip = NULL;
|
||||
HWND SkinHelper::hParams = NULL;
|
||||
|
||||
//--- SkinHelper -------------------------------------------------------
|
||||
SkinHelper::SkinHelper()
|
||||
{
|
||||
}
|
||||
|
||||
SkinHelper::~SkinHelper()
|
||||
{
|
||||
}
|
||||
|
||||
S32 gDamnit=0;
|
||||
|
||||
void SkinHelper::SetReference(S32 i, RefTargetHandle rtarg)
|
||||
{
|
||||
gDamnit++;
|
||||
}
|
||||
|
||||
Interval SkinHelper::LocalValidity(TimeValue t)
|
||||
{
|
||||
// if being edited, return NEVER forces a cache to be built
|
||||
// after previous modifier.
|
||||
if (TestAFlag(A_MOD_BEING_EDITED))
|
||||
return NEVER;
|
||||
//TODO: Return the validity interval of the modifier
|
||||
return NEVER;
|
||||
}
|
||||
|
||||
RefTargetHandle SkinHelper::Clone(RemapDir& remap)
|
||||
{
|
||||
SkinHelper* newmod = new SkinHelper();
|
||||
//TODO: Add the cloning code here
|
||||
return(newmod);
|
||||
}
|
||||
|
||||
void SkinHelper::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *pNode)
|
||||
{
|
||||
ISkin * skin;
|
||||
ISkinContextData * skinData;
|
||||
if (!pNode)
|
||||
return;
|
||||
findSkinData(pNode,&skin,&skinData);
|
||||
if (!skin || !skinData)
|
||||
return;
|
||||
|
||||
TriObject * triObj = (TriObject*)os->obj->ConvertToType(0,Class_ID(TRIOBJ_CLASS_ID,0));
|
||||
if (triObj!=os->obj)
|
||||
delete triObj;
|
||||
else
|
||||
modifyTriObject(triObj,skin,skinData);
|
||||
PatchObject * patchObj = (PatchObject*)os->obj->ConvertToType(0,Class_ID(PATCHOBJ_CLASS_ID,0));
|
||||
if (patchObj!=os->obj)
|
||||
delete patchObj;
|
||||
else
|
||||
modifyPatchObject(patchObj,skin,skinData);
|
||||
}
|
||||
|
||||
void SkinHelper::modifyTriObject(TriObject * triObj, ISkin * skin, ISkinContextData * skinData)
|
||||
{
|
||||
S32 numBones = skin->GetNumBones();
|
||||
|
||||
Mesh & maxMesh = triObj->mesh;
|
||||
S32 numVerts = maxMesh.getNumVerts();
|
||||
S32 numTVerts = maxMesh.getNumMapVerts(1);
|
||||
if (numVerts!=skinData->GetNumPoints())
|
||||
return;
|
||||
|
||||
S32 numChannels = 2+((numBones+1)>>1);
|
||||
UVVert tv(0,0,0);
|
||||
for (S32 i=2; i<numChannels; i++)
|
||||
{
|
||||
maxMesh.setMapSupport(i,true);
|
||||
maxMesh.setNumMapVerts(i,numVerts);
|
||||
for (S32 j=0; j<numVerts; j++)
|
||||
maxMesh.setMapVert(i,j,tv);
|
||||
maxMesh.setNumMapFaces(i,maxMesh.getNumFaces());
|
||||
// copy map faces from the first channel
|
||||
for (S32 j=0; j<maxMesh.getNumFaces(); j++)
|
||||
{
|
||||
Face & face = maxMesh.faces[j];
|
||||
TVFace & tvFace = maxMesh.mapFaces(i)[j];
|
||||
tvFace.t[0] = face.v[0];
|
||||
tvFace.t[1] = face.v[1];
|
||||
tvFace.t[2] = face.v[2];
|
||||
}
|
||||
}
|
||||
|
||||
for (S32 v=0; v<numVerts; v++)
|
||||
{
|
||||
for (S32 i=0; i<skinData->GetNumAssignedBones(v); i++)
|
||||
{
|
||||
S32 bone = skinData->GetAssignedBone(v,i);
|
||||
F32 w = skinData->GetBoneWeight(v,i);
|
||||
UVVert tv = maxMesh.mapVerts(2+(bone>>1))[v];
|
||||
if (bone&1)
|
||||
tv.y = w;
|
||||
else
|
||||
tv.x = w;
|
||||
maxMesh.setMapVert(2+(bone>>1),v,tv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkinHelper::modifyPatchObject(PatchObject * patchObj, ISkin * skin, ISkinContextData * skinData)
|
||||
{
|
||||
S32 numBones = skin->GetNumBones();
|
||||
S32 numPoints = skinData->GetNumPoints();
|
||||
S32 i;
|
||||
|
||||
PatchMesh & maxMesh = patchObj->patch;
|
||||
S32 numVerts = maxMesh.getNumVerts();
|
||||
if (numVerts>numPoints)
|
||||
// points should be more than verts...first set of points are the verts, the rest are control verts
|
||||
// we don't do anything with those weights...it limits the surface deformations that can take
|
||||
// place, but it's all we can do...
|
||||
return;
|
||||
|
||||
if (!numBones)
|
||||
return;
|
||||
|
||||
S32 numChannels = 2+((numBones+1)>>1);
|
||||
S32 numTVerts = maxMesh.getNumMapVerts(1);
|
||||
UVVert tv(0,0,0);
|
||||
|
||||
maxMesh.setNumMaps(numChannels);
|
||||
for (i=2; i<numChannels; i++)
|
||||
{
|
||||
// prepare each channel...
|
||||
S32 j;
|
||||
maxMesh.setNumMapVerts(i,numVerts);
|
||||
for (j=0; j<numVerts; j++)
|
||||
maxMesh.getMapVert(i,j) = tv;
|
||||
// set up tv patch faces
|
||||
maxMesh.setNumMapPatches(i,maxMesh.getNumPatches());
|
||||
for (j=0; j<maxMesh.getNumPatches(); j++)
|
||||
{
|
||||
Patch & patch = maxMesh.patches[j];
|
||||
TVPatch & tvPatch = maxMesh.getMapPatch(i,j);
|
||||
tvPatch.tv[0] = patch.v[0];
|
||||
tvPatch.tv[1] = patch.v[1];
|
||||
tvPatch.tv[2] = patch.v[2];
|
||||
tvPatch.tv[3] = patch.v[3];
|
||||
}
|
||||
}
|
||||
|
||||
for (S32 v=0; v<numVerts; v++)
|
||||
{
|
||||
for (i=0; i<skinData->GetNumAssignedBones(v); i++)
|
||||
{
|
||||
S32 bone = skinData->GetAssignedBone(v,i);
|
||||
F32 w = skinData->GetBoneWeight(v,i);
|
||||
S32 channel = 2 + (bone>>1);
|
||||
UVVert & tv = maxMesh.getMapVert(channel,v);
|
||||
if (bone&1)
|
||||
tv.y = w;
|
||||
else
|
||||
tv.x = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkinHelper::BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev )
|
||||
{
|
||||
this->ip = ip;
|
||||
if (!hParams) {
|
||||
hParams = ip->AddRollupPage(
|
||||
hInstance,
|
||||
MAKEINTRESOURCE(IDD_SKINHELP_PANEL),
|
||||
SkinHelperDlgProc,
|
||||
GetString(IDS_SKINHELP_PARAMS),
|
||||
(LPARAM)this);
|
||||
ip->RegisterDlgWnd(hParams);
|
||||
} else {
|
||||
SetWindowLong(hParams,GWL_USERDATA,(LONG)this);
|
||||
}
|
||||
}
|
||||
|
||||
void SkinHelper::EndEditParams( IObjParam *ip, ULONG flags,Animatable *next)
|
||||
{
|
||||
ip->UnRegisterDlgWnd(hParams);
|
||||
ip->DeleteRollupPage(hParams);
|
||||
hParams = NULL;
|
||||
this->ip = NULL;
|
||||
}
|
||||
|
||||
|
||||
//From ReferenceMaker
|
||||
RefResult SkinHelper::NotifyRefChanged(
|
||||
Interval changeInt, RefTargetHandle hTarget,
|
||||
PartID& partID, RefMessage message)
|
||||
{
|
||||
//TODO: Add code to handle the various reference changed messages
|
||||
return REF_SUCCEED;
|
||||
}
|
||||
|
||||
//From Object
|
||||
BOOL SkinHelper::HasUVW()
|
||||
{
|
||||
//TODO: Return whether the object has UVW coordinates or not
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SkinHelper::SetGenUVW(BOOL sw)
|
||||
{
|
||||
if (sw==HasUVW()) return;
|
||||
//TODO: Set the plugin internal value to sw
|
||||
}
|
||||
|
||||
IOResult SkinHelper::Load(ILoad *iload)
|
||||
{
|
||||
//TODO: Add code to allow plugin to load its data
|
||||
|
||||
return IO_OK;
|
||||
}
|
||||
|
||||
IOResult SkinHelper::Save(ISave *isave)
|
||||
{
|
||||
//TODO: Add code to allow plugin to save its data
|
||||
|
||||
return IO_OK;
|
||||
}
|
85
tools/max2dtsExporter/skinHelper.h
Executable file
85
tools/max2dtsExporter/skinHelper.h
Executable file
@ -0,0 +1,85 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SKINHELPER__H
|
||||
#define __SKINHELPER__H
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <Max.h>
|
||||
#include <istdplug.h>
|
||||
#include <iparamb2.h>
|
||||
#include <iparamm2.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _MAXUTIL_H_
|
||||
#include "max2dtsExporter/maxUtil.h"
|
||||
#endif
|
||||
|
||||
#define SKINHELPER_CLASS_ID Class_ID(0x20dfdba0, 0x60646cb4)
|
||||
extern ClassDesc* GetSkinHelperDesc();
|
||||
extern TCHAR *GetString(S32);
|
||||
|
||||
class SkinHelper : public WSModifier
|
||||
{
|
||||
public:
|
||||
static HWND hParams;
|
||||
static IObjParam *ip; //Access to the interface
|
||||
|
||||
// From Animatable
|
||||
TCHAR *GetObjectName() { return "SkinHelper"; }
|
||||
|
||||
//From Modifier
|
||||
ChannelMask ChannelsUsed() { return TEXMAP_CHANNEL; }
|
||||
ChannelMask ChannelsChanged() { return TEXMAP_CHANNEL; }
|
||||
void ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node);
|
||||
void modifyTriObject(TriObject *, ISkin *, ISkinContextData *);
|
||||
void modifyPatchObject(PatchObject *, ISkin *, ISkinContextData *);
|
||||
|
||||
Class_ID InputType() {return defObjectClassID;}
|
||||
Interval LocalValidity(TimeValue t);
|
||||
|
||||
// From BaseObject
|
||||
BOOL ChangeTopology() {return FALSE;}
|
||||
|
||||
CreateMouseCallBack* GetCreateMouseCallBack() {return NULL;}
|
||||
void BeginEditParams(IObjParam *ip, ULONG flags,Animatable *prev);
|
||||
void EndEditParams(IObjParam *ip, ULONG flags,Animatable *next);
|
||||
|
||||
Interval GetValidity(TimeValue t);
|
||||
|
||||
// Automatic texture support
|
||||
BOOL HasUVW();
|
||||
void SetGenUVW(BOOL sw);
|
||||
|
||||
// Loading/Saving
|
||||
IOResult Load(ILoad *iload);
|
||||
IOResult Save(ISave *isave);
|
||||
|
||||
//From Animatable
|
||||
Class_ID ClassID() {return SKINHELPER_CLASS_ID;}
|
||||
SClass_ID SuperClassID() { return WSM_CLASS_ID; }
|
||||
void GetClassName(TSTR& s) {s = "SkinHelper"; }
|
||||
|
||||
RefTargetHandle Clone( RemapDir &remap );
|
||||
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
|
||||
PartID& partID, RefMessage message);
|
||||
|
||||
int NumSubs() { return 0; }
|
||||
TSTR SubAnimName(int i) { return _T(""); }
|
||||
Animatable* SubAnim(int i) { return NULL; }
|
||||
int NumRefs() { return 0; }
|
||||
RefTargetHandle GetReference(int i) { return NULL; }
|
||||
void SetReference(int i, RefTargetHandle rtarg);
|
||||
|
||||
void DeleteThis() { delete this; }
|
||||
//Constructor/Destructor
|
||||
SkinHelper();
|
||||
~SkinHelper();
|
||||
};
|
||||
|
||||
#endif // __SKINHELPER__H
|
907
tools/max2dtsExporter/stripper.cc
Executable file
907
tools/max2dtsExporter/stripper.cc
Executable file
@ -0,0 +1,907 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "max2dtsExporter/stripper.h"
|
||||
|
||||
F32 Stripper::adjacencyWeight = 5;
|
||||
F32 Stripper::noswapWeight = 3;
|
||||
F32 Stripper::alreadyCachedWeight = 1;
|
||||
U32 Stripper::cacheSize = 16;
|
||||
U32 Stripper::simK = 5;
|
||||
|
||||
|
||||
Stripper::Stripper(Vector<TSDrawPrimitive> & _faces, Vector<U16> & _faceIndices)
|
||||
: faces(_faces), faceIndices(_faceIndices), adjacent(_faces.size(),_faces.size())
|
||||
{
|
||||
// keep track of whether face used in a strip yet
|
||||
used.setSize(faces.size());
|
||||
for (S32 i=0; i<faces.size(); i++)
|
||||
used[i]=false;
|
||||
|
||||
clearCache();
|
||||
cacheMisses = 0; // definitely don't want to clear this every time we clear the cache!
|
||||
|
||||
bestLength = -1;
|
||||
errorStr = NULL;
|
||||
}
|
||||
|
||||
Stripper::Stripper(Stripper & stripper)
|
||||
: faces(stripper.faces), faceIndices(stripper.faceIndices), adjacent(stripper.faces.size(),stripper.faces.size()),
|
||||
numAdjacent(stripper.numAdjacent), used(stripper.used), vertexCache(stripper.vertexCache),
|
||||
recentFaces(stripper.recentFaces), strips(stripper.strips), stripIndices(stripper.stripIndices)
|
||||
{
|
||||
currentFace = stripper.currentFace;
|
||||
limitStripLength = stripper.limitStripLength;
|
||||
bestLength = stripper.bestLength;
|
||||
cacheMisses = stripper.cacheMisses;
|
||||
adjacent.clearAllBits();
|
||||
for (S32 i=0; i<faces.size(); i++)
|
||||
for (S32 j=0; j<faces.size(); j++)
|
||||
if (stripper.adjacent.isSet(i,j))
|
||||
adjacent.setBit(i,j);
|
||||
errorStr = NULL;
|
||||
}
|
||||
|
||||
Stripper::~Stripper()
|
||||
{
|
||||
dFree(errorStr);
|
||||
}
|
||||
|
||||
void Stripper::testCache(S32 addedFace)
|
||||
{
|
||||
S32 * cache = &vertexCache.last();
|
||||
|
||||
// make sure last 3 verts on strip list are last 3 verts in cache
|
||||
U16 * indices = &stripIndices.last();
|
||||
if (*indices!=*cache || *(indices-1)!=*(cache-1) || *(indices-2)!=*(cache-2))
|
||||
{
|
||||
setExportError("Assertion failed when stripping (11)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (addedFace>=0)
|
||||
{
|
||||
// make sure current face is still last 3 items in the cache
|
||||
TSDrawPrimitive & face = faces[addedFace];
|
||||
U32 idx0 = faceIndices[face.start+0];
|
||||
U32 idx1 = faceIndices[face.start+1];
|
||||
U32 idx2 = faceIndices[face.start+2];
|
||||
if ( idx0!=*(cache) && idx0!=*(cache-1) && idx0!=*(cache-2))
|
||||
{
|
||||
setExportError("Assertion failed when stripping (8)");
|
||||
return;
|
||||
}
|
||||
if ( idx1!=*(cache) && idx1!=*(cache-1) && idx1!=*(cache-2))
|
||||
{
|
||||
setExportError("Assertion failed when stripping (9)");
|
||||
return;
|
||||
}
|
||||
if ( idx2!=*(cache) && idx2!=*(cache-1) && idx2!=*(cache-2))
|
||||
{
|
||||
setExportError("Assertion failed when stripping (10)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Stripper::copyParams(Stripper * from)
|
||||
{
|
||||
limitStripLength = from->limitStripLength;
|
||||
}
|
||||
|
||||
void Stripper::makeStrips()
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return;
|
||||
|
||||
// main strip loop...
|
||||
U32 start, end, i, sz;
|
||||
Vector<TSDrawPrimitive> someFaces;
|
||||
Vector<U16> someIndices;
|
||||
for (start = 0; start<faces.size(); start=end)
|
||||
{
|
||||
for (end=start; end<faces.size() && faces[start].matIndex==faces[end].matIndex; end++)
|
||||
;
|
||||
|
||||
if (start==0 && end==faces.size())
|
||||
{
|
||||
// all same material, no need to copy anything
|
||||
makeStripsB();
|
||||
return;
|
||||
}
|
||||
|
||||
// copy start to end faces into new list -- this is so we end up doing less copying
|
||||
// down the road (when we are doing the look ahead simulation)
|
||||
someFaces.clear();
|
||||
someIndices.clear();
|
||||
for (i=start;i<end;i++)
|
||||
{
|
||||
someFaces.push_back(faces[i]);
|
||||
someFaces.last().start = someIndices.size();
|
||||
someIndices.push_back(faceIndices[faces[i].start + 0]);
|
||||
someIndices.push_back(faceIndices[faces[i].start + 1]);
|
||||
someIndices.push_back(faceIndices[faces[i].start + 2]);
|
||||
}
|
||||
|
||||
// strip these...
|
||||
Stripper someStrips(someFaces,someIndices);
|
||||
someStrips.copyParams(this);
|
||||
someStrips.makeStripsB();
|
||||
if (isError()) return;
|
||||
|
||||
// copy these strips into our arrays
|
||||
sz = strips.size();
|
||||
strips.setSize(sz+someStrips.strips.size());
|
||||
for (i=0; i<someStrips.strips.size(); i++)
|
||||
{
|
||||
strips[i+sz] = someStrips.strips[i];
|
||||
strips[i+sz].start += stripIndices.size();
|
||||
}
|
||||
sz = stripIndices.size();
|
||||
stripIndices.setSize(sz+someStrips.stripIndices.size());
|
||||
dMemcpy(&stripIndices[sz],someStrips.stripIndices.address(),someStrips.stripIndices.size()*sizeof(U16));
|
||||
|
||||
// update cache misses
|
||||
cacheMisses += someStrips.getCacheMisses();
|
||||
}
|
||||
}
|
||||
|
||||
void Stripper::makeStripsB()
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return;
|
||||
|
||||
// set adjacency info
|
||||
setAdjacency(0,faces.size());
|
||||
|
||||
while (1)
|
||||
{
|
||||
strips.increment();
|
||||
TSDrawPrimitive & strip = strips.last();
|
||||
strip.start = stripIndices.size();
|
||||
strip.numElements = 0;
|
||||
if (faces[0].matIndex & TSDrawPrimitive::NoMaterial)
|
||||
strip.matIndex = TSDrawPrimitive::NoMaterial;
|
||||
else
|
||||
strip.matIndex = faces[0].matIndex & TSDrawPrimitive::MaterialMask;
|
||||
strip.matIndex |= TSDrawPrimitive::Strip | TSDrawPrimitive::Indexed;
|
||||
|
||||
if (!startStrip(strip,0,faces.size()))
|
||||
{
|
||||
strips.decrement();
|
||||
break;
|
||||
}
|
||||
|
||||
while (addStrip(strip,0,faces.size()));
|
||||
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return;
|
||||
}
|
||||
|
||||
// let's make sure everything is legit up till here
|
||||
U32 i;
|
||||
for (i=0; i<faces.size(); i++)
|
||||
{
|
||||
if (!used[i])
|
||||
{
|
||||
setExportError("Assertion failed when stripping (1)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i=0; i<numAdjacent.size(); i++)
|
||||
{
|
||||
if (numAdjacent[i])
|
||||
{
|
||||
setExportError("Assertion failed when stripping (2)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure all faces were used, o.w. it's an error
|
||||
for (i=0; i<used.size(); i++)
|
||||
{
|
||||
if (!used[i])
|
||||
{
|
||||
setExportError("Assertion failed when stripping (3)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void Stripper::makeStrips()
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return;
|
||||
|
||||
// main strip loop...
|
||||
U32 start, end, i;
|
||||
for (start = 0; start<faces.size(); start=end)
|
||||
{
|
||||
for (end=start; end<faces.size() && faces[start].matIndex==faces[end].matIndex; end++)
|
||||
;
|
||||
|
||||
// set adjacency info
|
||||
setAdjacency(start,end);
|
||||
|
||||
while (1)
|
||||
{
|
||||
strips.increment();
|
||||
TSDrawPrimitive & strip = strips.last();
|
||||
strip.start = stripIndices.size();
|
||||
strip.numElements = 0;
|
||||
if (faces[start].matIndex & TSDrawPrimitive::NoMaterial)
|
||||
strip.matIndex = TSDrawPrimitive::NoMaterial;
|
||||
else
|
||||
strip.matIndex = faces[start].matIndex & TSDrawPrimitive::MaterialMask;
|
||||
strip.matIndex |= TSDrawPrimitive::Strip | TSDrawPrimitive::Indexed;
|
||||
|
||||
if (!startStrip(strip,start,end))
|
||||
{
|
||||
strips.decrement();
|
||||
break;
|
||||
}
|
||||
|
||||
while (addStrip(strip,start,end));
|
||||
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return;
|
||||
}
|
||||
|
||||
// let's make sure everything is legit up till here
|
||||
for (i=start; i<end; i++)
|
||||
{
|
||||
if (!used[i])
|
||||
{
|
||||
setExportError("Assertion failed when stripping (1)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i=0; i<numAdjacent.size(); i++)
|
||||
{
|
||||
if (numAdjacent[i])
|
||||
{
|
||||
setExportError("Assertion failed when stripping (2)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure all faces were used, o.w. it's an error
|
||||
for (i=0; i<used.size(); i++)
|
||||
{
|
||||
if (!used[i])
|
||||
{
|
||||
setExportError("Assertion failed when stripping (3)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// used for simulating addition of "len" more faces with a forced strip restart after "restart" faces
|
||||
S32 Stripper::continueStrip(S32 startFace, S32 endFace, S32 len, S32 restart)
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return 0;
|
||||
|
||||
TSDrawPrimitive & strip = strips.last();
|
||||
|
||||
while (restart && addStrip(strip,startFace,endFace))
|
||||
restart--,len--;
|
||||
|
||||
// either restarted when we were forced to or restarted on our own
|
||||
// either way, continue adding faces till len==0
|
||||
while (len)
|
||||
{
|
||||
strips.increment();
|
||||
TSDrawPrimitive & strip = strips.last();
|
||||
strip.start = stripIndices.size();
|
||||
strip.numElements = 0;
|
||||
if (faces[startFace].matIndex & TSDrawPrimitive::NoMaterial)
|
||||
strip.matIndex = TSDrawPrimitive::NoMaterial;
|
||||
else
|
||||
strip.matIndex = faces[startFace].matIndex & TSDrawPrimitive::MaterialMask;
|
||||
strip.matIndex |= TSDrawPrimitive::Strip | TSDrawPrimitive::Indexed;
|
||||
|
||||
if (!startStrip(strip,startFace,endFace))
|
||||
{
|
||||
strips.decrement();
|
||||
break;
|
||||
}
|
||||
len--;
|
||||
|
||||
while (len && addStrip(strip,startFace,endFace))
|
||||
len--;
|
||||
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return 0;
|
||||
}
|
||||
|
||||
return restart;
|
||||
}
|
||||
|
||||
void Stripper::setAdjacency(S32 startFace, S32 endFace)
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return;
|
||||
|
||||
// two faces adjacent only if wound the same way (so shared edge must appear in opp. order)
|
||||
S32 i,j;
|
||||
numAdjacent.setSize(faces.size());
|
||||
for (i=0; i<numAdjacent.size(); i++)
|
||||
numAdjacent[i] = 0;
|
||||
|
||||
adjacent.clearAllBits();
|
||||
|
||||
for (i=startFace; i<endFace-1; i++)
|
||||
{
|
||||
// the i-indices...
|
||||
U32 idx0 = faceIndices[faces[i].start + 0];
|
||||
U32 idx1 = faceIndices[faces[i].start + 1];
|
||||
U32 idx2 = faceIndices[faces[i].start + 2];
|
||||
|
||||
for (j=i+1; j<endFace; j++)
|
||||
{
|
||||
// the j-indices...
|
||||
U32 jdx0 = faceIndices[faces[j].start + 0];
|
||||
U32 jdx1 = faceIndices[faces[j].start + 1];
|
||||
U32 jdx2 = faceIndices[faces[j].start + 2];
|
||||
|
||||
// we don't want to be adjacent if we share all our vertices...
|
||||
if ( ( idx0==jdx0 || idx0==jdx1 || idx0==jdx2) &&
|
||||
( idx1==jdx0 || idx1==jdx1 || idx1==jdx2) &&
|
||||
( idx2==jdx0 || idx2==jdx1 || idx2==jdx2) )
|
||||
continue;
|
||||
|
||||
// test adjacency...
|
||||
if ( ((idx0==jdx1) && (idx1==jdx0)) || ((idx0==jdx2) && (idx1==jdx1)) || ((idx0==jdx0) && (idx1==jdx2)) ||
|
||||
((idx1==jdx1) && (idx2==jdx0)) || ((idx1==jdx2) && (idx2==jdx1)) || ((idx1==jdx0) && (idx2==jdx2)) ||
|
||||
((idx2==jdx1) && (idx0==jdx0)) || ((idx2==jdx2) && (idx0==jdx1)) || ((idx2==jdx0) && (idx0==jdx2)) )
|
||||
{
|
||||
// i,j are adjacent
|
||||
if (adjacent.isSet(i,j) || adjacent.isSet(j,i))
|
||||
{
|
||||
setExportError("wtf (1)");
|
||||
return;
|
||||
}
|
||||
adjacent.setBit(i,j);
|
||||
adjacent.setBit(j,i);
|
||||
if (!adjacent.isSet(i,j) || !adjacent.isSet(j,i))
|
||||
{
|
||||
setExportError("wtf (2)");
|
||||
return;
|
||||
}
|
||||
numAdjacent[i]++;
|
||||
numAdjacent[j]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Stripper::clearCache()
|
||||
{
|
||||
vertexCache.setSize(cacheSize);
|
||||
for (S32 i=0; i<vertexCache.size(); i++)
|
||||
vertexCache[i] = -1;
|
||||
}
|
||||
|
||||
void Stripper::addToCache(S32 vertexIndex)
|
||||
{
|
||||
S32 i;
|
||||
for (i=0; i<vertexCache.size(); i++)
|
||||
if (vertexCache[i]==vertexIndex)
|
||||
break;
|
||||
if (i==vertexCache.size())
|
||||
cacheMisses++;
|
||||
|
||||
vertexCache.erase((U32)0);
|
||||
vertexCache.push_back(vertexIndex);
|
||||
}
|
||||
|
||||
void Stripper::addToCache(S32 vertexIndex, U32 posFromBack)
|
||||
{
|
||||
// theoretically this could result in a cache miss, but never used that way so
|
||||
// we won't check...
|
||||
|
||||
vertexCache.erase((U32)0);
|
||||
vertexCache.insert(vertexCache.size()-posFromBack);
|
||||
vertexCache[vertexCache.size()-1-posFromBack] = vertexIndex;
|
||||
}
|
||||
|
||||
bool Stripper::startStrip(TSDrawPrimitive & strip, S32 startFace, S32 endFace)
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return false;
|
||||
|
||||
S32 i,j;
|
||||
|
||||
S32 bestFace = -1;
|
||||
|
||||
// first search the list of faces with neighbors that were recently visited
|
||||
for (i=0;i<recentFaces.size();i++)
|
||||
{
|
||||
if (!used[recentFaces[i]])
|
||||
{
|
||||
bestFace = recentFaces[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
recentFaces.clear();
|
||||
|
||||
// if we didn't find one above, search for a good face
|
||||
if (bestFace<0)
|
||||
{
|
||||
S32 bestScore = -1;
|
||||
for (i=startFace; i<endFace; i++)
|
||||
{
|
||||
if (used[i])
|
||||
continue;
|
||||
|
||||
// how many of the verts are in the cache?
|
||||
// Question: should we favor verts that occur early/late in the cache?
|
||||
U32 inCache = 0;
|
||||
U32 idx0 = faceIndices[faces[i].start + 0];
|
||||
U32 idx1 = faceIndices[faces[i].start + 1];
|
||||
U32 idx2 = faceIndices[faces[i].start + 2];
|
||||
|
||||
for (j=0; j<vertexCache.size(); j++)
|
||||
if (vertexCache[j] == idx0)
|
||||
{
|
||||
inCache++;
|
||||
break;
|
||||
}
|
||||
for (j=0; j<vertexCache.size(); j++)
|
||||
if (vertexCache[j] == idx1)
|
||||
{
|
||||
inCache++;
|
||||
break;
|
||||
}
|
||||
for (j=0; j<vertexCache.size(); j++)
|
||||
if (vertexCache[j] == idx2)
|
||||
{
|
||||
inCache++;
|
||||
break;
|
||||
}
|
||||
S32 currentScore = (inCache<<4) + numAdjacent[i];
|
||||
if (currentScore>bestScore)
|
||||
{
|
||||
bestFace = i;
|
||||
bestScore = currentScore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if no face...
|
||||
if (bestFace<0)
|
||||
return false;
|
||||
|
||||
// start the strip -- add in standard order...may be changed later
|
||||
strip.numElements += 3;
|
||||
stripIndices.push_back(faceIndices[faces[bestFace].start + 0]);
|
||||
addToCache(stripIndices.last());
|
||||
stripIndices.push_back(faceIndices[faces[bestFace].start + 1]);
|
||||
addToCache(stripIndices.last());
|
||||
stripIndices.push_back(faceIndices[faces[bestFace].start + 2]);
|
||||
addToCache(stripIndices.last());
|
||||
|
||||
testCache(bestFace);
|
||||
|
||||
// adjust adjacency information
|
||||
for (j=startFace; j<endFace; j++)
|
||||
{
|
||||
if (j==bestFace || used[j])
|
||||
continue;
|
||||
if (adjacent.isSet(bestFace,j))
|
||||
{
|
||||
numAdjacent[j]--;
|
||||
if (numAdjacent[j]<0)
|
||||
{
|
||||
setExportError("Assertion failed when stripping (4)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mark face as used
|
||||
used[bestFace] = true;
|
||||
numAdjacent[bestFace] = 0;
|
||||
currentFace = bestFace;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Stripper::getVerts(S32 face, S32 & oldVert0, S32 & oldVert1, S32 & addVert)
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return;
|
||||
|
||||
Vector<S32> prev;
|
||||
addVert = -1;
|
||||
TSDrawPrimitive & addFace = faces[face];
|
||||
U32 idx0 = faceIndices[addFace.start+0];
|
||||
U32 idx1 = faceIndices[addFace.start+1];
|
||||
U32 idx2 = faceIndices[addFace.start+2];
|
||||
S32 * cache = &vertexCache.last();
|
||||
if (idx0==*cache || idx0==*(cache-1) || idx0==*(cache-2))
|
||||
prev.push_back(idx0);
|
||||
else
|
||||
addVert = idx0;
|
||||
if (idx1==*cache || idx1==*(cache-1) || idx1==*(cache-2))
|
||||
prev.push_back(idx1);
|
||||
else
|
||||
addVert = idx1;
|
||||
if (idx2==*cache || idx2==*(cache-1) || idx2==*(cache-2))
|
||||
prev.push_back(idx2);
|
||||
else
|
||||
addVert = idx2;
|
||||
if (addVert<0 || prev.size()!=2)
|
||||
{
|
||||
setExportError("Assertion failed when stripping (5)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx1==addVert)
|
||||
{
|
||||
// swap order of oldVerts
|
||||
oldVert0 = prev[1];
|
||||
oldVert1 = prev[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep order
|
||||
oldVert0 = prev[0];
|
||||
oldVert1 = prev[1];
|
||||
}
|
||||
}
|
||||
|
||||
// assumes start + 0,1,2 is a triangle or first 3 indices of a strip
|
||||
void Stripper::rotateFace(S32 start, Vector<U16> & indices)
|
||||
{
|
||||
U32 tmp = indices[start];
|
||||
indices[start] = indices[start+1];
|
||||
indices[start+1] = indices[start+2];
|
||||
indices[start+2] = tmp;
|
||||
|
||||
S32 * cache = &vertexCache.last();
|
||||
tmp = *(cache-2);
|
||||
*(cache-2) = *(cache-1);
|
||||
*(cache-1) = *cache;
|
||||
*cache = tmp;
|
||||
|
||||
testCache(currentFace);
|
||||
}
|
||||
|
||||
bool Stripper::swapNeeded(S32 oldVert0, S32 oldVert1)
|
||||
{
|
||||
S32 * cache = &vertexCache.last();
|
||||
|
||||
return (*cache!=oldVert0 || *(cache-1)!=oldVert1) && (*cache!=oldVert1 || *(cache-1)!=oldVert0);
|
||||
|
||||
// Long form:
|
||||
// if ( (*cache==oldVert0 && *(cache-1)==oldVert1) || (*cache==oldVert1 && *(cache-1)==oldVert0) )
|
||||
// return false;
|
||||
// else
|
||||
// return true;
|
||||
}
|
||||
|
||||
F32 Stripper::getScore(S32 face, bool ignoreOrder)
|
||||
{
|
||||
// score face depending on following criteria:
|
||||
// -- select face with fewest adjacencies?
|
||||
// -- select face that continues strip without swap?
|
||||
// -- select face with new vertex already in cache?
|
||||
// weighting of each criteria controlled by adjacencyWeight, noswapWeight, and alreadyCachedWeight
|
||||
// if ignoreOrder is true, don't worry about swaps
|
||||
|
||||
if (face<0)
|
||||
return -100000.0f;
|
||||
|
||||
// get the 2 verts from the last face and the 1 new vert
|
||||
S32 oldVert0, oldVert1, addVert;
|
||||
getVerts(face, oldVert0, oldVert1, addVert);
|
||||
|
||||
F32 score = 0.0f;
|
||||
|
||||
// fewer adjacent faces the better...
|
||||
score -= numAdjacent[face] * adjacencyWeight;
|
||||
|
||||
// reward if no swap needed...don't worry about order (only same facing faces get here)
|
||||
if (!ignoreOrder && !swapNeeded(oldVert0,oldVert1))
|
||||
score += noswapWeight;
|
||||
|
||||
// if new vertex in the cache, add the already in cache bonus...
|
||||
for (S32 i=0;i<vertexCache.size();i++)
|
||||
if (vertexCache[i]==addVert)
|
||||
{
|
||||
score += alreadyCachedWeight;
|
||||
break;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
bool Stripper::faceHasEdge(S32 face, U32 idx0, U32 idx1)
|
||||
{
|
||||
// return true if face has edge idx0, idx1 (in that order)
|
||||
S32 start = faces[face].start;
|
||||
U32 vi0 = faceIndices[start+0];
|
||||
U32 vi1 = faceIndices[start+1];
|
||||
U32 vi2 = faceIndices[start+2];
|
||||
|
||||
if ( (vi0==idx0 && vi1==idx1) || (vi1==idx0 && vi2==idx1) || (vi2==idx0 && vi0==idx1) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Stripper::getAdjacentFaces(S32 startFace, S32 endFace, S32 face, S32 & face0, S32 & face1, S32 & face2)
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return;
|
||||
|
||||
// we return one face per edge...ties go to face with fewest adjacencies
|
||||
S32 adj0=-1,adj1=-1,adj2=-1;
|
||||
face0=face1=face2=-1;
|
||||
|
||||
U32 idx0 = faceIndices[faces[face].start + 0];
|
||||
U32 idx1 = faceIndices[faces[face].start + 1];
|
||||
U32 idx2 = faceIndices[faces[face].start + 2];
|
||||
for (S32 i=startFace; i<endFace; i++)
|
||||
{
|
||||
if (i==face || used[i])
|
||||
continue;
|
||||
|
||||
if (!adjacent.isSet(face,i))
|
||||
continue;
|
||||
|
||||
// which edge is this face on
|
||||
if (faceHasEdge(i,idx1,idx0))
|
||||
{
|
||||
if (adj0<0 || numAdjacent[i]<adj0)
|
||||
{
|
||||
face0 = i;
|
||||
adj0 = numAdjacent[i];
|
||||
}
|
||||
}
|
||||
else if (faceHasEdge(i,idx2,idx1))
|
||||
{
|
||||
if (adj1<0 || numAdjacent[i]<adj1)
|
||||
{
|
||||
face1 = i;
|
||||
adj1 = numAdjacent[i];
|
||||
}
|
||||
}
|
||||
else if (faceHasEdge(i,idx0,idx2))
|
||||
{
|
||||
if (adj2<0 || numAdjacent[i]<adj2)
|
||||
{
|
||||
face2 = i;
|
||||
adj2 = numAdjacent[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setExportError("Assertion failed when stripping (6)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Stripper::stripLongEnough(S32 startFace, S32 endFace)
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return false;
|
||||
|
||||
if (!limitStripLength)
|
||||
return false;
|
||||
|
||||
// simulate stopping the strip here and continuing for cacheSize+simK more rounds
|
||||
Stripper strip0(*this);
|
||||
strip0.setLimitStripLength(false);
|
||||
strip0.resetCacheMisses();
|
||||
strip0.continueStrip(startFace,endFace,cacheSize+simK,0);
|
||||
U32 stop0 = strip0.getCacheMisses();
|
||||
|
||||
// re-simulate previous best length (-1)
|
||||
U32 bestMisses;
|
||||
if (--bestLength<2)
|
||||
bestLength = 1;
|
||||
Stripper stripper(*this);
|
||||
stripper.setLimitStripLength(false);
|
||||
stripper.resetCacheMisses();
|
||||
stripper.continueStrip(startFace,endFace,cacheSize+simK,bestLength);
|
||||
bestMisses = stripper.getCacheMisses();
|
||||
if (bestMisses<=stop0)
|
||||
return false;
|
||||
|
||||
for (S32 i=1; i<cacheSize+simK; i++)
|
||||
{
|
||||
if (i==bestLength)
|
||||
continue;
|
||||
|
||||
Stripper stripper(*this);
|
||||
stripper.setLimitStripLength(false);
|
||||
stripper.resetCacheMisses();
|
||||
S32 underShoot = stripper.continueStrip(startFace,endFace,cacheSize+simK,i);
|
||||
U32 misses = stripper.getCacheMisses();
|
||||
if (misses<bestMisses)
|
||||
{
|
||||
bestMisses = misses;
|
||||
bestLength = i - underShoot;
|
||||
}
|
||||
if (misses<=stop0)
|
||||
return false;
|
||||
// undershoot is how much we missed our restart target by...i.e., if we wanted
|
||||
// to restart after 5 faces and underShoot is 1, then we restarted after 4.
|
||||
// If undershoot is positive, then we're going to end up restarting at the same
|
||||
// place on future iterations, so break out of the loop now to save time
|
||||
if (underShoot>0)
|
||||
break;
|
||||
}
|
||||
|
||||
// survived the gauntlet...
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Stripper::canGo(S32 face)
|
||||
{
|
||||
if (face<0)
|
||||
return false;
|
||||
|
||||
U32 idx0 = faceIndices[faces[face].start + 0];
|
||||
U32 idx1 = faceIndices[faces[face].start + 1];
|
||||
U32 idx2 = faceIndices[faces[face].start + 2];
|
||||
|
||||
U32 last = stripIndices.last();
|
||||
if (last==idx0 || last==idx1 || last==idx2)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Stripper::addStrip(TSDrawPrimitive & strip, S32 startFace, S32 endFace)
|
||||
{
|
||||
// if already encountered an error, then
|
||||
// we'll just go through the motions
|
||||
if (isError()) return false;
|
||||
|
||||
if (strip.numElements>3 && stripLongEnough(startFace,endFace))
|
||||
return false;
|
||||
|
||||
testCache(currentFace);
|
||||
|
||||
// get unused faces adjacent to current face (choose only faces pointing same way)
|
||||
// if more than one face adjacent on an edge (unusual case) chooses one with lowest adjacency count
|
||||
S32 face0, face1, face2;
|
||||
getAdjacentFaces(startFace,endFace,currentFace,face0,face1,face2);
|
||||
|
||||
// one more check -- make sure most recent vert is in face
|
||||
// this can happen in exceptional case where we "back up"
|
||||
// using common edge between previous two faces, but not the
|
||||
// previous face (a v-junction?)
|
||||
bool bad0,bad1,bad2;
|
||||
bad0=bad1=bad2=false;
|
||||
if (strip.numElements!=3 && !canGo(face0))
|
||||
face0=-1;
|
||||
if (strip.numElements!=3 && !canGo(face1))
|
||||
face1=-1;
|
||||
if (strip.numElements!=3 && !canGo(face2))
|
||||
face2=-1;
|
||||
|
||||
if (face0<0 && face1<0 && face2<0)
|
||||
return false;
|
||||
|
||||
testCache(currentFace);
|
||||
|
||||
// score faces, choose highest score
|
||||
F32 score0 = getScore(face0,strip.numElements==3);
|
||||
F32 score1 = getScore(face1,strip.numElements==3);
|
||||
F32 score2 = getScore(face2,strip.numElements==3);
|
||||
S32 bestFace = -1;
|
||||
if (score0>=score1 && score0>=score2)
|
||||
bestFace = face0;
|
||||
else if (score1>=score0 && score1>=score2)
|
||||
bestFace = face1;
|
||||
else if (score2>=score1 && score2>=score0)
|
||||
bestFace = face2;
|
||||
|
||||
testCache(currentFace);
|
||||
|
||||
// add new element
|
||||
S32 oldVert0, oldVert1, addVert;
|
||||
getVerts(bestFace,oldVert0,oldVert1,addVert);
|
||||
|
||||
testCache(currentFace);
|
||||
|
||||
if (strip.numElements==3)
|
||||
{
|
||||
testCache(currentFace);
|
||||
|
||||
// special case...rotate previous element until we can add this face
|
||||
U32 doh=0;
|
||||
while (swapNeeded(oldVert0,oldVert1))
|
||||
{
|
||||
rotateFace(strip.start,stripIndices);
|
||||
if (++doh==3)
|
||||
{
|
||||
setExportError("Assertion error while stripping: infinite loop");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
stripIndices.push_back(addVert);
|
||||
addToCache(addVert);
|
||||
strip.numElements++;
|
||||
|
||||
testCache(bestFace);
|
||||
}
|
||||
else
|
||||
{
|
||||
testCache(currentFace);
|
||||
|
||||
if (swapNeeded(oldVert0,oldVert1))
|
||||
{
|
||||
U32 sz = stripIndices.size();
|
||||
U32 dup = stripIndices[sz-3];
|
||||
stripIndices.insert(sz-1);
|
||||
stripIndices[sz-1] = dup;
|
||||
addToCache(dup,1);
|
||||
strip.numElements++;
|
||||
|
||||
testCache(-1);
|
||||
}
|
||||
|
||||
stripIndices.push_back(addVert);
|
||||
strip.numElements++;
|
||||
addToCache(addVert);
|
||||
|
||||
testCache(bestFace);
|
||||
}
|
||||
|
||||
// add other faces to recentFaces list
|
||||
if (face0>=0 && face0!=bestFace)
|
||||
recentFaces.push_back(face0);
|
||||
if (face1>=0 && face1!=bestFace)
|
||||
recentFaces.push_back(face1);
|
||||
if (face2>=0 && face2!=bestFace)
|
||||
recentFaces.push_back(face2);
|
||||
|
||||
// adjust adjacency information
|
||||
for (S32 j=startFace; j<endFace; j++)
|
||||
{
|
||||
if (j==bestFace || used[j])
|
||||
continue;
|
||||
if (adjacent.isSet(bestFace,j))
|
||||
{
|
||||
numAdjacent[j]--;
|
||||
if (numAdjacent[j]<0)
|
||||
{
|
||||
setExportError("Assertion failed when stripping (7)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mark face as used
|
||||
used[bestFace] = true;
|
||||
numAdjacent[bestFace] = 0;
|
||||
currentFace = bestFace;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
87
tools/max2dtsExporter/stripper.h
Executable file
87
tools/max2dtsExporter/stripper.h
Executable file
@ -0,0 +1,87 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _TSSHAPE_H_
|
||||
#include "ts/tsShape.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/tVector.h"
|
||||
#endif
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _BITMATRIX_H_
|
||||
#include "core/bitMatrix.h"
|
||||
#endif
|
||||
|
||||
class Stripper
|
||||
{
|
||||
Vector<S32> numAdjacent;
|
||||
Vector<bool> used;
|
||||
BitMatrix adjacent;
|
||||
Vector<S32> vertexCache;
|
||||
Vector<S32> recentFaces;
|
||||
S32 currentFace;
|
||||
bool limitStripLength;
|
||||
S32 bestLength;
|
||||
U32 cacheMisses;
|
||||
|
||||
Vector<TSDrawPrimitive> strips;
|
||||
Vector<U16> stripIndices;
|
||||
|
||||
Vector<TSDrawPrimitive> & faces;
|
||||
Vector<U16> & faceIndices;
|
||||
|
||||
void clearCache();
|
||||
void addToCache(S32 vertexIndex);
|
||||
void addToCache(S32 vertexIndex, U32 posFromBack);
|
||||
|
||||
void getVerts(S32 face, S32 & oldVert0, S32 & oldVert1, S32 & addVert);
|
||||
void rotateFace(S32 start, Vector<U16> & indices);
|
||||
bool swapNeeded(S32 oldVert0, S32 oldVert1);
|
||||
F32 getScore(S32 face, bool ignoreOrder);
|
||||
bool faceHasEdge(S32 face, U32 idx0, U32 idx1);
|
||||
void getAdjacentFaces(S32 startFace, S32 endFace, S32 face, S32 & face0, S32 & face1, S32 & face2);
|
||||
|
||||
void setAdjacency(S32 startFace, S32 endFace);
|
||||
bool startStrip(TSDrawPrimitive & strip, S32 startFace, S32 endFace);
|
||||
bool addStrip(TSDrawPrimitive & strip, S32 startFace, S32 endFace);
|
||||
bool stripLongEnough(S32 startFace, S32 endFace);
|
||||
|
||||
void testCache(S32 addedFace);
|
||||
bool canGo(S32 face);
|
||||
|
||||
void makeStripsB(); // makeStrips() from faces...assumes all faces have same material index
|
||||
void copyParams(Stripper *from);
|
||||
|
||||
char * errorStr;
|
||||
void setExportError(const char * str) { errorStr = errorStr ? errorStr : dStrdup(str); }
|
||||
|
||||
public:
|
||||
|
||||
Stripper(Vector<TSDrawPrimitive> & faces, Vector<U16> & indices);
|
||||
Stripper(Stripper &);
|
||||
~Stripper();
|
||||
|
||||
void makeStrips();
|
||||
S32 continueStrip(S32 startFace, S32 endFace, S32 len, S32 restart); // used for simulation...
|
||||
void getStrips(Vector<TSDrawPrimitive> & s, Vector<U16> & si) { s=strips; si=stripIndices; }
|
||||
|
||||
void setLimitStripLength(bool lim) { limitStripLength = lim; }
|
||||
void resetCacheMisses() { cacheMisses = 0; }
|
||||
U32 getCacheMisses() { return cacheMisses; }
|
||||
|
||||
const char * getError() { return errorStr; }
|
||||
bool isError() { return errorStr!=NULL; }
|
||||
|
||||
// adjust strip building strategy
|
||||
static F32 adjacencyWeight;
|
||||
static F32 noswapWeight;
|
||||
static F32 alreadyCachedWeight;
|
||||
static U32 cacheSize;
|
||||
static U32 simK;
|
||||
};
|
||||
|
||||
|
1260
tools/max2dtsExporter/translucentSort.cc
Executable file
1260
tools/max2dtsExporter/translucentSort.cc
Executable file
File diff suppressed because it is too large
Load Diff
107
tools/max2dtsExporter/translucentSort.h
Executable file
107
tools/max2dtsExporter/translucentSort.h
Executable file
@ -0,0 +1,107 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _TRANS_SORT
|
||||
#define _TRANS_SORT
|
||||
|
||||
#ifndef _MMATH_H_
|
||||
#include "math/mMath.h"
|
||||
#endif
|
||||
#ifndef _TSINTEGERSET_H_
|
||||
#include "ts/tsIntegerSet.h"
|
||||
#endif
|
||||
#ifndef _TSSORTEDMESH_H_
|
||||
#include "ts/tsSortedMesh.h"
|
||||
#endif
|
||||
|
||||
struct TSDrawPrimitive;
|
||||
class TSIntegerSet;
|
||||
|
||||
class TranslucentSort
|
||||
{
|
||||
Vector<TSIntegerSet*> frontClusters;
|
||||
Vector<TSIntegerSet*> backClusters;
|
||||
Vector<S32> middleCluster;
|
||||
|
||||
Point3F splitNormal;
|
||||
F32 splitK;
|
||||
|
||||
S32 mNumBigFaces;
|
||||
S32 mMaxDepth;
|
||||
bool mZLayerUp;
|
||||
bool mZLayerDown;
|
||||
|
||||
S32 currentDepth;
|
||||
|
||||
TranslucentSort * frontSort;
|
||||
TranslucentSort * backSort;
|
||||
|
||||
struct FaceInfo
|
||||
{
|
||||
bool used;
|
||||
S32 priority;
|
||||
S32 parentFace;
|
||||
S32 childFace1;
|
||||
S32 childFace2;
|
||||
S32 childFace3;
|
||||
Point3F normal;
|
||||
F32 k;
|
||||
TSIntegerSet isInFrontOfMe;
|
||||
TSIntegerSet isBehindMe;
|
||||
TSIntegerSet isCutByMe;
|
||||
TSIntegerSet isCoplanarWithMe;
|
||||
};
|
||||
Vector<FaceInfo*> faceInfoList;
|
||||
Vector<FaceInfo*> saveFaceInfoList;
|
||||
|
||||
Vector<TSDrawPrimitive> & mFaces;
|
||||
Vector<U16> & mIndices;
|
||||
Vector<Point3F> & mVerts;
|
||||
Vector<Point3F> & mNorms;
|
||||
Vector<Point2F> & mTVerts;
|
||||
|
||||
void initFaces();
|
||||
void initFaceInfo(TSDrawPrimitive & face, FaceInfo & faceInfo, bool setPriority = true);
|
||||
void setFaceInfo(TSDrawPrimitive & face, FaceInfo & faceInfo);
|
||||
void clearFaces(TSIntegerSet &);
|
||||
void saveFaceInfo();
|
||||
void restoreFaceInfo();
|
||||
void addFaces(TSIntegerSet *, Vector<TSDrawPrimitive> & faces, Vector<U16> & indices, bool continueLast = false);
|
||||
void addFaces(Vector<TSIntegerSet *> &, Vector<TSDrawPrimitive> & faces, Vector<U16> & indices, bool continueLast = false);
|
||||
void addOrderedFaces(Vector<S32> &, Vector<TSDrawPrimitive> &, Vector<U16> & indices, bool continueLast = false);
|
||||
void splitFace(S32 faceIndex, Point3F normal, F32 k);
|
||||
void splitFace2(S32 faceIndex, Point3F normal, F32 k);
|
||||
void sort();
|
||||
|
||||
// routines for sorting faces when there is no perfect solution for all cases
|
||||
void copeSort(Vector<S32> &);
|
||||
void layerSort(Vector<S32> &, bool upFirst);
|
||||
|
||||
// these are for debugging
|
||||
bool anyInFrontOfPlane(Point3F normal, F32 k);
|
||||
bool anyBehindPlane(Point3F normal, F32 k);
|
||||
|
||||
//
|
||||
void generateClusters(Vector<TSSortedMesh::Cluster> & clusters, Vector<TSDrawPrimitive> & faces, Vector<U16> & indices, S32 retIndex = -1);
|
||||
|
||||
TranslucentSort(TranslucentSort *);
|
||||
TranslucentSort(Vector<TSDrawPrimitive> & faces,
|
||||
Vector<U16> & indices,
|
||||
Vector<Point3F> & verts,
|
||||
Vector<Point3F> & norms,
|
||||
Vector<Point2F> & tverts,
|
||||
S32 numBigFaces, S32 maxDepth, bool zLayerUp, bool zLayerDown);
|
||||
|
||||
~TranslucentSort();
|
||||
|
||||
public:
|
||||
|
||||
static void generateSortedMesh(TSSortedMesh * mesh, S32 numBigFaces, S32 maxDepth, bool zLayerUp, bool zLayerDown);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // _TRANS_SORT
|
||||
|
Reference in New Issue
Block a user