diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..bd91ccdb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +neo/MayaImport/fbxsdk/ diff --git a/neo/MayaImport.vcxproj b/neo/MayaImport.vcxproj index 786dcd80..bd1a02c4 100644 --- a/neo/MayaImport.vcxproj +++ b/neo/MayaImport.vcxproj @@ -163,775 +163,63 @@ - + + + MayaImport/fbxsdk/include;%(AdditionalIncludeDirectories) + + + ../$(TargetName)$(TargetExt) + + + + + MayaImport/fbxsdk/include;%(AdditionalIncludeDirectories) + + + ../$(TargetName)$(TargetExt) + + + + + MayaImport/fbxsdk/include;%(AdditionalIncludeDirectories) + + + ../$(TargetName)$(TargetExt) + + + + + MayaImport/fbxsdk/include;%(AdditionalIncludeDirectories) + + + ../$(TargetName)$(TargetExt) + + + + + MayaImport/fbxsdk/include;%(AdditionalIncludeDirectories) + + + ../$(TargetName)$(TargetExt) + + + + + MayaImport/fbxsdk/include;%(AdditionalIncludeDirectories) + + + ../$(TargetName)$(TargetExt) + + + + + MayaImport/fbxsdk/include;%(AdditionalIncludeDirectories) + + + ../$(TargetName)$(TargetExt) + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -956,6 +244,11 @@ false + + + + + diff --git a/neo/MayaImport.vcxproj.filters b/neo/MayaImport.vcxproj.filters index 03afbf2f..1815c97f 100644 --- a/neo/MayaImport.vcxproj.filters +++ b/neo/MayaImport.vcxproj.filters @@ -1,2324 +1,6 @@  - - {aae4acbc-7824-448a-bfb1-016aff3c33fb} - - - {7771e2b0-7015-45d4-b0ec-3e7fdef5f75e} - - - {476e85cf-2481-430a-b6a3-b27cd4b70899} - - - {7a5e50e7-603a-4860-85d5-2a88fa17bcec} - - - {0585a38e-8a62-49f2-9476-2babb9e258f7} - - - {c1abf073-d6cb-4e00-a8c1-b70546f1fa45} - - - - - Maya 4.5 - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 4.5\include - - - Maya 5.0 - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 5.0\include - - - Maya 6.0 - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - - - Maya 6.0\include - @@ -2329,4 +11,9 @@ + + + + + \ No newline at end of file diff --git a/neo/MayaImport/maya_main.cpp b/neo/MayaImport/maya_main.cpp index c1db98cb..0e38692b 100644 --- a/neo/MayaImport/maya_main.cpp +++ b/neo/MayaImport/maya_main.cpp @@ -2,9 +2,9 @@ =========================================================================== Doom 3 GPL Source Code -Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. +Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. -This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?). +This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?). 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 @@ -29,9 +29,18 @@ If you have questions concerning this license or the applicable additional terms #include "precompiled.h" #pragma hdrstop -#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) +#undef DotProduct +#define FLT_EPSILON 1.19209290e-07F + +#include + +// exporter.h was originally authored beside the Maya SDK and stores an MFnDagNode* +// in idExportJoint. For this FBX-backed build, make that member an FbxNode*. +class MObject; +class MFnSkinCluster; +#define MFnDagNode FbxNode #include "exporter.h" +#undef MFnDagNode #include "maya_main.h" idStr errorMessage; @@ -43,28 +52,28 @@ bool initialized = false; #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" }; +const char* componentNames[6] = { "Tx", "Ty", "Tz", "Qx", "Qy", "Qz" }; -idSys * sys = NULL; -idCommon * common = NULL; -idCVarSystem * cvarSystem = NULL; +idSys* sys = NULL; +idCommon* common = NULL; +idCVarSystem* cvarSystem = NULL; -idCVar * idCVar::staticVars = NULL; +idCVar* idCVar::staticVars = NULL; /* ================= MayaError ================= */ -void MayaError( const char *fmt, ... ) { +void MayaError(const char* fmt, ...) { va_list argptr; - char text[ 8192 ]; + char text[8192]; - va_start( argptr, fmt ); - idStr::vsnPrintf( text, sizeof( text ), fmt, argptr ); - va_end( argptr ); + va_start(argptr, fmt); + idStr::vsnPrintf(text, sizeof(text), fmt, argptr); + va_end(argptr); - throw idException( text ); + throw idException(text); } /* @@ -73,107 +82,107 @@ FS_WriteFloatString ================= */ #define MAX_PRINT_MSG 4096 -static int WriteFloatString( FILE *file, const char *fmt, ... ) { +static int WriteFloatString(FILE* file, const char* fmt, ...) { long i; unsigned long u; double f; - char *str; + char* str; int index; idStr tmp, format; va_list argPtr; - va_start( argPtr, fmt ); + va_start(argPtr, fmt); index = 0; - while( *fmt ) { - switch( *fmt ) { - case '%': - format = ""; + while (*fmt) { + switch (*fmt) { + case '%': + format = ""; + format += *fmt++; + while ((*fmt >= '0' && *fmt <= '9') || + *fmt == '.' || *fmt == '-' || *fmt == '+' || *fmt == '#') { 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()); } - 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; + else { + index += fprintf(file, format.c_str(), f); } - 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++; + 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: - index += fprintf( file, "%c", *fmt ); - fmt++; + 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 ); + va_end(argPtr); return index; } @@ -189,8 +198,8 @@ 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; +bool OSPathToRelativePath(const char* osPath, idStr& qpath, const char* game) { + char* s, * base; // skip a drive letter? @@ -198,33 +207,33 @@ bool OSPathToRelativePath( const char *osPath, idStr &qpath, const char *game ) // 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 ); + base = (char*)strstr(osPath, BASE_GAMEDIR); // _D3XP added mod support - if ( base == NULL && strlen(game) > 0 ) { + if (base == NULL && strlen(game) > 0) { - base = s = (char *)strstr( osPath, game ); + base = s = (char*)strstr(osPath, game); - while( s = strstr( s, game ) ) { - s += strlen( game ); - if ( s[0] == '/' || s[0] == '\\' ) { + while (s = strstr(s, game)) { + s += strlen(game); + if (s[0] == '/' || s[0] == '\\') { base = s; } } - } + } - if ( base ) { - s = strstr( base, "/" ); - if ( !s ) { - s = strstr( base, "\\" ); + if (base) { + s = strstr(base, "/"); + if (!s) { + s = strstr(base, "\\"); } - if ( s ) { + if (s) { qpath = s + 1; return true; } } - common->Printf( "OSPathToRelativePath failed on %s\n", osPath ); + common->Printf("OSPathToRelativePath failed on %s\n", osPath); qpath = osPath; return false; @@ -235,20 +244,20 @@ bool OSPathToRelativePath( const char *osPath, idStr &qpath, const char *game ) ConvertFromIdSpace =============== */ -idMat3 ConvertFromIdSpace( const idMat3 &idmat ) { +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 ]; - - mat[ 1 ][ 0 ] = idmat[ 1 ][ 0 ]; - mat[ 1 ][ 2 ] = -idmat[ 1 ][ 1 ]; - mat[ 1 ][ 1 ] = idmat[ 1 ][ 2 ]; - - mat[ 2 ][ 0 ] = idmat[ 2 ][ 0 ]; - mat[ 2 ][ 2 ] = -idmat[ 2 ][ 1 ]; - mat[ 2 ][ 1 ] = idmat[ 2 ][ 2 ]; + mat[0][0] = idmat[0][0]; + mat[0][2] = -idmat[0][1]; + mat[0][1] = idmat[0][2]; + + mat[1][0] = idmat[1][0]; + mat[1][2] = -idmat[1][1]; + mat[1][1] = idmat[1][2]; + + mat[2][0] = idmat[2][0]; + mat[2][2] = -idmat[2][1]; + mat[2][1] = idmat[2][2]; return mat; } @@ -258,7 +267,7 @@ idMat3 ConvertFromIdSpace( const idMat3 &idmat ) { ConvertFromIdSpace =============== */ -idVec3 ConvertFromIdSpace( const idVec3 &idpos ) { +idVec3 ConvertFromIdSpace(const idVec3& idpos) { idVec3 pos; pos.x = idpos.x; @@ -273,20 +282,20 @@ idVec3 ConvertFromIdSpace( const idVec3 &idpos ) { ConvertToIdSpace =============== */ -idMat3 ConvertToIdSpace( const idMat3 &mat ) { +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[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[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 ]; + idmat[2][0] = mat[2][0]; + idmat[2][1] = -mat[2][2]; + idmat[2][2] = mat[2][1]; return idmat; } @@ -296,7 +305,7 @@ idMat3 ConvertToIdSpace( const idMat3 &mat ) { ConvertToIdSpace =============== */ -idVec3 ConvertToIdSpace( const idVec3 &pos ) { +idVec3 ConvertToIdSpace(const idVec3& pos) { idVec3 idpos; idpos.x = pos.x; @@ -308,75 +317,43 @@ idVec3 ConvertToIdSpace( const idVec3 &pos ) { /* =============== -idVec +idVec / idMat FBX helpers =============== */ -idVec3 idVec( const MFloatPoint &point ) { - return idVec3( point[ 0 ], point[ 1 ], point[ 2 ] ); +static idVec3 idVec(const FbxVector4& point) { + return idVec3((float)point[0], (float)point[1], (float)point[2]); } -/* -=============== -idVec -=============== -*/ -idVec3 idVec( const MMatrix &matrix ) { - return idVec3( matrix[ 3 ][ 0 ], matrix[ 3 ][ 1 ], matrix[ 3 ][ 2 ] ); +static idVec3 idVec(const FbxDouble3& point) { + return idVec3((float)point[0], (float)point[1], (float)point[2]); } -/* -=============== -idMat -=============== -*/ -idMat3 idMat( const MMatrix &matrix ) { +static idMat3 idMat(const FbxAMatrix& matrix) { int j, k; idMat3 mat; - for( j = 0; j < 3; j++ ) { - for( k = 0; k < 3; k++ ) { - mat[ j ][ k ] = matrix[ j ][ k ]; + for (j = 0; j < 3; j++) { + for (k = 0; k < 3; k++) { + mat[j][k] = (float)matrix.Get(j, k); } } + mat.OrthoNormalizeSelf(); return mat; } -/* -=============== -GetParent -=============== -*/ -MFnDagNode *GetParent( MFnDagNode *joint ) { - MStatus status; - MObject parentObject; - - parentObject = joint->parent( 0, &status ); - if ( !status && status.statusCode() == MStatus::kInvalidParameter ) { - return NULL; +static FbxAMatrix FbxGetGeometryTransform(const FbxNode* node) { + FbxAMatrix geo; + geo.SetIdentity(); + if (node == NULL) { + return geo; } - 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; + FbxVector4 t = node->GetGeometricTranslation(FbxNode::eSourcePivot); + FbxVector4 r = node->GetGeometricRotation(FbxNode::eSourcePivot); + FbxVector4 s = node->GetGeometricScaling(FbxNode::eSourcePivot); + geo.SetTRS(t, r, s); + return geo; } /* @@ -392,25 +369,25 @@ MFnDagNode *GetParent( MFnDagNode *joint ) { idTokenizer::SetTokens ==================== */ -int idTokenizer::SetTokens( const char *buffer ) { - const char *cmd; +int idTokenizer::SetTokens(const char* buffer) { + const char* cmd; Clear(); // tokenize commandline cmd = buffer; - while ( *cmd ) { + while (*cmd) { // skip whitespace - while( *cmd && isspace( *cmd ) ) { + while (*cmd && isspace(*cmd)) { cmd++; } - if ( !*cmd ) { + if (!*cmd) { break; } - - idStr ¤t = tokens.Alloc(); - while( *cmd && !isspace( *cmd ) ) { + + idStr& current = tokens.Alloc(); + while (*cmd && !isspace(*cmd)) { current += *cmd; cmd++; } @@ -424,13 +401,13 @@ int idTokenizer::SetTokens( const char *buffer ) { idTokenizer::NextToken ==================== */ -const char *idTokenizer::NextToken( const char *errorstring ) { - if ( currentToken < tokens.Num() ) { - return tokens[ currentToken++ ]; +const char* idTokenizer::NextToken(const char* errorstring) { + if (currentToken < tokens.Num()) { + return tokens[currentToken++]; } - if ( errorstring ) { - MayaError( "Error: %s", errorstring ); + if (errorstring) { + MayaError("Error: %s", errorstring); } return NULL; @@ -449,29 +426,29 @@ const char *idTokenizer::NextToken( const char *errorstring ) { 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; +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 ); + tokens.SetTokens(commandline); keepjoints.Clear(); renamejoints.Clear(); @@ -487,215 +464,247 @@ void idExportOptions::Reset( const char *commandline ) { idExportOptions::idExportOptions ==================== */ -idExportOptions::idExportOptions( const char *commandline, const char *ospath ) { +idExportOptions::idExportOptions(const char* commandline, const char* ospath) { idStr token; idNamePair joints; int i; - idAnimGroup *group; + idAnimGroup* group; idStr sourceDir; idStr destDir; - Reset( commandline ); + Reset(commandline); - token = tokens.NextToken( "Missing export command" ); - if ( token == "mesh" ) { + token = tokens.NextToken("Missing export command"); + if (token == "mesh") { type = WRITE_MESH; - } else if ( token == "anim" ) { + } + else if (token == "md3") { + // MD3 uses the mesh command path internally, but dispatches to WriteMD3 below. + type = WRITE_MESH; + } + else if (token == "anim") { type = WRITE_ANIM; - } else if ( token == "camera" ) { + } + else if (token == "camera") { type = WRITE_CAMERA; - } else { - MayaError( "Unknown export command '%s'", token.c_str() ); + } + else { + MayaError("Unknown export command '%s'", token.c_str()); } - src = tokens.NextToken( "Missing source filename" ); + src = tokens.NextToken("Missing source filename"); dest = src; - for( token = tokens.NextToken(); token != ""; token = tokens.NextToken() ) { - if ( token == "-force" ) { + for (token = tokens.NextToken(); token != ""; token = tokens.NextToken()) { + if (token == "-force") { // skip - } else if ( token == "-game" ) { + } + else if (token == "-game") { // parse game name - game = tokens.NextToken( "Expecting game name after -game" ); + game = tokens.NextToken("Expecting game name after -game"); - } else if ( token == "-rename" ) { + } + 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 ); + 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 == "-prefix") { + prefix = tokens.NextToken("Missing name for -prefix. Usage: -prefix [joint prefix]"); - } else if ( token == "-parent" ) { + } + 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 ); + 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" ) ) { + } + else if (!token.Icmp("-sourcedir")) { // parse source directory - sourceDir = tokens.NextToken( "Missing filename for -sourcedir. Usage: -sourcedir [directory]" ); + sourceDir = tokens.NextToken("Missing filename for -sourcedir. Usage: -sourcedir [directory]"); - } else if ( !token.Icmp( "-destdir" ) ) { + } + else if (!token.Icmp("-destdir")) { // parse destination directory - destDir = tokens.NextToken( "Missing filename for -destdir. Usage: -destdir [directory]" ); + destDir = tokens.NextToken("Missing filename for -destdir. Usage: -destdir [directory]"); - } else if ( token == "-dest" ) { + } + else if (token == "-dest") { // parse destination filename - dest = tokens.NextToken( "Missing filename for -dest. Usage: -dest [filename]" ); + dest = tokens.NextToken("Missing filename for -dest. Usage: -dest [filename]"); - } else if ( token == "-range" ) { + } + 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 ); + 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." ); + if (startframe > endframe) { + MayaError("Start frame is greater than end frame."); } - } else if ( !token.Icmp( "-cycleStart" ) ) { + } + 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 ); + token = tokens.NextToken("Missing cycle start frame for -cycleStart. Usage: -cycleStart [first frame of cycle]"); + cycleStart = atoi(token); - } else if ( token == "-scale" ) { + } + else if (token == "-scale") { // parse scale - token = tokens.NextToken( "Missing scale amount for -scale. Usage: -scale [scale amount]" ); - scale = atof( token ); + token = tokens.NextToken("Missing scale amount for -scale. Usage: -scale [scale amount]"); + scale = atof(token); - } else if ( token == "-align" ) { + } + else if (token == "-align") { // parse align joint - align = tokens.NextToken( "Missing joint name for -align. Usage: -align [joint name]" ); + align = tokens.NextToken("Missing joint name for -align. Usage: -align [joint name]"); - } else if ( token == "-rotate" ) { + } + else if (token == "-rotate") { // parse angle rotation - token = tokens.NextToken( "Missing value for -rotate. Usage: -rotate [yaw]" ); - rotate = -atof( token ); + token = tokens.NextToken("Missing value for -rotate. Usage: -rotate [yaw]"); + rotate = -atof(token); - } else if ( token == "-nomesh" ) { + } + else if (token == "-nomesh") { ignoreMeshes = true; - } else if ( token == "-clearorigin" ) { + } + else if (token == "-clearorigin") { clearOrigin = true; clearOriginAxis = true; - } else if ( token == "-clearoriginaxis" ) { + } + else if (token == "-clearoriginaxis") { clearOriginAxis = true; - } else if ( token == "-ignorescale" ) { + } + else if (token == "-ignorescale") { ignoreScale = true; - } else if ( token == "-xyzprecision" ) { + } + 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" ); + 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" ) { + } + 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" ); + 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"); } - - } else if ( token == "-jointthreshold" ) { + + } + else if (token == "-jointthreshold") { // parse joint threshold - token = tokens.NextToken( "Missing weight for -jointthreshold. Usage: -jointthreshold [minimum joint weight]" ); - jointThreshold = atof( token ); + 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 == "-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 == "-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]" ); + } + 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 ) { + for (i = 0; i < groups.Num(); i++, group++) { + if (group->name == token) { break; } } - if ( i >= groups.Num() ) { + if (i >= groups.Num()) { // create a new group group = &groups.Alloc(); group->name = token; } - while( tokens.TokenAvailable() ) { + while (tokens.TokenAvailable()) { token = tokens.NextToken(); - if ( token[ 0 ] == '-' ) { + if (token[0] == '-') { tokens.UnGetToken(); break; } - group->joints.AddUnique( token ); + group->joints.AddUnique(token); } - } else if ( token == "-group" ) { + } + else if (token == "-group") { // add the list of groups to export (these don't affect the hierarchy) - while( tokens.TokenAvailable() ) { + while (tokens.TokenAvailable()) { token = tokens.NextToken(); - if ( token[ 0 ] == '-' ) { + if (token[0] == '-') { tokens.UnGetToken(); break; } group = groups.Ptr(); - for( i = 0; i < groups.Num(); i++, group++ ) { - if ( group->name == token ) { + for (i = 0; i < groups.Num(); i++, group++) { + if (group->name == token) { break; } } - if ( i >= groups.Num() ) { - MayaError( "Unknown group '%s'", token.c_str() ); + if (i >= groups.Num()) { + MayaError("Unknown group '%s'", token.c_str()); } - exportgroups.AddUnique( group ); + exportgroups.AddUnique(group); } - } else if ( token == "-keep" ) { + } + else if (token == "-keep") { // add joints that are kept whether they're used by a mesh or not - while( tokens.TokenAvailable() ) { + while (tokens.TokenAvailable()) { token = tokens.NextToken(); - if ( token[ 0 ] == '-' ) { + if (token[0] == '-') { tokens.UnGetToken(); break; } - keepjoints.AddUnique( token ); + keepjoints.AddUnique(token); } - } else { - MayaError( "Unknown option '%s'", token.c_str() ); + } + else { + MayaError("Unknown option '%s'", token.c_str()); } } token = src; src = ospath; src.BackSlashesToSlashes(); - src.AppendPath( sourceDir ); - src.AppendPath( token ); + src.AppendPath(sourceDir); + src.AppendPath(token); token = dest; dest = ospath; dest.BackSlashesToSlashes(); - dest.AppendPath( destDir ); - dest.AppendPath( token ); + 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." ); + if (skipmeshes.Num() && keepmeshes.Num()) { + MayaError("Can't use -keepmesh and -skipmesh together."); } } @@ -704,21 +713,21 @@ idExportOptions::idExportOptions( const char *commandline, const char *ospath ) idExportOptions::jointInExportGroup ==================== */ -bool idExportOptions::jointInExportGroup( const char *jointname ) { +bool idExportOptions::jointInExportGroup(const char* jointname) { int i; int j; - idAnimGroup *group; + idAnimGroup* group; - if ( !exportgroups.Num() ) { + 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 ) { + 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; } } @@ -736,56 +745,56 @@ idExportJoint */ idExportJoint::idExportJoint() { - index = 0; - exportNum = 0; + index = 0; + exportNum = 0; - mayaNode.SetOwner( this ); - exportNode.SetOwner( this ); + mayaNode.SetOwner(this); + exportNode.SetOwner(this); - dagnode = NULL; - - 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 ); + dagnode = NULL; + + 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; - - scale = other.scale; - invscale = other.invscale; - - dagnode = other.dagnode; +idExportJoint& idExportJoint::operator=(const idExportJoint& other) { + name = other.name; + realname = other.realname; + longname = other.longname; + index = other.index; + exportNum = other.exportNum; + keep = other.keep; - mayaNode = other.mayaNode; - exportNode = other.exportNode; - - t = other.t; - idt = other.idt; - wm = other.wm; - idwm = other.idwm; - bindpos = other.bindpos; - bindmat = other.bindmat; + scale = other.scale; + invscale = other.invscale; - animBits = other.animBits; + dagnode = other.dagnode; + + mayaNode = other.mayaNode; + exportNode = other.exportNode; + + 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; + baseFrame = other.baseFrame; - mayaNode.SetOwner( this ); - exportNode.SetOwner( this ); + mayaNode.SetOwner(this); + exportNode.SetOwner(this); return *this; } @@ -798,46 +807,47 @@ idExportMesh ============================================================================== */ -void idExportMesh::ShareVerts( void ) { +void idExportMesh::ShareVerts(void) { int i, j, k; exportVertex_t vert; idList 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 (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 ) { + for (k = 0; k < verts.Num(); k++) { + if (vert.numWeights != verts[k].numWeights) { continue; } - if ( vert.startweight != verts[ k ].startweight ) { + if (vert.startweight != verts[k].startweight) { continue; } - if ( !vert.pos.Compare( verts[ k ].pos, SLOP_VERTEX ) ) { + if (!vert.pos.Compare(verts[k].pos, SLOP_VERTEX)) { continue; } - if ( !vert.texCoords.Compare( verts[ k ].texCoords, SLOP_TEXCOORD ) ) { + 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 ); + if (k < verts.Num()) { + tris[i].indexes[j] = k; + } + else { + tris[i].indexes[j] = verts.Append(vert); } } } } -void idExportMesh::Merge( idExportMesh *mesh ) { +void idExportMesh::Merge(idExportMesh* mesh) { int i; int numverts; int numtris; @@ -845,58 +855,58 @@ void idExportMesh::Merge( idExportMesh *mesh ) { int numuvs; // merge name - sprintf( name, "%s, %s", name.c_str(), mesh->name.c_str() ); + 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(); + 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; + 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 ]; + 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 ]; + 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 { +void idExportMesh::GetBounds(idBounds& bounds) const { int i; int j; idVec3 pos; - const exportWeight_t *weight; - const exportVertex_t *vert; + const exportWeight_t* weight; + const exportVertex_t* vert; bounds.Clear(); weight = weights.Ptr(); vert = verts.Ptr(); - for( i = 0; i < verts.Num(); i++, vert++ ) { + 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 ); + 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 ); + bounds.AddPoint(pos); } } @@ -914,11 +924,11 @@ idExportModel::idExportModel ==================== */ ID_INLINE idExportModel::idExportModel() { - export_joints = 0; - skipjoints = 0; - frameRate = 24; - numFrames = 0; - exportOrigin = NULL; + export_joints = 0; + skipjoints = 0; + frameRate = 24; + numFrames = 0; + exportOrigin = NULL; } /* @@ -927,16 +937,16 @@ idExportModel::~idExportModel ==================== */ ID_INLINE idExportModel::~idExportModel() { - meshes.DeleteContents( true ); + meshes.DeleteContents(true); } -idExportJoint *idExportModel::FindJointReal( const char *name ) { - idExportJoint *joint; +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 ) { + for (i = 0; i < joints.Num(); i++, joint++) { + if (joint->realname == name) { return joint; } } @@ -944,13 +954,13 @@ idExportJoint *idExportModel::FindJointReal( const char *name ) { return NULL; } -idExportJoint *idExportModel::FindJoint( const char *name ) { - idExportJoint *joint; +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 ) { + for (i = 0; i < joints.Num(); i++, joint++) { + if (joint->name == name) { return joint; } } @@ -958,190 +968,193 @@ idExportJoint *idExportModel::FindJoint( const char *name ) { return NULL; } -bool idExportModel::WriteMesh( const char *filename, idExportOptions &options ) { +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; + idExportMesh* mesh; + idExportJoint* joint; + idExportJoint* parent; + idExportJoint* sibling; + FILE* file; + const char* parentName; int parentNum; - idList jointList; + idList jointList; - file = fopen( filename, "w" ); - if ( !file ) { + file = fopen(filename, "w"); + if (!file) { return false; } - for( joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) { - jointList.Append( joint ); + for (joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext()) { + jointList.Append(joint); } - for( i = 0; i < jointList.Num(); i++ ) { - joint = jointList[ i ]; + 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 ); + while (sibling) { + if (idStr::Cmp(joint->name, sibling->name) > 0) { + joint->exportNode.MakeSiblingAfter(sibling->exportNode); sibling = joint->exportNode.GetSibling(); - } else { + } + else { sibling = sibling->exportNode.GetSibling(); } } } jointList.Clear(); - for( joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) { - joint->exportNum = jointList.Append( joint ); + 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 ) { + 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() ); + 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, "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 ]; + WriteFloatString(file, "joints {\n"); + for (i = 0; i < jointList.Num(); i++) { + joint = jointList[i]; parent = joint->exportNode.GetParent(); - if ( parent ) { + if (parent) { parentNum = parent->exportNum; parentName = parent->name.c_str(); - } else { + } + else { parentNum = -1; parentName = ""; } idCQuat bindQuat = joint->bindmat.ToQuat().ToCQuat(); - WriteFloatString( file, "\t\"%s\"\t%d ( %f %f %f ) ( %f %f %f )\t\t// %s\n", joint->name.c_str(), parentNum, - joint->bindpos.x, joint->bindpos.y, joint->bindpos.z, bindQuat[ 0 ], bindQuat[ 1 ], bindQuat[ 2 ], parentName ); + WriteFloatString(file, "\t\"%s\"\t%d ( %f %f %f ) ( %f %f %f )\t\t// %s\n", joint->name.c_str(), parentNum, + joint->bindpos.x, joint->bindpos.y, joint->bindpos.z, bindQuat[0], bindQuat[1], bindQuat[2], parentName); } - WriteFloatString( file, "}\n" ); + WriteFloatString(file, "}\n"); // write meshes - for( i = 0; i < meshes.Num(); i++ ) { - mesh = meshes[ i ]; - if ( !mesh->keep ) { + for (i = 0; i < meshes.Num(); i++) { + mesh = meshes[i]; + if (!mesh->keep) { continue; } - WriteFloatString( file, "\nmesh {\n" ); - WriteFloatString( file, "\t// meshes: %s\n", mesh->name.c_str() ); - WriteFloatString( file, "\tshader \"%s\"\n", mesh->shader.c_str() ); - - WriteFloatString( file, "\n\tnumverts %d\n", mesh->verts.Num() ); - for( j = 0; j < mesh->verts.Num(); j++ ) { - WriteFloatString( file, "\tvert %d ( %f %f ) %d %d\n", j, mesh->verts[ j ].texCoords[ 0 ], mesh->verts[ j ].texCoords[ 1 ], - mesh->verts[ j ].startweight, mesh->verts[ j ].numWeights ); + WriteFloatString(file, "\nmesh {\n"); + WriteFloatString(file, "\t// meshes: %s\n", mesh->name.c_str()); + WriteFloatString(file, "\tshader \"%s\"\n", mesh->shader.c_str()); + + WriteFloatString(file, "\n\tnumverts %d\n", mesh->verts.Num()); + for (j = 0; j < mesh->verts.Num(); j++) { + WriteFloatString(file, "\tvert %d ( %f %f ) %d %d\n", j, mesh->verts[j].texCoords[0], mesh->verts[j].texCoords[1], + mesh->verts[j].startweight, mesh->verts[j].numWeights); } - WriteFloatString( file, "\n\tnumtris %d\n", mesh->tris.Num() ); - for( j = 0; j < mesh->tris.Num(); j++ ) { - WriteFloatString( file, "\ttri %d %d %d %d\n", j, mesh->tris[ j ].indexes[ 2 ], mesh->tris[ j ].indexes[ 1 ], mesh->tris[ j ].indexes[ 0 ] ); + WriteFloatString(file, "\n\tnumtris %d\n", mesh->tris.Num()); + for (j = 0; j < mesh->tris.Num(); j++) { + WriteFloatString(file, "\ttri %d %d %d %d\n", j, mesh->tris[j].indexes[2], mesh->tris[j].indexes[1], mesh->tris[j].indexes[0]); } - WriteFloatString( file, "\n\tnumweights %d\n", mesh->weights.Num() ); - for( j = 0; j < mesh->weights.Num(); j++ ) { - exportWeight_t *weight; + WriteFloatString(file, "\n\tnumweights %d\n", mesh->weights.Num()); + for (j = 0; j < mesh->weights.Num(); j++) { + exportWeight_t* weight; - weight = &mesh->weights[ j ]; - WriteFloatString( file, "\tweight %d %d %f ( %f %f %f )\n", j, - weight->joint->exportNum, weight->jointWeight, weight->offset.x, weight->offset.y, weight->offset.z ); + weight = &mesh->weights[j]; + WriteFloatString(file, "\tweight %d %d %f ( %f %f %f )\n", j, + weight->joint->exportNum, weight->jointWeight, weight->offset.x, weight->offset.y, weight->offset.z); } - WriteFloatString( file, "}\n" ); + WriteFloatString(file, "}\n"); } - fclose( file ); + fclose(file); return true; } -bool idExportModel::WriteAnim( const char *filename, idExportOptions &options ) { +bool idExportModel::WriteAnim(const char* filename, idExportOptions& options) { int i, j; - idExportJoint *joint; - idExportJoint *parent; - idExportJoint *sibling; - jointFrame_t *frame; - FILE *file; + idExportJoint* joint; + idExportJoint* parent; + idExportJoint* sibling; + jointFrame_t* frame; + FILE* file; int numAnimatedComponents; - idList jointList; + idList jointList; - file = fopen( filename, "w" ); - if ( !file ) { + file = fopen(filename, "w"); + if (!file) { return false; } - for( joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) { - jointList.Append( joint ); + for (joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext()) { + jointList.Append(joint); } - for( i = 0; i < jointList.Num(); i++ ) { - joint = jointList[ i ]; + 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 ); + while (sibling) { + if (idStr::Cmp(joint->name, sibling->name) > 0) { + joint->exportNode.MakeSiblingAfter(sibling->exportNode); sibling = joint->exportNode.GetSibling(); - } else { + } + else { sibling = sibling->exportNode.GetSibling(); } } } jointList.Clear(); - for( joint = exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext() ) { - joint->exportNum = jointList.Append( joint ); + 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 ]; + for (i = 0; i < jointList.Num(); i++) { + joint = jointList[i]; joint->exportNum = i; - joint->baseFrame = frames[ 0 ][ joint->index ]; + 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 ) { + 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 ) { + 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 ) { + 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 ) { + 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 ) { + 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 ) { + if (fabs(frame->q[2] - joint->baseFrame.q[2]) > options.quatPrecision) { joint->animBits |= ANIM_QZ; } - if ( ( joint->animBits & 63 ) == 63 ) { + if ((joint->animBits & 63) == 63) { break; } } - if ( joint->animBits ) { + if (joint->animBits) { joint->firstComponent = numAnimatedComponents; - for( j = 0; j < 6; j++ ) { - if ( joint->animBits & BIT( j ) ) { + for (j = 0; j < 6; j++) { + if (joint->animBits & BIT(j)) { numAnimatedComponents++; } } @@ -1149,125 +1162,127 @@ bool idExportModel::WriteAnim( const char *filename, idExportOptions &options ) } // write version info - WriteFloatString( file, MD5_VERSION_STRING " %d\n", MD5_VERSION ); - WriteFloatString( file, "commandline \"%s\"\n\n", options.commandLine.c_str() ); + 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); - 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 ); - // write out the hierarchy - WriteFloatString( file, "\nhierarchy {\n" ); - for( i = 0; i < jointList.Num(); i++ ) { - joint = jointList[ i ]; + WriteFloatString(file, "\nhierarchy {\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 (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 ] ); + 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"); } } - WriteFloatString( file, "}\n" ); + WriteFloatString(file, "}\n"); // write the frame bounds - WriteFloatString( file, "\nbounds {\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, "\nbounds {\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" ); + WriteFloatString(file, "}\n"); // write the base frame - WriteFloatString( file, "\nbaseframe {\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, "\nbaseframe {\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" ); + WriteFloatString(file, "}\n"); // write the frames - for( i = 0; i < numFrames; i++ ) { - WriteFloatString( file, "\nframe %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 ] ); + for (i = 0; i < numFrames; i++) { + WriteFloatString(file, "\nframe %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_TY) { + WriteFloatString(file, " %f", frame->t[1]); } - if ( joint->animBits & ANIM_TZ ) { - WriteFloatString( file, " %f", frame->t[ 2 ] ); + 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_QX) { + WriteFloatString(file, " %f", frame->q[0]); } - if ( joint->animBits & ANIM_QY ) { - WriteFloatString( file, " %f", frame->q[ 1 ] ); + if (joint->animBits & ANIM_QY) { + WriteFloatString(file, " %f", frame->q[1]); } - if ( joint->animBits & ANIM_QZ ) { - WriteFloatString( file, " %f", frame->q[ 2 ] ); + if (joint->animBits & ANIM_QZ) { + WriteFloatString(file, " %f", frame->q[2]); } - WriteFloatString( file, "\n" ); + WriteFloatString(file, "\n"); } } - WriteFloatString( file, "}\n" ); + WriteFloatString(file, "}\n"); } - fclose( file ); + fclose(file); return true; } -bool idExportModel::WriteCamera( const char *filename, idExportOptions &options ) { +bool idExportModel::WriteCamera(const char* filename, idExportOptions& options) { int i; - FILE *file; + FILE* file; - file = fopen( filename, "w" ); - if ( !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, 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()); - WriteFloatString( file, "numFrames %d\n", camera.Num() ); - WriteFloatString( file, "frameRate %d\n", frameRate ); - WriteFloatString( file, "numCuts %d\n", cameraCuts.Num() ); - // write out the cuts - WriteFloatString( file, "\ncuts {\n" ); - for( i = 0; i < cameraCuts.Num(); i++ ) { - WriteFloatString( file, "\t%d\n", cameraCuts[ i ] ); + WriteFloatString(file, "\ncuts {\n"); + for (i = 0; i < cameraCuts.Num(); i++) { + WriteFloatString(file, "\t%d\n", cameraCuts[i]); } - WriteFloatString( file, "}\n" ); + WriteFloatString(file, "}\n"); // write out the frames - WriteFloatString( file, "\ncamera {\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, "\ncamera {\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" ); + WriteFloatString(file, "}\n"); - fclose( file ); + fclose(file); return true; } @@ -1275,500 +1290,760 @@ bool idExportModel::WriteCamera( const char *filename, idExportOptions &options /* ============================================================================== -Maya +FBX scene extraction ============================================================================== */ -/* -=============== -idMayaExport::~idMayaExport - -=============== -*/ -idMayaExport::~idMayaExport() { - FreeDagNodes(); - - // free up the file in Maya - MFileIO::newFile( true ); +static bool IsMD3Export(idExportOptions& options) { + idTokenizer tokens; + tokens.SetTokens(options.commandLine.c_str()); + idStr first = tokens.NextToken(); + if (first == "md3") { + return true; + } + if (options.dest.Length() >= 4) { + idStr ext = options.dest.Right(4); + if (!ext.Icmp(".md3")) { + return true; + } + } + return false; } -/* -=============== -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 ); +static const char* FbxSafeName(const char* name) { + return (name && name[0]) ? name : "unnamed"; } -/* -=============== -idMayaExport::GetMayaFrameNum -=============== -*/ -int idMayaExport::GetMayaFrameNum( int num ) const { - int frameNum; +static void MD3_CopyString(char* dst, int dstSize, const char* src) { + memset(dst, 0, dstSize); + if (src == NULL) { + return; + } + strncpy(dst, src, dstSize - 1); +} - 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. +static int MD3_ClampShort(int v) { + if (v < -32768) { + return -32768; + } + if (v > 32767) { + return 32767; + } + return v; +} + +static short MD3_EncodeNormal(const idVec3& normal) { + const float twoPi = 6.28318530717958647692f; + idVec3 n = normal; + if (n.Normalize() == 0.0f) { + return 0; + } + + int lat = (int)(atan2(n.y, n.x) * 255.0f / twoPi); + int lng = (int)(acos(n.z) * 255.0f / twoPi); + return (short)(((lat & 0xff) << 8) | (lng & 0xff)); +} + +static void MD3_BuildWorldPose(idExportModel& model, jointFrame_t* frame) { + idExportJoint* joint; + idExportJoint* parent; + idVec3 jointpos; + idMat3 jointaxis; + + 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; + } + } +} + +static void MD3_BuildMeshPositions(idExportMesh* mesh, idList& positions) { + int i, j; + exportVertex_t* vert; + exportWeight_t* weight; + idVec3 pos; + + positions.SetNum(mesh->verts.Num()); + for (i = 0; i < mesh->verts.Num(); i++) { + vert = &mesh->verts[i]; + pos.Zero(); + weight = &mesh->weights[vert->startweight]; + for (j = 0; j < vert->numWeights; j++, weight++) { + pos += weight->jointWeight * (weight->joint->idwm * weight->offset + weight->joint->idt); + } + positions[i] = pos; + } +} + +static void MD3_BuildMeshNormals(idExportMesh* mesh, const idList& positions, idList& normals) { + int i, j; + idVec3 a, b, n; + int indexes[3]; + + normals.SetNum(mesh->verts.Num()); + for (i = 0; i < normals.Num(); i++) { + normals[i].Zero(); + } + + for (i = 0; i < mesh->tris.Num(); i++) { + indexes[0] = mesh->tris[i].indexes[2]; + indexes[1] = mesh->tris[i].indexes[1]; + indexes[2] = mesh->tris[i].indexes[0]; + a = positions[indexes[1]] - positions[indexes[0]]; + b = positions[indexes[2]] - positions[indexes[0]]; + n = a.Cross(b); + n.Normalize(); + for (j = 0; j < 3; j++) { + normals[indexes[j]] += n; + } + } + + for (i = 0; i < normals.Num(); i++) { + normals[i].Normalize(); + } +} + +static void MD3_BuildTagList(idExportModel& model, idList& tags) { + idExportJoint* joint; + + tags.Clear(); + for (joint = model.exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext()) { + if (!joint->name.Icmpn("tag_", 4)) { + if (tags.Num() >= MD3_MAX_TAGS) { + MayaError("MD3 export supports only %d tags", MD3_MAX_TAGS); + } + tags.Append(joint); + } + } +} + +static bool WriteMD3Model(idExportModel& model, const char* filename, idExportOptions& options) { + int i, j, frameNum; + int numSurfaces; + idBounds bounds; + idList tags; + idList md3Frames; + idList positions; + idList normals; + idExportMesh* mesh; + FILE* file; + + MD3_BuildTagList(model, tags); + + if (model.numFrames < 1 || model.numFrames > MD3_MAX_FRAMES) { + MayaError("MD3 export requires 1..%d frames, got %d", MD3_MAX_FRAMES, model.numFrames); + } + + numSurfaces = 0; + for (i = 0; i < model.meshes.Num(); i++) { + if (model.meshes[i]->keep) { + numSurfaces++; + } + } + if (numSurfaces < 1) { + MayaError("MD3 export has no mesh surfaces"); + } + if (numSurfaces > MD3_MAX_SURFACES) { + MayaError("MD3 export supports only %d surfaces, got %d", MD3_MAX_SURFACES, numSurfaces); + } + + md3Frames.SetNum(model.numFrames); + for (frameNum = 0; frameNum < model.numFrames; frameNum++) { + MD3_BuildWorldPose(model, model.frames[frameNum]); + + bounds.Clear(); + for (i = 0; i < model.meshes.Num(); i++) { + mesh = model.meshes[i]; + if (!mesh->keep) { + continue; + } + MD3_BuildMeshPositions(mesh, positions); + for (j = 0; j < positions.Num(); j++) { + bounds.AddPoint(positions[j]); + } + } + + memset(&md3Frames[frameNum], 0, sizeof(md3Frames[frameNum])); + md3Frames[frameNum].bounds[0] = bounds[0]; + md3Frames[frameNum].bounds[1] = bounds[1]; + md3Frames[frameNum].localOrigin = (bounds[0] + bounds[1]) * 0.5f; + md3Frames[frameNum].radius = 0.0f; + for (i = 0; i < 8; i++) { + idVec3 corner; + corner.x = (i & 1) ? bounds[1].x : bounds[0].x; + corner.y = (i & 2) ? bounds[1].y : bounds[0].y; + corner.z = (i & 4) ? bounds[1].z : bounds[0].z; + float radius = (corner - md3Frames[frameNum].localOrigin).Length(); + if (radius > md3Frames[frameNum].radius) { + md3Frames[frameNum].radius = radius; + } + } + sprintf(md3Frames[frameNum].name, "frame%d", frameNum); + } + + file = fopen(filename, "wb"); + if (!file) { + return false; + } + + md3Header_t header; + memset(&header, 0, sizeof(header)); + header.ident = MD3_IDENT; + header.version = MD3_VERSION; + MD3_CopyString(header.name, sizeof(header.name), filename); + header.numFrames = model.numFrames; + header.numTags = tags.Num(); + header.numSurfaces = numSurfaces; + header.numSkins = 0; + header.ofsFrames = sizeof(md3Header_t); + header.ofsTags = header.ofsFrames + sizeof(md3Frame_t) * header.numFrames; + header.ofsSurfaces = header.ofsTags + sizeof(md3Tag_t) * header.numFrames * header.numTags; + header.ofsEnd = header.ofsSurfaces; + for (i = 0; i < model.meshes.Num(); i++) { + mesh = model.meshes[i]; + if (!mesh->keep) { + continue; + } + if (mesh->verts.Num() > MD3_MAX_VERTS) { + MayaError("MD3 surface '%s' has %d verts, max is %d", mesh->name.c_str(), mesh->verts.Num(), MD3_MAX_VERTS); + } + if (mesh->tris.Num() > MD3_MAX_TRIANGLES) { + MayaError("MD3 surface '%s' has %d tris, max is %d", mesh->name.c_str(), mesh->tris.Num(), MD3_MAX_TRIANGLES); + } + header.ofsEnd += sizeof(md3Surface_t) + sizeof(md3Shader_t) + sizeof(md3Triangle_t) * mesh->tris.Num() + sizeof(md3St_t) * mesh->verts.Num() + sizeof(md3XyzNormal_t) * mesh->verts.Num() * model.numFrames; + } + + fwrite(&header, sizeof(header), 1, file); + fwrite(md3Frames.Ptr(), sizeof(md3Frame_t), md3Frames.Num(), file); + + for (frameNum = 0; frameNum < model.numFrames; frameNum++) { + MD3_BuildWorldPose(model, model.frames[frameNum]); + for (i = 0; i < tags.Num(); i++) { + md3Tag_t tag; + memset(&tag, 0, sizeof(tag)); + MD3_CopyString(tag.name, sizeof(tag.name), tags[i]->name.c_str()); + tag.origin = tags[i]->idt; + tag.axis[0] = tags[i]->idwm[0]; + tag.axis[1] = tags[i]->idwm[1]; + tag.axis[2] = tags[i]->idwm[2]; + fwrite(&tag, sizeof(tag), 1, file); + } + } + + for (i = 0; i < model.meshes.Num(); i++) { + mesh = model.meshes[i]; + if (!mesh->keep) { + continue; + } + + md3Surface_t surface; + memset(&surface, 0, sizeof(surface)); + surface.ident = MD3_IDENT; + MD3_CopyString(surface.name, sizeof(surface.name), mesh->name.c_str()); + surface.flags = 0; + surface.numFrames = model.numFrames; + surface.numShaders = 1; + surface.numVerts = mesh->verts.Num(); + surface.numTriangles = mesh->tris.Num(); + surface.ofsShaders = sizeof(md3Surface_t); + surface.ofsTriangles = surface.ofsShaders + sizeof(md3Shader_t) * surface.numShaders; + surface.ofsSt = surface.ofsTriangles + sizeof(md3Triangle_t) * surface.numTriangles; + surface.ofsXyzNormals = surface.ofsSt + sizeof(md3St_t) * surface.numVerts; + surface.ofsEnd = surface.ofsXyzNormals + sizeof(md3XyzNormal_t) * surface.numVerts * surface.numFrames; + fwrite(&surface, sizeof(surface), 1, file); + + md3Shader_t shader; + memset(&shader, 0, sizeof(shader)); + if (mesh->shader.Length()) { + MD3_CopyString(shader.name, sizeof(shader.name), mesh->shader.c_str()); + } + else { + MD3_CopyString(shader.name, sizeof(shader.name), mesh->name.c_str()); + } + shader.shaderIndex = 0; + fwrite(&shader, sizeof(shader), 1, file); + + for (j = 0; j < mesh->tris.Num(); j++) { + md3Triangle_t tri; + tri.indexes[0] = mesh->tris[j].indexes[2]; + tri.indexes[1] = mesh->tris[j].indexes[1]; + tri.indexes[2] = mesh->tris[j].indexes[0]; + fwrite(&tri, sizeof(tri), 1, file); + } + + for (j = 0; j < mesh->verts.Num(); j++) { + md3St_t st; + st.st[0] = mesh->verts[j].texCoords[0]; + st.st[1] = mesh->verts[j].texCoords[1]; + fwrite(&st, sizeof(st), 1, file); + } + + for (frameNum = 0; frameNum < model.numFrames; frameNum++) { + MD3_BuildWorldPose(model, model.frames[frameNum]); + MD3_BuildMeshPositions(mesh, positions); + MD3_BuildMeshNormals(mesh, positions, normals); + for (j = 0; j < positions.Num(); j++) { + md3XyzNormal_t xyz; + xyz.xyz[0] = (short)MD3_ClampShort((int)floor(positions[j].x / MD3_XYZ_SCALE + 0.5f)); + xyz.xyz[1] = (short)MD3_ClampShort((int)floor(positions[j].y / MD3_XYZ_SCALE + 0.5f)); + xyz.xyz[2] = (short)MD3_ClampShort((int)floor(positions[j].z / MD3_XYZ_SCALE + 0.5f)); + xyz.normal = MD3_EncodeNormal(normals[j]); + fwrite(&xyz, sizeof(xyz), 1, file); + } + } + } + + fclose(file); + return true; +} + +class idFbxExport { +private: + idExportModel model; + idExportOptions& options; + FbxManager* sdkManager; + FbxScene* scene; + FbxAnimStack* animStack; + FbxTime currentTime; + + void LoadScene(void); + void SetDefaultFrameRange(void); + float TimeForFrame(int num) const; + int GetFbxFrameNum(int num) const; + FbxTime TimeForFbxFrame(int num) const; + void SetFrame(int num); + void AddNodesRecursive(FbxNode* node); + void CreateJoints(float scale); + idExportJoint* FindJointForNode(FbxNode* node); + void SetJointBindPose(idExportJoint* joint, const FbxAMatrix& matrix, float scale); + void GetWorldTransform(idExportJoint* joint, idVec3& pos, idMat3& mat, float scale); + void PruneJoints(idStrList& keepjoints, idStr& prefix); + void RenameJoints(idList& renamejoints, idStr& prefix); + bool RemapParents(idList& remapjoints); + void GetTextureForMesh(idExportMesh* mesh, FbxNode* node); + idExportMesh* CopyMesh(FbxNode* node, FbxMesh* fbxMesh, float scale); + void CreateMeshRecursive(FbxNode* node, int& count); + void CreateMesh(float scale); + void CombineMeshes(void); + void GetAlignment(idStr& alignName, idMat3& align, float rotate, int startframe); + idExportJoint* FindFirstCamera(void); + float GetCameraFov(idExportJoint* joint); + void GetCameraFrame(idExportJoint* camera, idMat3& align, cameraFrame_t* cam); + void CreateCameraAnim(idMat3& align); + void GetDefaultPose(idMat3& align); + void CreateAnimation(idMat3& align); + +public: + idFbxExport(idExportOptions& exportOptions) : options(exportOptions) { + sdkManager = NULL; + scene = NULL; + animStack = NULL; + currentTime.SetFrame(0, FbxTime::eFrames24); + }; + ~idFbxExport() { + if (sdkManager != NULL) { + sdkManager->Destroy(); + sdkManager = NULL; + scene = NULL; + animStack = NULL; + } + }; + void ConvertModel(void); +}; + +void idFbxExport::LoadScene(void) { + sdkManager = FbxManager::Create(); + if (sdkManager == NULL) { + MayaError("FBX SDK manager creation failed"); + } + + FbxIOSettings* ios = FbxIOSettings::Create(sdkManager, IOSROOT); + sdkManager->SetIOSettings(ios); + + FbxImporter* importer = FbxImporter::Create(sdkManager, ""); + if (importer == NULL) { + MayaError("FBX importer creation failed"); + } + + if (!importer->Initialize(options.src.c_str(), -1, sdkManager->GetIOSettings())) { + const char* err = importer->GetStatus().GetErrorString(); + importer->Destroy(); + MayaError("Error opening FBX '%s': '%s'", options.src.c_str(), err ? err : "unknown error"); + } + + scene = FbxScene::Create(sdkManager, "doom3_fbx_scene"); + if (scene == NULL) { + importer->Destroy(); + MayaError("FBX scene creation failed"); + } + + if (!importer->Import(scene)) { + const char* err = importer->GetStatus().GetErrorString(); + importer->Destroy(); + MayaError("Error importing FBX '%s': '%s'", options.src.c_str(), err ? err : "unknown error"); + } + importer->Destroy(); + + // Match the old Maya exporter assumptions before applying ConvertToIdSpace(). + FbxAxisSystem::MayaYUp.ConvertScene(scene); + FbxSystemUnit::cm.ConvertScene(scene); + + FbxGeometryConverter converter(sdkManager); + converter.Triangulate(scene, true); + + animStack = scene->GetSrcObject(0); + if (animStack != NULL) { + scene->SetCurrentAnimationStack(animStack); + } +} + +FbxTime idFbxExport::TimeForFbxFrame(int num) const { + FbxTime time; + time.SetFrame(num, FbxTime::eFrames24); + return time; +} + +float idFbxExport::TimeForFrame(int num) const { + return (float)TimeForFbxFrame(num).GetSecondDouble(); +} + +void idFbxExport::SetDefaultFrameRange(void) { + if (options.startframe < 0 || options.endframe < 0) { + FbxTime start; + FbxTime stop; + start.SetFrame(0, FbxTime::eFrames24); + stop.SetFrame(0, FbxTime::eFrames24); + + if (animStack != NULL) { + FbxTimeSpan span = animStack->GetLocalTimeSpan(); + start = span.GetStart(); + stop = span.GetStop(); + } + else if (scene != NULL && scene->GetRootNode() != NULL) { + FbxTimeSpan span; + if (scene->GetRootNode()->GetAnimationInterval(span, animStack)) { + start = span.GetStart(); + stop = span.GetStop(); + } + } + + if (options.startframe < 0) { + options.startframe = (int)start.GetFrameCount(FbxTime::eFrames24); + } + if (options.endframe < 0) { + options.endframe = (int)stop.GetFrameCount(FbxTime::eFrames24); + } + } + + 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) { + options.cycleStart = options.startframe; + } +} + +int idFbxExport::GetFbxFrameNum(int num) const { + int frameNum; + + if (options.cycleStart > options.startframe) { frameNum = options.cycleStart + num; - if ( frameNum > options.endframe ) { + if (frameNum > options.endframe) { frameNum -= options.endframe - options.startframe; } - if ( frameNum < options.startframe ) { - frameNum = options.startframe + 1; + if (frameNum < options.startframe) { + frameNum = options.startframe + 1; } - } else { + } + else { frameNum = options.startframe + num; - if ( frameNum > options.endframe ) { + if (frameNum > options.endframe) { frameNum -= options.endframe + 1 - options.startframe; } - if ( frameNum < options.startframe ) { - frameNum = 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 ); +void idFbxExport::SetFrame(int num) { + currentTime = TimeForFbxFrame(GetFbxFrameNum(num)); } -/* -=============== -idMayaExport::PruneJoints -=============== -*/ -void idMayaExport::PruneJoints( idStrList &keepjoints, idStr &prefix ) { +void idFbxExport::AddNodesRecursive(FbxNode* node) { + int i; + idExportJoint* joint; + + if (node == NULL) { + return; + } + + if (node != scene->GetRootNode()) { + joint = &model.joints.Alloc(); + joint->index = model.joints.Num() - 1; + joint->dagnode = node; + joint->name = FbxSafeName(node->GetName()); + joint->realname = joint->name; + } + + for (i = 0; i < node->GetChildCount(); i++) { + AddNodesRecursive(node->GetChild(i)); + } +} + +idExportJoint* idFbxExport::FindJointForNode(FbxNode* node) { + int i; + if (node == NULL) { + return NULL; + } + for (i = 0; i < model.joints.Num(); i++) { + if (model.joints[i].dagnode == node) { + return &model.joints[i]; + } + } + return NULL; +} + +void idFbxExport::SetJointBindPose(idExportJoint* joint, const FbxAMatrix& matrix, float scale) { + if (joint == NULL) { + return; + } + joint->bindmat = ConvertToIdSpace(idMat(matrix)); + joint->bindmat.OrthoNormalizeSelf(); + joint->bindpos = ConvertToIdSpace(idVec(matrix.GetT())) * scale; + joint->scale = 1.0f; + joint->invscale = 1.0f; +} + +void idFbxExport::CreateJoints(float scale) { + int i, j; + idExportJoint* joint; + idExportJoint* parent; + + SetFrame(0); + AddNodesRecursive(scene->GetRootNode()); + + model.exportOrigin = &model.joints.Alloc(); + model.exportOrigin->index = model.joints.Num() - 1; + model.exportOrigin->dagnode = NULL; + + for (i = 0; i < model.joints.Num(); i++) { + joint = &model.joints[i]; + if (!joint->dagnode) { + continue; + } + + joint->mayaNode.ParentTo(model.mayaHead); + joint->exportNode.ParentTo(model.exportHead); + + FbxNode* parentNode = joint->dagnode->GetParent(); + while (parentNode != NULL && parentNode != scene->GetRootNode()) { + for (j = 0; j < model.joints.Num(); j++) { + if (model.joints[j].dagnode == parentNode) { + joint->mayaNode.ParentTo(model.joints[j].mayaNode); + joint->exportNode.ParentTo(model.joints[j].exportNode); + break; + } + } + if (j < model.joints.Num()) { + break; + } + parentNode = parentNode->GetParent(); + } + + parent = joint->mayaNode.GetParent(); + if (parent) { + joint->longname = parent->longname + "/" + joint->name; + } + else { + joint->longname = joint->name; + } + + SetJointBindPose(joint, joint->dagnode->EvaluateGlobalTransform(currentTime), scale); + } +} + +void idFbxExport::GetWorldTransform(idExportJoint* joint, idVec3& pos, idMat3& mat, float scale) { + pos.Zero(); + mat.Identity(); + if (joint == NULL || joint->dagnode == NULL) { + return; + } + + FbxAMatrix global = joint->dagnode->EvaluateGlobalTransform(currentTime, FbxNode::eSourcePivot, false, true); + pos = idVec(global.GetT()) * scale; + mat = idMat(global); + mat.OrthoNormalizeSelf(); +} + +void idFbxExport::PruneJoints(idStrList& keepjoints, idStr& prefix) { int i; int j; - idExportMesh *mesh; - idExportJoint *joint; - idExportJoint *joint2; - idExportJoint *parent; + 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 + if (!keepjoints.Num() && !prefix.Length()) { + if (!model.meshes.Num() || options.ignoreMeshes) { joint = model.joints.Ptr(); - for( i = 0; i < model.joints.Num(); i++, joint++ ) { + 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 { + for (i = 0; i < model.meshes.Num(); i++) { + 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 ) { + } + else { + 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 ]; + 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 ) { + 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; + } + else if (prefix.Length() && !mesh->weights[j].joint->realname.Cmpn(prefix, prefix.Length())) { + mesh->weights[j].joint->keep = true; num_weights++; } } - if ( num_weights != mesh->weights.Num() ) { + 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 ) { + for (i = 0; i < model.joints.Num(); i++, joint++) { + if (!joint->keep) { joint->exportNode.RemoveFromHierarchy(); - } else { + } + 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 ) { + 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 ); + 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 (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() ); + 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; - } - - 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 ) { +void idFbxExport::RenameJoints(idList& renamejoints, idStr& prefix) { int i; - int j; - idExportJoint *joint; - idExportJoint *parent; - MStatus status; - MDagPath dagPath; - MFnDagNode *parentNode; + idExportJoint* joint; - 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; - } - - // 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 ); - GetBindPose( dagPath.node( &status ), joint, scale ); - } -} - -/* -=============== -idMayaExport::RenameJoints -=============== -*/ -void idMayaExport::RenameJoints( idList &renamejoints, idStr &prefix ) { - int i; - idExportJoint *joint; - - // rename joints that match the prefix - if ( prefix.Length() ) { + 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() ); + for (i = 0; i < model.joints.Num(); i++, joint++) { + if (!joint->name.Cmpn(prefix, prefix.Length())) { + 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; + 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 &remapjoints ) { +bool idFbxExport::RemapParents(idList& remapjoints) { int i; - idExportJoint *joint; - idExportJoint *parent; - idExportJoint *origin; - idExportJoint *sibling; + 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() ); + for (i = 0; i < remapjoints.Num(); i++) { + joint = model.FindJoint(remapjoints[i].from); + if (!joint) { + 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() ); + parent = model.FindJoint(remapjoints[i].to); + if (!parent) { + 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() ); + 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 ); + 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.FindJoint("origin"); + if (!origin) { origin = model.exportOrigin; - origin->dagnode = NULL; - origin->name = "origin"; + 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->exportNode.ParentTo(model.exportHead); origin->keep = true; - - // make all root joints children of the origin joint + joint = model.exportHead.GetChild(); - while( joint ) { + while (joint) { sibling = joint->exportNode.GetSibling(); - if ( joint != origin ) { - joint->exportNode.ParentTo( origin->exportNode ); + if (joint != origin) { + joint->exportNode.ParentTo(origin->exportNode); } joint = sibling; } @@ -1776,837 +2051,509 @@ bool idMayaExport::RemapParents( idList &remapjoints ) { return true; } -/* -=============== -idMayaExport::FindShader +void idFbxExport::GetTextureForMesh(idExportMesh* mesh, FbxNode* node) { + int i; + FbxSurfaceMaterial* material; + FbxProperty prop; -Find the shading node for the given shading group set node. -=============== -*/ -MObject idMayaExport::FindShader( MObject& setNode ) { - MStatus status; - MFnDependencyNode fnNode( setNode ); - MPlug shaderPlug; - - shaderPlug = fnNode.findPlug( "surfaceShader" ); - 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(); - } - } - - 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; - - status = dagNode.getPath( path ); - if ( !status ) { + mesh->shader = ""; + if (node == NULL) { 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(); - } - - // Get a list of all sets pertaining to the selected shape and the - // members of those sets. - // - 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 - // shader attached to the and print out the texture file name for the - // set along with the polygons in the set. - // - 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() ); - continue; - } - - // Make sure the set is a polygonal set. If not, continue. - MItMeshPolygon piter(path, comp, &status); - if (status == MS::kFailure) { - continue; - } - - // 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. - // - MObject shaderNode = FindShader( set ); - if ( shaderNode == MObject::kNullObj ) { + for (i = 0; i < node->GetMaterialCount(); i++) { + material = node->GetMaterial(i); + if (material == NULL) { continue; } - MPlug colorPlug = MFnDependencyNode(shaderNode).findPlug("color", &status); - if ( status == MS::kFailure ) { - continue; + prop = material->FindProperty(FbxSurfaceMaterial::sDiffuse); + if (prop.IsValid()) { + int textureCount = prop.GetSrcObjectCount(); + if (textureCount > 0) { + FbxFileTexture* texture = prop.GetSrcObject(0); + if (texture != NULL && texture->GetFileName() != NULL && texture->GetFileName()[0]) { + OSPathToRelativePath(texture->GetFileName(), mesh->shader, options.game); + mesh->shader.StripFileExtension(); + return; + } + } } - MItDependencyGraph dgIt(colorPlug, MFn::kFileTexture, - MItDependencyGraph::kUpstream, - MItDependencyGraph::kBreadthFirst, - MItDependencyGraph::kNodeLevel, - &status); - - if ( status == MS::kFailure ) { - continue; + if (material->GetName() && material->GetName()[0]) { + mesh->shader = material->GetName(); + return; } - - dgIt.disablePruningOnFilter(); - - // If no texture file node was found, just continue. - // - if ( dgIt.isDone() ) { - continue; - } - - // Print out the texture node name and texture file that it references. - // - MObject textureNode = dgIt.thisNode(); - MPlug filenamePlug = MFnDependencyNode( textureNode ).findPlug( "fileTextureName" ); - MString textureName; - filenamePlug.getValue( textureName ); - - // 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; +idExportMesh* idFbxExport::CopyMesh(FbxNode* node, FbxMesh* fbxMesh, float scale) { + int i, j, k; + int cpCount; + int polygonCount; + idStr name, altname; + idExportMesh* mesh; + bool allowUnskinned; + bool hasSkin; + FbxAMatrix meshBindMatrix; + FbxAMatrix geometryMatrix; + FbxStringList uvSets; + const char* uvSetName; - status = skinCluster.getInputGeometry( objarray ); - if ( !status ) { - MayaError( "CopyMesh: Error getting input geometry (%s)", status.errorString().asChar() ); + if (node == NULL || fbxMesh == NULL) { 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; - } - } - - 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; - - p = fnmesh.numPolygons( &status ); - mesh->tris.SetNum( p ); - mesh->uv.SetNum( p ); - - MString setName; - - 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 ]; - - status = fnmesh.getPolygonUV( j, k, uv_u, uv_v, &setName ); - if ( !status ) { - MayaError( "CopyMesh: MFnMesh::getPolygonUV failed (%s)", status.errorString().asChar() ); - } - - mesh->uv[ j ].uv[ k ][ 0 ] = uv_u; - mesh->uv[ j ].uv[ k ][ 1 ] = uv_v; - } - } - - return mesh; + name = FbxSafeName(fbxMesh->GetName()); + altname = FbxSafeName(node->GetName()); + if (!name.Length() || name == "unnamed") { + name = altname; } - return NULL; + 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; + } + } + + if (options.skipmeshes.Find(name) || options.skipmeshes.Find(altname)) { + common->Printf("Skipping mesh '%s' ('%s')\n", name.c_str(), altname.c_str()); + return NULL; + } + + allowUnskinned = IsMD3Export(options); + hasSkin = fbxMesh->GetDeformerCount(FbxDeformer::eSkin) > 0; + if (!hasSkin && !allowUnskinned) { + MayaError("Mesh '%s': No skin deformers found. MD5 export expects a skinned FBX mesh.", altname.c_str()); + } + + mesh = new idExportMesh(); + model.meshes.Append(mesh); + mesh->name = altname.Length() ? altname : name; + GetTextureForMesh(mesh, node); + + cpCount = fbxMesh->GetControlPointsCount(); + mesh->verts.SetNum(cpCount); + geometryMatrix = FbxGetGeometryTransform(node); + meshBindMatrix = node->EvaluateGlobalTransform(currentTime) * geometryMatrix; + + for (i = 0; i < cpCount; i++) { + memset(&mesh->verts[i], 0, sizeof(mesh->verts[i])); + FbxVector4 p = meshBindMatrix.MultT(fbxMesh->GetControlPointAt(i)); + mesh->verts[i].pos = ConvertToIdSpace(idVec(p)) * scale; + } + + polygonCount = fbxMesh->GetPolygonCount(); + mesh->tris.SetNum(polygonCount); + mesh->uv.SetNum(polygonCount); + + fbxMesh->GetUVSetNames(uvSets); + uvSetName = (uvSets.GetCount() > 0) ? uvSets[0] : NULL; + for (i = 0; i < polygonCount; i++) { + if (fbxMesh->GetPolygonSize(i) != 3) { + MayaError("CopyMesh: FBX triangulation failed; polygon %d on '%s' has %d vertices", i, mesh->name.c_str(), fbxMesh->GetPolygonSize(i)); + } + for (j = 0; j < 3; j++) { + mesh->tris[i].indexes[j] = fbxMesh->GetPolygonVertex(i, j); + mesh->uv[i].uv[j][0] = 0.0f; + mesh->uv[i].uv[j][1] = 0.0f; + if (uvSetName != NULL) { + FbxVector2 uv; + bool unmapped = false; + if (fbxMesh->GetPolygonVertexUV(i, j, uvSetName, uv, unmapped) && !unmapped) { + mesh->uv[i].uv[j][0] = (float)uv[0]; + mesh->uv[i].uv[j][1] = (float)uv[1]; + } + } + } + } + + idList< idList > cpWeights; + cpWeights.SetNum(cpCount); + + if (hasSkin) { + bool meshBindSet = false; + for (i = 0; i < fbxMesh->GetDeformerCount(FbxDeformer::eSkin); i++) { + FbxSkin* skin = (FbxSkin*)fbxMesh->GetDeformer(i, FbxDeformer::eSkin); + if (skin == NULL) { + continue; + } + + for (j = 0; j < skin->GetClusterCount(); j++) { + FbxCluster* cluster = skin->GetCluster(j); + if (cluster == NULL || cluster->GetLink() == NULL) { + continue; + } + + idExportJoint* joint = FindJointForNode(cluster->GetLink()); + if (joint == NULL) { + MayaError("Mesh '%s': joint '%s' not found", mesh->name.c_str(), FbxSafeName(cluster->GetLink()->GetName())); + } + + FbxAMatrix linkMatrix; + cluster->GetTransformLinkMatrix(linkMatrix); + SetJointBindPose(joint, linkMatrix, scale); + + if (!meshBindSet) { + cluster->GetTransformMatrix(meshBindMatrix); + meshBindMatrix = meshBindMatrix * geometryMatrix; + for (k = 0; k < cpCount; k++) { + FbxVector4 p = meshBindMatrix.MultT(fbxMesh->GetControlPointAt(k)); + mesh->verts[k].pos = ConvertToIdSpace(idVec(p)) * scale; + } + meshBindSet = true; + } + + int* indices = cluster->GetControlPointIndices(); + double* weights = cluster->GetControlPointWeights(); + int weightCount = cluster->GetControlPointIndicesCount(); + for (k = 0; k < weightCount; k++) { + int cpIndex = indices[k]; + if (cpIndex < 0 || cpIndex >= cpCount) { + continue; + } + if (weights[k] <= 0.0) { + continue; + } + exportWeight_t weight; + weight.joint = joint; + weight.jointWeight = (float)weights[k]; + weight.offset.Zero(); + cpWeights[cpIndex].Append(weight); + } + } + } + } + else { + idExportJoint* joint = FindJointForNode(node); + if (joint == NULL) { + joint = model.exportOrigin; + joint->name = "origin"; + joint->realname = "origin"; + joint->bindmat.Identity(); + joint->bindpos.Zero(); + joint->keep = true; + } + else { + SetJointBindPose(joint, node->EvaluateGlobalTransform(currentTime), scale); + } + + for (i = 0; i < cpCount; i++) { + exportWeight_t weight; + weight.joint = joint; + weight.jointWeight = 1.0f; + weight.offset.Zero(); + cpWeights[i].Append(weight); + } + } + + for (i = 0; i < cpCount; i++) { + exportVertex_t* vert = &mesh->verts[i]; + vert->startweight = mesh->weights.Num(); + float totalWeight = 0.0f; + int nonZeroWeights = 0; + + for (j = 0; j < cpWeights[i].Num(); j++) { + if (cpWeights[i][j].jointWeight > 0.0f) { + nonZeroWeights++; + } + if (cpWeights[i][j].jointWeight <= options.jointThreshold) { + continue; + } + + exportWeight_t weight = cpWeights[i][j]; + 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 (nonZeroWeights) { + MayaError("Error on mesh '%s': Vertex %d doesn't have any joint weights exceeding jointThreshold (%f).", mesh->name.c_str(), i, options.jointThreshold); + } + else { + MayaError("Error on mesh '%s': Vertex %d doesn't have any joint weights.", mesh->name.c_str(), i); + } + } + else if (!totalWeight) { + MayaError("Error on mesh '%s': Combined weight of 0 on vertex %d.", mesh->name.c_str(), i); + } + + for (j = 0; j < vert->numWeights; j++) { + mesh->weights[vert->startweight + j].jointWeight /= totalWeight; + } + } + + return mesh; } -/* -=============== -idMayaExport::CreateMesh -=============== -*/ -void idMayaExport::CreateMesh( float scale ) { - size_t count; - idExportMesh *mesh; - MStatus status; - exportWeight_t weight; - unsigned int nGeoms; +void idFbxExport::CreateMeshRecursive(FbxNode* node, int& count) { + if (node == NULL) { + return; + } - // Iterate through graph and search for skinCluster nodes - MItDependencyNodes iter( MFn::kSkinClusterFilter ); - count = 0; - for ( ; !iter.isDone(); iter.next() ) { - MObject object = iter.item(); - - count++; - - // 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() ); - } - - 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() ); - } - - // 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 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 ]; - - 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; + FbxMesh* mesh = node->GetMesh(); + if (mesh != NULL) { + if (CopyMesh(node, mesh, options.scale) != NULL) { + count++; } } - if ( !count && !options.ignoreMeshes ) { - MayaError( "CreateMesh: No skinClusters found in this scene.\n" ); + for (int i = 0; i < node->GetChildCount(); i++) { + CreateMeshRecursive(node->GetChild(i), count); } } -/* -=============== -idMayaExport::CombineMeshes +void idFbxExport::CreateMesh(float scale) { + int count = 0; + CreateMeshRecursive(scene->GetRootNode(), count); + if (!count && !options.ignoreMeshes) { + MayaError("CreateMesh: No FBX meshes found in this scene.\n"); + } +} -combine surfaces with the same shader. -=============== -*/ -void idMayaExport::CombineMeshes( void ) { +void idFbxExport::CombineMeshes(void) { int i, j; int count; - idExportMesh *mesh; - idExportMesh *combine; - idList oldmeshes; + idExportMesh* mesh; + idExportMesh* combine; + idList oldmeshes; oldmeshes = model.meshes; model.meshes.Clear(); count = 0; - for( i = 0; i < oldmeshes.Num(); i++ ) { - mesh = oldmeshes[ i ]; - if ( !mesh->keep ) { + 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 ]; + 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 ); + if (combine) { + combine->Merge(mesh); delete mesh; count++; - } else { - model.meshes.Append( mesh ); + } + else { + model.meshes.Append(mesh); } } - // share verts - for( i = 0; i < model.meshes.Num(); i++ ) { - model.meshes[ i ]->ShareVerts(); + for (i = 0; i < model.meshes.Num(); i++) { + model.meshes[i]->ShareVerts(); } - common->Printf( "Merged %d meshes\n", count ); + common->Printf("Merged %d meshes\n", count); } -/* -=============== -idMayaExport::GetAlignment -=============== -*/ -void idMayaExport::GetAlignment( idStr &alignName, idMat3 &align, float rotate, int startframe ) { +void idFbxExport::GetAlignment(idStr& alignName, idMat3& align, float rotate, int startframe) { idVec3 pos; - idExportJoint *joint; - idAngles ang( 0, rotate, 0 ); + idExportJoint* joint; + idAngles ang(0, rotate, 0); idMat3 mat; align.Identity(); - if ( alignName.Length() ) { - SetFrame( 0 ); + 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() ); + 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 ]; + 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[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 ]; + align[2][0] = mat[1][0]; + align[2][1] = -mat[1][2]; + align[2][2] = mat[1][1]; - if ( rotate ) { + if (rotate) { align *= ang.ToMat3(); } - } else if ( rotate ) { + } + else if (rotate) { align = ang.ToMat3(); } align.TransposeSelf(); } -/* -=============== -idMayaExport::GetObjectType +idExportJoint* idFbxExport::FindFirstCamera(void) { + int i; + idExportJoint* joint; -return the type of the object -=============== -*/ -const char *idMayaExport::GetObjectType( MObject object ) { - if( object.isNull() ) { - return "(Null)"; + joint = model.FindJoint(MAYA_DEFAULT_CAMERA); + if (joint && joint->dagnode && joint->dagnode->GetCamera()) { + return joint; } - 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 ); - - 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; + for (i = 0; i < model.joints.Num(); i++) { + joint = &model.joints[i]; + if (joint->dagnode && joint->dagnode->GetCamera()) { + return joint; } } - return fov; + return NULL; } -/* -=============== -idMayaExport::GetCameraFrame -=============== -*/ -void idMayaExport::GetCameraFrame( idExportJoint *camera, idMat3 &align, cameraFrame_t *cam ) { +float idFbxExport::GetCameraFov(idExportJoint* joint) { + if (joint == NULL || joint->dagnode == NULL || joint->dagnode->GetCamera() == NULL) { + return 90.0f; + } + + FbxCamera* camera = joint->dagnode->GetCamera(); + if (camera->GetApertureMode() == FbxCamera::eFocalLength) { + return (float)camera->ComputeFieldOfView(camera->FocalLength.Get()); + } + if (camera->GetApertureMode() == FbxCamera::eHorizAndVert) { + return (float)camera->FieldOfViewX.Get(); + } + return (float)camera->FieldOfView.Get(); +} + +void idFbxExport::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 ); - - // convert to id coordinates - cam->t = ConvertToIdSpace( pos ) * align; + GetWorldTransform(camera, pos, axis, 1.0f); - // correct the orientation for the game - axis = ConvertToIdSpace( axis ) * align; - mat[ 0 ] = -axis[ 2 ]; - mat[ 1 ] = -axis[ 0 ]; - mat[ 2 ] = axis[ 1 ]; + cam->t = ConvertToIdSpace(pos) * align; + + 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 ); + 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; +void idFbxExport::CreateCameraAnim(idMat3& align) { + float start, end; + int frameNum; + idExportJoint* camJoint; - start = TimeForFrame( options.startframe ); - end = TimeForFrame( options.endframe ); + 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 ); + 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." ); + 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 ) ); - } + model.camera.Clear(); + model.cameraCuts.Clear(); + camJoint = FindFirstCamera(); + if (camJoint == NULL) { + MayaError("Couldn't find an FBX camera node"); } - camJoint = model.FindJoint( currentCam ); - if ( !camJoint ) { - MayaError( "Couldn't find camera '%s'", currentCam.c_str() ); + for (frameNum = 0; frameNum < model.numFrames; frameNum++) { + common->Printf("\rFrame %d/%d...", options.startframe + frameNum, options.endframe); + SetFrame(frameNum); + GetCameraFrame(camJoint, align, &model.camera.Alloc()); } - for( frameNum = 0; frameNum < model.numFrames; frameNum++ ) { - common->Printf( "\rFrame %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" ); + common->Printf("\n"); } -/* -=============== -idMayaExport::GetDefaultPose -=============== -*/ -void idMayaExport::GetDefaultPose( idMat3 &align ) { +void idFbxExport::GetDefaultPose(idMat3& align) { float start; - MDagPath dagPath; idMat3 jointaxis; idVec3 jointpos; - idExportJoint *joint, *parent; - idBounds bnds; - idBounds meshBounds; + idExportJoint* joint, * parent; idList frame; - start = TimeForFrame( options.startframe ); + start = TimeForFrame(options.startframe); - common->Printf( "default pose frame = %d\n", options.startframe ); - common->Printf( " default pose time = %f\n", start ); + common->Printf("default pose frame = %d\n", options.startframe); + common->Printf(" default pose time = %f\n", start); - frame.SetNum( model.joints.Num() ); - SetFrame( 0 ); + 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 + for (joint = model.exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext()) { + if (!joint->dagnode) { joint->idwm.Identity(); joint->idt.Zero(); - frame[ joint->index ].t.Zero(); - frame[ joint->index ].q.Set( 0.0f, 0.0f, 0.0f ); + 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 ); - - // convert to id coordinates - jointaxis = ConvertToIdSpace( jointaxis ) * align; - jointpos = ConvertToIdSpace( jointpos ) * align; + GetWorldTransform(joint, jointpos, jointaxis, options.scale); - // save worldspace position of joint for children - joint->idwm = jointaxis; - joint->idt = jointpos; + jointaxis = ConvertToIdSpace(jointaxis) * align; + jointpos = ConvertToIdSpace(jointpos) * align; + + joint->idwm = jointaxis; + joint->idt = jointpos; parent = joint->exportNode.GetParent(); - if ( parent ) { - // convert to local coordinates - jointpos = ( jointpos - parent->idt ) * parent->idwm.Transpose(); + if (parent) { + jointpos = (jointpos - parent->idt) * parent->idwm.Transpose(); jointaxis = jointaxis * parent->idwm.Transpose(); - } else if ( joint->name == "origin" ) { - if ( options.clearOrigin ) { + } + else if (joint->name == "origin") { + if (options.clearOrigin) { jointpos.Zero(); } - if ( options.clearOriginAxis ) { + if (options.clearOriginAxis) { jointaxis.Identity(); } } - frame[ joint->index ].t = jointpos; - frame[ joint->index ].q = jointaxis.ToQuat().ToCQuat(); + 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(); + 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(); + 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 ) { + if (parent) { joint->idwm = jointaxis * parent->idwm; joint->idt = parent->idt + jointpos * parent->idwm; - } else { + } + else { joint->idwm = jointaxis; joint->idt = jointpos; } @@ -2615,444 +2562,223 @@ void idMayaExport::GetDefaultPose( idMat3 &align ) { joint->bindpos = joint->idt; } - common->Printf( "\n" ); + common->Printf("\n"); } -/* -=============== -idMayaExport::CreateAnimation -=============== -*/ -void idMayaExport::CreateAnimation( idMat3 &align ) { +void idFbxExport::CreateAnimation(idMat3& align) { int i; float start, end; - MDagPath dagPath; idMat3 jointaxis; idVec3 jointpos; int frameNum; - idExportJoint *joint, *parent; + idExportJoint* joint, * parent; idBounds bnds; idBounds meshBounds; - jointFrame_t *frame; + jointFrame_t* frame; int cycleStart; idVec3 totalDelta; - idList copyFrames; + idList copyFrames; - start = TimeForFrame( options.startframe ); - end = TimeForFrame( options.endframe ); + 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 ); + 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." ); + 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 ]; + 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( "\rFrame %d/%d...", options.startframe + frameNum, options.endframe ); + for (frameNum = 0; frameNum < model.numFrames; frameNum++) { + common->Printf("\rFrame %d/%d...", options.startframe + frameNum, options.endframe); - frame = model.frames[ frameNum ]; - SetFrame( frameNum ); + 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 + for (joint = model.exportHead.GetNext(); joint != NULL; joint = joint->exportNode.GetNext()) { + if (!joint->dagnode) { joint->idwm.Identity(); joint->idt.Zero(); - frame[ joint->index ].t.Zero(); - frame[ joint->index ].q.Set( 0.0f, 0.0f, 0.0f ); + 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 ); - - // convert to id coordinates - jointaxis = ConvertToIdSpace( jointaxis ) * align; - jointpos = ConvertToIdSpace( jointpos ) * align; + GetWorldTransform(joint, jointpos, jointaxis, options.scale); + jointaxis = ConvertToIdSpace(jointaxis) * align; + jointpos = ConvertToIdSpace(jointpos) * align; - // save worldspace position of joint for children - joint->idwm = jointaxis; - joint->idt = jointpos; + joint->idwm = jointaxis; + joint->idt = jointpos; parent = joint->exportNode.GetParent(); - if ( parent ) { - // convert to local coordinates - jointpos = ( jointpos - parent->idt ) * parent->idwm.Transpose(); + if (parent) { + jointpos = (jointpos - parent->idt) * parent->idwm.Transpose(); jointaxis = jointaxis * parent->idwm.Transpose(); - } else if ( joint->name == "origin" ) { - if ( options.clearOrigin ) { + } + else if (joint->name == "origin") { + if (options.clearOrigin) { jointpos.Zero(); } - if ( options.clearOriginAxis ) { + if (options.clearOriginAxis) { jointaxis.Identity(); } } - frame[ joint->index ].t = jointpos; - frame[ joint->index ].q = jointaxis.ToQuat().ToCQuat(); + 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; + 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; + frame = model.frames[model.numFrames - 1]; + totalDelta = frame[joint->index].t - origin; } - // shift the frames when cycleStart is used - if ( options.cycleStart > options.startframe ) { + if (options.cycleStart > options.startframe) { copyFrames = model.jointFrames; - for( i = 0; i < model.numFrames; i++ ) { + 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 = i + (options.cycleStart - options.startframe); + if (frameNum >= model.numFrames) { frameNum -= model.numFrames - 1; shiftorigin = true; } - memcpy( &model.jointFrames[ model.joints.Num() * i ], ©Frames[ model.joints.Num() * frameNum ], model.joints.Num() * sizeof( copyFrames[ 0 ] ) ); + memcpy(&model.jointFrames[model.joints.Num() * i], ©Frames[model.joints.Num() * frameNum], model.joints.Num() * sizeof(copyFrames[0])); - if ( joint && shiftorigin ) { - model.frames[ i ][ joint->index ].t += totalDelta; + 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; + if (joint) { + 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 ]; + for (frameNum = 0; frameNum < model.numFrames; frameNum++) { + frame = model.frames[frameNum]; + MD3_BuildWorldPose(model, frame); - // 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 ); + 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 ]; + model.bounds[frameNum][0] = bnds[0]; + model.bounds[frameNum][1] = bnds[1]; } - common->Printf( "\n" ); + common->Printf("\n"); } -/* -=============== -idMayaExport::ConvertModel -=============== -*/ -void idMayaExport::ConvertModel( void ) { - MStatus status; - idMat3 align; +void idFbxExport::ConvertModel(void) { + idMat3 align; - common->Printf( "Converting %s to %s...\n", options.src.c_str(), options.dest.c_str() ); + 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() ); + FILE* file = fopen(options.dest, "r"); + if (file) { + fclose(file); + FILE* file = fopen(options.dest, "r+"); + if (!file) { + MayaError("Unable to write to the file '%s'", options.dest.c_str()); } - fclose( file ); + fclose(file); } - MString filename( options.src ); - MFileIO::newFile( true ); + common->Printf("Loading FBX file...\n"); + LoadScene(); + SetDefaultFrameRange(); - // 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() ); - } + common->Printf("Creating joints...\n"); + CreateJoints(options.scale); - // 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" ); + 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 ); + common->Printf("Align model...\n"); + GetAlignment(options.align, align, options.rotate, 0); - switch( options.type ) { - case WRITE_MESH : - common->Printf( "Grabbing default pose:\n" ); - GetDefaultPose( align ); - common->Printf( "Writing file...\n" ); - if ( !model.WriteMesh( options.dest, options ) ) { - MayaError( "error writing to '%s'", options.dest.c_str() ); + if (IsMD3Export(options)) { + common->Printf("Creating MD3 vertex frames:\n"); + CreateAnimation(align); + common->Printf("Writing MD3 file...\n"); + if (!WriteMD3Model(model, options.dest, options)) { + MayaError("error writing to '%s'", options.dest.c_str()); + } + common->Printf("done\n\n"); + return; + } + + switch (options.type) { + case WRITE_MESH: + common->Printf("Grabbing default pose:\n"); + 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 : - common->Printf( "Creating animation frames:\n" ); - CreateAnimation( align ); - common->Printf( "Writing file...\n" ); - if ( !model.WriteAnim( options.dest, options ) ) { - MayaError( "error writing to '%s'", options.dest.c_str() ); + case WRITE_ANIM: + common->Printf("Creating animation frames:\n"); + 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() ); + 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; - md3Frame_t *frame; - 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; - - version = LittleLong (pinmodel->version); - 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; - size = LittleLong(pinmodel->ofsEnd); - mod->dataSize += size; - mod->md3[lod] = ri.Hunk_Alloc( size ); - - memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) ); - - 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); - - if ( mod->md3[lod]->numFrames < 1 ) { - common->Printf( "R_LoadMD3: %s has no frames\n", mod_name ); - return qfalse; - } - - // swap all the frames - 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] ); - } - } - - // swap all the tags - 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++ ) { - 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] ); - } - } - - // swap all the surfaces - surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces ); - for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) { - - 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); - - 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 ); - } - - // 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; - } - - // register the shaders - shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); - for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) { - shader_t *sh; - - sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue ); - if ( sh->defaultShader ) { - shader->shaderIndex = 0; - } else { - shader->shaderIndex = sh->index; - } - } - - // 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 - 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] ); - } - - // swap all the XyzNormals - xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); - for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) - { - xyz->xyz[0] = LittleShort( xyz->xyz[0] ); - xyz->xyz[1] = LittleShort( xyz->xyz[1] ); - xyz->xyz[2] = LittleShort( xyz->xyz[2] ); - - xyz->normal = LittleShort( xyz->normal ); - } - - - // find the next surface - surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); - } - return true; -#endif + common->Printf("done\n\n"); } /* @@ -3068,13 +2794,12 @@ dll setup Maya_Shutdown =============== */ -void Maya_Shutdown( void ) { - if ( initialized ) { +void Maya_Shutdown(void) { + if (initialized) { errorMessage.Clear(); initialized = false; - // This shuts down the entire app somehow, so just ignore it. - //MLibrary::cleanup(); + // FbxManager instances are owned per conversion and destroyed by idFbxExport. } } @@ -3083,18 +2808,18 @@ void Maya_Shutdown( void ) { Maya_ConvertModel =============== */ -const char *Maya_ConvertModel( const char *ospath, const char *commandline ) { - +const char* Maya_ConvertModel(const char* ospath, const char* commandline) { + errorMessage = "Ok"; - + try { - idExportOptions options( commandline, ospath ); - idMayaExport exportM( options ); + idExportOptions options(commandline, ospath); + idFbxExport exportM(options); exportM.ConvertModel(); } - - catch( idException &exception ) { + + catch (idException& exception) { errorMessage = exception.error; } @@ -3106,9 +2831,9 @@ const char *Maya_ConvertModel( const char *ospath, const char *commandline ) { dllEntry =============== */ -bool dllEntry( int version, idCommon *common, idSys *sys ) { +bool dllEntry(int version, idCommon* common, idSys* sys) { - if ( !common || !sys ) { + if (!common || !sys) { return false; } @@ -3116,29 +2841,19 @@ bool dllEntry( int version, idCommon *common, idSys *sys ) { ::sys = sys; ::cvarSystem = NULL; - idLib::sys = sys; - idLib::common = common; - idLib::cvarSystem = NULL; - idLib::fileSystem = 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 ); + if (version != MD5_VERSION) { + common->Printf("Error initializing FBX 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; - } + initialized = true; return true; } diff --git a/neo/_MayaImport.props b/neo/_MayaImport.props index 711467ca..4001b965 100644 --- a/neo/_MayaImport.props +++ b/neo/_MayaImport.props @@ -12,7 +12,7 @@ Level3 - Foundation.lib;OpenMaya.lib;OpenMayaAnim.lib;%(AdditionalDependencies) + %(AdditionalDependencies) MayaImport/maya5.0/libs;%(AdditionalLibraryDirectories) diff --git a/neo/idlib/Str.h b/neo/idlib/Str.h index 58120229..4e3170bc 100644 --- a/neo/idlib/Str.h +++ b/neo/idlib/Str.h @@ -37,41 +37,6 @@ If you have questions concerning this license or the applicable additional terms =============================================================================== */ -// these library functions should not be used for cross platform compatibility -#define strcmp idStr::Cmp // use_idStr_Cmp -#define strncmp use_idStr_Cmpn - -#if defined( StrCmpN ) -#undef StrCmpN -#endif -#define StrCmpN use_idStr_Cmpn - -#if defined( strcmpi ) -#undef strcmpi -#endif -#define strcmpi use_idStr_Icmp - -#if defined( StrCmpI ) -#undef StrCmpI -#endif -#define StrCmpI use_idStr_Icmp - -#if defined( StrCmpNI ) -#undef StrCmpNI -#endif -#define StrCmpNI use_idStr_Icmpn - -#define stricmp idStr::Icmp // use_idStr_Icmp -#define _stricmp use_idStr_Icmp -#define strcasecmp use_idStr_Icmp -#define strnicmp use_idStr_Icmpn -#define _strnicmp use_idStr_Icmpn -#define _memicmp use_idStr_Icmpn -#define snprintf use_idStr_snPrintf -#define _snprintf use_idStr_snPrintf -#define vsnprintf use_idStr_vsnPrintf -#define _vsnprintf use_idStr_vsnPrintf - class idVec4; #ifndef FILE_HASH_SIZE diff --git a/neo/idlib/precompiled.h b/neo/idlib/precompiled.h index b5a7f238..9ba6f56a 100644 --- a/neo/idlib/precompiled.h +++ b/neo/idlib/precompiled.h @@ -32,6 +32,7 @@ If you have questions concerning this license or the applicable additional terms #include #include + #ifdef __cplusplus //-----------------------------------------------------