2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 GPL Source Code
2011-12-06 18:20:15 +00:00
Copyright ( C ) 1999 - 2011 id Software LLC , a ZeniMax Media company .
2011-11-22 21:28:15 +00:00
2011-12-06 16:14:59 +00:00
This file is part of the Doom 3 GPL Source Code ( " Doom 3 Source Code " ) .
2011-11-22 21:28:15 +00:00
Doom 3 Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2011-12-16 22:28:29 +00:00
# include "sys/platform.h"
2011-11-22 21:28:15 +00:00
# include "Maya5.0/maya.h"
//#include "Maya6.0/maya.h" // must also change include directory in project from "MayaImport\Maya4.5\include" to "MayaImport\Maya6.0\include" (requires MSDev 7.1)
2011-12-16 22:28:29 +00:00
# include "MayaImport/exporter.h"
# include "MayaImport/maya_main.h"
2011-11-22 21:28:15 +00:00
idStr errorMessage ;
bool initialized = false ;
# define DEFAULT_ANIM_EPSILON 0.125f
# define DEFAULT_QUAT_EPSILON ( 1.0f / 8192.0f )
# define SLOP_VERTEX 0.01f // merge xyz coordinates this far apart
# define SLOP_TEXCOORD 0.001f // merge texture coordinates this far apart
const char * componentNames [ 6 ] = { " Tx " , " Ty " , " Tz " , " Qx " , " Qy " , " Qz " } ;
idSys * sys = NULL ;
idCommon * common = NULL ;
idCVarSystem * cvarSystem = NULL ;
idCVar * idCVar : : staticVars = NULL ;
/*
= = = = = = = = = = = = = = = = =
MayaError
= = = = = = = = = = = = = = = = =
*/
void MayaError ( const char * fmt , . . . ) {
va_list argptr ;
char text [ 8192 ] ;
va_start ( argptr , fmt ) ;
idStr : : vsnPrintf ( text , sizeof ( text ) , fmt , argptr ) ;
va_end ( argptr ) ;
throw idException ( text ) ;
}
/*
= = = = = = = = = = = = = = = = =
FS_WriteFloatString
= = = = = = = = = = = = = = = = =
*/
# define MAX_PRINT_MSG 4096
static int WriteFloatString ( FILE * file , const char * fmt , . . . ) {
long i ;
unsigned long u ;
double f ;
char * str ;
int index ;
idStr tmp , format ;
va_list argPtr ;
va_start ( argPtr , fmt ) ;
index = 0 ;
while ( * fmt ) {
switch ( * fmt ) {
case ' % ' :
format = " " ;
format + = * fmt + + ;
while ( ( * fmt > = ' 0 ' & & * fmt < = ' 9 ' ) | |
* fmt = = ' . ' | | * fmt = = ' - ' | | * fmt = = ' + ' | | * fmt = = ' # ' ) {
format + = * fmt + + ;
}
format + = * fmt ;
switch ( * fmt ) {
case ' f ' :
case ' e ' :
case ' E ' :
case ' g ' :
case ' G ' :
f = va_arg ( argPtr , double ) ;
if ( format . Length ( ) < = 2 ) {
// high precision floating point number without trailing zeros
sprintf ( tmp , " %1.10f " , f ) ;
tmp . StripTrailing ( ' 0 ' ) ;
tmp . StripTrailing ( ' . ' ) ;
index + = fprintf ( file , " %s " , tmp . c_str ( ) ) ;
}
else {
index + = fprintf ( file , format . c_str ( ) , f ) ;
}
break ;
case ' d ' :
case ' i ' :
i = va_arg ( argPtr , long ) ;
index + = fprintf ( file , format . c_str ( ) , i ) ;
break ;
case ' u ' :
u = va_arg ( argPtr , unsigned long ) ;
index + = fprintf ( file , format . c_str ( ) , u ) ;
break ;
case ' o ' :
u = va_arg ( argPtr , unsigned long ) ;
index + = fprintf ( file , format . c_str ( ) , u ) ;
break ;
case ' x ' :
u = va_arg ( argPtr , unsigned long ) ;
index + = fprintf ( file , format . c_str ( ) , u ) ;
break ;
case ' X ' :
u = va_arg ( argPtr , unsigned long ) ;
index + = fprintf ( file , format . c_str ( ) , u ) ;
break ;
case ' c ' :
i = va_arg ( argPtr , long ) ;
index + = fprintf ( file , format . c_str ( ) , ( char ) i ) ;
break ;
case ' s ' :
str = va_arg ( argPtr , char * ) ;
index + = fprintf ( file , format . c_str ( ) , str ) ;
break ;
case ' % ' :
index + = fprintf ( file , format . c_str ( ) ) ;
break ;
default :
MayaError ( " WriteFloatString: invalid format %s " , format . c_str ( ) ) ;
break ;
}
fmt + + ;
break ;
case ' \\ ' :
fmt + + ;
switch ( * fmt ) {
case ' t ' :
index + = fprintf ( file , " \t " ) ;
break ;
case ' n ' :
index + = fprintf ( file , " \n " ) ;
default :
MayaError ( " WriteFloatString: unknown escape character \' %c \' " , * fmt ) ;
break ;
}
fmt + + ;
break ;
default :
index + = fprintf ( file , " %c " , * fmt ) ;
fmt + + ;
break ;
}
}
va_end ( argPtr ) ;
return index ;
}
/*
= = = = = = = = = = = = = = = =
OSPathToRelativePath
takes a full OS path , as might be found in data from a media creation
program , and converts it to a qpath by stripping off directories
Returns false if the osPath tree doesn ' t match any of the existing
search paths .
= = = = = = = = = = = = = = = =
*/
bool OSPathToRelativePath ( const char * osPath , idStr & qpath , const char * game ) {
char * s , * base ;
// skip a drive letter?
// search for anything with BASE_GAMEDIR in it
// Ase files from max may have the form of:
// "//Purgatory/purgatory/doom/base/models/mapobjects/bitch/hologirl.tga"
// which won't match any of our drive letter based search paths
base = ( char * ) strstr ( osPath , BASE_GAMEDIR ) ;
// _D3XP added mod support
if ( base = = NULL & & strlen ( game ) > 0 ) {
base = s = ( char * ) strstr ( osPath , game ) ;
while ( s = strstr ( s , game ) ) {
s + = strlen ( game ) ;
if ( s [ 0 ] = = ' / ' | | s [ 0 ] = = ' \\ ' ) {
base = s ;
}
}
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
if ( base ) {
s = strstr ( base , " / " ) ;
if ( ! s ) {
s = strstr ( base , " \\ " ) ;
}
if ( s ) {
qpath = s + 1 ;
return true ;
}
}
common - > Printf ( " OSPathToRelativePath failed on %s \n " , osPath ) ;
qpath = osPath ;
return false ;
}
/*
= = = = = = = = = = = = = = =
ConvertFromIdSpace
= = = = = = = = = = = = = = =
*/
idMat3 ConvertFromIdSpace ( const idMat3 & idmat ) {
idMat3 mat ;
mat [ 0 ] [ 0 ] = idmat [ 0 ] [ 0 ] ;
mat [ 0 ] [ 2 ] = - idmat [ 0 ] [ 1 ] ;
mat [ 0 ] [ 1 ] = idmat [ 0 ] [ 2 ] ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
mat [ 1 ] [ 0 ] = idmat [ 1 ] [ 0 ] ;
mat [ 1 ] [ 2 ] = - idmat [ 1 ] [ 1 ] ;
mat [ 1 ] [ 1 ] = idmat [ 1 ] [ 2 ] ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
mat [ 2 ] [ 0 ] = idmat [ 2 ] [ 0 ] ;
mat [ 2 ] [ 2 ] = - idmat [ 2 ] [ 1 ] ;
mat [ 2 ] [ 1 ] = idmat [ 2 ] [ 2 ] ;
return mat ;
}
/*
= = = = = = = = = = = = = = =
ConvertFromIdSpace
= = = = = = = = = = = = = = =
*/
idVec3 ConvertFromIdSpace ( const idVec3 & idpos ) {
idVec3 pos ;
pos . x = idpos . x ;
pos . z = - idpos . y ;
pos . y = idpos . z ;
return pos ;
}
/*
= = = = = = = = = = = = = = =
ConvertToIdSpace
= = = = = = = = = = = = = = =
*/
idMat3 ConvertToIdSpace ( const idMat3 & mat ) {
idMat3 idmat ;
idmat [ 0 ] [ 0 ] = mat [ 0 ] [ 0 ] ;
idmat [ 0 ] [ 1 ] = - mat [ 0 ] [ 2 ] ;
idmat [ 0 ] [ 2 ] = mat [ 0 ] [ 1 ] ;
idmat [ 1 ] [ 0 ] = mat [ 1 ] [ 0 ] ;
idmat [ 1 ] [ 1 ] = - mat [ 1 ] [ 2 ] ;
idmat [ 1 ] [ 2 ] = mat [ 1 ] [ 1 ] ;
idmat [ 2 ] [ 0 ] = mat [ 2 ] [ 0 ] ;
idmat [ 2 ] [ 1 ] = - mat [ 2 ] [ 2 ] ;
idmat [ 2 ] [ 2 ] = mat [ 2 ] [ 1 ] ;
return idmat ;
}
/*
= = = = = = = = = = = = = = =
ConvertToIdSpace
= = = = = = = = = = = = = = =
*/
idVec3 ConvertToIdSpace ( const idVec3 & pos ) {
idVec3 idpos ;
idpos . x = pos . x ;
idpos . y = - pos . z ;
idpos . z = pos . y ;
return idpos ;
}
/*
= = = = = = = = = = = = = = =
idVec
= = = = = = = = = = = = = = =
*/
idVec3 idVec ( const MFloatPoint & point ) {
return idVec3 ( point [ 0 ] , point [ 1 ] , point [ 2 ] ) ;
}
/*
= = = = = = = = = = = = = = =
idVec
= = = = = = = = = = = = = = =
*/
idVec3 idVec ( const MMatrix & matrix ) {
return idVec3 ( matrix [ 3 ] [ 0 ] , matrix [ 3 ] [ 1 ] , matrix [ 3 ] [ 2 ] ) ;
}
/*
= = = = = = = = = = = = = = =
idMat
= = = = = = = = = = = = = = =
*/
idMat3 idMat ( const MMatrix & matrix ) {
int j , k ;
idMat3 mat ;
for ( j = 0 ; j < 3 ; j + + ) {
for ( k = 0 ; k < 3 ; k + + ) {
mat [ j ] [ k ] = matrix [ j ] [ k ] ;
}
}
return mat ;
}
/*
= = = = = = = = = = = = = = =
GetParent
= = = = = = = = = = = = = = =
*/
MFnDagNode * GetParent ( MFnDagNode * joint ) {
MStatus status ;
MObject parentObject ;
parentObject = joint - > parent ( 0 , & status ) ;
if ( ! status & & status . statusCode ( ) = = MStatus : : kInvalidParameter ) {
return NULL ;
}
while ( ! parentObject . hasFn ( MFn : : kTransform ) ) {
MFnDagNode parentNode ( parentObject , & status ) ;
if ( ! status ) {
return NULL ;
}
parentObject = parentNode . parent ( 0 , & status ) ;
if ( ! status & & status . statusCode ( ) = = MStatus : : kInvalidParameter ) {
return NULL ;
}
}
MFnDagNode * parentNode ;
parentNode = new MFnDagNode ( parentObject , & status ) ;
if ( ! status ) {
delete parentNode ;
return NULL ;
}
return parentNode ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idTokenizer
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = =
idTokenizer : : SetTokens
= = = = = = = = = = = = = = = = = = = =
*/
int idTokenizer : : SetTokens ( const char * buffer ) {
const char * cmd ;
Clear ( ) ;
// tokenize commandline
cmd = buffer ;
while ( * cmd ) {
// skip whitespace
while ( * cmd & & isspace ( * cmd ) ) {
cmd + + ;
}
if ( ! * cmd ) {
break ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
idStr & current = tokens . Alloc ( ) ;
while ( * cmd & & ! isspace ( * cmd ) ) {
current + = * cmd ;
cmd + + ;
}
}
return tokens . Num ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
idTokenizer : : NextToken
= = = = = = = = = = = = = = = = = = = =
*/
const char * idTokenizer : : NextToken ( const char * errorstring ) {
if ( currentToken < tokens . Num ( ) ) {
return tokens [ currentToken + + ] ;
}
if ( errorstring ) {
MayaError ( " Error: %s " , errorstring ) ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idExportOptions
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = =
idExportOptions : : Reset
= = = = = = = = = = = = = = = = = = = =
*/
void idExportOptions : : Reset ( const char * commandline ) {
scale = 1.0f ;
type = WRITE_MESH ;
startframe = - 1 ;
endframe = - 1 ;
ignoreMeshes = false ;
clearOrigin = false ;
clearOriginAxis = false ;
framerate = 24 ;
align = " " ;
rotate = 0.0f ;
commandLine = commandline ;
prefix = " " ;
jointThreshold = 0.05f ;
ignoreScale = false ;
xyzPrecision = DEFAULT_ANIM_EPSILON ;
quatPrecision = DEFAULT_QUAT_EPSILON ;
cycleStart = - 1 ;
src . Clear ( ) ;
dest . Clear ( ) ;
tokens . SetTokens ( commandline ) ;
keepjoints . Clear ( ) ;
renamejoints . Clear ( ) ;
remapjoints . Clear ( ) ;
exportgroups . Clear ( ) ;
skipmeshes . Clear ( ) ;
keepmeshes . Clear ( ) ;
groups . Clear ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
idExportOptions : : idExportOptions
= = = = = = = = = = = = = = = = = = = =
*/
idExportOptions : : idExportOptions ( const char * commandline , const char * ospath ) {
idStr token ;
idNamePair joints ;
int i ;
idAnimGroup * group ;
idStr sourceDir ;
idStr destDir ;
Reset ( commandline ) ;
token = tokens . NextToken ( " Missing export command " ) ;
if ( token = = " mesh " ) {
type = WRITE_MESH ;
} else if ( token = = " anim " ) {
type = WRITE_ANIM ;
} else if ( token = = " camera " ) {
type = WRITE_CAMERA ;
} else {
MayaError ( " Unknown export command '%s' " , token . c_str ( ) ) ;
}
src = tokens . NextToken ( " Missing source filename " ) ;
dest = src ;
for ( token = tokens . NextToken ( ) ; token ! = " " ; token = tokens . NextToken ( ) ) {
if ( token = = " -force " ) {
// skip
} else if ( token = = " -game " ) {
// parse game name
game = tokens . NextToken ( " Expecting game name after -game " ) ;
} else if ( token = = " -rename " ) {
// parse joint to rename
joints . from = tokens . NextToken ( " Missing joint name for -rename. Usage: -rename [joint name] [new name] " ) ;
joints . to = tokens . NextToken ( " Missing new name for -rename. Usage: -rename [joint name] [new name] " ) ;
renamejoints . Append ( joints ) ;
} else if ( token = = " -prefix " ) {
prefix = tokens . NextToken ( " Missing name for -prefix. Usage: -prefix [joint prefix] " ) ;
} else if ( token = = " -parent " ) {
// parse joint to reparent
joints . from = tokens . NextToken ( " Missing joint name for -parent. Usage: -parent [joint name] [new parent] " ) ;
joints . to = tokens . NextToken ( " Missing new parent for -parent. Usage: -parent [joint name] [new parent] " ) ;
remapjoints . Append ( joints ) ;
} else if ( ! token . Icmp ( " -sourcedir " ) ) {
// parse source directory
sourceDir = tokens . NextToken ( " Missing filename for -sourcedir. Usage: -sourcedir [directory] " ) ;
} else if ( ! token . Icmp ( " -destdir " ) ) {
// parse destination directory
destDir = tokens . NextToken ( " Missing filename for -destdir. Usage: -destdir [directory] " ) ;
} else if ( token = = " -dest " ) {
// parse destination filename
dest = tokens . NextToken ( " Missing filename for -dest. Usage: -dest [filename] " ) ;
} else if ( token = = " -range " ) {
// parse frame range to export
token = tokens . NextToken ( " Missing start frame for -range. Usage: -range [start frame] [end frame] " ) ;
startframe = atoi ( token ) ;
token = tokens . NextToken ( " Missing end frame for -range. Usage: -range [start frame] [end frame] " ) ;
endframe = atoi ( token ) ;
if ( startframe > endframe ) {
MayaError ( " Start frame is greater than end frame. " ) ;
}
} else if ( ! token . Icmp ( " -cycleStart " ) ) {
// parse start frame of cycle
token = tokens . NextToken ( " Missing cycle start frame for -cycleStart. Usage: -cycleStart [first frame of cycle] " ) ;
cycleStart = atoi ( token ) ;
} else if ( token = = " -scale " ) {
// parse scale
token = tokens . NextToken ( " Missing scale amount for -scale. Usage: -scale [scale amount] " ) ;
scale = atof ( token ) ;
} else if ( token = = " -align " ) {
// parse align joint
align = tokens . NextToken ( " Missing joint name for -align. Usage: -align [joint name] " ) ;
} else if ( token = = " -rotate " ) {
// parse angle rotation
token = tokens . NextToken ( " Missing value for -rotate. Usage: -rotate [yaw] " ) ;
rotate = - atof ( token ) ;
} else if ( token = = " -nomesh " ) {
ignoreMeshes = true ;
} else if ( token = = " -clearorigin " ) {
clearOrigin = true ;
clearOriginAxis = true ;
} else if ( token = = " -clearoriginaxis " ) {
clearOriginAxis = true ;
} else if ( token = = " -ignorescale " ) {
ignoreScale = true ;
} else if ( token = = " -xyzprecision " ) {
// parse quaternion precision
token = tokens . NextToken ( " Missing value for -xyzprecision. Usage: -xyzprecision [precision] " ) ;
xyzPrecision = atof ( token ) ;
if ( xyzPrecision < 0.0f ) {
MayaError ( " Invalid value for -xyzprecision. Must be >= 0 " ) ;
}
} else if ( token = = " -quatprecision " ) {
// parse quaternion precision
token = tokens . NextToken ( " Missing value for -quatprecision. Usage: -quatprecision [precision] " ) ;
quatPrecision = atof ( token ) ;
if ( quatPrecision < 0.0f ) {
MayaError ( " Invalid value for -quatprecision. Must be >= 0 " ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
} else if ( token = = " -jointthreshold " ) {
// parse joint threshold
token = tokens . NextToken ( " Missing weight for -jointthreshold. Usage: -jointthreshold [minimum joint weight] " ) ;
jointThreshold = atof ( token ) ;
} else if ( token = = " -skipmesh " ) {
token = tokens . NextToken ( " Missing name for -skipmesh. Usage: -skipmesh [name of mesh to skip] " ) ;
skipmeshes . AddUnique ( token ) ;
} else if ( token = = " -keepmesh " ) {
token = tokens . NextToken ( " Missing name for -keepmesh. Usage: -keepmesh [name of mesh to keep] " ) ;
keepmeshes . AddUnique ( token ) ;
} else if ( token = = " -jointgroup " ) {
token = tokens . NextToken ( " Missing name for -jointgroup. Usage: -jointgroup [group name] [joint1] [joint2]...[joint n] " ) ;
group = groups . Ptr ( ) ;
for ( i = 0 ; i < groups . Num ( ) ; i + + , group + + ) {
if ( group - > name = = token ) {
break ;
}
}
if ( i > = groups . Num ( ) ) {
// create a new group
group = & groups . Alloc ( ) ;
group - > name = token ;
}
while ( tokens . TokenAvailable ( ) ) {
token = tokens . NextToken ( ) ;
if ( token [ 0 ] = = ' - ' ) {
tokens . UnGetToken ( ) ;
break ;
}
group - > joints . AddUnique ( token ) ;
}
} else if ( token = = " -group " ) {
// add the list of groups to export (these don't affect the hierarchy)
while ( tokens . TokenAvailable ( ) ) {
token = tokens . NextToken ( ) ;
if ( token [ 0 ] = = ' - ' ) {
tokens . UnGetToken ( ) ;
break ;
}
group = groups . Ptr ( ) ;
for ( i = 0 ; i < groups . Num ( ) ; i + + , group + + ) {
if ( group - > name = = token ) {
break ;
}
}
if ( i > = groups . Num ( ) ) {
MayaError ( " Unknown group '%s' " , token . c_str ( ) ) ;
}
exportgroups . AddUnique ( group ) ;
}
} else if ( token = = " -keep " ) {
// add joints that are kept whether they're used by a mesh or not
while ( tokens . TokenAvailable ( ) ) {
token = tokens . NextToken ( ) ;
if ( token [ 0 ] = = ' - ' ) {
tokens . UnGetToken ( ) ;
break ;
}
keepjoints . AddUnique ( token ) ;
}
} else {
MayaError ( " Unknown option '%s' " , token . c_str ( ) ) ;
}
}
token = src ;
src = ospath ;
src . BackSlashesToSlashes ( ) ;
src . AppendPath ( sourceDir ) ;
src . AppendPath ( token ) ;
token = dest ;
dest = ospath ;
dest . BackSlashesToSlashes ( ) ;
dest . AppendPath ( destDir ) ;
dest . AppendPath ( token ) ;
// Maya only accepts unix style path separators
src . BackSlashesToSlashes ( ) ;
dest . BackSlashesToSlashes ( ) ;
if ( skipmeshes . Num ( ) & & keepmeshes . Num ( ) ) {
MayaError ( " Can't use -keepmesh and -skipmesh together. " ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = =
idExportOptions : : jointInExportGroup
= = = = = = = = = = = = = = = = = = = =
*/
bool idExportOptions : : jointInExportGroup ( const char * jointname ) {
int i ;
int j ;
idAnimGroup * group ;
if ( ! exportgroups . Num ( ) ) {
// if we don't have any groups specified as export then export every joint
return true ;
}
// search through all exported groups to see if this joint is exported
for ( i = 0 ; i < exportgroups . Num ( ) ; i + + ) {
group = exportgroups [ i ] ;
for ( j = 0 ; j < group - > joints . Num ( ) ; j + + ) {
if ( group - > joints [ j ] = = jointname ) {
return true ;
}
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idExportJoint
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
idExportJoint : : idExportJoint ( ) {
index = 0 ;
exportNum = 0 ;
mayaNode . SetOwner ( this ) ;
exportNode . SetOwner ( this ) ;
dagnode = NULL ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
t = vec3_zero ;
wm = mat3_default ;
bindpos = vec3_zero ;
bindmat = mat3_default ;
keep = false ;
scale = 1.0f ;
invscale = 1.0f ;
animBits = 0 ;
firstComponent = 0 ;
baseFrame . q . Set ( 0.0f , 0.0f , 0.0f ) ;
baseFrame . t . Zero ( ) ;
}
idExportJoint & idExportJoint : : operator = ( const idExportJoint & other ) {
name = other . name ;
realname = other . realname ;
longname = other . longname ;
index = other . index ;
exportNum = other . exportNum ;
keep = other . keep ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
scale = other . scale ;
invscale = other . invscale ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
dagnode = other . dagnode ;
mayaNode = other . mayaNode ;
exportNode = other . exportNode ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
t = other . t ;
idt = other . idt ;
wm = other . wm ;
idwm = other . idwm ;
bindpos = other . bindpos ;
bindmat = other . bindmat ;
animBits = other . animBits ;
firstComponent = other . firstComponent ;
baseFrame = other . baseFrame ;
mayaNode . SetOwner ( this ) ;
exportNode . SetOwner ( this ) ;
return * this ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idExportMesh
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void idExportMesh : : ShareVerts ( void ) {
int i , j , k ;
exportVertex_t vert ;
idList < exportVertex_t > v ;
v = verts ;
verts . Clear ( ) ;
for ( i = 0 ; i < tris . Num ( ) ; i + + ) {
for ( j = 0 ; j < 3 ; j + + ) {
vert = v [ tris [ i ] . indexes [ j ] ] ;
vert . texCoords [ 0 ] = uv [ i ] . uv [ j ] [ 0 ] ;
vert . texCoords [ 1 ] = 1.0f - uv [ i ] . uv [ j ] [ 1 ] ;
for ( k = 0 ; k < verts . Num ( ) ; k + + ) {
if ( vert . numWeights ! = verts [ k ] . numWeights ) {
continue ;
}
if ( vert . startweight ! = verts [ k ] . startweight ) {
continue ;
}
if ( ! vert . pos . Compare ( verts [ k ] . pos , SLOP_VERTEX ) ) {
continue ;
}
if ( ! vert . texCoords . Compare ( verts [ k ] . texCoords , SLOP_TEXCOORD ) ) {
continue ;
}
break ;
}
if ( k < verts . Num ( ) ) {
tris [ i ] . indexes [ j ] = k ;
} else {
tris [ i ] . indexes [ j ] = verts . Append ( vert ) ;
}
}
}
}
void idExportMesh : : Merge ( idExportMesh * mesh ) {
int i ;
int numverts ;
int numtris ;
int numweights ;
int numuvs ;
// merge name
sprintf ( name , " %s, %s " , name . c_str ( ) , mesh - > name . c_str ( ) ) ;
// merge verts
numverts = verts . Num ( ) ;
verts . SetNum ( numverts + mesh - > verts . Num ( ) ) ;
for ( i = 0 ; i < mesh - > verts . Num ( ) ; i + + ) {
verts [ numverts + i ] = mesh - > verts [ i ] ;
verts [ numverts + i ] . startweight + = weights . Num ( ) ;
}
// merge triangles
numtris = tris . Num ( ) ;
tris . SetNum ( numtris + mesh - > tris . Num ( ) ) ;
for ( i = 0 ; i < mesh - > tris . Num ( ) ; i + + ) {
tris [ numtris + i ] . indexes [ 0 ] = mesh - > tris [ i ] . indexes [ 0 ] + numverts ;
tris [ numtris + i ] . indexes [ 1 ] = mesh - > tris [ i ] . indexes [ 1 ] + numverts ;
tris [ numtris + i ] . indexes [ 2 ] = mesh - > tris [ i ] . indexes [ 2 ] + numverts ;
}
// merge weights
numweights = weights . Num ( ) ;
weights . SetNum ( numweights + mesh - > weights . Num ( ) ) ;
for ( i = 0 ; i < mesh - > weights . Num ( ) ; i + + ) {
weights [ numweights + i ] = mesh - > weights [ i ] ;
}
// merge uvs
numuvs = uv . Num ( ) ;
uv . SetNum ( numuvs + mesh - > uv . Num ( ) ) ;
for ( i = 0 ; i < mesh - > uv . Num ( ) ; i + + ) {
uv [ numuvs + i ] = mesh - > uv [ i ] ;
}
}
void idExportMesh : : GetBounds ( idBounds & bounds ) const {
int i ;
int j ;
idVec3 pos ;
const exportWeight_t * weight ;
const exportVertex_t * vert ;
bounds . Clear ( ) ;
weight = weights . Ptr ( ) ;
vert = verts . Ptr ( ) ;
for ( i = 0 ; i < verts . Num ( ) ; i + + , vert + + ) {
pos . Zero ( ) ;
weight = & weights [ vert - > startweight ] ;
for ( j = 0 ; j < vert - > numWeights ; j + + , weight + + ) {
pos + = weight - > jointWeight * ( weight - > joint - > idwm * weight - > offset + weight - > joint - > idt ) ;
}
bounds . AddPoint ( pos ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idExportModel
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = =
idExportModel : : idExportModel
= = = = = = = = = = = = = = = = = = = =
*/
ID_INLINE idExportModel : : idExportModel ( ) {
export_joints = 0 ;
skipjoints = 0 ;
frameRate = 24 ;
numFrames = 0 ;
exportOrigin = NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = =
idExportModel : : ~ idExportModel
= = = = = = = = = = = = = = = = = = = =
*/
ID_INLINE idExportModel : : ~ idExportModel ( ) {
meshes . DeleteContents ( true ) ;
}
idExportJoint * idExportModel : : FindJointReal ( const char * name ) {
idExportJoint * joint ;
int i ;
joint = joints . Ptr ( ) ;
for ( i = 0 ; i < joints . Num ( ) ; i + + , joint + + ) {
if ( joint - > realname = = name ) {
return joint ;
}
}
return NULL ;
}
idExportJoint * idExportModel : : FindJoint ( const char * name ) {
idExportJoint * joint ;
int i ;
joint = joints . Ptr ( ) ;
for ( i = 0 ; i < joints . Num ( ) ; i + + , joint + + ) {
if ( joint - > name = = name ) {
return joint ;
}
}
return NULL ;
}
bool idExportModel : : WriteMesh ( const char * filename , idExportOptions & options ) {
int i , j ;
int numMeshes ;
idExportMesh * mesh ;
idExportJoint * joint ;
idExportJoint * parent ;
idExportJoint * sibling ;
FILE * file ;
const char * parentName ;
int parentNum ;
idList < idExportJoint * > jointList ;
file = fopen ( filename , " w " ) ;
if ( ! file ) {
return false ;
}
for ( joint = exportHead . GetNext ( ) ; joint ! = NULL ; joint = joint - > exportNode . GetNext ( ) ) {
jointList . Append ( joint ) ;
}
for ( i = 0 ; i < jointList . Num ( ) ; i + + ) {
joint = jointList [ i ] ;
sibling = joint - > exportNode . GetSibling ( ) ;
while ( sibling ) {
if ( idStr : : Cmp ( joint - > name , sibling - > name ) > 0 ) {
joint - > exportNode . MakeSiblingAfter ( sibling - > exportNode ) ;
sibling = joint - > exportNode . GetSibling ( ) ;
} else {
sibling = sibling - > exportNode . GetSibling ( ) ;
}
}
}
jointList . Clear ( ) ;
for ( joint = exportHead . GetNext ( ) ; joint ! = NULL ; joint = joint - > exportNode . GetNext ( ) ) {
joint - > exportNum = jointList . Append ( joint ) ;
}
numMeshes = 0 ;
if ( ! options . ignoreMeshes ) {
for ( i = 0 ; i < meshes . Num ( ) ; i + + ) {
if ( meshes [ i ] - > keep ) {
numMeshes + + ;
}
}
}
// write version info
WriteFloatString ( file , MD5_VERSION_STRING " %d \n " , MD5_VERSION ) ;
WriteFloatString ( file , " commandline \" %s \" \n \n " , options . commandLine . c_str ( ) ) ;
// write joints
WriteFloatString ( file , " numJoints %d \n " , jointList . Num ( ) ) ;
WriteFloatString ( file , " numMeshes %d \n \n " , numMeshes ) ;
WriteFloatString ( file , " joints { \n " ) ;
for ( i = 0 ; i < jointList . Num ( ) ; i + + ) {
joint = jointList [ i ] ;
parent = joint - > exportNode . GetParent ( ) ;
if ( parent ) {
parentNum = parent - > exportNum ;
parentName = parent - > name . c_str ( ) ;
} else {
parentNum = - 1 ;
parentName = " " ;
}
idCQuat bindQuat = joint - > bindmat . ToQuat ( ) . ToCQuat ( ) ;
2011-12-06 18:20:15 +00:00
WriteFloatString ( file , " \t \" %s \" \t %d ( %f %f %f ) ( %f %f %f ) \t \t // %s \n " , joint - > name . c_str ( ) , parentNum ,
2011-11-22 21:28:15 +00:00
joint - > bindpos . x , joint - > bindpos . y , joint - > bindpos . z , bindQuat [ 0 ] , bindQuat [ 1 ] , bindQuat [ 2 ] , parentName ) ;
}
WriteFloatString ( file , " } \n " ) ;
// write meshes
for ( i = 0 ; i < meshes . Num ( ) ; i + + ) {
mesh = meshes [ i ] ;
if ( ! mesh - > keep ) {
continue ;
}
WriteFloatString ( file , " \n mesh { \n " ) ;
WriteFloatString ( file , " \t // meshes: %s \n " , mesh - > name . c_str ( ) ) ;
WriteFloatString ( file , " \t shader \" %s \" \n " , mesh - > shader . c_str ( ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
WriteFloatString ( file , " \n \t numverts %d \n " , mesh - > verts . Num ( ) ) ;
for ( j = 0 ; j < mesh - > verts . Num ( ) ; j + + ) {
WriteFloatString ( file , " \t vert %d ( %f %f ) %d %d \n " , j , mesh - > verts [ j ] . texCoords [ 0 ] , mesh - > verts [ j ] . texCoords [ 1 ] ,
2011-12-06 18:20:15 +00:00
mesh - > verts [ j ] . startweight , mesh - > verts [ j ] . numWeights ) ;
2011-11-22 21:28:15 +00:00
}
WriteFloatString ( file , " \n \t numtris %d \n " , mesh - > tris . Num ( ) ) ;
for ( j = 0 ; j < mesh - > tris . Num ( ) ; j + + ) {
WriteFloatString ( file , " \t tri %d %d %d %d \n " , j , mesh - > tris [ j ] . indexes [ 2 ] , mesh - > tris [ j ] . indexes [ 1 ] , mesh - > tris [ j ] . indexes [ 0 ] ) ;
}
WriteFloatString ( file , " \n \t numweights %d \n " , mesh - > weights . Num ( ) ) ;
for ( j = 0 ; j < mesh - > weights . Num ( ) ; j + + ) {
exportWeight_t * weight ;
weight = & mesh - > weights [ j ] ;
2011-12-06 18:20:15 +00:00
WriteFloatString ( file , " \t weight %d %d %f ( %f %f %f ) \n " , j ,
2011-11-22 21:28:15 +00:00
weight - > joint - > exportNum , weight - > jointWeight , weight - > offset . x , weight - > offset . y , weight - > offset . z ) ;
}
WriteFloatString ( file , " } \n " ) ;
}
fclose ( file ) ;
return true ;
}
bool idExportModel : : WriteAnim ( const char * filename , idExportOptions & options ) {
int i , j ;
idExportJoint * joint ;
idExportJoint * parent ;
idExportJoint * sibling ;
jointFrame_t * frame ;
FILE * file ;
int numAnimatedComponents ;
idList < idExportJoint * > jointList ;
file = fopen ( filename , " w " ) ;
if ( ! file ) {
return false ;
}
for ( joint = exportHead . GetNext ( ) ; joint ! = NULL ; joint = joint - > exportNode . GetNext ( ) ) {
jointList . Append ( joint ) ;
}
for ( i = 0 ; i < jointList . Num ( ) ; i + + ) {
joint = jointList [ i ] ;
sibling = joint - > exportNode . GetSibling ( ) ;
while ( sibling ) {
if ( idStr : : Cmp ( joint - > name , sibling - > name ) > 0 ) {
joint - > exportNode . MakeSiblingAfter ( sibling - > exportNode ) ;
sibling = joint - > exportNode . GetSibling ( ) ;
} else {
sibling = sibling - > exportNode . GetSibling ( ) ;
}
}
}
jointList . Clear ( ) ;
for ( joint = exportHead . GetNext ( ) ; joint ! = NULL ; joint = joint - > exportNode . GetNext ( ) ) {
joint - > exportNum = jointList . Append ( joint ) ;
}
numAnimatedComponents = 0 ;
for ( i = 0 ; i < jointList . Num ( ) ; i + + ) {
joint = jointList [ i ] ;
joint - > exportNum = i ;
joint - > baseFrame = frames [ 0 ] [ joint - > index ] ;
joint - > animBits = 0 ;
for ( j = 1 ; j < numFrames ; j + + ) {
frame = & frames [ j ] [ joint - > index ] ;
if ( fabs ( frame - > t [ 0 ] - joint - > baseFrame . t [ 0 ] ) > options . xyzPrecision ) {
joint - > animBits | = ANIM_TX ;
}
if ( fabs ( frame - > t [ 1 ] - joint - > baseFrame . t [ 1 ] ) > options . xyzPrecision ) {
joint - > animBits | = ANIM_TY ;
}
if ( fabs ( frame - > t [ 2 ] - joint - > baseFrame . t [ 2 ] ) > options . xyzPrecision ) {
joint - > animBits | = ANIM_TZ ;
}
if ( fabs ( frame - > q [ 0 ] - joint - > baseFrame . q [ 0 ] ) > options . quatPrecision ) {
joint - > animBits | = ANIM_QX ;
}
if ( fabs ( frame - > q [ 1 ] - joint - > baseFrame . q [ 1 ] ) > options . quatPrecision ) {
joint - > animBits | = ANIM_QY ;
}
if ( fabs ( frame - > q [ 2 ] - joint - > baseFrame . q [ 2 ] ) > options . quatPrecision ) {
joint - > animBits | = ANIM_QZ ;
}
if ( ( joint - > animBits & 63 ) = = 63 ) {
break ;
}
}
if ( joint - > animBits ) {
joint - > firstComponent = numAnimatedComponents ;
for ( j = 0 ; j < 6 ; j + + ) {
if ( joint - > animBits & BIT ( j ) ) {
numAnimatedComponents + + ;
}
}
}
}
// write version info
WriteFloatString ( file , MD5_VERSION_STRING " %d \n " , MD5_VERSION ) ;
WriteFloatString ( file , " commandline \" %s \" \n \n " , options . commandLine . c_str ( ) ) ;
WriteFloatString ( file , " numFrames %d \n " , numFrames ) ;
WriteFloatString ( file , " numJoints %d \n " , jointList . Num ( ) ) ;
WriteFloatString ( file , " frameRate %d \n " , frameRate ) ;
WriteFloatString ( file , " numAnimatedComponents %d \n " , numAnimatedComponents ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// write out the hierarchy
WriteFloatString ( file , " \n hierarchy { \n " ) ;
for ( i = 0 ; i < jointList . Num ( ) ; i + + ) {
joint = jointList [ i ] ;
parent = joint - > exportNode . GetParent ( ) ;
if ( parent ) {
WriteFloatString ( file , " \t \" %s \" \t %d %d %d \t // %s " , joint - > name . c_str ( ) , parent - > exportNum , joint - > animBits , joint - > firstComponent , parent - > name . c_str ( ) ) ;
} else {
WriteFloatString ( file , " \t \" %s \" \t -1 %d %d \t // " , joint - > name . c_str ( ) , joint - > animBits , joint - > firstComponent ) ;
}
if ( ! joint - > animBits ) {
WriteFloatString ( file , " \n " ) ;
} else {
WriteFloatString ( file , " ( " ) ;
for ( j = 0 ; j < 6 ; j + + ) {
if ( joint - > animBits & BIT ( j ) ) {
WriteFloatString ( file , " %s " , componentNames [ j ] ) ;
}
}
WriteFloatString ( file , " ) \n " ) ;
}
}
WriteFloatString ( file , " } \n " ) ;
// write the frame bounds
WriteFloatString ( file , " \n bounds { \n " ) ;
for ( i = 0 ; i < numFrames ; i + + ) {
WriteFloatString ( file , " \t ( %f %f %f ) ( %f %f %f ) \n " , bounds [ i ] [ 0 ] . x , bounds [ i ] [ 0 ] . y , bounds [ i ] [ 0 ] . z , bounds [ i ] [ 1 ] . x , bounds [ i ] [ 1 ] . y , bounds [ i ] [ 1 ] . z ) ;
}
WriteFloatString ( file , " } \n " ) ;
// write the base frame
WriteFloatString ( file , " \n baseframe { \n " ) ;
for ( i = 0 ; i < jointList . Num ( ) ; i + + ) {
joint = jointList [ i ] ;
WriteFloatString ( file , " \t ( %f %f %f ) ( %f %f %f ) \n " , joint - > baseFrame . t [ 0 ] , joint - > baseFrame . t [ 1 ] , joint - > baseFrame . t [ 2 ] ,
joint - > baseFrame . q [ 0 ] , joint - > baseFrame . q [ 1 ] , joint - > baseFrame . q [ 2 ] ) ;
}
WriteFloatString ( file , " } \n " ) ;
// write the frames
for ( i = 0 ; i < numFrames ; i + + ) {
WriteFloatString ( file , " \n frame %d { \n " , i ) ;
for ( j = 0 ; j < jointList . Num ( ) ; j + + ) {
joint = jointList [ j ] ;
frame = & frames [ i ] [ joint - > index ] ;
if ( joint - > animBits ) {
WriteFloatString ( file , " \t " ) ;
if ( joint - > animBits & ANIM_TX ) {
WriteFloatString ( file , " %f " , frame - > t [ 0 ] ) ;
}
if ( joint - > animBits & ANIM_TY ) {
WriteFloatString ( file , " %f " , frame - > t [ 1 ] ) ;
}
if ( joint - > animBits & ANIM_TZ ) {
WriteFloatString ( file , " %f " , frame - > t [ 2 ] ) ;
}
if ( joint - > animBits & ANIM_QX ) {
WriteFloatString ( file , " %f " , frame - > q [ 0 ] ) ;
}
if ( joint - > animBits & ANIM_QY ) {
WriteFloatString ( file , " %f " , frame - > q [ 1 ] ) ;
}
if ( joint - > animBits & ANIM_QZ ) {
WriteFloatString ( file , " %f " , frame - > q [ 2 ] ) ;
}
WriteFloatString ( file , " \n " ) ;
}
}
WriteFloatString ( file , " } \n " ) ;
}
fclose ( file ) ;
return true ;
}
bool idExportModel : : WriteCamera ( const char * filename , idExportOptions & options ) {
int i ;
FILE * file ;
file = fopen ( filename , " w " ) ;
if ( ! file ) {
return false ;
}
// write version info
WriteFloatString ( file , MD5_VERSION_STRING " %d \n " , MD5_VERSION ) ;
WriteFloatString ( file , " commandline \" %s \" \n \n " , options . commandLine . c_str ( ) ) ;
WriteFloatString ( file , " numFrames %d \n " , camera . Num ( ) ) ;
WriteFloatString ( file , " frameRate %d \n " , frameRate ) ;
WriteFloatString ( file , " numCuts %d \n " , cameraCuts . Num ( ) ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// write out the cuts
WriteFloatString ( file , " \n cuts { \n " ) ;
for ( i = 0 ; i < cameraCuts . Num ( ) ; i + + ) {
WriteFloatString ( file , " \t %d \n " , cameraCuts [ i ] ) ;
}
WriteFloatString ( file , " } \n " ) ;
// write out the frames
WriteFloatString ( file , " \n camera { \n " ) ;
cameraFrame_t * frame = camera . Ptr ( ) ;
for ( i = 0 ; i < camera . Num ( ) ; i + + , frame + + ) {
WriteFloatString ( file , " \t ( %f %f %f ) ( %f %f %f ) %f \n " , frame - > t . x , frame - > t . y , frame - > t . z , frame - > q [ 0 ] , frame - > q [ 1 ] , frame - > q [ 2 ] , frame - > fov ) ;
}
WriteFloatString ( file , " } \n " ) ;
fclose ( file ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Maya
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = =
idMayaExport : : ~ idMayaExport
= = = = = = = = = = = = = = =
*/
idMayaExport : : ~ idMayaExport ( ) {
FreeDagNodes ( ) ;
// free up the file in Maya
MFileIO : : newFile ( true ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : TimeForFrame
= = = = = = = = = = = = = = =
*/
float idMayaExport : : TimeForFrame ( int num ) const {
MTime time ;
// set time unit to 24 frames per second
time . setUnit ( MTime : : kFilm ) ;
time . setValue ( num ) ;
return time . as ( MTime : : kSeconds ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetMayaFrameNum
= = = = = = = = = = = = = = =
*/
int idMayaExport : : GetMayaFrameNum ( int num ) const {
int frameNum ;
if ( options . cycleStart > options . startframe ) {
// in cycles, the last frame is a duplicate of the first frame, so with cycleStart we need to
// duplicate one of the interior frames instead and chop off the first frame.
frameNum = options . cycleStart + num ;
if ( frameNum > options . endframe ) {
frameNum - = options . endframe - options . startframe ;
}
if ( frameNum < options . startframe ) {
frameNum = options . startframe + 1 ;
}
} else {
frameNum = options . startframe + num ;
if ( frameNum > options . endframe ) {
frameNum - = options . endframe + 1 - options . startframe ;
}
if ( frameNum < options . startframe ) {
frameNum = options . startframe ;
}
}
return frameNum ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : SetFrame
= = = = = = = = = = = = = = =
*/
void idMayaExport : : SetFrame ( int num ) {
MTime time ;
int frameNum ;
frameNum = GetMayaFrameNum ( num ) ;
// set time unit to 24 frames per second
time . setUnit ( MTime : : kFilm ) ;
time . setValue ( frameNum ) ;
MGlobal : : viewFrame ( time ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : PruneJoints
= = = = = = = = = = = = = = =
*/
void idMayaExport : : PruneJoints ( idStrList & keepjoints , idStr & prefix ) {
int i ;
int j ;
idExportMesh * mesh ;
idExportJoint * joint ;
idExportJoint * joint2 ;
idExportJoint * parent ;
int num_weights ;
// if we don't have any joints specified to keep, mark the ones used by the meshes as keep
if ( ! keepjoints . Num ( ) & & ! prefix . Length ( ) ) {
if ( ! model . meshes . Num ( ) | | options . ignoreMeshes ) {
// export all joints
joint = model . joints . Ptr ( ) ;
for ( i = 0 ; i < model . joints . Num ( ) ; i + + , joint + + ) {
joint - > keep = true ;
}
} else {
for ( i = 0 ; i < model . meshes . Num ( ) ; i + + , mesh + + ) {
mesh = model . meshes [ i ] ;
for ( j = 0 ; j < mesh - > weights . Num ( ) ; j + + ) {
mesh - > weights [ j ] . joint - > keep = true ;
}
}
}
} else {
// mark the joints to keep
for ( i = 0 ; i < keepjoints . Num ( ) ; i + + ) {
joint = model . FindJoint ( keepjoints [ i ] ) ;
if ( joint ) {
joint - > keep = true ;
}
}
// count valid meshes
for ( i = 0 ; i < model . meshes . Num ( ) ; i + + ) {
mesh = model . meshes [ i ] ;
num_weights = 0 ;
for ( j = 0 ; j < mesh - > weights . Num ( ) ; j + + ) {
if ( mesh - > weights [ j ] . joint - > keep ) {
num_weights + + ;
} else if ( prefix . Length ( ) & & ! mesh - > weights [ j ] . joint - > realname . Cmpn ( prefix , prefix . Length ( ) ) ) {
// keep the joint if it's used by the mesh and it has the right prefix
mesh - > weights [ j ] . joint - > keep = true ;
num_weights + + ;
}
}
if ( num_weights ! = mesh - > weights . Num ( ) ) {
mesh - > keep = false ;
}
}
}
// find all joints aren't exported and reparent joint's children
model . export_joints = 0 ;
joint = model . joints . Ptr ( ) ;
for ( i = 0 ; i < model . joints . Num ( ) ; i + + , joint + + ) {
if ( ! joint - > keep ) {
joint - > exportNode . RemoveFromHierarchy ( ) ;
} else {
joint - > index = model . export_joints ;
model . export_joints + + ;
// make sure we are parented to an exported joint
for ( parent = joint - > exportNode . GetParent ( ) ; parent ! = NULL ; parent = parent - > exportNode . GetParent ( ) ) {
if ( parent - > keep ) {
break ;
}
}
if ( parent ! = NULL ) {
joint - > exportNode . ParentTo ( parent - > exportNode ) ;
} else {
joint - > exportNode . ParentTo ( model . exportHead ) ;
}
}
}
// check if we have any duplicate joint names
for ( joint = model . exportHead . GetNext ( ) ; joint ! = NULL ; joint = joint - > exportNode . GetNext ( ) ) {
if ( ! joint - > keep ) {
MayaError ( " Non-kept joint in export tree ('%s') " , joint - > name . c_str ( ) ) ;
}
for ( joint2 = model . exportHead . GetNext ( ) ; joint2 ! = NULL ; joint2 = joint2 - > exportNode . GetNext ( ) ) {
if ( ( joint2 ! = joint ) & & ( joint2 - > name = = joint - > name ) ) {
MayaError ( " Two joints found with the same name ('%s') " , joint - > name . c_str ( ) ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : FreeDagNodes
= = = = = = = = = = = = = = =
*/
void idMayaExport : : FreeDagNodes ( void ) {
int i ;
for ( i = 0 ; i < model . joints . Num ( ) ; i + + ) {
delete model . joints [ i ] . dagnode ;
model . joints [ i ] . dagnode = NULL ;
}
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetBindPose
= = = = = = = = = = = = = = =
*/
void idMayaExport : : GetBindPose ( MObject & jointNode , idExportJoint * joint , float scale ) {
MStatus status ;
MFnDependencyNode fnJoint ( jointNode ) ;
MObject aBindPose = fnJoint . attribute ( " bindPose " , & status ) ;
joint - > bindpos = vec3_zero ;
joint - > bindmat = mat3_default ;
if ( MS : : kSuccess = = status ) {
unsigned ii ;
unsigned jointIndex ;
unsigned connLength ;
MPlugArray connPlugs ;
MPlug pBindPose ( jointNode , aBindPose ) ;
pBindPose . connectedTo ( connPlugs , false , true ) ;
connLength = connPlugs . length ( ) ;
for ( ii = 0 ; ii < connLength ; + + ii ) {
if ( connPlugs [ ii ] . node ( ) . apiType ( ) = = MFn : : kDagPose ) {
MObject aMember = connPlugs [ ii ] . attribute ( ) ;
MFnAttribute fnAttr ( aMember ) ;
if ( fnAttr . name ( ) = = " worldMatrix " ) {
jointIndex = connPlugs [ ii ] . logicalIndex ( ) ;
MFnDependencyNode nDagPose ( connPlugs [ ii ] . node ( ) ) ;
// construct plugs for this joint's world matrix
MObject aWorldMatrix = nDagPose . attribute ( " worldMatrix " ) ;
MPlug pWorldMatrix ( connPlugs [ ii ] . node ( ) , aWorldMatrix ) ;
pWorldMatrix . selectAncestorLogicalIndex ( jointIndex , aWorldMatrix ) ;
// get the world matrix data
MObject worldMatrix ;
MStatus status = pWorldMatrix . getValue ( worldMatrix ) ;
if ( MS : : kSuccess ! = status ) {
// Problem retrieving world matrix
return ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
MFnMatrixData dMatrix ( worldMatrix ) ;
MMatrix wMatrix = dMatrix . matrix ( & status ) ;
joint - > bindmat = ConvertToIdSpace ( idMat ( wMatrix ) ) ;
joint - > bindpos = ConvertToIdSpace ( idVec ( wMatrix ) ) * scale ;
if ( ! options . ignoreScale ) {
joint - > bindpos * = joint - > scale ;
} else {
joint - > bindmat [ 0 ] . Normalize ( ) ;
joint - > bindmat [ 1 ] . Normalize ( ) ;
joint - > bindmat [ 2 ] . Normalize ( ) ;
}
return ;
}
}
}
}
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetLocalTransform
= = = = = = = = = = = = = = =
*/
void idMayaExport : : GetLocalTransform ( idExportJoint * joint , idVec3 & pos , idMat3 & mat ) {
MStatus status ;
MDagPath dagPath ;
pos . Zero ( ) ;
mat . Identity ( ) ;
if ( ! joint - > dagnode ) {
return ;
}
status = joint - > dagnode - > getPath ( dagPath ) ;
if ( ! status ) {
return ;
}
MObject transformNode = dagPath . transform ( & status ) ;
if ( ! status & & ( status . statusCode ( ) = = MStatus : : kInvalidParameter ) ) {
return ;
}
MFnDagNode transform ( transformNode , & status ) ;
if ( ! status ) {
return ;
}
pos = idVec ( transform . transformationMatrix ( ) ) ;
mat = idMat ( transform . transformationMatrix ( ) ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetWorldTransform
= = = = = = = = = = = = = = =
*/
void idMayaExport : : GetWorldTransform ( idExportJoint * joint , idVec3 & pos , idMat3 & mat , float scale ) {
idExportJoint * parent ;
GetLocalTransform ( joint , pos , mat ) ;
mat . OrthoNormalizeSelf ( ) ;
pos * = scale ;
parent = joint - > mayaNode . GetParent ( ) ;
if ( parent ) {
idVec3 parentpos ;
idMat3 parentmat ;
GetWorldTransform ( parent , parentpos , parentmat , scale ) ;
pos = parentpos + ( parentmat * ( pos * parent - > scale ) ) ;
mat = mat * parentmat ;
}
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : CreateJoints
= = = = = = = = = = = = = = =
*/
void idMayaExport : : CreateJoints ( float scale ) {
int i ;
int j ;
idExportJoint * joint ;
idExportJoint * parent ;
MStatus status ;
MDagPath dagPath ;
MFnDagNode * parentNode ;
SetFrame ( 0 ) ;
// create an initial list with all of the transformable nodes in the scene
MItDag dagIterator ( MItDag : : kDepthFirst , MFn : : kTransform , & status ) ;
for ( ; ! dagIterator . isDone ( ) ; dagIterator . next ( ) ) {
status = dagIterator . getPath ( dagPath ) ;
if ( ! status ) {
MayaError ( " CreateJoints: MItDag::getPath failed (%s) " , status . errorString ( ) . asChar ( ) ) ;
continue ;
}
joint = & model . joints . Alloc ( ) ;
joint - > index = model . joints . Num ( ) - 1 ;
joint - > dagnode = new MFnDagNode ( dagPath , & status ) ;
if ( ! status ) {
MayaError ( " CreateJoints: MFnDagNode constructor failed (%s) " , status . errorString ( ) . asChar ( ) ) ;
continue ;
}
joint - > name = joint - > dagnode - > name ( ) . asChar ( ) ;
joint - > realname = joint - > name ;
}
// allocate an extra joint in case we need to add an origin later
model . exportOrigin = & model . joints . Alloc ( ) ;
model . exportOrigin - > index = model . joints . Num ( ) - 1 ;
// create scene hierarchy
joint = model . joints . Ptr ( ) ;
for ( i = 0 ; i < model . joints . Num ( ) ; i + + , joint + + ) {
if ( ! joint - > dagnode ) {
continue ;
}
joint - > mayaNode . ParentTo ( model . mayaHead ) ;
joint - > exportNode . ParentTo ( model . exportHead ) ;
parentNode = GetParent ( joint - > dagnode ) ;
if ( parentNode ) {
// find the parent joint in our jointlist
for ( j = 0 ; j < model . joints . Num ( ) ; j + + ) {
if ( ! model . joints [ j ] . dagnode ) {
continue ;
}
if ( model . joints [ j ] . dagnode - > name ( ) = = parentNode - > name ( ) ) {
joint - > mayaNode . ParentTo ( model . joints [ j ] . mayaNode ) ;
joint - > exportNode . ParentTo ( model . joints [ j ] . exportNode ) ;
break ;
}
}
delete parentNode ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// create long name
parent = joint - > mayaNode . GetParent ( ) ;
if ( parent ) {
joint - > longname = parent - > longname + " / " + joint - > name ;
} else {
joint - > longname = joint - > name ;
}
// get the joint's scale
GetLocalTransform ( & model . joints [ i ] , joint - > t , joint - > wm ) ;
joint - > scale = joint - > wm [ 0 ] . Length ( ) ;
if ( parent ) {
joint - > scale * = parent - > scale ;
if ( joint - > scale ! = 0 ) {
joint - > invscale = 1.0f / joint - > scale ;
} else {
joint - > invscale = 0 ;
}
}
joint - > dagnode - > getPath ( dagPath ) ;
2011-12-06 18:20:15 +00:00
GetBindPose ( dagPath . node ( & status ) , joint , scale ) ;
2011-11-22 21:28:15 +00:00
}
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : RenameJoints
= = = = = = = = = = = = = = =
*/
void idMayaExport : : RenameJoints ( idList < idNamePair > & renamejoints , idStr & prefix ) {
int i ;
idExportJoint * joint ;
// rename joints that match the prefix
if ( prefix . Length ( ) ) {
joint = model . joints . Ptr ( ) ;
for ( i = 0 ; i < model . joints . Num ( ) ; i + + , joint + + ) {
if ( ! joint - > name . Cmpn ( prefix , prefix . Length ( ) ) ) {
// remove the prefix from the name
joint - > name = joint - > name . Right ( joint - > name . Length ( ) - prefix . Length ( ) ) ;
}
}
}
// rename joints if necessary
for ( i = 0 ; i < renamejoints . Num ( ) ; i + + ) {
joint = model . FindJoint ( renamejoints [ i ] . from ) ;
if ( joint ) {
joint - > name = renamejoints [ i ] . to ;
}
}
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : RemapParents
= = = = = = = = = = = = = = =
*/
bool idMayaExport : : RemapParents ( idList < idNamePair > & remapjoints ) {
int i ;
idExportJoint * joint ;
idExportJoint * parent ;
idExportJoint * origin ;
idExportJoint * sibling ;
for ( i = 0 ; i < remapjoints . Num ( ) ; i + + ) {
// find joint to reparent
joint = model . FindJoint ( remapjoints [ i ] . from ) ;
if ( ! joint ) {
// couldn't find joint, fail
MayaError ( " Couldn't find joint '%s' to reparent \n " , remapjoints [ i ] . from . c_str ( ) ) ;
}
// find new parent joint
parent = model . FindJoint ( remapjoints [ i ] . to ) ;
if ( ! parent ) {
// couldn't find parent, fail
MayaError ( " Couldn't find joint '%s' to be new parent for '%s' \n " , remapjoints [ i ] . to . c_str ( ) , remapjoints [ i ] . from . c_str ( ) ) ;
}
if ( parent - > exportNode . ParentedBy ( joint - > exportNode ) ) {
MayaError ( " Joint '%s' is a child of joint '%s' and can't become the parent. " , joint - > name . c_str ( ) , parent - > name . c_str ( ) ) ;
}
joint - > exportNode . ParentTo ( parent - > exportNode ) ;
}
// if we have an origin, make it the first node in the export list, otherwise add one
origin = model . FindJoint ( " origin " ) ;
if ( ! origin ) {
origin = model . exportOrigin ;
origin - > dagnode = NULL ;
origin - > name = " origin " ;
origin - > realname = " origin " ;
origin - > bindmat . Identity ( ) ;
origin - > bindpos . Zero ( ) ;
}
origin - > exportNode . ParentTo ( model . exportHead ) ;
// force the joint to be kept
origin - > keep = true ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// make all root joints children of the origin joint
joint = model . exportHead . GetChild ( ) ;
while ( joint ) {
sibling = joint - > exportNode . GetSibling ( ) ;
if ( joint ! = origin ) {
joint - > exportNode . ParentTo ( origin - > exportNode ) ;
}
joint = sibling ;
}
return true ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : FindShader
Find the shading node for the given shading group set node .
= = = = = = = = = = = = = = =
*/
MObject idMayaExport : : FindShader ( MObject & setNode ) {
MStatus status ;
MFnDependencyNode fnNode ( setNode ) ;
MPlug shaderPlug ;
2011-12-06 18:20:15 +00:00
shaderPlug = fnNode . findPlug ( " surfaceShader " ) ;
2011-11-22 21:28:15 +00:00
if ( ! shaderPlug . isNull ( ) ) {
MPlugArray connectedPlugs ;
bool asSrc = false ;
bool asDst = true ;
shaderPlug . connectedTo ( connectedPlugs , asDst , asSrc , & status ) ;
if ( connectedPlugs . length ( ) ! = 1 ) {
MayaError ( " FindShader: Error getting shader (%s) " , status . errorString ( ) . asChar ( ) ) ;
} else {
return connectedPlugs [ 0 ] . node ( ) ;
}
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
return MObject : : kNullObj ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetTextureForMesh
Find the texture files that apply to the color of each polygon of
a selected shape if the shape has its polygons organized into sets .
= = = = = = = = = = = = = = =
*/
void idMayaExport : : GetTextureForMesh ( idExportMesh * mesh , MFnDagNode & dagNode ) {
MStatus status ;
MDagPath path ;
int i ;
int instanceNum ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
status = dagNode . getPath ( path ) ;
if ( ! status ) {
return ;
}
path . extendToShape ( ) ;
// If the shape is instanced then we need to determine which
// instance this path refers to.
//
instanceNum = 0 ;
if ( path . isInstanced ( ) ) {
instanceNum = path . instanceNumber ( ) ;
}
2011-12-06 18:20:15 +00:00
// Get a list of all sets pertaining to the selected shape and the
// members of those sets.
//
2011-11-22 21:28:15 +00:00
MFnMesh fnMesh ( path ) ;
MObjectArray sets ;
MObjectArray comps ;
status = fnMesh . getConnectedSetsAndMembers ( instanceNum , sets , comps , true ) ;
if ( ! status ) {
MayaError ( " GetTextureForMesh: MFnMesh::getConnectedSetsAndMembers failed (%s) " , status . errorString ( ) . asChar ( ) ) ;
}
// Loop through all the sets. If the set is a polygonal set, find the
2011-12-06 18:20:15 +00:00
// shader attached to the and print out the texture file name for the
// set along with the polygons in the set.
2011-11-22 21:28:15 +00:00
//
for ( i = 0 ; i < ( int ) sets . length ( ) ; i + + ) {
MObject set = sets [ i ] ;
MObject comp = comps [ i ] ;
MFnSet fnSet ( set , & status ) ;
if ( status = = MS : : kFailure ) {
MayaError ( " GetTextureForMesh: MFnSet constructor failed (%s) " , status . errorString ( ) . asChar ( ) ) ;
2011-12-06 18:20:15 +00:00
continue ;
}
2011-11-22 21:28:15 +00:00
2011-12-06 18:20:15 +00:00
// Make sure the set is a polygonal set. If not, continue.
2011-11-22 21:28:15 +00:00
MItMeshPolygon piter ( path , comp , & status ) ;
if ( status = = MS : : kFailure ) {
2011-12-06 18:20:15 +00:00
continue ;
2011-11-22 21:28:15 +00:00
}
// Find the texture that is applied to this set. First, get the
// shading node connected to the set. Then, if there is an input
// attribute called "color", search upstream from it for a texture
// file node.
2011-12-06 18:20:15 +00:00
//
2011-11-22 21:28:15 +00:00
MObject shaderNode = FindShader ( set ) ;
if ( shaderNode = = MObject : : kNullObj ) {
continue ;
}
MPlug colorPlug = MFnDependencyNode ( shaderNode ) . findPlug ( " color " , & status ) ;
if ( status = = MS : : kFailure ) {
continue ;
}
MItDependencyGraph dgIt ( colorPlug , MFn : : kFileTexture ,
2011-12-06 18:20:15 +00:00
MItDependencyGraph : : kUpstream ,
2011-11-22 21:28:15 +00:00
MItDependencyGraph : : kBreadthFirst ,
2011-12-06 18:20:15 +00:00
MItDependencyGraph : : kNodeLevel ,
2011-11-22 21:28:15 +00:00
& status ) ;
if ( status = = MS : : kFailure ) {
continue ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
dgIt . disablePruningOnFilter ( ) ;
2011-12-06 18:20:15 +00:00
// If no texture file node was found, just continue.
//
2011-11-22 21:28:15 +00:00
if ( dgIt . isDone ( ) ) {
continue ;
}
2011-12-06 18:20:15 +00:00
// Print out the texture node name and texture file that it references.
//
2011-11-22 21:28:15 +00:00
MObject textureNode = dgIt . thisNode ( ) ;
2011-12-06 18:20:15 +00:00
MPlug filenamePlug = MFnDependencyNode ( textureNode ) . findPlug ( " fileTextureName " ) ;
MString textureName ;
filenamePlug . getValue ( textureName ) ;
2011-11-22 21:28:15 +00:00
// remove the OS path and save it in the mesh
OSPathToRelativePath ( textureName . asChar ( ) , mesh - > shader , options . game ) ;
mesh - > shader . StripFileExtension ( ) ;
return ;
}
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : CopyMesh
= = = = = = = = = = = = = = =
*/
idExportMesh * idMayaExport : : CopyMesh ( MFnSkinCluster & skinCluster , float scale ) {
MStatus status ;
MObjectArray objarray ;
MObjectArray outputarray ;
int nGeom ;
int i , j , k ;
idExportMesh * mesh ;
float uv_u , uv_v ;
idStr name , altname ;
int pos ;
status = skinCluster . getInputGeometry ( objarray ) ;
if ( ! status ) {
MayaError ( " CopyMesh: Error getting input geometry (%s) " , status . errorString ( ) . asChar ( ) ) ;
return NULL ;
}
nGeom = objarray . length ( ) ;
for ( i = 0 ; i < nGeom ; i + + ) {
MFnDagNode dagNode ( objarray [ i ] , & status ) ;
if ( ! status ) {
common - > Printf ( " CopyMesh: MFnDagNode Constructor failed (%s) " , status . errorString ( ) . asChar ( ) ) ;
continue ;
}
MFnMesh fnmesh ( objarray [ i ] , & status ) ;
if ( ! status ) {
// object isn't an MFnMesh
continue ;
}
status = skinCluster . getOutputGeometry ( outputarray ) ;
if ( ! status ) {
common - > Printf ( " CopyMesh: Error getting output geometry (%s) " , status . errorString ( ) . asChar ( ) ) ;
return NULL ;
}
if ( outputarray . length ( ) < 1 ) {
return NULL ;
}
name = fnmesh . name ( ) . asChar ( ) ;
if ( options . prefix . Length ( ) ) {
if ( ! name . Cmpn ( options . prefix , options . prefix . Length ( ) ) ) {
// remove the prefix from the name
name = name . Right ( name . Length ( ) - options . prefix . Length ( ) ) ;
} else {
// name doesn't match prefix, so don't use this mesh
//return NULL;
}
}
pos = name . Find ( " ShapeOrig " ) ;
if ( pos > = 0 ) {
name . CapLength ( pos ) ;
}
MFnDagNode dagNode2 ( outputarray [ 0 ] , & status ) ;
if ( ! status ) {
common - > Printf ( " CopyMesh: MFnDagNode Constructor failed (%s) " , status . errorString ( ) . asChar ( ) ) ;
continue ;
}
altname = name ;
MObject parent = fnmesh . parent ( 0 , & status ) ;
if ( status ) {
MFnDagNode parentNode ( parent , & status ) ;
if ( status ) {
altname = parentNode . name ( ) . asChar ( ) ;
}
}
name . StripLeadingOnce ( options . prefix ) ;
altname . StripLeadingOnce ( options . prefix ) ;
if ( options . keepmeshes . Num ( ) ) {
if ( ! options . keepmeshes . Find ( name ) & & ! options . keepmeshes . Find ( altname ) ) {
if ( altname ! = name ) {
common - > Printf ( " Skipping mesh '%s' ('%s') \n " , name . c_str ( ) , altname . c_str ( ) ) ;
} else {
common - > Printf ( " Skipping mesh '%s' \n " , name . c_str ( ) ) ;
}
return NULL ;
}
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( options . skipmeshes . Find ( name ) | | options . skipmeshes . Find ( altname ) ) {
common - > Printf ( " Skipping mesh '%s' ('%s') \n " , name . c_str ( ) , altname . c_str ( ) ) ;
return NULL ;
}
mesh = new idExportMesh ( ) ;
model . meshes . Append ( mesh ) ;
if ( altname . Length ( ) ) {
mesh - > name = altname ;
} else {
mesh - > name = name ;
}
GetTextureForMesh ( mesh , dagNode2 ) ;
int v = fnmesh . numVertices ( & status ) ;
mesh - > verts . SetNum ( v ) ;
MFloatPointArray vertexArray ;
fnmesh . getPoints ( vertexArray , MSpace : : kPreTransform ) ;
for ( j = 0 ; j < v ; j + + ) {
memset ( & mesh - > verts [ j ] , 0 , sizeof ( mesh - > verts [ j ] ) ) ;
mesh - > verts [ j ] . pos = ConvertToIdSpace ( idVec ( vertexArray [ j ] ) ) * scale ;
}
MIntArray vertexList ;
int p ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
p = fnmesh . numPolygons ( & status ) ;
mesh - > tris . SetNum ( p ) ;
mesh - > uv . SetNum ( p ) ;
MString setName ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
status = fnmesh . getCurrentUVSetName ( setName ) ;
if ( ! status ) {
MayaError ( " CopyMesh: MFnMesh::getCurrentUVSetName failed (%s) " , status . errorString ( ) . asChar ( ) ) ;
}
for ( j = 0 ; j < p ; j + + ) {
fnmesh . getPolygonVertices ( j , vertexList ) ;
if ( vertexList . length ( ) ! = 3 ) {
MayaError ( " CopyMesh: Too many vertices on a face (%d) \n " , vertexList . length ( ) ) ;
}
for ( k = 0 ; k < 3 ; k + + ) {
mesh - > tris [ j ] . indexes [ k ] = vertexList [ k ] ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
status = fnmesh . getPolygonUV ( j , k , uv_u , uv_v , & setName ) ;
if ( ! status ) {
MayaError ( " CopyMesh: MFnMesh::getPolygonUV failed (%s) " , status . errorString ( ) . asChar ( ) ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
mesh - > uv [ j ] . uv [ k ] [ 0 ] = uv_u ;
mesh - > uv [ j ] . uv [ k ] [ 1 ] = uv_v ;
}
}
return mesh ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : CreateMesh
= = = = = = = = = = = = = = =
*/
void idMayaExport : : CreateMesh ( float scale ) {
size_t count ;
idExportMesh * mesh ;
MStatus status ;
exportWeight_t weight ;
unsigned int nGeoms ;
// Iterate through graph and search for skinCluster nodes
MItDependencyNodes iter ( MFn : : kSkinClusterFilter ) ;
count = 0 ;
for ( ; ! iter . isDone ( ) ; iter . next ( ) ) {
MObject object = iter . item ( ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
count + + ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// For each skinCluster node, get the list of influence objects
MFnSkinCluster skinCluster ( object , & status ) ;
if ( ! status ) {
MayaError ( " %s: Error getting skin cluster (%s) " , object . apiTypeStr ( ) , status . errorString ( ) . asChar ( ) ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
mesh = CopyMesh ( skinCluster , scale ) ;
if ( ! mesh ) {
continue ;
}
MDagPathArray infs ;
unsigned int nInfs = skinCluster . influenceObjects ( infs , & status ) ;
if ( ! status ) {
MayaError ( " Mesh '%s': Error getting influence objects (%s) " , mesh - > name . c_str ( ) , status . errorString ( ) . asChar ( ) ) ;
}
if ( 0 = = nInfs ) {
MayaError ( " Mesh '%s': No influence objects found " , mesh - > name . c_str ( ) ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// loop through the geometries affected by this cluster
nGeoms = skinCluster . numOutputConnections ( ) ;
for ( size_t ii = 0 ; ii < nGeoms ; + + ii ) {
unsigned int index = skinCluster . indexForOutputConnection ( ii , & status ) ;
if ( ! status ) {
MayaError ( " Mesh '%s': Error getting geometry index (%s) " , mesh - > name . c_str ( ) , status . errorString ( ) . asChar ( ) ) ;
}
// get the dag path of the ii'th geometry
MDagPath skinPath ;
status = skinCluster . getPathAtIndex ( index , skinPath ) ;
if ( ! status ) {
MayaError ( " Mesh '%s': Error getting geometry path (%s) " , mesh - > name . c_str ( ) , status . errorString ( ) . asChar ( ) ) ;
}
// iterate through the components of this geometry
MItGeometry gIter ( skinPath ) ;
// print out the influence objects
idList < idExportJoint * > joints ;
idExportJoint * joint ;
exportVertex_t * vert ;
joints . Resize ( nInfs ) ;
for ( size_t kk = 0 ; kk < nInfs ; + + kk ) {
const char * c ;
MString s ;
s = infs [ kk ] . partialPathName ( ) ;
c = s . asChar ( ) ;
joint = model . FindJointReal ( c ) ;
if ( ! joint ) {
MayaError ( " Mesh '%s': joint %s not found " , mesh - > name . c_str ( ) , c ) ;
}
joints . Append ( joint ) ;
}
for ( /* nothing */ ; ! gIter . isDone ( ) ; gIter . next ( ) ) {
MObject comp = gIter . component ( & status ) ;
if ( ! status ) {
MayaError ( " Mesh '%s': Error getting component (%s) " , mesh - > name . c_str ( ) , status . errorString ( ) . asChar ( ) ) ;
}
// Get the weights for this vertex (one per influence object)
MFloatArray wts ;
unsigned infCount ;
status = skinCluster . getWeights ( skinPath , comp , wts , infCount ) ;
if ( ! status ) {
MayaError ( " Mesh '%s': Error getting weights (%s) " , mesh - > name . c_str ( ) , status . errorString ( ) . asChar ( ) ) ;
}
if ( 0 = = infCount ) {
MayaError ( " Mesh '%s': Error: 0 influence objects. " , mesh - > name . c_str ( ) ) ;
}
int num = gIter . index ( ) ;
vert = & mesh - > verts [ num ] ;
vert - > startweight = mesh - > weights . Num ( ) ;
float totalweight = 0.0f ;
// copy the weight data for this vertex
int numNonZeroWeights = 0 ;
int jj ;
for ( jj = 0 ; jj < ( int ) infCount ; + + jj ) {
float w = ( float ) wts [ jj ] ;
if ( w > 0.0f ) {
numNonZeroWeights + + ;
}
if ( w > options . jointThreshold ) {
weight . joint = joints [ jj ] ;
weight . jointWeight = wts [ jj ] ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
if ( ! options . ignoreScale ) {
weight . joint - > bindmat . ProjectVector ( vert - > pos - ( weight . joint - > bindpos * weight . joint - > invscale ) , weight . offset ) ;
weight . offset * = weight . joint - > scale ;
} else {
weight . joint - > bindmat . ProjectVector ( vert - > pos - weight . joint - > bindpos , weight . offset ) ;
}
mesh - > weights . Append ( weight ) ;
totalweight + = weight . jointWeight ;
}
}
vert - > numWeights = mesh - > weights . Num ( ) - vert - > startweight ;
if ( ! vert - > numWeights ) {
if ( numNonZeroWeights ) {
MayaError ( " Error on mesh '%s': Vertex %d doesn't have any joint weights exceeding jointThreshold (%f). " , mesh - > name . c_str ( ) , num , options . jointThreshold ) ;
} else {
MayaError ( " Error on mesh '%s': Vertex %d doesn't have any joint weights. " , mesh - > name . c_str ( ) , num ) ;
}
} else if ( ! totalweight ) {
MayaError ( " Error on mesh '%s': Combined weight of 0 on vertex %d. " , mesh - > name . c_str ( ) , num ) ;
}
//if ( numNonZeroWeights ) {
// common->Printf( "Mesh '%s': skipped %d out of %d weights on vertex %d\n", mesh->name.c_str(), numNonZeroWeights, numNonZeroWeights + vert->numWeights, num );
//}
// normalize the joint weights
for ( jj = 0 ; jj < vert - > numWeights ; jj + + ) {
mesh - > weights [ vert - > startweight + jj ] . jointWeight / = totalweight ;
}
}
break ;
}
}
if ( ! count & & ! options . ignoreMeshes ) {
MayaError ( " CreateMesh: No skinClusters found in this scene. \n " ) ;
}
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : CombineMeshes
combine surfaces with the same shader .
= = = = = = = = = = = = = = =
*/
void idMayaExport : : CombineMeshes ( void ) {
int i , j ;
int count ;
idExportMesh * mesh ;
idExportMesh * combine ;
idList < idExportMesh * > oldmeshes ;
oldmeshes = model . meshes ;
model . meshes . Clear ( ) ;
count = 0 ;
for ( i = 0 ; i < oldmeshes . Num ( ) ; i + + ) {
mesh = oldmeshes [ i ] ;
if ( ! mesh - > keep ) {
delete mesh ;
continue ;
}
combine = NULL ;
for ( j = 0 ; j < model . meshes . Num ( ) ; j + + ) {
if ( model . meshes [ j ] - > shader = = mesh - > shader ) {
combine = model . meshes [ j ] ;
break ;
}
}
if ( combine ) {
combine - > Merge ( mesh ) ;
delete mesh ;
count + + ;
} else {
model . meshes . Append ( mesh ) ;
}
}
// share verts
for ( i = 0 ; i < model . meshes . Num ( ) ; i + + ) {
model . meshes [ i ] - > ShareVerts ( ) ;
}
common - > Printf ( " Merged %d meshes \n " , count ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetAlignment
= = = = = = = = = = = = = = =
*/
void idMayaExport : : GetAlignment ( idStr & alignName , idMat3 & align , float rotate , int startframe ) {
idVec3 pos ;
idExportJoint * joint ;
idAngles ang ( 0 , rotate , 0 ) ;
idMat3 mat ;
align . Identity ( ) ;
if ( alignName . Length ( ) ) {
SetFrame ( 0 ) ;
joint = model . FindJoint ( alignName ) ;
if ( ! joint ) {
MayaError ( " could not find joint '%s' to align model to. \n " , alignName . c_str ( ) ) ;
}
// found it
GetWorldTransform ( joint , pos , mat , 1.0f ) ;
align [ 0 ] [ 0 ] = mat [ 2 ] [ 0 ] ;
align [ 0 ] [ 1 ] = - mat [ 2 ] [ 2 ] ;
align [ 0 ] [ 2 ] = mat [ 2 ] [ 1 ] ;
align [ 1 ] [ 0 ] = mat [ 0 ] [ 0 ] ;
align [ 1 ] [ 1 ] = - mat [ 0 ] [ 2 ] ;
align [ 1 ] [ 2 ] = mat [ 0 ] [ 1 ] ;
align [ 2 ] [ 0 ] = mat [ 1 ] [ 0 ] ;
align [ 2 ] [ 1 ] = - mat [ 1 ] [ 2 ] ;
align [ 2 ] [ 2 ] = mat [ 1 ] [ 1 ] ;
if ( rotate ) {
align * = ang . ToMat3 ( ) ;
}
} else if ( rotate ) {
align = ang . ToMat3 ( ) ;
}
align . TransposeSelf ( ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetObjectType
return the type of the object
= = = = = = = = = = = = = = =
*/
const char * idMayaExport : : GetObjectType ( MObject object ) {
if ( object . isNull ( ) ) {
return " (Null) " ;
}
MStatus stat ;
MFnDependencyNode dgNode ;
MString typeName ;
stat = dgNode . setObject ( object ) ;
typeName = dgNode . typeName ( & stat ) ;
if ( MS : : kSuccess ! = stat ) {
// can not get the type name of this object
return " (Unknown) " ;
}
return typeName . asChar ( ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetCameraFov
= = = = = = = = = = = = = = =
*/
float idMayaExport : : GetCameraFov ( idExportJoint * joint ) {
int childCount ;
int j ;
double horiz ;
double focal ;
MStatus status ;
const char * n1 , * n2 ;
MFnDagNode * dagnode ;
float fov ;
dagnode = joint - > dagnode ;
MObject cameraNode = dagnode - > object ( ) ;
childCount = dagnode - > childCount ( ) ;
fov = 90.0f ;
for ( j = 0 ; j < childCount ; j + + ) {
MObject childNode = dagnode - > child ( j ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
n1 = GetObjectType ( cameraNode ) ;
n2 = GetObjectType ( childNode ) ;
if ( ( ! strcmp ( " transform " , n1 ) ) & & ( ! strcmp ( " camera " , n2 ) ) ) {
MFnCamera camera ( childNode ) ;
focal = camera . focalLength ( ) ;
horiz = camera . horizontalFilmAperture ( ) ;
fov = RAD2DEG ( 2 * atan ( ( horiz * 0.5 ) / ( focal / 25.4 ) ) ) ;
break ;
}
}
return fov ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetCameraFrame
= = = = = = = = = = = = = = =
*/
void idMayaExport : : GetCameraFrame ( idExportJoint * camera , idMat3 & align , cameraFrame_t * cam ) {
idMat3 mat ;
idMat3 axis ;
idVec3 pos ;
// get the worldspace positions of the joint
GetWorldTransform ( camera , pos , axis , 1.0f ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// convert to id coordinates
cam - > t = ConvertToIdSpace ( pos ) * align ;
// correct the orientation for the game
axis = ConvertToIdSpace ( axis ) * align ;
mat [ 0 ] = - axis [ 2 ] ;
mat [ 1 ] = - axis [ 0 ] ;
mat [ 2 ] = axis [ 1 ] ;
cam - > q = mat . ToQuat ( ) . ToCQuat ( ) ;
// get it's fov
cam - > fov = GetCameraFov ( camera ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : CreateCameraAnim
= = = = = = = = = = = = = = =
*/
void idMayaExport : : CreateCameraAnim ( idMat3 & align ) {
float start , end ;
MDagPath dagPath ;
int frameNum ;
short v ;
MStatus status ;
cameraFrame_t cam ;
idExportJoint * refCam ;
idExportJoint * camJoint ;
idStr currentCam ;
idStr newCam ;
MPlug plug ;
MFnEnumAttribute cameraAttribute ;
start = TimeForFrame ( options . startframe ) ;
end = TimeForFrame ( options . endframe ) ;
#if 0
options . framerate = 60 ;
model . numFrames = ( int ) ( ( end - start ) * ( float ) options . framerate ) + 1 ;
model . frameRate = options . framerate ;
# else
model . numFrames = options . endframe + 1 - options . startframe ;
model . frameRate = options . framerate ;
# endif
common - > Printf ( " start frame = %d \n end frame = %d \n " , options . startframe , options . endframe ) ;
common - > Printf ( " start time = %f \n end time = %f \n total time = %f \n " , start , end , end - start ) ;
if ( start > end ) {
MayaError ( " Start frame is greater than end frame. " ) ;
}
refCam = model . FindJoint ( " refcam " ) ;
if ( refCam = = NULL ) {
currentCam = MAYA_DEFAULT_CAMERA ;
} else {
MObject cameraNode = refCam - > dagnode - > object ( ) ;
MFnDependencyNode cameraDG ( cameraNode , & status ) ;
if ( MS : : kSuccess ! = status ) {
MayaError ( " Can't find 'refcam' dependency node. " ) ;
return ;
}
MObject attr = cameraDG . attribute ( MString ( " Camera " ) , & status ) ;
if ( MS : : kSuccess ! = status ) {
MayaError ( " Can't find 'Camera' attribute on 'refcam'. " ) ;
return ;
}
plug = MPlug ( cameraNode , attr ) ;
status = cameraAttribute . setObject ( attr ) ;
if ( MS : : kSuccess ! = status ) {
MayaError ( " Bad 'Camera' attribute on 'refcam'. " ) ;
return ;
}
model . camera . Clear ( ) ;
model . cameraCuts . Clear ( ) ;
SetFrame ( 0 ) ;
status = plug . getValue ( v ) ;
currentCam = cameraAttribute . fieldName ( v , & status ) . asChar ( ) ;
if ( MS : : kSuccess ! = status ) {
MayaError ( " Error getting camera name on frame %d " , GetMayaFrameNum ( 0 ) ) ;
}
}
2011-12-06 18:20:15 +00:00
camJoint = model . FindJoint ( currentCam ) ;
2011-11-22 21:28:15 +00:00
if ( ! camJoint ) {
MayaError ( " Couldn't find camera '%s' " , currentCam . c_str ( ) ) ;
}
for ( frameNum = 0 ; frameNum < model . numFrames ; frameNum + + ) {
common - > Printf ( " \r Frame %d/%d... " , options . startframe + frameNum , options . endframe ) ;
#if 0
MTime time ;
time . setUnit ( MTime : : kSeconds ) ;
time . setValue ( start + ( ( float ) frameNum / ( float ) options . framerate ) ) ;
MGlobal : : viewFrame ( time ) ;
# else
SetFrame ( frameNum ) ;
# endif
// get the position for this frame
GetCameraFrame ( camJoint , align , & model . camera . Alloc ( ) ) ;
if ( refCam ! = NULL ) {
status = plug . getValue ( v ) ;
newCam = cameraAttribute . fieldName ( v , & status ) . asChar ( ) ;
if ( MS : : kSuccess ! = status ) {
MayaError ( " Error getting camera name on frame %d " , GetMayaFrameNum ( frameNum ) ) ;
}
if ( newCam ! = currentCam ) {
// place a cut at our last frame
model . cameraCuts . Append ( model . camera . Num ( ) - 1 ) ;
currentCam = newCam ;
camJoint = model . FindJoint ( currentCam ) ;
if ( ! camJoint ) {
MayaError ( " Couldn't find camera '%s' " , currentCam . c_str ( ) ) ;
}
// get the position for this frame
GetCameraFrame ( camJoint , align , & model . camera . Alloc ( ) ) ;
}
}
}
common - > Printf ( " \n " ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : GetDefaultPose
= = = = = = = = = = = = = = =
*/
void idMayaExport : : GetDefaultPose ( idMat3 & align ) {
float start ;
MDagPath dagPath ;
idMat3 jointaxis ;
idVec3 jointpos ;
idExportJoint * joint , * parent ;
idBounds bnds ;
idBounds meshBounds ;
idList < jointFrame_t > frame ;
start = TimeForFrame ( options . startframe ) ;
common - > Printf ( " default pose frame = %d \n " , options . startframe ) ;
common - > Printf ( " default pose time = %f \n " , start ) ;
frame . SetNum ( model . joints . Num ( ) ) ;
SetFrame ( 0 ) ;
// convert joints into local coordinates and save in channels
for ( joint = model . exportHead . GetNext ( ) ; joint ! = NULL ; joint = joint - > exportNode . GetNext ( ) ) {
if ( ! joint - > dagnode ) {
// custom origin joint
joint - > idwm . Identity ( ) ;
joint - > idt . Zero ( ) ;
frame [ joint - > index ] . t . Zero ( ) ;
frame [ joint - > index ] . q . Set ( 0.0f , 0.0f , 0.0f ) ;
continue ;
}
// get the worldspace positions of the joint
GetWorldTransform ( joint , jointpos , jointaxis , options . scale ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// convert to id coordinates
jointaxis = ConvertToIdSpace ( jointaxis ) * align ;
jointpos = ConvertToIdSpace ( jointpos ) * align ;
// save worldspace position of joint for children
joint - > idwm = jointaxis ;
joint - > idt = jointpos ;
parent = joint - > exportNode . GetParent ( ) ;
if ( parent ) {
// convert to local coordinates
jointpos = ( jointpos - parent - > idt ) * parent - > idwm . Transpose ( ) ;
jointaxis = jointaxis * parent - > idwm . Transpose ( ) ;
} else if ( joint - > name = = " origin " ) {
if ( options . clearOrigin ) {
jointpos . Zero ( ) ;
}
if ( options . clearOriginAxis ) {
jointaxis . Identity ( ) ;
}
}
frame [ joint - > index ] . t = jointpos ;
frame [ joint - > index ] . q = jointaxis . ToQuat ( ) . ToCQuat ( ) ;
}
// relocate origin to start at 0, 0, 0 for first frame
joint = model . FindJoint ( " origin " ) ;
if ( joint ) {
frame [ joint - > index ] . t . Zero ( ) ;
}
// transform the hierarchy
for ( joint = model . exportHead . GetNext ( ) ; joint ! = NULL ; joint = joint - > exportNode . GetNext ( ) ) {
jointpos = frame [ joint - > index ] . t ;
jointaxis = frame [ joint - > index ] . q . ToQuat ( ) . ToMat3 ( ) ;
parent = joint - > exportNode . GetParent ( ) ;
if ( parent ) {
joint - > idwm = jointaxis * parent - > idwm ;
joint - > idt = parent - > idt + jointpos * parent - > idwm ;
} else {
joint - > idwm = jointaxis ;
joint - > idt = jointpos ;
}
joint - > bindmat = joint - > idwm ;
joint - > bindpos = joint - > idt ;
}
common - > Printf ( " \n " ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : CreateAnimation
= = = = = = = = = = = = = = =
*/
void idMayaExport : : CreateAnimation ( idMat3 & align ) {
int i ;
float start , end ;
MDagPath dagPath ;
idMat3 jointaxis ;
idVec3 jointpos ;
int frameNum ;
idExportJoint * joint , * parent ;
idBounds bnds ;
idBounds meshBounds ;
jointFrame_t * frame ;
int cycleStart ;
idVec3 totalDelta ;
idList < jointFrame_t > copyFrames ;
start = TimeForFrame ( options . startframe ) ;
end = TimeForFrame ( options . endframe ) ;
model . numFrames = options . endframe + 1 - options . startframe ;
model . frameRate = options . framerate ;
common - > Printf ( " start frame = %d \n end frame = %d \n " , options . startframe , options . endframe ) ;
common - > Printf ( " start time = %f \n end time = %f \n total time = %f \n " , start , end , end - start ) ;
if ( start > end ) {
MayaError ( " Start frame is greater than end frame. " ) ;
}
model . bounds . SetNum ( model . numFrames ) ;
model . jointFrames . SetNum ( model . numFrames * model . joints . Num ( ) ) ;
model . frames . SetNum ( model . numFrames ) ;
for ( i = 0 ; i < model . numFrames ; i + + ) {
model . frames [ i ] = & model . jointFrames [ model . joints . Num ( ) * i ] ;
}
// *sigh*. cyclestart doesn't work nicely with the anims.
// may just want to not do it in SetTime anymore.
cycleStart = options . cycleStart ;
options . cycleStart = options . startframe ;
for ( frameNum = 0 ; frameNum < model . numFrames ; frameNum + + ) {
common - > Printf ( " \r Frame %d/%d... " , options . startframe + frameNum , options . endframe ) ;
frame = model . frames [ frameNum ] ;
SetFrame ( frameNum ) ;
// convert joints into local coordinates and save in channels
for ( joint = model . exportHead . GetNext ( ) ; joint ! = NULL ; joint = joint - > exportNode . GetNext ( ) ) {
if ( ! joint - > dagnode ) {
// custom origin joint
joint - > idwm . Identity ( ) ;
joint - > idt . Zero ( ) ;
frame [ joint - > index ] . t . Zero ( ) ;
frame [ joint - > index ] . q . Set ( 0.0f , 0.0f , 0.0f ) ;
continue ;
}
// get the worldspace positions of the joint
GetWorldTransform ( joint , jointpos , jointaxis , options . scale ) ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// convert to id coordinates
jointaxis = ConvertToIdSpace ( jointaxis ) * align ;
jointpos = ConvertToIdSpace ( jointpos ) * align ;
// save worldspace position of joint for children
joint - > idwm = jointaxis ;
joint - > idt = jointpos ;
parent = joint - > exportNode . GetParent ( ) ;
if ( parent ) {
// convert to local coordinates
jointpos = ( jointpos - parent - > idt ) * parent - > idwm . Transpose ( ) ;
jointaxis = jointaxis * parent - > idwm . Transpose ( ) ;
} else if ( joint - > name = = " origin " ) {
if ( options . clearOrigin ) {
jointpos . Zero ( ) ;
}
if ( options . clearOriginAxis ) {
jointaxis . Identity ( ) ;
}
}
frame [ joint - > index ] . t = jointpos ;
frame [ joint - > index ] . q = jointaxis . ToQuat ( ) . ToCQuat ( ) ;
}
}
options . cycleStart = cycleStart ;
totalDelta . Zero ( ) ;
joint = model . FindJoint ( " origin " ) ;
if ( joint ) {
frame = model . frames [ 0 ] ;
idVec3 origin = frame [ joint - > index ] . t ;
frame = model . frames [ model . numFrames - 1 ] ;
totalDelta = frame [ joint - > index ] . t - origin ;
}
// shift the frames when cycleStart is used
if ( options . cycleStart > options . startframe ) {
copyFrames = model . jointFrames ;
for ( i = 0 ; i < model . numFrames ; i + + ) {
bool shiftorigin = false ;
frameNum = i + ( options . cycleStart - options . startframe ) ;
if ( frameNum > = model . numFrames ) {
// wrap around, skipping the first frame, since it's a dupe of the last frame
frameNum - = model . numFrames - 1 ;
shiftorigin = true ;
}
memcpy ( & model . jointFrames [ model . joints . Num ( ) * i ] , & copyFrames [ model . joints . Num ( ) * frameNum ] , model . joints . Num ( ) * sizeof ( copyFrames [ 0 ] ) ) ;
if ( joint & & shiftorigin ) {
model . frames [ i ] [ joint - > index ] . t + = totalDelta ;
}
}
}
if ( joint ) {
// relocate origin to start at 0, 0, 0 for first frame
frame = model . frames [ 0 ] ;
idVec3 origin = frame [ joint - > index ] . t ;
for ( i = 0 ; i < model . numFrames ; i + + ) {
frame = model . frames [ i ] ;
frame [ joint - > index ] . t - = origin ;
}
}
// get the bounds for each frame
for ( frameNum = 0 ; frameNum < model . numFrames ; frameNum + + ) {
frame = model . frames [ frameNum ] ;
// transform the hierarchy
for ( joint = model . exportHead . GetNext ( ) ; joint ! = NULL ; joint = joint - > exportNode . GetNext ( ) ) {
jointpos = frame [ joint - > index ] . t ;
jointaxis = frame [ joint - > index ] . q . ToQuat ( ) . ToMat3 ( ) ;
parent = joint - > exportNode . GetParent ( ) ;
if ( parent ) {
joint - > idwm = jointaxis * parent - > idwm ;
joint - > idt = parent - > idt + jointpos * parent - > idwm ;
} else {
joint - > idwm = jointaxis ;
joint - > idt = jointpos ;
}
}
// get bounds for this frame
bnds . Clear ( ) ;
for ( i = 0 ; i < model . meshes . Num ( ) ; i + + ) {
if ( model . meshes [ i ] - > keep ) {
model . meshes [ i ] - > GetBounds ( meshBounds ) ;
bnds . AddBounds ( meshBounds ) ;
}
}
model . bounds [ frameNum ] [ 0 ] = bnds [ 0 ] ;
model . bounds [ frameNum ] [ 1 ] = bnds [ 1 ] ;
}
common - > Printf ( " \n " ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : ConvertModel
= = = = = = = = = = = = = = =
*/
void idMayaExport : : ConvertModel ( void ) {
MStatus status ;
idMat3 align ;
common - > Printf ( " Converting %s to %s... \n " , options . src . c_str ( ) , options . dest . c_str ( ) ) ;
// see if the destination file exists
FILE * file = fopen ( options . dest , " r " ) ;
if ( file ) {
fclose ( file ) ;
// make sure we can write to the destination
FILE * file = fopen ( options . dest , " r+ " ) ;
if ( ! file ) {
MayaError ( " Unable to write to the file '%s' " , options . dest . c_str ( ) ) ;
}
fclose ( file ) ;
}
MString filename ( options . src ) ;
MFileIO : : newFile ( true ) ;
// Load the file into Maya
common - > Printf ( " Loading file... \n " ) ;
status = MFileIO : : open ( filename , NULL , true ) ;
if ( ! status ) {
MayaError ( " Error loading '%s': '%s' \n " , filename . asChar ( ) , status . errorString ( ) . asChar ( ) ) ;
}
// force Maya to update the frame. When using references, sometimes
// the model is posed the way it is in the source. Since Maya only
// updates it when the frame time changes to a value other than the
// current, just setting the time to the min time doesn't guarantee
// that the model gets updated.
MGlobal : : viewFrame ( MAnimControl : : maxTime ( ) ) ;
MGlobal : : viewFrame ( MAnimControl : : minTime ( ) ) ;
if ( options . startframe < 0 ) {
options . startframe = MAnimControl : : minTime ( ) . as ( MTime : : kFilm ) ;
}
if ( options . endframe < 0 ) {
options . endframe = MAnimControl : : maxTime ( ) . as ( MTime : : kFilm ) ;
}
if ( options . cycleStart < 0 ) {
options . cycleStart = options . startframe ;
} else if ( ( options . cycleStart < options . startframe ) | | ( options . cycleStart > options . endframe ) ) {
MayaError ( " cycleStart (%d) out of frame range (%d to %d) \n " , options . cycleStart , options . startframe , options . endframe ) ;
} else if ( options . cycleStart = = options . endframe ) {
// end frame is a duplicate of the first frame in cycles, so just disable cycleStart
options . cycleStart = options . startframe ;
}
// create a list of the transform nodes that will make up our heirarchy
common - > Printf ( " Creating joints... \n " ) ;
CreateJoints ( options . scale ) ;
if ( options . type ! = WRITE_CAMERA ) {
common - > Printf ( " Creating meshes... \n " ) ;
CreateMesh ( options . scale ) ;
common - > Printf ( " Renaming joints... \n " ) ;
RenameJoints ( options . renamejoints , options . prefix ) ;
common - > Printf ( " Remapping parents... \n " ) ;
RemapParents ( options . remapjoints ) ;
common - > Printf ( " Pruning joints... \n " ) ;
PruneJoints ( options . keepjoints , options . prefix ) ;
common - > Printf ( " Combining meshes... \n " ) ;
CombineMeshes ( ) ;
}
common - > Printf ( " Align model... \n " ) ;
GetAlignment ( options . align , align , options . rotate , 0 ) ;
switch ( options . type ) {
case WRITE_MESH :
2011-12-06 18:20:15 +00:00
common - > Printf ( " Grabbing default pose: \n " ) ;
2011-11-22 21:28:15 +00:00
GetDefaultPose ( align ) ;
common - > Printf ( " Writing file... \n " ) ;
if ( ! model . WriteMesh ( options . dest , options ) ) {
MayaError ( " error writing to '%s' " , options . dest . c_str ( ) ) ;
}
break ;
case WRITE_ANIM :
2011-12-06 18:20:15 +00:00
common - > Printf ( " Creating animation frames: \n " ) ;
2011-11-22 21:28:15 +00:00
CreateAnimation ( align ) ;
common - > Printf ( " Writing file... \n " ) ;
if ( ! model . WriteAnim ( options . dest , options ) ) {
MayaError ( " error writing to '%s' " , options . dest . c_str ( ) ) ;
}
break ;
case WRITE_CAMERA :
common - > Printf ( " Creating camera frames: \n " ) ;
CreateCameraAnim ( align ) ;
common - > Printf ( " Writing file... \n " ) ;
if ( ! model . WriteCamera ( options . dest , options ) ) {
MayaError ( " error writing to '%s' " , options . dest . c_str ( ) ) ;
}
break ;
}
common - > Printf ( " done \n \n " ) ;
}
/*
= = = = = = = = = = = = = = =
idMayaExport : : ConvertToMD3
= = = = = = = = = = = = = = =
*/
void idMayaExport : : ConvertToMD3 ( void ) {
#if 0
int i , j ;
md3Header_t * pinmodel ;
2011-12-06 18:20:15 +00:00
md3Frame_t * frame ;
2011-11-22 21:28:15 +00:00
md3Surface_t * surf ;
md3Shader_t * shader ;
md3Triangle_t * tri ;
md3St_t * st ;
md3XyzNormal_t * xyz ;
md3Tag_t * tag ;
int version ;
int size ;
//model_t *mod, int lod, void *buffer, const char *mod_name
pinmodel = ( md3Header_t * ) buffer ;
2012-06-28 10:49:24 +00:00
version = LittleInt ( pinmodel - > version ) ;
2011-11-22 21:28:15 +00:00
if ( version ! = MD3_VERSION ) {
common - > Printf ( " R_LoadMD3: %s has wrong version (%i should be %i) \n " ,
mod_name , version , MD3_VERSION ) ;
return qfalse ;
}
mod - > type = MOD_MESH ;
2012-06-28 10:49:24 +00:00
size = LittleInt ( pinmodel - > ofsEnd ) ;
2011-11-22 21:28:15 +00:00
mod - > dataSize + = size ;
mod - > md3 [ lod ] = ri . Hunk_Alloc ( size ) ;
2012-06-28 10:49:24 +00:00
memcpy ( mod - > md3 [ lod ] , buffer , LittleInt ( pinmodel - > ofsEnd ) ) ;
2011-11-22 21:28:15 +00:00
2011-12-06 18:20:15 +00:00
LL ( mod - > md3 [ lod ] - > ident ) ;
LL ( mod - > md3 [ lod ] - > version ) ;
LL ( mod - > md3 [ lod ] - > numFrames ) ;
LL ( mod - > md3 [ lod ] - > numTags ) ;
LL ( mod - > md3 [ lod ] - > numSurfaces ) ;
LL ( mod - > md3 [ lod ] - > ofsFrames ) ;
LL ( mod - > md3 [ lod ] - > ofsTags ) ;
LL ( mod - > md3 [ lod ] - > ofsSurfaces ) ;
LL ( mod - > md3 [ lod ] - > ofsEnd ) ;
2011-11-22 21:28:15 +00:00
if ( mod - > md3 [ lod ] - > numFrames < 1 ) {
common - > Printf ( " R_LoadMD3: %s has no frames \n " , mod_name ) ;
return qfalse ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// swap all the frames
2011-12-06 18:20:15 +00:00
frame = ( md3Frame_t * ) ( ( byte * ) mod - > md3 [ lod ] + mod - > md3 [ lod ] - > ofsFrames ) ;
for ( i = 0 ; i < mod - > md3 [ lod ] - > numFrames ; i + + , frame + + ) {
frame - > radius = LittleFloat ( frame - > radius ) ;
for ( j = 0 ; j < 3 ; j + + ) {
frame - > bounds [ 0 ] [ j ] = LittleFloat ( frame - > bounds [ 0 ] [ j ] ) ;
frame - > bounds [ 1 ] [ j ] = LittleFloat ( frame - > bounds [ 1 ] [ j ] ) ;
frame - > localOrigin [ j ] = LittleFloat ( frame - > localOrigin [ j ] ) ;
}
2011-11-22 21:28:15 +00:00
}
// swap all the tags
2011-12-06 18:20:15 +00:00
tag = ( md3Tag_t * ) ( ( byte * ) mod - > md3 [ lod ] + mod - > md3 [ lod ] - > ofsTags ) ;
for ( i = 0 ; i < mod - > md3 [ lod ] - > numTags * mod - > md3 [ lod ] - > numFrames ; i + + , tag + + ) {
for ( j = 0 ; j < 3 ; j + + ) {
2011-11-22 21:28:15 +00:00
tag - > origin [ j ] = LittleFloat ( tag - > origin [ j ] ) ;
tag - > axis [ 0 ] [ j ] = LittleFloat ( tag - > axis [ 0 ] [ j ] ) ;
tag - > axis [ 1 ] [ j ] = LittleFloat ( tag - > axis [ 1 ] [ j ] ) ;
tag - > axis [ 2 ] [ j ] = LittleFloat ( tag - > axis [ 2 ] [ j ] ) ;
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
}
// swap all the surfaces
surf = ( md3Surface_t * ) ( ( byte * ) mod - > md3 [ lod ] + mod - > md3 [ lod ] - > ofsSurfaces ) ;
for ( i = 0 ; i < mod - > md3 [ lod ] - > numSurfaces ; i + + ) {
2011-12-06 18:20:15 +00:00
LL ( surf - > ident ) ;
LL ( surf - > flags ) ;
LL ( surf - > numFrames ) ;
LL ( surf - > numShaders ) ;
LL ( surf - > numTriangles ) ;
LL ( surf - > ofsTriangles ) ;
LL ( surf - > numVerts ) ;
LL ( surf - > ofsShaders ) ;
LL ( surf - > ofsSt ) ;
LL ( surf - > ofsXyzNormals ) ;
LL ( surf - > ofsEnd ) ;
2011-11-22 21:28:15 +00:00
if ( surf - > numVerts > SHADER_MAX_VERTEXES ) {
ri . Error ( ERR_DROP , " R_LoadMD3: %s has more than %i verts on a surface (%i) " ,
mod_name , SHADER_MAX_VERTEXES , surf - > numVerts ) ;
}
if ( surf - > numTriangles * 3 > SHADER_MAX_INDEXES ) {
ri . Error ( ERR_DROP , " R_LoadMD3: %s has more than %i triangles on a surface (%i) " ,
mod_name , SHADER_MAX_INDEXES / 3 , surf - > numTriangles ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
// change to surface identifier
surf - > ident = SF_MD3 ;
// lowercase the surface name so skin compares are faster
Q_strlwr ( surf - > name ) ;
// strip off a trailing _1 or _2
// this is a crutch for q3data being a mess
j = strlen ( surf - > name ) ;
if ( j > 2 & & surf - > name [ j - 2 ] = = ' _ ' ) {
surf - > name [ j - 2 ] = 0 ;
}
2011-12-06 18:20:15 +00:00
// register the shaders
shader = ( md3Shader_t * ) ( ( byte * ) surf + surf - > ofsShaders ) ;
for ( j = 0 ; j < surf - > numShaders ; j + + , shader + + ) {
shader_t * sh ;
2011-11-22 21:28:15 +00:00
2011-12-06 18:20:15 +00:00
sh = R_FindShader ( shader - > name , LIGHTMAP_NONE , qtrue ) ;
2011-11-22 21:28:15 +00:00
if ( sh - > defaultShader ) {
shader - > shaderIndex = 0 ;
} else {
shader - > shaderIndex = sh - > index ;
}
2011-12-06 18:20:15 +00:00
}
2011-11-22 21:28:15 +00:00
// swap all the triangles
tri = ( md3Triangle_t * ) ( ( byte * ) surf + surf - > ofsTriangles ) ;
for ( j = 0 ; j < surf - > numTriangles ; j + + , tri + + ) {
LL ( tri - > indexes [ 0 ] ) ;
LL ( tri - > indexes [ 1 ] ) ;
LL ( tri - > indexes [ 2 ] ) ;
}
// swap all the ST
2011-12-06 18:20:15 +00:00
st = ( md3St_t * ) ( ( byte * ) surf + surf - > ofsSt ) ;
for ( j = 0 ; j < surf - > numVerts ; j + + , st + + ) {
st - > st [ 0 ] = LittleFloat ( st - > st [ 0 ] ) ;
st - > st [ 1 ] = LittleFloat ( st - > st [ 1 ] ) ;
}
2011-11-22 21:28:15 +00:00
// swap all the XyzNormals
2011-12-06 18:20:15 +00:00
xyz = ( md3XyzNormal_t * ) ( ( byte * ) surf + surf - > ofsXyzNormals ) ;
for ( j = 0 ; j < surf - > numVerts * surf - > numFrames ; j + + , xyz + + )
2011-11-22 21:28:15 +00:00
{
2011-12-06 18:20:15 +00:00
xyz - > xyz [ 0 ] = LittleShort ( xyz - > xyz [ 0 ] ) ;
xyz - > xyz [ 1 ] = LittleShort ( xyz - > xyz [ 1 ] ) ;
xyz - > xyz [ 2 ] = LittleShort ( xyz - > xyz [ 2 ] ) ;
2011-11-22 21:28:15 +00:00
2011-12-06 18:20:15 +00:00
xyz - > normal = LittleShort ( xyz - > normal ) ;
}
2011-11-22 21:28:15 +00:00
// find the next surface
surf = ( md3Surface_t * ) ( ( byte * ) surf + surf - > ofsEnd ) ;
}
return true ;
# endif
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
dll setup
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = =
Maya_Shutdown
= = = = = = = = = = = = = = =
*/
void Maya_Shutdown ( void ) {
if ( initialized ) {
errorMessage . Clear ( ) ;
initialized = false ;
// This shuts down the entire app somehow, so just ignore it.
//MLibrary::cleanup();
}
}
/*
= = = = = = = = = = = = = = =
Maya_ConvertModel
= = = = = = = = = = = = = = =
*/
const char * Maya_ConvertModel ( const char * ospath , const char * commandline ) {
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
errorMessage = " Ok " ;
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
try {
idExportOptions options ( commandline , ospath ) ;
idMayaExport exportM ( options ) ;
exportM . ConvertModel ( ) ;
}
2011-12-06 18:20:15 +00:00
2011-11-22 21:28:15 +00:00
catch ( idException & exception ) {
errorMessage = exception . error ;
}
return errorMessage ;
}
/*
= = = = = = = = = = = = = = =
dllEntry
= = = = = = = = = = = = = = =
*/
bool dllEntry ( int version , idCommon * common , idSys * sys ) {
if ( ! common | | ! sys ) {
return false ;
}
: : common = common ;
: : sys = sys ;
: : cvarSystem = NULL ;
idLib : : sys = sys ;
idLib : : common = common ;
idLib : : cvarSystem = NULL ;
idLib : : fileSystem = NULL ;
idLib : : Init ( ) ;
if ( version ! = MD5_VERSION ) {
common - > Printf ( " Error initializing Maya exporter: DLL version %d different from .exe version %d \n " , MD5_VERSION , version ) ;
return false ;
}
if ( ! initialized ) {
MStatus status ;
status = MLibrary : : initialize ( GAME_NAME , true ) ;
if ( ! status ) {
common - > Printf ( " Error calling MLibrary::initialize (%s) \n " , status . errorString ( ) . asChar ( ) ) ;
return false ;
}
initialized = true ;
}
return true ;
}
// Force type checking on the interface functions to help ensure that they match the ones in the .exe
const exporterDLLEntry_t ValidateEntry = & dllEntry ;
const exporterInterface_t ValidateConvert = & Maya_ConvertModel ;
const exporterShutdown_t ValidateShutdown = & Maya_Shutdown ;