added everything
This commit is contained in:
80
tools/max2dtsExporterPlus/DllEntry.cpp
Executable file
80
tools/max2dtsExporterPlus/DllEntry.cpp
Executable file
@ -0,0 +1,80 @@
|
||||
/**********************************************************************
|
||||
*<
|
||||
FILE: DllEntry.cpp
|
||||
|
||||
DESCRIPTION: Contains the Dll Entry stuff
|
||||
|
||||
CREATED BY:
|
||||
|
||||
HISTORY:
|
||||
|
||||
*> Copyright (c) 2000, All Rights Reserved.
|
||||
**********************************************************************/
|
||||
#include "max2dtsExporterPlus.h"
|
||||
#include "skinHelper.h"
|
||||
|
||||
extern ClassDesc2* GetMax2dtsExporterPlusDesc();
|
||||
|
||||
HINSTANCE hInstance;
|
||||
int controlsInit = FALSE;
|
||||
|
||||
// This function is called by Windows when the DLL is loaded. This
|
||||
// function may also be called many times during time critical operations
|
||||
// like rendering. Therefore developers need to be careful what they
|
||||
// do inside this function. In the code below, note how after the DLL is
|
||||
// loaded the first time only a few statements are executed.
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
|
||||
{
|
||||
hInstance = hinstDLL; // Hang on to this DLL's instance handle.
|
||||
|
||||
if (!controlsInit) {
|
||||
controlsInit = TRUE;
|
||||
InitCustomControls(hInstance); // Initialize MAX's custom controls
|
||||
InitCommonControls(); // Initialize Win95 controls
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
// This function returns a string that describes the DLL and where the user
|
||||
// could purchase the DLL if they don't have it.
|
||||
__declspec( dllexport ) const TCHAR* LibDescription()
|
||||
{
|
||||
return GetString(IDS_LIBDESCRIPTION);
|
||||
}
|
||||
|
||||
// This function returns the number of plug-in classes this DLL
|
||||
// Must change this number when adding a new class
|
||||
__declspec( dllexport ) int LibNumberClasses()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// This function returns the number of plug-in classes this DLL
|
||||
__declspec( dllexport ) ClassDesc* LibClassDesc(int i)
|
||||
{
|
||||
switch(i) {
|
||||
case 0: return GetMax2dtsExporterPlusDesc();
|
||||
case 1: return GetSkinHelperDesc();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// This function returns a pre-defined constant indicating the version of
|
||||
// the system under which it was compiled. It is used to allow the system
|
||||
// to catch obsolete DLLs.
|
||||
__declspec( dllexport ) ULONG LibVersion()
|
||||
{
|
||||
return VERSION_3DSMAX;
|
||||
}
|
||||
|
||||
TCHAR *GetString(int id)
|
||||
{
|
||||
static TCHAR buf[256];
|
||||
|
||||
if (hInstance)
|
||||
return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
BIN
tools/max2dtsExporterPlus/max2dtsExporterPlus.aps
Executable file
BIN
tools/max2dtsExporterPlus/max2dtsExporterPlus.aps
Executable file
Binary file not shown.
210
tools/max2dtsExporterPlus/max2dtsExporterPlus.cpp
Executable file
210
tools/max2dtsExporterPlus/max2dtsExporterPlus.cpp
Executable file
@ -0,0 +1,210 @@
|
||||
/**********************************************************************
|
||||
*<
|
||||
FILE: max2dtsExporterPlus.cpp
|
||||
|
||||
DESCRIPTION: Appwizard generated plugin
|
||||
|
||||
CREATED BY:
|
||||
|
||||
HISTORY:
|
||||
|
||||
*> Copyright (c) 2000, All Rights Reserved.
|
||||
**********************************************************************/
|
||||
|
||||
#include "max2dtsExporterPlus.h"
|
||||
#include "maxSceneEnum.h"
|
||||
#include "appConfig.h"
|
||||
#include <fstream>
|
||||
|
||||
|
||||
#define MAX2DTSEXPORTERPLUS_CLASS_ID Class_ID(0x612c5c7, 0x5924d160)
|
||||
|
||||
class Max2dtsExporterPlus : public SceneExport {
|
||||
public:
|
||||
|
||||
|
||||
static HWND hParams;
|
||||
|
||||
|
||||
int ExtCount(); // Number of extensions supported
|
||||
const TCHAR * Ext(int n); // Extension #n (i.e. "3DS")
|
||||
const TCHAR * LongDesc(); // Long ASCII description (i.e. "Autodesk 3D Studio File")
|
||||
const TCHAR * ShortDesc(); // Short ASCII description (i.e. "3D Studio")
|
||||
const TCHAR * AuthorName(); // ASCII Author name
|
||||
const TCHAR * CopyrightMessage(); // ASCII Copyright message
|
||||
const TCHAR * OtherMessage1(); // Other message #1
|
||||
const TCHAR * OtherMessage2(); // Other message #2
|
||||
unsigned int Version(); // Version number * 100 (i.e. v3.01 = 301)
|
||||
void ShowAbout(HWND hWnd); // Show DLL's "About..." box
|
||||
|
||||
BOOL SupportsOptions(int ext, DWORD options);
|
||||
int DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts=FALSE, DWORD options=0);
|
||||
|
||||
void alert(const char * title, const char * message, BOOL suppressPrompts);
|
||||
|
||||
//Constructor/Destructor
|
||||
|
||||
Max2dtsExporterPlus();
|
||||
~Max2dtsExporterPlus();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Max2dtsExporterPlusClassDesc:public ClassDesc2 {
|
||||
public:
|
||||
int IsPublic() { return TRUE; }
|
||||
void * Create(BOOL loading = FALSE) { return new Max2dtsExporterPlus(); }
|
||||
const TCHAR * ClassName() { return GetString(IDS_CLASS_NAME); }
|
||||
SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
|
||||
Class_ID ClassID() { return MAX2DTSEXPORTERPLUS_CLASS_ID; }
|
||||
const TCHAR* Category() { return GetString(IDS_CATEGORY); }
|
||||
|
||||
const TCHAR* InternalName() { return _T("Max2dtsExporterPlus"); } // returns fixed parsable name (scripter-visible name)
|
||||
HINSTANCE HInstance() { return hInstance; } // returns owning module handle
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
static Max2dtsExporterPlusClassDesc Max2dtsExporterPlusDesc;
|
||||
ClassDesc2* GetMax2dtsExporterPlusDesc() { return &Max2dtsExporterPlusDesc; }
|
||||
|
||||
|
||||
BOOL CALLBACK Max2dtsExporterPlusOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) {
|
||||
static Max2dtsExporterPlus *imp = NULL;
|
||||
|
||||
switch(message) {
|
||||
case WM_INITDIALOG:
|
||||
imp = (Max2dtsExporterPlus *)lParam;
|
||||
CenterWindow(hWnd,GetParent(hWnd));
|
||||
return TRUE;
|
||||
|
||||
case WM_CLOSE:
|
||||
EndDialog(hWnd, 0);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//--- Max2dtsExporterPlus -------------------------------------------------------
|
||||
Max2dtsExporterPlus::Max2dtsExporterPlus()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Max2dtsExporterPlus::~Max2dtsExporterPlus()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Max2dtsExporterPlus::ExtCount()
|
||||
{
|
||||
// Returns the number of file name extensions supported by the plug-in.
|
||||
return 1;
|
||||
}
|
||||
|
||||
const TCHAR *Max2dtsExporterPlus::Ext(int n)
|
||||
{
|
||||
// Return the 'i-th' file name extension
|
||||
return _T("DTS");
|
||||
}
|
||||
|
||||
const TCHAR *Max2dtsExporterPlus::LongDesc()
|
||||
{
|
||||
//Return long ASCII description
|
||||
return _T("Torque game engine dts shape file");
|
||||
}
|
||||
|
||||
const TCHAR *Max2dtsExporterPlus::ShortDesc()
|
||||
{
|
||||
//Return short ASCII description
|
||||
return _T("DTS Shape");
|
||||
}
|
||||
|
||||
const TCHAR *Max2dtsExporterPlus::AuthorName()
|
||||
{
|
||||
//Return ASCII Author name
|
||||
return _T("Clark Fagot");
|
||||
}
|
||||
|
||||
const TCHAR *Max2dtsExporterPlus::CopyrightMessage()
|
||||
{
|
||||
// Return ASCII Copyright message
|
||||
return _T("Copyright GarageGames");
|
||||
}
|
||||
|
||||
const TCHAR *Max2dtsExporterPlus::OtherMessage1()
|
||||
{
|
||||
//Return Other message #1 if any
|
||||
return _T("");
|
||||
}
|
||||
|
||||
const TCHAR *Max2dtsExporterPlus::OtherMessage2()
|
||||
{
|
||||
//Return other message #2 in any
|
||||
return _T("");
|
||||
}
|
||||
|
||||
unsigned int Max2dtsExporterPlus::Version()
|
||||
{
|
||||
//Return Version number * 100 (i.e. v3.01 = 301)
|
||||
return 100;
|
||||
}
|
||||
|
||||
void Max2dtsExporterPlus::ShowAbout(HWND hWnd)
|
||||
{
|
||||
// Optional
|
||||
}
|
||||
|
||||
BOOL Max2dtsExporterPlus::SupportsOptions(int ext, DWORD options)
|
||||
{
|
||||
// Decide which options to support. Simply return
|
||||
// true for each option supported by each Extension
|
||||
// the exporter supports.
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Max2dtsExporterPlus::alert(const char * title, const char * message, BOOL suppressPrompts)
|
||||
{
|
||||
if (suppressPrompts)
|
||||
DTS::AppConfig::PrintDump(-1,message);
|
||||
else
|
||||
{
|
||||
TSTR str1(message);
|
||||
TSTR str2(title);
|
||||
MessageBox(GetActiveWindow(), str1, str2, MB_OK);
|
||||
}
|
||||
}
|
||||
|
||||
int Max2dtsExporterPlus::DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)
|
||||
{
|
||||
// Implement the actual file Export here and
|
||||
// return TRUE If the file is exported properly
|
||||
if (!DTS::AppConfig::SetDumpFile(name))
|
||||
alert("Dump file error",DTS::avar("Unable to create dumpfile for shape \"%s\".",name),suppressPrompts);
|
||||
|
||||
// Get config file if it exists...
|
||||
const char * configBase = i->GetCurFilePath();
|
||||
DTS::AppConfig::ReadConfigFile(configBase);
|
||||
|
||||
DTS::MaxSceneEnum maxSceneEnum(ei->theScene);
|
||||
DTS::Shape * shape = maxSceneEnum.processScene();
|
||||
if (!DTS::AppConfig::IsExportError())
|
||||
{
|
||||
std::ofstream os;
|
||||
os.open(name,std::ofstream::binary);
|
||||
shape->save(os);
|
||||
os.close();
|
||||
}
|
||||
DTS::AppConfig::CloseDumpFile();
|
||||
delete shape;
|
||||
|
||||
if (DTS::AppConfig::IsExportError())
|
||||
alert("Export error",DTS::AppConfig::GetExportError(),suppressPrompts);
|
||||
|
||||
return !DTS::AppConfig::IsExportError();
|
||||
}
|
||||
|
||||
|
8
tools/max2dtsExporterPlus/max2dtsExporterPlus.def
Executable file
8
tools/max2dtsExporterPlus/max2dtsExporterPlus.def
Executable file
@ -0,0 +1,8 @@
|
||||
LIBRARY max2dtsExporterPlus
|
||||
EXPORTS
|
||||
LibDescription @1
|
||||
LibNumberClasses @2
|
||||
LibClassDesc @3
|
||||
LibVersion @4
|
||||
SECTIONS
|
||||
.data READ WRITE
|
26
tools/max2dtsExporterPlus/max2dtsExporterPlus.h
Executable file
26
tools/max2dtsExporterPlus/max2dtsExporterPlus.h
Executable file
@ -0,0 +1,26 @@
|
||||
/**********************************************************************
|
||||
*<
|
||||
FILE: max2dtsExporterPlus.h
|
||||
|
||||
DESCRIPTION: Includes for Plugins
|
||||
|
||||
CREATED BY:
|
||||
|
||||
HISTORY:
|
||||
|
||||
*> Copyright (c) 2000, All Rights Reserved.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __MAX2DTSEXPORTERPLUS__H
|
||||
#define __MAX2DTSEXPORTERPLUS__H
|
||||
|
||||
#include "Max.h"
|
||||
#include "resource.h"
|
||||
#include "istdplug.h"
|
||||
#include "iparamb2.h"
|
||||
#include "iparamm2.h"
|
||||
|
||||
extern TCHAR *GetString(int id);
|
||||
extern HINSTANCE hInstance;
|
||||
|
||||
#endif // __MAX2DTSEXPORTERPLUS__H
|
168
tools/max2dtsExporterPlus/max2dtsExporterPlus.rc
Executable file
168
tools/max2dtsExporterPlus/max2dtsExporterPlus.rc
Executable file
@ -0,0 +1,168 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef IDC_STATIC
|
||||
#undef IDC_STATIC
|
||||
#endif
|
||||
#define IDC_STATIC (-1) // all static controls
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_PANEL DIALOGEX 0, 0, 108, 156
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_TOOLWINDOW
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x1
|
||||
BEGIN
|
||||
CTEXT "Generated by Plugin AppWizard\nCode && design by\nRavi Karra - Discreet",
|
||||
IDC_STATIC,7,7,94,36
|
||||
CONTROL "",IDC_EDIT,"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_PANEL, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 101
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 149
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifndef _MAC
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "\0"
|
||||
VALUE "CompanyName", "BraveTree Productions\0"
|
||||
VALUE "FileDescription", "max2dtsExporterPlus\0"
|
||||
VALUE "FileVersion", "1, 0, 0, 1\0"
|
||||
VALUE "InternalName", "max2dtsExporterPlus\0"
|
||||
VALUE "LegalCopyright", "Copyright <20> 2004\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "max2dtsExporterPlus.dle\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "ProductName", "BraveTree Productions max2dtsExporterPlus\0"
|
||||
VALUE "ProductVersion", "1, 0, 0, 1\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // !_MAC
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_LIBDESCRIPTION "Export Torque DTS files using dtsSDKPlus"
|
||||
IDS_CATEGORY "I like turnips"
|
||||
IDS_CLASS_NAME "Max2dtsExporterPlus"
|
||||
IDS_PARAMS "Parameters"
|
||||
IDS_SPIN "Spin"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
483
tools/max2dtsExporterPlus/maxAppMesh.cpp
Executable file
483
tools/max2dtsExporterPlus/maxAppMesh.cpp
Executable file
@ -0,0 +1,483 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "maxAppMesh.h"
|
||||
#include "maxAppNode.h"
|
||||
#include "appConfig.h"
|
||||
#include "appIfl.h"
|
||||
#include "skinHelper.h"
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <max.h>
|
||||
#include <iparamb2.h>
|
||||
#include <ISkin.h>
|
||||
#include <modstack.h>
|
||||
#include <istdplug.h>
|
||||
#include <stdmat.h>
|
||||
#include <maxtypes.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// 3dsMax utility function:
|
||||
// Grab the tri object from the max mesh node
|
||||
//----------------------------------------------------------------
|
||||
TriObject * getTriObject( INode *pNode, S32 time, bool & deleteIt)
|
||||
{
|
||||
TriObject * tri = NULL;
|
||||
IParamBlock * paramBlock = NULL;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// 3dsMax utility function:
|
||||
// Grab the skin data from the max mesh node
|
||||
//----------------------------------------------------------------
|
||||
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
|
||||
}
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
MaxAppMesh::MaxAppMesh(INode * maxNode, AppNode * appNode)
|
||||
{
|
||||
mMaxNode = maxNode;
|
||||
mAppNode = appNode;
|
||||
}
|
||||
|
||||
Matrix<4,4,F32> MaxAppMesh::getMeshTransform(const AppTime & time)
|
||||
{
|
||||
assert(!mLocked && "Mesh is locked");
|
||||
|
||||
Matrix<4,4,F32> ret;
|
||||
Matrix3 mat = mMaxNode->GetObjTMAfterWSM(SecToTicks(time.getF32()));
|
||||
return convertFromMaxMatrix(mat);
|
||||
}
|
||||
|
||||
F32 MaxAppMesh::getVisValue(const AppTime & time)
|
||||
{
|
||||
assert(!mLocked && "Mesh is locked");
|
||||
|
||||
return mMaxNode->GetVisibility(SecToTicks(time.getF32()));
|
||||
}
|
||||
|
||||
bool MaxAppMesh::getMaterial(S32 matIdx, Material & mat)
|
||||
{
|
||||
mat.reflectance = -1;
|
||||
mat.bump = -1;
|
||||
mat.detail = -1;
|
||||
mat.detailScale = 1.0f;
|
||||
mat.reflection = 1.0f;
|
||||
mat.flags = 0;
|
||||
|
||||
// do some hocus pocus to get the material....
|
||||
|
||||
Mtl * mtl = mMaxNode->GetMtl();
|
||||
if( !mtl )
|
||||
return false;
|
||||
|
||||
if( mtl->ClassID() == Class_ID(MULTI_CLASS_ID,0) )
|
||||
{
|
||||
MultiMtl * multiMtl = (MultiMtl*)mtl;
|
||||
if (multiMtl->NumSubMtls()==0)
|
||||
return false;
|
||||
matIdx %= multiMtl->NumSubMtls();
|
||||
|
||||
mtl = multiMtl->GetSubMtl( matIdx );
|
||||
}
|
||||
|
||||
if( mtl->ClassID() != Class_ID(DMTL_CLASS_ID,0) )
|
||||
{
|
||||
AppConfig::SetExportError("max1", avar("Unexpected material type on mesh \"%s\".",mMaxNode->GetName()));
|
||||
return false;
|
||||
}
|
||||
|
||||
StdMat * stdMat = (StdMat*)mtl;
|
||||
|
||||
// we now have a standard material...this guy has a number of maps
|
||||
// the diffuse map corresponds to the texture
|
||||
// the reflection map is used for environment mapping (normally this will be in the alpha of
|
||||
// the texture, but under some circumstances -- translucency -- you want a separate map for it)
|
||||
// the material also has a bump map and a detail map (we look for this in the ambient map...
|
||||
// ambient because detail maps add ambiance... :)
|
||||
|
||||
// get diffuse map...
|
||||
|
||||
if (stdMat->GetSubTexmap(ID_DI) == NULL || !stdMat->MapEnabled(ID_DI))
|
||||
// no diffuse...
|
||||
return false;
|
||||
|
||||
if (stdMat->GetSubTexmap(ID_DI)->ClassID() != Class_ID(BMTEX_CLASS_ID,0))
|
||||
{
|
||||
AppConfig::SetExportError("max2", avar("Diffuse channel on mesh \"%s\" has a non-bitmap texture map.",mMaxNode->GetName()));
|
||||
return false;
|
||||
}
|
||||
|
||||
BitmapTex * diffuse = (BitmapTex*)stdMat->GetSubTexmap(ID_DI);
|
||||
mat.name = diffuse->GetMapName();
|
||||
|
||||
// set up texture flags
|
||||
if (stdMat->MapEnabled(ID_OP))
|
||||
{
|
||||
// note: translucent if opacity channel is enabled
|
||||
mat.flags |= Material::Translucent;
|
||||
if (stdMat->GetTransparencyType() == TRANSP_ADDITIVE)
|
||||
mat.flags |= Material::Additive;
|
||||
else if (stdMat->GetTransparencyType() == TRANSP_SUBTRACTIVE)
|
||||
mat.flags |= Material::Subtractive;
|
||||
}
|
||||
if (!stdMat->MapEnabled(ID_RL))
|
||||
// only environment map if reflectance check box is set (but no material necessary)
|
||||
mat.flags |= Material::NeverEnvMap;
|
||||
mat.reflection = stdMat->GetTexmapAmt(ID_RL,0);
|
||||
|
||||
if (diffuse->GetUVGen()->GetTextureTiling() & U_WRAP)
|
||||
mat.flags |= Material::SWrap;
|
||||
if (diffuse->GetUVGen()->GetTextureTiling() & V_WRAP)
|
||||
mat.flags |= Material::TWrap;
|
||||
if ( stdMat->GetSelfIllum(0) > 0.99f)
|
||||
mat.flags |= Material::SelfIlluminating;
|
||||
|
||||
//------------
|
||||
// If this is an ifl, then create the ifl material if it doesn't exist and mark as ifl
|
||||
const char * dot = strchr(mat.name.c_str(),'.');
|
||||
if (dot && !_stricmp(dot+1,"ifl"))
|
||||
{
|
||||
mat.flags |= Material::IFLMaterial;
|
||||
while (mIfls.size()<=matIdx)
|
||||
mIfls.push_back(NULL);
|
||||
if (!mIfls[matIdx])
|
||||
mIfls[matIdx] = new AppIfl(mat.name.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaxAppMesh::animatesFrame(const AppSequenceData & seqData)
|
||||
{
|
||||
assert(!mLocked && "Mesh is locked");
|
||||
|
||||
S32 startTime = SecToTicks(seqData.startTime.getF32());
|
||||
S32 endTime = SecToTicks(seqData.endTime.getF32());
|
||||
|
||||
bool deleteIt;
|
||||
TriObject * tri = getTriObject(mMaxNode,startTime,deleteIt);
|
||||
if (!tri)
|
||||
return false;
|
||||
|
||||
Interval ivalid;
|
||||
ivalid = tri->ChannelValidity(startTime, GEOM_CHAN_NUM);
|
||||
|
||||
if (deleteIt)
|
||||
tri->DeleteMe();
|
||||
|
||||
return (ivalid.Start() > startTime || ivalid.End() < endTime);
|
||||
}
|
||||
|
||||
bool MaxAppMesh::animatesMatFrame(const AppSequenceData & seqData)
|
||||
{
|
||||
assert(!mLocked && "Mesh is locked");
|
||||
|
||||
S32 startTime = SecToTicks(seqData.startTime.getF32());
|
||||
S32 endTime = SecToTicks(seqData.endTime.getF32());
|
||||
|
||||
bool deleteIt;
|
||||
TriObject * tri = getTriObject(mMaxNode,startTime,deleteIt);
|
||||
if (!tri)
|
||||
return false;
|
||||
|
||||
Interval ivalid;
|
||||
ivalid = tri->ChannelValidity(startTime, TEXMAP_CHAN_NUM);
|
||||
|
||||
if (deleteIt)
|
||||
tri->DeleteMe();
|
||||
|
||||
return (ivalid.Start() > startTime || ivalid.End() < endTime);
|
||||
}
|
||||
|
||||
AppMeshLock MaxAppMesh::lockMesh(const AppTime & time, const Matrix<4,4,F32> & objectOffset)
|
||||
{
|
||||
// are we mirrored?
|
||||
AffineParts parts;
|
||||
decomp_affine(objectOffset,&parts);
|
||||
bool mirror = parts.sign < 0.0f;
|
||||
|
||||
bool delTri;
|
||||
TriObject * tri = getTriObject(mMaxNode,SecToTicks(time.getF32()),delTri);
|
||||
::Mesh & maxMesh = tri->mesh;
|
||||
|
||||
S32 i;
|
||||
S32 lastMatIdx = -1;
|
||||
Matrix3 uvTransform;
|
||||
|
||||
// start lists empty
|
||||
mFaces.clear();
|
||||
mVerts.clear();
|
||||
mTVerts.clear();
|
||||
mIndices.clear();
|
||||
mSmooth.clear();
|
||||
mVertId.clear();
|
||||
|
||||
// start out with faces and crop data allocated
|
||||
mFaces.resize(maxMesh.getNumFaces());
|
||||
|
||||
// if no faces, detect it (use redundant test just in case
|
||||
bool tmap = maxMesh.mapSupport(1) && maxMesh.tVerts; // 1 == default map
|
||||
|
||||
// get faces, points & materials
|
||||
for (i=0; i<mFaces.size();i++)
|
||||
{
|
||||
Face & maxFace = maxMesh.faces[i];
|
||||
Primitive & tsFace = mFaces[i];
|
||||
|
||||
// set faces material index
|
||||
tsFace.type = maxFace.getMatID(); // use max mat idx (get's converted by shapemimic)
|
||||
tsFace.firstElement = mIndices.size();
|
||||
tsFace.numElements = 3;
|
||||
tsFace.type |= Primitive::Triangles|Primitive::Indexed;
|
||||
|
||||
// set vertex indices
|
||||
S32 idx0 = maxFace.v[0];
|
||||
S32 idx1 = maxFace.v[2]; // switch the order to be CW
|
||||
S32 idx2 = maxFace.v[1]; // switch the order to be CW
|
||||
if (mirror)
|
||||
{
|
||||
S32 tmp = idx1;
|
||||
idx1 = idx2;
|
||||
idx2 = tmp;
|
||||
}
|
||||
Point3D v0(maxMesh.verts[idx0].x,maxMesh.verts[idx0].y,maxMesh.verts[idx0].z);
|
||||
Point3D v1(maxMesh.verts[idx1].x,maxMesh.verts[idx1].y,maxMesh.verts[idx1].z);
|
||||
Point3D v2(maxMesh.verts[idx2].x,maxMesh.verts[idx2].y,maxMesh.verts[idx2].z);
|
||||
|
||||
Point3D vert0 = objectOffset * v0;
|
||||
Point3D vert1 = objectOffset * v1;
|
||||
Point3D vert2 = objectOffset * v2;
|
||||
|
||||
// set texture vertex indices
|
||||
Point2D tvert0(0,0);
|
||||
Point2D tvert1(0,0);
|
||||
Point2D tvert2(0,0);
|
||||
if (tmap)
|
||||
{
|
||||
TVFace & maxTVFace = maxMesh.mapFaces(1)[i]; // 1 == default map
|
||||
|
||||
S32 tidx0 = maxTVFace.getTVert(0);
|
||||
S32 tidx1 = maxTVFace.getTVert(2); // switch the order to be CW
|
||||
S32 tidx2 = maxTVFace.getTVert(1); // switch the order to be CW
|
||||
if (mirror)
|
||||
{
|
||||
S32 tmp = tidx1;
|
||||
tidx1 = tidx2;
|
||||
tidx2 = tmp;
|
||||
}
|
||||
|
||||
if (lastMatIdx != maxFace.getMatID())
|
||||
{
|
||||
// get texture transform for this material
|
||||
uvTransform.IdentityMatrix();
|
||||
Mtl * mtl = mMaxNode->GetMtl();
|
||||
if( mtl )
|
||||
{
|
||||
if( mtl->ClassID() == Class_ID(MULTI_CLASS_ID,0) )
|
||||
{
|
||||
MultiMtl * multiMtl = (MultiMtl*)mtl;
|
||||
if (multiMtl->NumSubMtls()>0)
|
||||
mtl = multiMtl->GetSubMtl( maxFace.getMatID() % multiMtl->NumSubMtls());
|
||||
}
|
||||
|
||||
if( mtl->ClassID() == Class_ID(DMTL_CLASS_ID,0) )
|
||||
{
|
||||
StdMat * stdMat = (StdMat*)mtl;
|
||||
if (stdMat->GetSubTexmap(ID_DI)!=NULL && stdMat->MapEnabled(ID_DI) && stdMat->GetSubTexmap(ID_DI)->ClassID() == Class_ID(BMTEX_CLASS_ID,0))
|
||||
{
|
||||
BitmapTex * diffuse = (BitmapTex*)stdMat->GetSubTexmap(ID_DI);
|
||||
diffuse->GetUVGen()->GetUVTransform(uvTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastMatIdx = maxFace.getMatID();
|
||||
}
|
||||
|
||||
Point2 tv0 = maxMesh.mapVerts(1)[tidx0] * uvTransform;
|
||||
Point2 tv1 = maxMesh.mapVerts(1)[tidx1] * uvTransform;
|
||||
Point2 tv2 = maxMesh.mapVerts(1)[tidx2] * uvTransform;
|
||||
tvert0.x(tv0.x);
|
||||
tvert0.y(1.0f-tv0.y);
|
||||
tvert1.x(tv1.x);
|
||||
tvert1.y(1.0f-tv1.y);
|
||||
tvert2.x(tv2.x);
|
||||
tvert2.y(1.0f-tv2.y);
|
||||
}
|
||||
tsFace.type |= maxFace.getMatID(); // return max mat id...gets converted to ts mat id by shapemimic
|
||||
|
||||
// now add indices...this is easy right now...later we'll mess this up
|
||||
mIndices.push_back(addVertex(vert0,tvert0,idx0,maxFace.smGroup));
|
||||
mIndices.push_back(addVertex(vert1,tvert1,idx1,maxFace.smGroup));
|
||||
mIndices.push_back(addVertex(vert2,tvert2,idx2,maxFace.smGroup));
|
||||
}
|
||||
|
||||
if (delTri)
|
||||
delete tri;
|
||||
|
||||
return Parent::lockMesh(time,objectOffset);
|
||||
}
|
||||
|
||||
void MaxAppMesh::unlockMesh()
|
||||
{
|
||||
Parent::unlockMesh();
|
||||
|
||||
// no more cleanup...but if there were some to do, we'd do it here
|
||||
}
|
||||
|
||||
void MaxAppMesh::getSkinData()
|
||||
{
|
||||
if (mSkinDataFetched)
|
||||
return;
|
||||
mSkinDataFetched = true;
|
||||
|
||||
ISkin * skin;
|
||||
ISkinContextData * skinData;
|
||||
findSkinData(mMaxNode,&skin,&skinData);
|
||||
if (!skin || !skinData || !skin->GetNumBones())
|
||||
return;
|
||||
|
||||
// This is a hack to avoid making the skin helper a ws modifier
|
||||
// A hack, but needed because ws modifiers screw things up (add
|
||||
// offsets for some reason).
|
||||
SkinHelper::smTheOnlyOne = mMaxNode;
|
||||
|
||||
// add skin helper modifier...
|
||||
::Object * obj = mMaxNode->GetObjectRef();
|
||||
IDerivedObject * dobj = (IDerivedObject*)CreateDerivedObject(mMaxNode->GetObjectRef());
|
||||
SkinHelper * skinHelper = (SkinHelper*)CreateInstance(GetSkinHelperDesc()->SuperClassID(),GetSkinHelperDesc()->ClassID());
|
||||
dobj->AddModifier(skinHelper);
|
||||
mMaxNode->SetObjectRef(dobj);
|
||||
|
||||
// get bones
|
||||
S32 i,j, numBones = skin->GetNumBones();
|
||||
for (i=0; i<numBones; i++)
|
||||
{
|
||||
mBones.push_back(new MaxAppNode(skin->GetBone(i)));
|
||||
AppConfig::PrintDump(PDPass2,avar("Adding skin object from skin \"%s\" to bone \"%s\" (%i).\r\n",mMaxNode->GetName(),mBones[i]->getName(),i));
|
||||
}
|
||||
|
||||
bool delTri;
|
||||
TriObject * tri = NULL;
|
||||
|
||||
// get skin mesh
|
||||
tri = getTriObject(mMaxNode,0,delTri);
|
||||
|
||||
// get vertex weights from alternate tv channels
|
||||
S32 numPoints = tri->mesh.getNumVerts();
|
||||
if (tri->mesh.getNumMaps()<2+((1+numBones)>>1))
|
||||
{
|
||||
AppConfig::SetExportError("max3", "Assertion failed on skin object");
|
||||
return;
|
||||
}
|
||||
mWeights.resize(numBones);
|
||||
for (i=0; i<mWeights.size(); i++)
|
||||
{
|
||||
mWeights[i] = new std::vector<F32>;
|
||||
mWeights[i]->resize(numPoints);
|
||||
for (j=0; j<numPoints; j++)
|
||||
(*mWeights[i])[j]=0.0f;
|
||||
}
|
||||
|
||||
for (j=0; j<numBones; j++)
|
||||
{
|
||||
AppConfig::PrintDump(-1,avar("Adding weights for bone %i (\"%s\")\r\n",j,mBones[j]->getName()));
|
||||
std::vector<bool> gotWeight;
|
||||
gotWeight.resize(tri->mesh.numVerts);
|
||||
for (i=0; i<gotWeight.size(); i++)
|
||||
gotWeight[i]=false;
|
||||
for (i=0; i<tri->mesh.numFaces; i++)
|
||||
{
|
||||
S32 ch = 2+(j>>1);
|
||||
Face & face = tri->mesh.faces[i];
|
||||
TVFace & tvFace = tri->mesh.mapFaces(ch)[i];
|
||||
|
||||
for (S32 count=0; count<3; count++)
|
||||
{
|
||||
S32 idx = face.v[count];
|
||||
if (!gotWeight[idx])
|
||||
{
|
||||
UVVert tv = tri->mesh.mapVerts(ch)[tvFace.t[count]];
|
||||
F32 w = (j&1) ? tv.y : tv.x;
|
||||
(*mWeights[j])[idx] = w;
|
||||
if (w>0.01f)
|
||||
AppConfig::PrintDump(-1,avar(" Vertex %i, weight %f\r\n",idx,w));
|
||||
gotWeight[idx]=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delTri)
|
||||
delete tri;
|
||||
|
||||
// done with helper...remove it now...
|
||||
dobj->DeleteModifier(); // this'll be our skin helper
|
||||
SkinHelper::smTheOnlyOne = NULL;
|
||||
|
||||
// following copied from AVCUtil.cpp...is needed to get rid of bar in modifier list
|
||||
if (dobj->NumModifiers() == 0 && !dobj->TestAFlag(A_DERIVEDOBJ_DONTDELETE))
|
||||
{
|
||||
obj = dobj->GetObjRef();
|
||||
obj->TransferReferences(dobj);
|
||||
dobj->SetAFlag(A_LOCK_TARGET);
|
||||
dobj->NotifyDependents(FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED);
|
||||
obj->NotifyDependents(FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED);
|
||||
dobj->ClearAFlag(A_LOCK_TARGET);
|
||||
dobj->MaybeAutoDelete();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
59
tools/max2dtsExporterPlus/maxAppMesh.h
Executable file
59
tools/max2dtsExporterPlus/maxAppMesh.h
Executable file
@ -0,0 +1,59 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef DTSMAXAPPMESH_H_
|
||||
#define DTSMAXAPPMESH_H_
|
||||
|
||||
#include "appMesh.h"
|
||||
#include "appNode.h"
|
||||
|
||||
class INode;
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
class MaxAppMesh : public AppMesh
|
||||
{
|
||||
typedef AppMesh Parent;
|
||||
|
||||
protected:
|
||||
|
||||
// Don't hold onto anything mesh-like in max, keep the node instead
|
||||
INode * mMaxNode;
|
||||
|
||||
// Hold this in addition just for convenience of a few methods that
|
||||
// use app node methods
|
||||
AppNode * mAppNode;
|
||||
|
||||
void getSkinData();
|
||||
|
||||
public:
|
||||
|
||||
MaxAppMesh(INode * maxNode, AppNode * appNode);
|
||||
|
||||
const char * getName() { return mAppNode->getName(); }
|
||||
bool getFloat(const char * propName, F32 & defaultVal) { return mAppNode->getFloat(propName,defaultVal); }
|
||||
bool getInt(const char * propName, S32 & defaultVal) { return mAppNode->getInt(propName,defaultVal); }
|
||||
bool getBool(const char * propName, bool & defaultVal) { return mAppNode->getBool(propName,defaultVal); }
|
||||
|
||||
Matrix<4,4,F32> getMeshTransform(const AppTime & time);
|
||||
F32 getVisValue(const AppTime & time);
|
||||
|
||||
bool getMaterial(S32 matIdx, Material &);
|
||||
|
||||
S32 getNumBones();
|
||||
AppNode * getBone(S32 idx);
|
||||
F32 getWeight(S32 boneIdx, S32 vertIdx);
|
||||
|
||||
bool animatesMatFrame(const AppSequenceData & seqData);
|
||||
bool animatesFrame(const AppSequenceData & seqData);
|
||||
|
||||
AppMeshLock lockMesh(const AppTime & time, const Matrix<4,4,F32> & objectOffset);
|
||||
void unlockMesh();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif // DTSMAXAPPMESH_H_
|
135
tools/max2dtsExporterPlus/maxAppNode.cpp
Executable file
135
tools/max2dtsExporterPlus/maxAppNode.cpp
Executable file
@ -0,0 +1,135 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "maxAppNode.h"
|
||||
#include "maxAppMesh.h"
|
||||
#include "DTSUtil.h"
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <max.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
MaxAppNode::MaxAppNode(INode * maxNode)
|
||||
{
|
||||
mMaxNode = maxNode;
|
||||
}
|
||||
|
||||
void MaxAppNode::buildMeshList()
|
||||
{
|
||||
::ObjectState os = mMaxNode->EvalWorldState(0);
|
||||
if (os.obj->CanConvertToType(triObjectClassID))
|
||||
mMeshes.push_back(new MaxAppMesh(mMaxNode,this));
|
||||
}
|
||||
|
||||
void MaxAppNode::buildChildList()
|
||||
{
|
||||
for (S32 i=0; i<mMaxNode->NumberOfChildren(); i++)
|
||||
{
|
||||
INode * child = mMaxNode->GetChildNode(i);
|
||||
mChildNodes.push_back(new MaxAppNode(child));
|
||||
}
|
||||
}
|
||||
|
||||
bool MaxAppNode::isEqual(AppNode * node)
|
||||
{
|
||||
MaxAppNode * maxAppNode = dynamic_cast<MaxAppNode*>(node);
|
||||
return maxAppNode && (maxAppNode->mMaxNode == mMaxNode);
|
||||
}
|
||||
|
||||
Matrix<4,4,F32> MaxAppNode::getNodeTransform(const AppTime & time)
|
||||
{
|
||||
// Get the node marix then copy from max format into our matrix struct
|
||||
// Note that this results in a transpose of the matrix...
|
||||
Matrix3 nodeMat = mMaxNode->GetNodeTM( SecToTicks(time.getF32()) );
|
||||
return convertFromMaxMatrix(nodeMat);
|
||||
}
|
||||
|
||||
bool MaxAppNode::animatesTransform(const AppSequenceData & seqData)
|
||||
{
|
||||
Interval range(SecToTicks(seqData.startTime.getF32()),SecToTicks(seqData.endTime.getF32()));
|
||||
Interval test = range;
|
||||
|
||||
// does this sequence animate the bounds node, if so, add ground transform
|
||||
S32 midpoint = (range.Start() + range.End()) / 2;
|
||||
mMaxNode->GetNodeTM(midpoint,&test);
|
||||
return ( test.Start()!=range.Start() || test.End()!=range.End() );
|
||||
}
|
||||
|
||||
const char * MaxAppNode::getName()
|
||||
{
|
||||
if (!mName)
|
||||
mName = strnew(mMaxNode->GetName());
|
||||
return mName;
|
||||
}
|
||||
|
||||
const char * MaxAppNode::getParentName()
|
||||
{
|
||||
if (!mParentName)
|
||||
mParentName = mMaxNode->GetParentNode() ? strnew(mMaxNode->GetParentNode()->GetName()) : strnew("ROOT");
|
||||
return mParentName;
|
||||
}
|
||||
|
||||
bool MaxAppNode::isParentRoot()
|
||||
{
|
||||
return (mMaxNode->GetParentNode()==NULL) || mMaxNode->GetParentNode()->IsRootNode();
|
||||
}
|
||||
|
||||
bool MaxAppNode::getFloat(const char * propName, F32 & defaultVal)
|
||||
{
|
||||
// don't trust max not to touch value...
|
||||
F32 val;
|
||||
if (mMaxNode->GetUserPropFloat(propName,val))
|
||||
{
|
||||
defaultVal = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaxAppNode::getInt(const char * propName, S32 & defaultVal)
|
||||
{
|
||||
// don't trust max not to touch value...
|
||||
S32 val;
|
||||
if (mMaxNode->GetUserPropInt(propName,val))
|
||||
{
|
||||
defaultVal = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaxAppNode::getBool(const char * propName, bool & defaultVal)
|
||||
{
|
||||
// don't trust max not to touch value...
|
||||
BOOL val;
|
||||
if (mMaxNode->GetUserPropBool(propName,val))
|
||||
{
|
||||
defaultVal = val ? true : false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Matrix<4,4,F32> convertFromMaxMatrix(Matrix3 & mat)
|
||||
{
|
||||
Matrix<4,4,F32> ret;
|
||||
for (S32 i=0; i<4; i++)
|
||||
{
|
||||
Point3 row = mat.GetRow(i);
|
||||
Vector<F32,4> col;
|
||||
col.set(0,row.x);
|
||||
col.set(1,row.y);
|
||||
col.set(2,row.z);
|
||||
col.set(3,i==3 ? 1 : 0);
|
||||
ret.setCol(i,col);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
};
|
||||
|
47
tools/max2dtsExporterPlus/maxAppNode.h
Executable file
47
tools/max2dtsExporterPlus/maxAppNode.h
Executable file
@ -0,0 +1,47 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef DTSMAXAPPNODE_H_
|
||||
#define DTSMAXAPPNODE_H_
|
||||
|
||||
#include "appNode.h"
|
||||
|
||||
class INode;
|
||||
class Matrix3;
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
class MaxAppNode : public AppNode
|
||||
{
|
||||
typedef AppNode Parent;
|
||||
|
||||
INode * mMaxNode;
|
||||
|
||||
void buildMeshList();
|
||||
void buildChildList();
|
||||
|
||||
public:
|
||||
|
||||
MaxAppNode(INode * maxNode);
|
||||
|
||||
bool isEqual(AppNode *);
|
||||
|
||||
Matrix<4,4,F32> getNodeTransform(const AppTime & time);
|
||||
bool animatesTransform(const AppSequenceData & seqData);
|
||||
const char * getName();
|
||||
const char * getParentName();
|
||||
bool isParentRoot();
|
||||
bool getFloat(const char * propName, F32 & defaultVal);
|
||||
bool getInt(const char * propName, S32 & defaultVal);
|
||||
bool getBool(const char * propName, bool & defaultVal);
|
||||
};
|
||||
|
||||
extern Matrix<4,4,F32> convertFromMaxMatrix(Matrix3 & mat);
|
||||
|
||||
};
|
||||
|
||||
#endif // DTSMAXAPPNODE_H_
|
||||
|
58
tools/max2dtsExporterPlus/maxSceneEnum.cpp
Executable file
58
tools/max2dtsExporterPlus/maxSceneEnum.cpp
Executable file
@ -0,0 +1,58 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4786)
|
||||
#endif
|
||||
|
||||
#include "maxSceneEnum.h"
|
||||
#include "maxAppNode.h"
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <max.h>
|
||||
#include <ISTDPLUG.H>
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
class PrivateMaxEnum : public ITreeEnumProc
|
||||
{
|
||||
|
||||
MaxSceneEnum * mMaxSceneEnum;
|
||||
|
||||
public:
|
||||
|
||||
PrivateMaxEnum(MaxSceneEnum * sceneEnum) { mMaxSceneEnum = sceneEnum; }
|
||||
S32 callback( INode * node ) { return mMaxSceneEnum->callback(node); }
|
||||
void enumScene(IScene * scene ) { scene->EnumTree(this); }
|
||||
};
|
||||
|
||||
MaxSceneEnum::MaxSceneEnum(IScene * theScene)
|
||||
{
|
||||
mTheScene = theScene;
|
||||
}
|
||||
|
||||
MaxSceneEnum::~MaxSceneEnum()
|
||||
{
|
||||
}
|
||||
|
||||
S32 MaxSceneEnum::callback(INode * node)
|
||||
{
|
||||
MaxAppNode * maxAppNode = new MaxAppNode(node);
|
||||
if (!processNode(maxAppNode))
|
||||
delete maxAppNode;
|
||||
return TREE_CONTINUE;
|
||||
}
|
||||
|
||||
void MaxSceneEnum::enumScene()
|
||||
{
|
||||
PrivateMaxEnum pme(this);
|
||||
pme.enumScene(mTheScene);
|
||||
}
|
||||
|
||||
}; // namespace DTS
|
||||
|
32
tools/max2dtsExporterPlus/maxSceneEnum.h
Executable file
32
tools/max2dtsExporterPlus/maxSceneEnum.h
Executable file
@ -0,0 +1,32 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef DTSMAXSCENEENUM_H_
|
||||
#define DTSMAXSCENEENUM_H_
|
||||
|
||||
#include "appSceneEnum.h"
|
||||
|
||||
class INode;
|
||||
class IScene;
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
class MaxSceneEnum : public AppSceneEnum
|
||||
{
|
||||
protected:
|
||||
IScene * mTheScene;
|
||||
|
||||
public:
|
||||
MaxSceneEnum(IScene*);
|
||||
~MaxSceneEnum();
|
||||
|
||||
S32 callback(INode * node);
|
||||
void enumScene();
|
||||
};
|
||||
|
||||
}; // namespace DTS
|
||||
|
||||
#endif // #define DTSMAXSCENEENUM_H_
|
27
tools/max2dtsExporterPlus/resource.h
Executable file
27
tools/max2dtsExporterPlus/resource.h
Executable file
@ -0,0 +1,27 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by max2dtsExporterPlus.rc
|
||||
//
|
||||
#define IDS_LIBDESCRIPTION 1
|
||||
#define IDS_CATEGORY 2
|
||||
#define IDS_CLASS_NAME 3
|
||||
#define IDS_PARAMS 4
|
||||
#define IDS_SPIN 5
|
||||
#define IDS_SKINHELP_PARAMS 6
|
||||
#define IDD_PANEL 101
|
||||
#define IDC_CLOSEBUTTON 1000
|
||||
#define IDC_DOSTUFF 1000
|
||||
#define IDC_COLOR 1456
|
||||
#define IDC_EDIT 1490
|
||||
#define IDC_SPIN 1496
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
248
tools/max2dtsExporterPlus/skinHelper.cpp
Executable file
248
tools/max2dtsExporterPlus/skinHelper.cpp
Executable file
@ -0,0 +1,248 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "skinHelper.h"
|
||||
#include "appConfig.h"
|
||||
|
||||
#pragma pack(push,8)
|
||||
#include <Max.h>
|
||||
#include <decomp.h>
|
||||
#include <dummy.h>
|
||||
#include <ISkin.h>
|
||||
#include <modstack.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
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 OSM_CLASS_ID;}
|
||||
Class_ID ClassID() {return SKINHELPER_CLASS_ID;}
|
||||
const TCHAR* Category() {return "General";}
|
||||
void ResetClassParams(BOOL) {}
|
||||
};
|
||||
|
||||
static SkinHelperClassDesc SkinHelperDesc;
|
||||
ClassDesc* GetSkinHelperDesc() {return &SkinHelperDesc;}
|
||||
|
||||
IObjParam * SkinHelper::ip = NULL;
|
||||
INode * SkinHelper::smTheOnlyOne = NULL;
|
||||
|
||||
//--- SkinHelper -------------------------------------------------------
|
||||
SkinHelper::SkinHelper()
|
||||
{
|
||||
}
|
||||
|
||||
SkinHelper::~SkinHelper()
|
||||
{
|
||||
}
|
||||
|
||||
S32 gShouldOnlyBeOne=0;
|
||||
|
||||
void SkinHelper::SetReference(S32 i, RefTargetHandle rtarg)
|
||||
{
|
||||
gShouldOnlyBeOne++;
|
||||
if (gShouldOnlyBeOne != 1)
|
||||
DTS::AppConfig::SetExportError("max4", "Assertion failed on skin object -- added two skin helper objects");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// This sits in maxAppMesh.cpp
|
||||
extern void findSkinData(INode * pNode, ISkin **skin, ISkinContextData ** skinData);
|
||||
|
||||
void SkinHelper::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *pNode)
|
||||
{
|
||||
pNode = smTheOnlyOne;
|
||||
if (!pNode)
|
||||
return;
|
||||
|
||||
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);
|
||||
S32 i,j;
|
||||
for (i=2; i<numChannels; i++)
|
||||
{
|
||||
maxMesh.setMapSupport(i,true);
|
||||
maxMesh.setNumMapVerts(i,numVerts);
|
||||
for (j=0; j<numVerts; j++)
|
||||
maxMesh.setMapVert(i,j,tv);
|
||||
maxMesh.setNumMapFaces(i,maxMesh.getNumFaces());
|
||||
// copy map faces from the first channel
|
||||
for (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 (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;
|
||||
}
|
||||
|
||||
void SkinHelper::EndEditParams( IObjParam *ip, ULONG flags,Animatable *next)
|
||||
{
|
||||
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;
|
||||
}
|
86
tools/max2dtsExporterPlus/skinHelper.h
Executable file
86
tools/max2dtsExporterPlus/skinHelper.h
Executable file
@ -0,0 +1,86 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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>
|
||||
#include <ISkin.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
#include "DTSPlusTypes.h"
|
||||
|
||||
// Note: this skinhelper is same as skin helper in original max2dts
|
||||
// But we give it a different id so that it can co-exist with the old one.
|
||||
//#define SKINHELPER_CLASS_ID Class_ID(0x20dfdba0, 0x60646cb4)
|
||||
#define SKINHELPER_CLASS_ID Class_ID(0x449d28a3, 0x4dd3242b)
|
||||
|
||||
extern ClassDesc* GetSkinHelperDesc();
|
||||
extern TCHAR *GetString(S32);
|
||||
|
||||
class SkinHelper : public OSModifier
|
||||
{
|
||||
public:
|
||||
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 OSM_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();
|
||||
|
||||
static INode * smTheOnlyOne;
|
||||
};
|
||||
|
||||
#endif // __SKINHELPER__H
|
Reference in New Issue
Block a user