diff --git a/COLLADAMax/FEATURES b/COLLADAMax/FEATURES index 6c2d7fecf..d4b0184b7 100644 --- a/COLLADAMax/FEATURES +++ b/COLLADAMax/FEATURES @@ -8,24 +8,39 @@ Scene graph - Geometries - Materials - Effects + - Cameras + - Light Geometry - Mesh: - POSITION, VERTEX, NORMAL, TEXCOORD (multiple also), COLOR - POLYLIST or TRIANGLES - - Extra tags for primitives (box, sphere, ...) + - Extra tags for primitives (box, sphere, ...) Materials / Effects - Texture and color materials - Materials Phong and Blinn Animation - - LINEAR, STEP, BEZIER - - Rotation / Transformation / Scale + - Animation types: LINEAR, STEP, BEZIER + - All kinds of node transformations + - Material parameters like color + - Morph controller weights - Extra parameters of camera, light, primitives +Controller + - Skin and morph controller + - multiple controllers + Camera + - orthographic and perspective Light + - ambient, point, spot, directional + +XRefs + - Geometries + - Materials + - Transformations diff --git a/COLLADAMax/README b/COLLADAMax/README index 68944290f..a68b19779 100644 --- a/COLLADAMax/README +++ b/COLLADAMax/README @@ -1,7 +1,7 @@ COLLADAMax is a new implementation of a 3ds Max plug-in to export a Max scene or parts of it to a COLLADA file, released under an MIT-license. In contrast to other existing 3ds Max to COLLADA exporters, this new plug-in does not store the -COLLADA document in an intermidiate data model by writes it directly to file. This leads to a dramatic +COLLADA document in an intermidiate data model but writes it directly to file. This leads to a dramatic reduction of memory consumption and to much a better performance. diff --git a/COLLADAMax/include/COLLADAMaxControllerList.h b/COLLADAMax/include/COLLADAMaxControllerList.h index 9614b7256..92b322eac 100644 --- a/COLLADAMax/include/COLLADAMaxControllerList.h +++ b/COLLADAMax/include/COLLADAMaxControllerList.h @@ -71,7 +71,7 @@ namespace COLLADAMax /** Resolves all the controllers of the node, represented by the exportNode and stores them in @a mControllers. We iterate thru the modifier stack, starting with the last one that is applied, until we hit the first modifier that is not support by COLLADA, i.e. is neither a skin nor a morph controller.*/ - void resolveControllers(const ExportNode& exportNode, Object * object); + void resolveControllers(const ExportNode& exportNode); protected: diff --git a/COLLADAMax/include/COLLADAMaxExportNode.h b/COLLADAMax/include/COLLADAMaxExportNode.h index ebf66fc77..5c2503cf0 100644 --- a/COLLADAMax/include/COLLADAMaxExportNode.h +++ b/COLLADAMax/include/COLLADAMaxExportNode.h @@ -57,7 +57,8 @@ namespace COLLADAMax LIGHT, BONE, HELPER, - MATERIAL + MATERIAL, + XREF_OBJECT }; struct Symbol @@ -72,6 +73,27 @@ namespace COLLADAMax private: typedef std::vector Children; + enum Flags + { + NONE = 0x0000, + + /** Indicates if the node is a joint*/ + ISJOINT = 0x0001, + + /** Indicates if the node is in the visual scene, i.e. not hidden or selected if export selection only + is choosen.*/ + ISINVISUALSCENE = 0x0002, + + /** Indicates if the node is referenced some where.*/ + ISREFERENCED = 0x0004, + + /** Indicates if the nodes object is an XRef object.*/ + ISXREFOBJECT = 0x0008, + + /** Indicates if the nodes object is an XRef material.*/ + ISXREFMATERIAL = 0x0010 + }; + private: /** Maps max material to symbol name.*/ MeshSymbolMap mMeshSymbolMap; @@ -87,17 +109,10 @@ namespace COLLADAMax Children mChildren; /** The type of the node.*/ - mutable Type mType; + Type mType; - /** Indicates if the node is a joint*/ - bool mIsJoint; - - /** Indicates if the node is in the visual scene, i.e. not hidden or selected if export selection only - is choosen.*/ - bool mIsInVisualScene; - - /** Indicates if the node is referenced some where.*/ - bool mIsReferenced; + /** Flags used to store properties of the export node*/ + int mFlags; /** The unique id of the node.*/ String mId; @@ -145,13 +160,13 @@ namespace COLLADAMax void setTypeToUnknown() {mType = UNKNOWN;} /** Returns the type of the node.*/ - Type getType() const; + Type getType() const { return mType; }; /** Returns if the node is a joint*/ - bool getIsJoint()const {return mIsJoint; } + bool getIsJoint()const {return (mFlags & ISJOINT) != 0;} /** Sets if the node is a joint*/ - void setIsJoint(bool isJoint = true){mIsJoint=isJoint;} + void setIsJoint(bool isJoint = true){ isJoint ? mFlags |= ISJOINT : mFlags &= ~ISJOINT;} /** Returns the INode associated with this Export Node.*/ INode * getINode() const @@ -170,17 +185,29 @@ namespace COLLADAMax /** Returns if the node is in the visual scene, i.e. not hidden or selected if export selection only is choosen.*/ - bool getIsInVisualScene()const {return mIsInVisualScene;} + bool getIsInVisualScene()const {return (mFlags & ISINVISUALSCENE) != 0;} /** Sets if the node is in the visual scene, i.e. not hidden or selected if export selection only is choosen.*/ - void setIsInVisualScene(bool isInVisualScene){mIsInVisualScene = isInVisualScene;} + void setIsInVisualScene(bool isInVisualScene = true){isInVisualScene ? mFlags |= ISINVISUALSCENE : mFlags &= ~ISINVISUALSCENE;} /** Returns if the node is referenced some where.*/ - bool getIsReferenced()const {return mIsReferenced;} + bool getIsReferenced()const {return (mFlags & ISREFERENCED) != 0;} /** Sets if the node is referenced some where.*/ - void setIsReferenced(bool isReferenced){mIsReferenced = isReferenced;} + void setIsReferenced(bool isReferenced = true){isReferenced ? mFlags |= ISREFERENCED : mFlags &= ~ISREFERENCED;} + + /** Returns if the nodes object is an XRef object.*/ + bool getIsXRefObject()const {return (mFlags & ISXREFOBJECT) != 0;} + + /** Sets if the nodes object is an XRef object.*/ + void setIsXRefObject(bool isXRef = true){isXRef ? mFlags |= ISXREFOBJECT : mFlags &= ~ISXREFOBJECT;} + + /** Returns if the nodes material is an XRef material.*/ + bool getIsXRefMaterial()const {return (mFlags & ISXREFMATERIAL) != 0;} + + /** Sets if the nodes material is an XRef material.*/ + void setIsXRefMaterial(bool isXRef = true){isXRef ? mFlags |= ISXREFMATERIAL : mFlags &= ~ISXREFMATERIAL;} /** Returns the parent or NULL if it has no parent.*/ ExportNode* getParent()const{return mParent;} @@ -226,9 +253,6 @@ namespace COLLADAMax /** Returns the final pose of the object, after all controllers are applied.*/ Object* getFinalPose()const; - /** Determines and returns the type of @a INode.*/ - static Type determineType ( INode * iNode ); - /** Adds channel @a channel with corresponding effect id @a effectId. The symbol is marked as unused.*/ void addSymbol ( Mtl * material, const String & symbol ); @@ -247,7 +271,6 @@ namespace COLLADAMax return mMeshSymbolMap; } - /** Sets the wire frame color.*/ void setWireFrameColor ( DWORD color ) { @@ -283,9 +306,11 @@ namespace COLLADAMax ExportNode ( INode * iNode, ExportNode* parent, Type type ); private: + /** Determines and returns the type of @a INode.*/ + Type determineType ( INode * iNode ); /** Determines the type of the export node.*/ - Type determineType() const; + void determineType(); }; } diff --git a/COLLADAMax/include/COLLADAMaxOptions.h b/COLLADAMax/include/COLLADAMaxOptions.h index 87d5a922a..7e4b15152 100644 --- a/COLLADAMax/include/COLLADAMaxOptions.h +++ b/COLLADAMax/include/COLLADAMaxOptions.h @@ -56,7 +56,7 @@ namespace COLLADAMax Interface* mMaxInterface; bool mNormals; //!< export normals bool mTriangulate; //!< convert Editable Polygons to triangles - bool mXrefs; //!< export external references + bool mIncludeXrefs; //!< export external references bool mTangents; //!< export tangents and binormals bool mAnimations; //!< export animations; bool mSampleAnimation; //!< export sampled animation @@ -96,9 +96,9 @@ namespace COLLADAMax } /** Returns, if XRef are exported.*/ - bool getExportXRefs() const + bool getIncludeXRefs() const { - return mXrefs; + return mIncludeXrefs; } /** Returns, if tangents are exported.*/ diff --git a/COLLADAMax/include/COLLADAMaxPrerequisites.h b/COLLADAMax/include/COLLADAMaxPrerequisites.h index e18240a26..31ec34b23 100644 --- a/COLLADAMax/include/COLLADAMaxPrerequisites.h +++ b/COLLADAMax/include/COLLADAMaxPrerequisites.h @@ -21,18 +21,55 @@ #define UNUSED(a) /**< Removes a piece of code during the pre-process. This macro is useful for these pesky unused variable warnings. */ +#include "maxversion.h" + + +#if ( MAX_VERSION_MAJOR >= 7 ) +# define MAX_7_OR_NEWER +#endif +#if ( MAX_VERSION_MAJOR == 7 ) +# define MAX_7 +#endif + +#if ( MAX_VERSION_MAJOR >= 8 ) +# define MAX_8_OR_NEWER +#endif +#if ( MAX_VERSION_MAJOR == 8 ) +# define MAX_8 +#endif + +#if ( MAX_VERSION_MAJOR >= 9 ) +# define MAX_9_OR_NEWER +#endif +#if ( MAX_VERSION_MAJOR == 9 ) +# define MAX_9 +#endif + +#if ( MAX_VERSION_MAJOR >= 10 ) +# define MAX_2008_OR_NEWER +#endif +#if ( MAX_VERSION_MAJOR == 10 ) +# define MAX_2008 +#endif + +#if ( MAX_VERSION_MAJOR >= 11 ) +# define MAX_2009_OR_NEWER +#endif +#if ( MAX_VERSION_MAJOR == 11 ) +# define MAX_2009 +#endif // Max 2009 requires RTTI to be enabled -#ifdef MAX_2009 +#ifdef MAX_2009_OR_NEWER #ifndef _CPPRTTI -#error "Max 2009 requires RTTI to be enabled. Please enable and try again..." +#error "Max 2009 or newer requires RTTI to be enabled. Please enable and try again..." #endif #endif #define TIME_INITIAL_POSE 0 -#define TIME_EXPORT_START 0//OPTS->AnimStart() +//#define TIME_EXPORT_START 0//OPTS->AnimStart() #include diff --git a/COLLADAMax/include/COLLADAMaxStableHeaders.h b/COLLADAMax/include/COLLADAMaxStableHeaders.h index da37272b7..83c33418d 100644 --- a/COLLADAMax/include/COLLADAMaxStableHeaders.h +++ b/COLLADAMax/include/COLLADAMaxStableHeaders.h @@ -20,11 +20,13 @@ #define __COLLADAMAX_STABLE_HEADERS_H__ +#include "COLLADAMaxPrerequisites.h" + #ifdef MAX_9 #pragma message ("Compling for Max9") -#elif MAX_2008 +#elif defined MAX_2008 #pragma message ("Compling for Max2008") -#elif MAX_2009 +#elif defined MAX_2009 #pragma message ("Compling for Max2009") #endif @@ -49,6 +51,8 @@ #include "MorphR3.h" //for morph controller MorphR3 +#include "COLLADAMaxXRefIncludes.h" + //STL #include diff --git a/COLLADAMax/include/COLLADAMaxXRefExporter.h b/COLLADAMax/include/COLLADAMaxXRefExporter.h new file mode 100644 index 000000000..686c5b928 --- /dev/null +++ b/COLLADAMax/include/COLLADAMaxXRefExporter.h @@ -0,0 +1,67 @@ +/* + Copyright (c) 2008 NetAllied Systems GmbH + + This file is part of COLLADAMax. + + Portions of the code are: + Copyright (c) 2005-2007 Feeling Software Inc. + Copyright (c) 2005-2007 Sony Computer Entertainment America + + Based on the 3dsMax COLLADA Tools: + Copyright (c) 2005-2006 Autodesk Media Entertainment + + Licensed under the MIT Open Source License, + for details please see LICENSE file or the website + http://www.opensource.org/licenses/mit-license.php +*/ + + +#ifndef __COLLADAMAX_XREFEXPORTER_H__ +#define __COLLADAMAX_XREFEXPORTER_H__ + +#include "COLLADAMaxPrerequisites.h" + + + +namespace COLLADAMax +{ + class ExportSceneGraph; + class ExportNode; + class DocumentExporter; + + /** Base class to export extra tags in max.*/ + + class XRefExporter : public COLLADA::LibraryControllers + { + + public: + + private: + ExportSceneGraph* mExportSceneGraph; + DocumentExporter* mDocumentExporter; + + public: + /** Constructor + @param streamWriter the stream the extra tags should be written to.*/ + XRefExporter ( COLLADA::StreamWriter * streamWriter, ExportSceneGraph * exportSceneGraph, DocumentExporter * documentExporter ); + + /** Destructor*/ + virtual ~XRefExporter() + {} + + /** Exports all the controllers in the export scene graph.*/ + void doExport(); + + + private: + + /** Exports all the controllers in @a node and all its child nodes.*/ + void doExport ( ExportNode* exportNode ); + }; + + +} + + +#endif //__COLLADAMAX_XREFEXPORTER_H__ + diff --git a/COLLADAMax/include/COLLADAMaxXRefFile.h b/COLLADAMax/include/COLLADAMaxXRefFile.h new file mode 100644 index 000000000..c0e5a69bf --- /dev/null +++ b/COLLADAMax/include/COLLADAMaxXRefFile.h @@ -0,0 +1,98 @@ +/* + Copyright (c) 2008 NetAllied Systems GmbH + + This file is part of COLLADAMax. + + Portions of the code are: + Copyright (c) 2005-2007 Feeling Software Inc. + Copyright (c) 2005-2007 Sony Computer Entertainment America + + Based on the 3dsMax COLLADA Tools: + Copyright (c) 2005-2006 Autodesk Media Entertainment + + Licensed under the MIT Open Source License, + for details please see LICENSE file or the website + http://www.opensource.org/licenses/mit-license.php +*/ + + +#ifndef __COLLADAMAX_CONTROLLEREXPORTER_H__ +#define __COLLADAMAX_CONTROLLEREXPORTER_H__ + +#include "COLLADAMaxPrerequisites.h" + +#include "COLLADALibraryControllers.h" +#include "COLLADAMaxTypes.h" +#include "COLLADAMaxController.h" + + +namespace COLLADAMax +{ + class ExportSceneGraph; + class ExportNode; + class DocumentExporter; + class SkinController; + class MorphController; + class ControllerList; + + /** Base class to export extra tags in max.*/ + + class ControllerExporter : public COLLADA::LibraryControllers + { + + public: + + private: + ExportSceneGraph* mExportSceneGraph; + DocumentExporter* mDocumentExporter; + + public: + /** Constructor + @param streamWriter the stream the extra tags should be written to.*/ + ControllerExporter ( COLLADA::StreamWriter * streamWriter, ExportSceneGraph * exportSceneGraph, DocumentExporter * documentExporter ); + + /** Destructor*/ + virtual ~ControllerExporter() + {} + + /** Exports all the controllers in the export scene graph.*/ + void doExport(); + + /** Creates an id for the controller, derived from the node id of @a exportNode and the number @a number*/ + static String getControllerId(const ExportNode& exportNode, size_t number, Controller::ControllerType controllerType); + + + private: + + /** Exports all the controllers in @a node and all its child nodes.*/ + void doExport ( ExportNode* exportNode ); + + /** Exports all the controllers in @a controllerList.*/ + void exportControllers( ExportNode* exportNode ); + + /** Exports @a controller.*/ + void exportController( ExportNode* exportNode, Controller* controller, const String& controllerId, const String& controllerSource ); + + /** Exports @a skinController.*/ + void exportSkinController( ExportNode* exportNode, SkinController* skinController, const String& controllerId, const String& skinSource); + + /** Exports @a morphController.*/ + void exportMorphController( ExportNode* exportNode, MorphController* morphController, const String& controllerId, const String& morphSource); + + /** Determines the referenced joints. This is required to export the skeleton elements.*/ + void determineReferencedJoints(ExportNode* exportNode, SkinController* skinController); + + /** Determines the skeleton roots of. */ + static void determineSkeletonRoots( const ExportNodeSet &referencedJoints, ControllerList * controllerList); + + /** Determines if one of the parents of @a joint is in @a jointSet. + @return Returns true if @a joint is in @a jointSet set, otherwise false.*/ + static bool isOneParentInSet(ExportNode *joint, const ExportNodeSet &jointSet); + }; + + +} + + +#endif //__COLLADAMAX_CONTROLLEREXPORTER_H__ + diff --git a/COLLADAMax/include/COLLADAMaxXRefFunctions.h b/COLLADAMax/include/COLLADAMaxXRefFunctions.h new file mode 100644 index 000000000..1c9e7af69 --- /dev/null +++ b/COLLADAMax/include/COLLADAMaxXRefFunctions.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2008 NetAllied Systems GmbH + + This file is part of COLLADAMax. + + Portions of the code are: + Copyright (c) 2005-2007 Feeling Software Inc. + Copyright (c) 2005-2007 Sony Computer Entertainment America + + Based on the 3dsMax COLLADA Tools: + Copyright (c) 2005-2006 Autodesk Media Entertainment + + Licensed under the MIT Open Source License, + for details please see LICENSE file or the website + http://www.opensource.org/licenses/mit-license.php +*/ + + +#ifndef __COLLADAMAX_XREFFUNCTIONS_H__ +#define __COLLADAMAX_XREFFUNCTIONS_H__ + +#include "COLLADAMaxPrerequisites.h" + + +class Animatable; +class Object; +class Mtl; + +namespace COLLADAMax +{ + + /** This class contains static helper functions to handle XRefs*/ + class XRefFunctions + { + public: + + /** Checks, if @a object is a XRef object. + @return True, if @a object is a XRef object, false if not.*/ + static bool isXRefObject(Animatable* object); + + /** Checks, if @a object is a XRef item. + @return True, if @a object is a XRef item, false if not.*/ + static bool isXRefItem(Animatable* object); + + /** Checks, if @a material is a XRef object. + @return True, if @a material is a XRef object, false if not.*/ + static bool isXRefMaterial(Animatable* material); + + static String GetURL(Animatable* xref); + static bool IsXRefCOLLADA(Animatable* xref); + static String GetSourceName(Animatable* xref); + + /** Recursively resolves the XRef object, i.e. it returns the object that is referenced. + @return The resolved object. It is garanteed to be not an Xref object.*/ + static Object* getXRefObjectSource(Object* xRefObject, Tab< Modifier * > * modifiers = 0); + + /** Recursively resolves the XRef object, i.e. it returns the object that is referenced. + @return The resolved object. It is garanteed to be not an Xref object.*/ + static IDerivedObject* getXRefItemSource(Object* xRefObject); + + /** Recursively resolves the XRef material, i.e. it returns the object that is referenced. + @return The resolved material. It is garanteed to be not an Xref material.*/ + static Mtl* getXRefMaterialSource(Mtl* xRefMaterial); + + static String GetXRefObjectName(Object* xref); + + }; + + +} + + +#endif //__COLLADAMAX_XREFFUNCTIONS_H__ + diff --git a/COLLADAMax/include/COLLADAMaxXRefIncludes.h b/COLLADAMax/include/COLLADAMaxXRefIncludes.h new file mode 100644 index 000000000..073745c96 --- /dev/null +++ b/COLLADAMax/include/COLLADAMaxXRefIncludes.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2008 NetAllied Systems GmbH + + This file is part of COLLADAMax. + + Portions of the code are: + Copyright (c) 2005-2007 Feeling Software Inc. + Copyright (c) 2005-2007 Sony Computer Entertainment America + + Based on the 3dsMax COLLADA Tools: + Copyright (c) 2005-2006 Autodesk Media Entertainment + + Licensed under the MIT Open Source License, + for details please see LICENSE file or the website + http://www.opensource.org/licenses/mit-license.php +*/ + + +#ifndef __COLLADAMAX_XREFINCLUDE_H__ +#define __COLLADAMAX_XREFINCLUDE_H__ + +#include "COLLADAMaxPrerequisites.h" + + +#ifdef MAX_8_OR_NEWER + +#pragma warning(disable:4100) +#pragma warning(disable:4238) +#pragma warning(disable:4267) + +#include +#include +#include + +#pragma warning(default:4267) +#pragma warning(default:4238) +#pragma warning(default:4100) + +#else + +#error "This header ahs not been tested with max version prior to Max 8" + +#include + +// re-define a class took from the debug build +class XRefObject_REDEFINITION : public IXRefObject { +public: + TSTR xrefFile; + TSTR xrefObj; + TSTR xrefFileProxy; + TSTR xrefObjProxy; + Object *obj; + DWORD flags; + + // don't care about the rest... +}; + +#endif // MAX_8_OR_NEWER else + + + +#endif //__COLLADAMAX_XREFINCLUDE_H__ + diff --git a/COLLADAMax/res/ColladaMax.rc b/COLLADAMax/res/ColladaMax.rc index 0a17651c0..67cdf6267 100644 --- a/COLLADAMax/res/ColladaMax.rc +++ b/COLLADAMax/res/ColladaMax.rc @@ -49,7 +49,7 @@ BEGIN CONTROL "Bake Matrices",IDC_BAKE_MATRICES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,19,61,10 CONTROL "Relative Paths",IDC_RELATIVE_PATHS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,84,19,62,10 CONTROL "Tangents/Binormals",IDC_GEOM_TANGENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,61,79,10 - CONTROL "XRefs",IDC_GEOM_XREFS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,163,49,69,10 + CONTROL "Include XRefs",IDC_GEOM_XREFS,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,163,49,69,10 CONTROL "Enable export",IDC_ANIM_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,92,59,10 END diff --git a/COLLADAMax/scripts/COLLADAMax.vcproj b/COLLADAMax/scripts/COLLADAMax.vcproj index e1cf4f54a..b48fa54c4 100644 --- a/COLLADAMax/scripts/COLLADAMax.vcproj +++ b/COLLADAMax/scripts/COLLADAMax.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\include;..\..\COLLADAStreamWriter\include;"$(MAX_SDK_PATH9)/include";..\res" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MAX_9" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL" MinimalRebuild="false" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -126,7 +126,7 @@ Optimization="3" FavorSizeOrSpeed="1" AdditionalIncludeDirectories="..\include;..\..\COLLADAStreamWriter\include;"$(MAX_SDK_PATH9)/include";..\res" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;Max_9" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL" BasicRuntimeChecks="0" RuntimeLibrary="2" BufferSecurityCheck="false" @@ -210,7 +210,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\include;..\res;..\..\COLLADAStreamWriter\include;"$(MAX_SDK_PATH2009)/include";$(NOINHERIT)" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MAX_2009" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL" MinimalRebuild="false" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -296,7 +296,7 @@ Optimization="3" FavorSizeOrSpeed="1" AdditionalIncludeDirectories="..\include;..\res;..\..\COLLADAStreamWriter\include;"$(MAX_SDK_PATH2009)/include"" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MAX_2009" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL" BasicRuntimeChecks="0" RuntimeLibrary="2" BufferSecurityCheck="false" @@ -382,7 +382,7 @@ Optimization="3" FavorSizeOrSpeed="1" AdditionalIncludeDirectories="..\include;..\res;..\..\COLLADAStreamWriter\include;"$(MAX_SDK_PATH2008)/include"" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MAX_2008" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL" BasicRuntimeChecks="0" RuntimeLibrary="2" BufferSecurityCheck="false" @@ -466,7 +466,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\include;..\res;..\..\COLLADAStreamWriter\include;"$(MAX_SDK_PATH2008)/include"" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MAX_2008" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL" MinimalRebuild="false" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -492,7 +492,7 @@ AdditionalDependencies="COLLADAStreamWriter.lib maxutil.lib core.lib paramblk2.lib geom.lib bmm.lib mesh.lib mnmath.lib" OutputFile="$(OutDir)\$(ProjectName).dle" LinkIncremental="2" - AdditionalLibraryDirectories="..\..\COLLADAStreamWriter\lib\Debug;"$(MAX_SDK_PATH2009)/lib"" + AdditionalLibraryDirectories="..\..\COLLADAStreamWriter\lib\Debug;"$(MAX_SDK_PATH2008)/lib"" GenerateDebugInformation="true" SubSystem="2" TargetMachine="1" @@ -671,6 +671,114 @@ RelativePath="..\src\COLLADAMaxVisualSceneExporter.cpp" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IsAnimated(); + bool animated = isAnimated(controller) || iNode; if ( !animated ) return false; if ( forceFullCheck ) return checkIfIsAnimated(animation); + return animated; } @@ -527,11 +529,21 @@ namespace COLLADAMax //--------------------------------------------------------------- bool AnimationExporter::checkIfIsAnimated ( const Animation& animation ) { - Control* controller = animation.getController(); + Control * controller = animation.getController(); + INode * iNode = animation.getNode(); - bool isSampling = mDocumentExporter->getOptions().getSampleAnimation(); + bool isSampling = !controller || mDocumentExporter->getOptions().getSampleAnimation(); + + IKeyControl * keyInterface = 0; - IKeyControl * keyInterface = GetKeyControlInterface ( controller ); + if (!isSampling) + { + keyInterface = GetKeyControlInterface ( controller ); + if ( !keyInterface ) + isSampling = true; + else if (keyInterface->GetNumKeys() <= 1) + return false; + } if ( !isSampling ) { diff --git a/COLLADAMax/src/COLLADAMaxControllerExporter.cpp b/COLLADAMax/src/COLLADAMaxControllerExporter.cpp index c46e70aa7..cc7142374 100644 --- a/COLLADAMax/src/COLLADAMaxControllerExporter.cpp +++ b/COLLADAMax/src/COLLADAMaxControllerExporter.cpp @@ -220,9 +220,11 @@ namespace COLLADAMax ISkinContextData* contextData = skin->GetContextInterface(iNode); + assert(contextData); + int vertexCount = contextData->GetNumPoints(); - //count weights, excluding the ones that are + //count weights, excluding the ones equals one int weightsCount = 1; for (int i = 0; i < vertexCount; ++i) { diff --git a/COLLADAMax/src/COLLADAMaxControllerList.cpp b/COLLADAMax/src/COLLADAMaxControllerList.cpp index 570a0cd86..0069e1a57 100644 --- a/COLLADAMax/src/COLLADAMaxControllerList.cpp +++ b/COLLADAMax/src/COLLADAMaxControllerList.cpp @@ -21,6 +21,8 @@ #include "COLLADAMaxControllerList.h" #include "COLLADAMaxExportNode.h" +#include "COLLADAMaxXRefFunctions.h" + #include @@ -31,13 +33,20 @@ namespace COLLADAMax //--------------------------------------------------------------- ControllerList::ControllerList(const ExportNode& exportNode) { - Object* object = exportNode.getINode()->GetObjectRef(); - resolveControllers(exportNode, object); + resolveControllers(exportNode); } //--------------------------------------------------------------- - void ControllerList::resolveControllers( const ExportNode& exportNode, Object * object ) + void ControllerList::resolveControllers( const ExportNode& exportNode ) { + Object* object = exportNode.getINode()->GetObjectRef(); + + if ( !object ) + return; + + if ( exportNode.getIsXRefObject() ) + object = XRefFunctions::getXRefItemSource(object); + if ( !object ) return; diff --git a/COLLADAMax/src/COLLADAMaxEffectExporter.cpp b/COLLADAMax/src/COLLADAMaxEffectExporter.cpp index c8ccc3a25..7259b7a3f 100644 --- a/COLLADAMax/src/COLLADAMaxEffectExporter.cpp +++ b/COLLADAMax/src/COLLADAMaxEffectExporter.cpp @@ -25,6 +25,8 @@ #include "COLLADAMaxAnimationExporter.h" #include "COLLADAMaxConversionFunctor.h" +#include "COLLADAMaxXRefFunctions.h" + #include "COLLADANode.h" //#include "COLLADATextureModifier.h" @@ -153,6 +155,24 @@ namespace COLLADAMax //--------------------------------------------------------------- void EffectExporter::exportEffect ( ExportNode* exportNode, Mtl* material ) { + + // check for XRefs + if (XRefFunctions::isXRefMaterial(material)) + { + if ( mDocumentExporter->getOptions().getIncludeXRefs() ) + { + // we don't export XRef materials, but remember them for later use + material = XRefFunctions::getXRefMaterialSource(material); + } + else + { + assert(false); +// xRefedMaterialList.push_back(mat); + return; + } + } + + if ( material->IsMultiMtl() ) { // This material type is used for meshes with multiple materials: @@ -178,23 +198,21 @@ namespace COLLADAMax void EffectExporter::exportSimpleEffect ( ExportNode* exportNode, Mtl* baseMaterial ) { // check if this is not an XRef -#if 0 - if ( XRefFunctions::IsXRefMaterial ( baseMaterial ) ) + if ( XRefFunctions::isXRefMaterial ( baseMaterial ) ) { - if ( OPTS->ExportXRefs() ) + if ( mDocumentExporter->getOptions().getIncludeXRefs() ) { // don't generate the FCDMaterial - return ; + baseMaterial = XRefFunctions::getXRefMaterialSource( baseMaterial ); } else { - baseMaterial = XRefFunctions::GetXRefMaterialSource ( baseMaterial ); + return ; } } -#endif EffectMap::iterator it = mEffectMap.find ( baseMaterial ); diff --git a/COLLADAMax/src/COLLADAMaxExportNode.cpp b/COLLADAMax/src/COLLADAMaxExportNode.cpp index 95916afcc..ef2ed045d 100644 --- a/COLLADAMax/src/COLLADAMaxExportNode.cpp +++ b/COLLADAMax/src/COLLADAMaxExportNode.cpp @@ -21,6 +21,8 @@ #include "COLLADAMaxExportNode.h" #include "COLLADAMaxControllerExporter.h" +#include "COLLADAMaxXRefFunctions.h" + #include #include #include @@ -34,32 +36,22 @@ namespace COLLADAMax : mINode ( iNode ), mParent(parent), mType ( UNDETERMINED ), - mIsJoint(false), - mIsInVisualScene(false), - mIsReferenced(false), + mFlags(NONE), mControllerList(0) - {} + { + determineType(); + } //--------------------------------------------------------------- ExportNode::ExportNode ( INode * iNode, ExportNode* parent , Type type ) : mINode ( iNode ), mParent(parent), mType ( type ), - mIsJoint(false), - mIsInVisualScene(false), - mIsReferenced(false), + mFlags(NONE), mControllerList(0) - {} - - - //--------------------------------------------------------------- - ExportNode::Type ExportNode::getType() const { - if ( mType == UNDETERMINED ) - mType = determineType(); - - return mType; - } + determineType(); + } //--------------------------------------------------------------- @@ -78,19 +70,40 @@ namespace COLLADAMax { Animatable * animatable = iNode->GetObjectRef(); - if ( animatable == 0 ) + if ( !animatable ) return ExportNode::UNKNOWN; Animatable* base = animatable; String gg = iNode->GetName(); - // Modifiers are applied to the object, acquire the base object - while ( base->SuperClassID() == GEN_DERIVOB_CLASS_ID ) - { - IDerivedObject * derivedObject = ( IDerivedObject* ) base; - base = derivedObject->GetObjRef(); - } + + // check for an XRef + if (XRefFunctions::isXRefItem(base)) + { + setIsXRefObject(); + // replace the current animatable by the x-ref object + base = XRefFunctions::getXRefItemSource((Object*)base); + if ( !base ) + return ExportNode::UNKNOWN; + } + else if (XRefFunctions::isXRefMaterial(base)) + { + setIsXRefMaterial(); + base = XRefFunctions::getXRefMaterialSource((Mtl*)base); + if ( !base ) + return ExportNode::UNKNOWN; + } + + + // Modifiers are applied to the object, acquire the base object + while ( base->SuperClassID() == GEN_DERIVOB_CLASS_ID ) + { + IDerivedObject * derivedObject = ( IDerivedObject* ) base; + base = derivedObject->GetObjRef(); + } + + SClass_ID superClassId = base->SuperClassID(); @@ -98,19 +111,16 @@ namespace COLLADAMax switch ( superClassId ) { - case GEOMOBJECT_CLASS_ID: { - //we need this, as soon as we support bones // Check for a Max bone mesh - if ( classId == BONE_OBJ_CLASSID ) return ExportNode::BONE; // Check for biped Control* control = iNode->GetTMController(); - if ( control != NULL ) + if ( control ) { Class_ID controllerClassId = control->ClassID(); @@ -152,16 +162,14 @@ namespace COLLADAMax return MATERIAL; } - - return ExportNode::UNKNOWN; } //--------------------------------------------------------------- - ExportNode::Type ExportNode::determineType() const + void ExportNode::determineType() { - return determineType ( mINode ); + mType = determineType ( mINode ); } @@ -197,13 +205,18 @@ namespace COLLADAMax //--------------------------------------------------------------- Object* ExportNode::getInitialPose() const { + Object* initialPose = 0; + if ( mControllerList ) - { - Object* initialPose = mControllerList->getInitialPose(); - if ( initialPose ) - return initialPose; - } - return mINode->GetObjectRef(); + initialPose = mControllerList->getInitialPose(); + + if ( !initialPose ) + initialPose = mINode->GetObjectRef(); + + if ( getIsXRefObject() ) + return XRefFunctions::getXRefItemSource(initialPose); + else + return initialPose; } diff --git a/COLLADAMax/src/COLLADAMaxExportSceneGraph.cpp b/COLLADAMax/src/COLLADAMaxExportSceneGraph.cpp index bf1c8d58e..45204feb6 100644 --- a/COLLADAMax/src/COLLADAMaxExportSceneGraph.cpp +++ b/COLLADAMax/src/COLLADAMaxExportSceneGraph.cpp @@ -67,8 +67,6 @@ namespace COLLADAMax int numberOfChildren = iNode->NumberOfChildren(); - String name = iNode->GetName(); - for ( int i = 0; i < numberOfChildren; ++i ) { INode * child = iNode->GetChildNode ( i ); @@ -81,21 +79,12 @@ namespace COLLADAMax isInVisualScene = true; } - // if ( exportCurrentNode ) - { + exportNode->setId ( mNodeIdList.addId ( iNode->GetName() ) ); + mINodeExportNodeMap[iNode] = exportNode; + exportNode->createControllerList(); + exportNode->setIsInVisualScene(isInVisualScene); - exportNode->setId ( mNodeIdList.addId ( exportNode->getINode()->GetName() ) ); - mINodeExportNodeMap[iNode] = exportNode; - exportNode->createControllerList(); - exportNode->setIsInVisualScene(isInVisualScene); - return exportNode; - } -/* else - { - delete exportNode; - return 0; - } - */ + return exportNode; } diff --git a/COLLADAMax/src/COLLADAMaxGeometryExporter.cpp b/COLLADAMax/src/COLLADAMaxGeometryExporter.cpp index b77e6acd1..b09ab503a 100644 --- a/COLLADAMax/src/COLLADAMaxGeometryExporter.cpp +++ b/COLLADAMax/src/COLLADAMaxGeometryExporter.cpp @@ -33,6 +33,8 @@ #include "COLLADAMaxMultiMtl.h" +#include "COLLADAMaxXRefFunctions.h" + #include #include @@ -147,6 +149,8 @@ namespace COLLADAMax SClass_ID sid; getBaseObjectAndID ( object, sid ); + TimeValue animationStart = mDocumentExporter->getOptions().getAnimationStart(); + Class_ID id = object->ClassID(); bool exportEPolyAsTriangles = mDocumentExporter->getOptions().getExportEPolyAsTriangles(); @@ -195,7 +199,7 @@ namespace COLLADAMax { if ( object->CanConvertToType ( Class_ID ( TRIOBJ_CLASS_ID, 0 ) ) ) { - mTriObject = ( TriObject* ) object->ConvertToType ( TIME_EXPORT_START, Class_ID ( TRIOBJ_CLASS_ID, 0 ) ); + mTriObject = ( TriObject* ) object->ConvertToType ( animationStart, Class_ID ( TRIOBJ_CLASS_ID, 0 ) ); mDeleteObject = true; } } @@ -204,13 +208,13 @@ namespace COLLADAMax if ( !mTriObject && !exportEPolyAsTriangles && object->CanConvertToType ( Class_ID ( POLYOBJ_CLASS_ID, 0 ) ) ) { - mPolyObject = ( PolyObject* ) object->ConvertToType ( TIME_EXPORT_START, Class_ID ( POLYOBJ_CLASS_ID, 0 ) ); + mPolyObject = ( PolyObject* ) object->ConvertToType ( animationStart, Class_ID ( POLYOBJ_CLASS_ID, 0 ) ); mDeleteObject = true; } if ( !mTriObject && !mPolyObject && object->CanConvertToType ( Class_ID ( TRIOBJ_CLASS_ID, 0 ) ) ) { - mTriObject = ( TriObject* ) object->ConvertToType ( TIME_EXPORT_START, Class_ID ( TRIOBJ_CLASS_ID, 0 ) ); + mTriObject = ( TriObject* ) object->ConvertToType ( animationStart, Class_ID ( TRIOBJ_CLASS_ID, 0 ) ); // ST - Copy over animated vertices, this is not done by default if ( id == EPOLYOBJ_CLASS_ID || id.PartA() == POLYOBJ_CLASS_ID ) @@ -246,8 +250,8 @@ namespace COLLADAMax if ( object->CanConvertToType ( Class_ID ( POLYOBJ_CLASS_ID, 0 ) ) ) { - PolyObject * tempPolyObject = ( PolyObject* ) object->ConvertToType ( TIME_EXPORT_START, Class_ID ( POLYOBJ_CLASS_ID, 0 ) ); - mTriObject = ( TriObject* ) tempPolyObject->ConvertToType ( TIME_EXPORT_START, Class_ID ( TRIOBJ_CLASS_ID, 0 ) ); + PolyObject * tempPolyObject = ( PolyObject* ) object->ConvertToType ( animationStart, Class_ID ( POLYOBJ_CLASS_ID, 0 ) ); + mTriObject = ( TriObject* ) tempPolyObject->ConvertToType ( animationStart, Class_ID ( TRIOBJ_CLASS_ID, 0 ) ); tempPolyObject->DeleteMe(); mDeleteObject = true; } @@ -279,6 +283,10 @@ namespace COLLADAMax else object = mExportNode->getInitialPose(); + + if ( !object ) + return; + if ( object ) { @@ -319,7 +327,7 @@ namespace COLLADAMax mId = GeometriesExporter::getGeometryId(*mExportNode); if ( !mMorphControllerHelperGeometry ) - mDocumentExporter->insertExportedObject(ObjectIdentifier(object), mExportNode); + mDocumentExporter->insertExportedObject(ObjectIdentifier( object ), mExportNode); mGeometriesExporter->openMesh ( mId, COLLADA::Utils::checkNCName ( iNode->GetName() ) ); @@ -461,21 +469,17 @@ namespace COLLADAMax if ( subMaterial ) { - // check for XRefs - /* if (XRefFunctions::IsXRefMaterial(subMaterial)) - { - if (!OPTS->ExportXRefs()) - { - // resolve the source - subMaterial = XRefFunctions::GetXRefMaterialSource(subMaterial); - } - // else do nothing, this is only a material instance - } - */ - // if this is a XRef it'll return NULL + if (XRefFunctions::isXRefMaterial(subMaterial)) + { + if ( mDocumentExporter->getOptions().getIncludeXRefs() ) + { + // resolve the source + subMaterial = XRefFunctions::getXRefMaterialSource(subMaterial); + } + // else do nothing, this is only a material instance + } symbol = mExportNode->getSymbolByMaterialAndSetAsUsed ( subMaterial ); - } else @@ -552,7 +556,7 @@ namespace COLLADAMax if (!OPTS->ExportXRefs()) { // resolve the source - subMaterial = XRefFunctions::GetXRefMaterialSource(subMaterial); + subMaterial = XRefFunctions::getXRefMaterialSource(subMaterial); } // else do nothing, this is only a material instance } @@ -1024,16 +1028,14 @@ namespace COLLADAMax void GeometryExporter::flattenMaterials ( Mtl* material, MaterialList& materialMap, int materialIndex ) { // check for XRefs - /* if (material != NULL && XRefFunctions::IsXRefMaterial(material)) - { - material = XRefFunctions::GetXRefMaterialSource(material); - } - */ - // KEEP THE NULL POINTER! Null pointers are actually allowed in max, and we need to + if ( material && XRefFunctions::isXRefMaterial(material)) + { + material = XRefFunctions::getXRefMaterialSource(material); + } + + // KEEP THE NULL POINTER! Null pointers are actually allowed in max, and we need to // maintain the material list. - Class_ID matId = ( material == NULL ) ? - Class_ID ( STANDIN_CLASS_ID, STANDIN_CLASS_ID ) : - material->ClassID(); + Class_ID matId = !material ? Class_ID ( STANDIN_CLASS_ID, STANDIN_CLASS_ID ) : material->ClassID(); if ( matId == Class_ID ( MULTI_CLASS_ID, 0 ) ) { diff --git a/COLLADAMax/src/COLLADAMaxMaterialExporter.cpp b/COLLADAMax/src/COLLADAMaxMaterialExporter.cpp index a8f0d8e73..55cac3e4d 100644 --- a/COLLADAMax/src/COLLADAMaxMaterialExporter.cpp +++ b/COLLADAMax/src/COLLADAMaxMaterialExporter.cpp @@ -96,11 +96,11 @@ namespace COLLADAMax Mtl* MaterialExporter::GetSubMaterialById ( Mtl* mtl, int materialId ) { if ( !mtl->IsMultiMtl() ) - return NULL; + return 0; IParamBlock2* subMaterialParameters = ( IParamBlock2* ) mtl->GetReference ( MultiMaterial::PBLOCK_REF ); - if ( subMaterialParameters == NULL ) + if ( !subMaterialParameters ) return mtl->GetSubMtl ( materialId ); // check if we ever reach this point @@ -110,18 +110,18 @@ namespace COLLADAMax for ( int subMaterialIndex = 0; subMaterialIndex < subMaterialCount; ++subMaterialIndex ) { - int subMatId = subMaterialParameters->GetInt ( MultiMaterial::multi_ids, TIME_EXPORT_START, subMaterialIndex ); + int subMatId = subMaterialParameters->GetInt ( MultiMaterial::multi_ids,0 , subMaterialIndex ); if ( subMatId == materialId ) { Mtl * material = mtl->GetSubMtl ( subMaterialIndex ); - if ( material != NULL ) + if ( material ) return material; } } - return NULL; + return 0; } } diff --git a/COLLADAMax/src/COLLADAMaxOptions.cpp b/COLLADAMax/src/COLLADAMaxOptions.cpp index 136f6ab0e..2ca1c72d1 100644 --- a/COLLADAMax/src/COLLADAMaxOptions.cpp +++ b/COLLADAMax/src/COLLADAMaxOptions.cpp @@ -86,7 +86,7 @@ namespace COLLADAMax // Set the option values to their default mNormals(true), mTriangulate(true), - mXrefs(true), + mIncludeXrefs(true), mTangents(false), mAnimations(true), mSampleAnimation(false), @@ -153,7 +153,7 @@ namespace COLLADAMax // setup checkboxes CheckDlgButton(hWnd, IDC_GEOM_NORMALS, mNormals); CheckDlgButton(hWnd, IDC_GEOM_TRIANGLES, mTriangulate); - CheckDlgButton(hWnd, IDC_GEOM_XREFS, mXrefs); + CheckDlgButton(hWnd, IDC_GEOM_XREFS, mIncludeXrefs); CheckDlgButton(hWnd, IDC_GEOM_TANGENTS, mTangents); CheckDlgButton(hWnd, IDC_ANIM_ENABLE, mAnimations); CheckDlgButton(hWnd, IDC_ANIM_SAMPLE, mSampleAnimation); @@ -230,7 +230,7 @@ namespace COLLADAMax mCreateClip = IsDlgButtonChecked(hWnd, IDC_ANIM_CLIP) == BST_CHECKED; mNormals = IsDlgButtonChecked(hWnd, IDC_GEOM_NORMALS) == BST_CHECKED; mTriangulate = IsDlgButtonChecked(hWnd, IDC_GEOM_TRIANGLES) == BST_CHECKED; - mXrefs = IsDlgButtonChecked(hWnd, IDC_GEOM_XREFS) == BST_CHECKED; + mIncludeXrefs = IsDlgButtonChecked(hWnd, IDC_GEOM_XREFS) == BST_CHECKED; mTangents = IsDlgButtonChecked(hWnd, IDC_GEOM_TANGENTS) == BST_CHECKED; spin = GetISpinner(GetDlgItem(hWnd, IDC_ANIM_START_SPIN)); @@ -294,7 +294,7 @@ namespace COLLADAMax writeOption(file, OPTION_NORMALS_NAME, mNormals ); writeOption(file, OPTION_TRIANGULAT_NAME, mTriangulate ); - writeOption(file, OPTION_XREFS_NAME, mXrefs ); + writeOption(file, OPTION_XREFS_NAME, mIncludeXrefs ); writeOption(file, OPTION_TANGENTS_NAME, mTangents ); writeOption(file, OPTION_ANIMATIONS_NAME, mAnimations ); writeOption(file, OPTION_SAMPLEANIMATIONS_NAME, mSampleAnimation ); @@ -350,7 +350,7 @@ namespace COLLADAMax // Look for/read in the ColladaMax options. readOption(token, OPTION_NORMALS_NAME, value, mNormals) || readOption(token, OPTION_TRIANGULAT_NAME, value, mTriangulate) || - readOption(token, OPTION_XREFS_NAME, value, mXrefs) || + readOption(token, OPTION_XREFS_NAME, value, mIncludeXrefs) || readOption(token, OPTION_TRIANGULAT_NAME, value, mTangents) || readOption(token, OPTION_SAMPLEANIMATIONS_NAME, value, mSampleAnimation) || readOption(token, OPTION_ANIMATIONS_NAME, value, mAnimations) || diff --git a/COLLADAMax/src/COLLADAMaxXRefExporter.cpp b/COLLADAMax/src/COLLADAMaxXRefExporter.cpp new file mode 100644 index 000000000..434f3c574 --- /dev/null +++ b/COLLADAMax/src/COLLADAMaxXRefExporter.cpp @@ -0,0 +1,35 @@ +/* + Copyright (c) 2008 NetAllied Systems GmbH + + This file is part of COLLADAMax. + + Portions of the code are: + Copyright (c) 2005-2007 Feeling Software Inc. + Copyright (c) 2005-2007 Sony Computer Entertainment America + + Based on the 3dsMax COLLADA Tools: + Copyright (c) 2005-2006 Autodesk Media Entertainment + + Licensed under the MIT Open Source License, + for details please see LICENSE file or the website + http://www.opensource.org/licenses/mit-license.php +*/ + + +#include "ColladaMaxStableHeaders.h" + +#include "COLLADAMaxXRefExporter.h" +namespace COLLADAMax +{ + + + //--------------------------------------------------------------- + XRefExporter::XRefExporter ( COLLADA::StreamWriter * streamWriter, ExportSceneGraph * exportSceneGraph, DocumentExporter * documentExporter ) + : COLLADA::LibraryControllers ( streamWriter ), + mExportSceneGraph(exportSceneGraph), + mDocumentExporter(documentExporter) + {} + + + +} diff --git a/COLLADAMax/src/COLLADAMaxXRefFile.cpp b/COLLADAMax/src/COLLADAMaxXRefFile.cpp new file mode 100644 index 000000000..c46e70aa7 --- /dev/null +++ b/COLLADAMax/src/COLLADAMaxXRefFile.cpp @@ -0,0 +1,468 @@ +/* + Copyright (c) 2008 NetAllied Systems GmbH + + This file is part of COLLADAMax. + + Portions of the code are: + Copyright (c) 2005-2007 Feeling Software Inc. + Copyright (c) 2005-2007 Sony Computer Entertainment America + + Based on the 3dsMax COLLADA Tools: + Copyright (c) 2005-2006 Autodesk Media Entertainment + + Licensed under the MIT Open Source License, + for details please see LICENSE file or the website + http://www.opensource.org/licenses/mit-license.php +*/ + + +#include "ColladaMaxStableHeaders.h" + +#include "COLLADAMaxControllerExporter.h" +#include "COLLADAMaxGeometriesExporter.h" +#include "COLLADAMaxVisualSceneExporter.h" +#include "COLLADAMaxAnimationExporter.h" +#include "COLLADAMaxTypes.h" +#include "COLLADAMaxConversionFunctor.h" + +#include "COLLADASource.h" +#include "COLLADABaseInputElement.h" +#include "COLLADAPrimitves.h" +#include "COLLADAURI.h" + +#include +#include +#include "MorphR3.h" + +namespace COLLADAMax +{ + + + //--------------------------------------------------------------- + ControllerExporter::ControllerExporter ( COLLADA::StreamWriter * streamWriter, ExportSceneGraph * exportSceneGraph, DocumentExporter * documentExporter ) + : COLLADA::LibraryControllers ( streamWriter ), + mExportSceneGraph(exportSceneGraph), + mDocumentExporter(documentExporter) + {} + + + //--------------------------------------------------------------- + COLLADA::String ControllerExporter::getControllerId( const ExportNode& exportNode, size_t number, Controller::ControllerType controllerType ) + { + switch ( controllerType ) + { + case Controller::SKIN: + return GeometriesExporter::getGeometryId(exportNode) + LibraryControllers::SKIN_CONTROLLER_ID_SUFFIX + COLLADA::Utils::toString(number); + case Controller::MORPH: + return GeometriesExporter::getGeometryId(exportNode) + LibraryControllers::MORPH_CONTROLLER_ID_SUFFIX + COLLADA::Utils::toString(number); + } + return EMPTY_STRING; + } + + + //--------------------------------------------------------------- + void ControllerExporter::doExport() + { + doExport ( mExportSceneGraph->getRootExportNode() ); + closeLibrary(); + } + + + + //--------------------------------------------------------------- + void ControllerExporter::doExport( ExportNode* exportNode ) + { + if ( !exportNode->getIsInVisualScene() ) + return; + + exportControllers(exportNode); + + size_t numberOfChildren = exportNode->getNumberOfChildren(); + for ( size_t i = 0; i < numberOfChildren; ++i ) + doExport ( exportNode->getChild ( i ) ); + } + + //--------------------------------------------------------------- + void ControllerExporter::exportControllers( ExportNode* exportNode ) + { + ControllerList* controllerList = exportNode->getControllerList(); + + if ( !controllerList->hasControllers() ) + return; + + size_t controllerCount = controllerList->getControllerCount(); + for ( size_t j = 0; j < controllerCount; ++j) + { + size_t i = controllerCount - j - 1; + + Controller* controller = controllerList->getController(i); + + ObjectIdentifier poseAfter(controller->getDerivedObject(), (int)i); + + if ( mDocumentExporter->isExportedObject(poseAfter) ) + { + if ( controller->getType() == Controller::SKIN ) + determineReferencedJoints(exportNode, (SkinController*)controller); + continue; + } + + String controllerId = getControllerId(*exportNode, controllerCount - i, controller->getType()); + String controllerSource; + if ( i < controllerCount - 1) + { + ExportNode* previousControllerExportNode = mDocumentExporter->getExportedObjectExportNode(ObjectIdentifier(controllerList->getController(i+1)->getDerivedObject(), (int)i+1)); + assert( previousControllerExportNode ); + controllerSource = '#' + getControllerId(*previousControllerExportNode, controllerCount - i - 1, controllerList->getController(i+1)->getType()); + } + else + { + ExportNode* geometryExportNode = mDocumentExporter->getExportedObjectExportNode(ObjectIdentifier(exportNode->getInitialPose())); + assert( geometryExportNode ); + controllerSource = '#' + GeometriesExporter::getGeometryId(*geometryExportNode); + } + exportController(exportNode, controller, controllerId, controllerSource); + mDocumentExporter->insertExportedObject(poseAfter, exportNode); + } + } + + + //--------------------------------------------------------------- + void ControllerExporter::exportController( ExportNode* exportNode, Controller* controller, const String& controllerId, const String& controllerSource ) + { + if ( controller->getControllerType() == Controller::SKIN ) + exportSkinController(exportNode, (SkinController*)controller, controllerId, controllerSource); + else if ( controller->getControllerType() == Controller::MORPH ) + exportMorphController(exportNode, (MorphController*)controller, controllerId, controllerSource); + + closeController(); + } + + + //--------------------------------------------------------------- + void ControllerExporter::exportSkinController( ExportNode* exportNode, SkinController* skinController, const String& controllerId, const String& skinSource ) + { + ISkin* skin = skinController->getSkin(); + + if ( !skin ) + return; + + openSkin(controllerId, skinSource); + + INode* iNode = exportNode->getINode(); + + Matrix3 bindShapeTransformationMatrix; + skin->GetSkinInitTM(iNode, bindShapeTransformationMatrix, true); + double bindShapeTransformationArray[4][4]; + VisualSceneExporter::matrix3ToDouble4x4(bindShapeTransformationArray, bindShapeTransformationMatrix); + + addBindShapeTransform(bindShapeTransformationArray); + + int jointCount = skin->GetNumBones(); + INodeList boneINodes; + + + // Export joints source + String jointsId = controllerId + JOINTS_SOURCE_ID_SUFFIX; + COLLADA::NameSource jointSource(mSW); + jointSource.setId(jointsId); + jointSource.setArrayId(jointsId + ARRAY_ID_SUFFIX); + jointSource.setAccessorStride(1); + jointSource.getParameterNameList().push_back("JOINT"); + jointSource.setAccessorCount(jointCount); + jointSource.prepareToAppendValues(); + + for (int i = 0; i < jointCount; ++i) + { + // there should not be any null bone. + // the ISkin::GetBone, not GetBoneFlat, function is called here. + INode* boneNode = skin->GetBone(i); + assert(boneNode); + boneINodes.push_back(boneNode); + + ExportNode* jointExportNode = mExportSceneGraph->getExportNode(boneNode); + assert(jointExportNode); + + if ( !jointExportNode->hasSid() ) + jointExportNode->setSid(mExportSceneGraph->createJointSid()); + + jointExportNode->setIsJoint(); + + jointSource.appendValues(jointExportNode->getSid()); + } + jointSource.finish(); + + determineReferencedJoints(exportNode, skinController); + + //export inverse bind matrix source + String inverseBindMatrixId = controllerId + BIND_POSES_SOURCE_ID_SUFFIX; + COLLADA::Float4x4Source inverseBindMatrixSource(mSW); + inverseBindMatrixSource.setId(inverseBindMatrixId); + inverseBindMatrixSource.setArrayId(inverseBindMatrixId + ARRAY_ID_SUFFIX); + inverseBindMatrixSource.setAccessorStride(16); + inverseBindMatrixSource.getParameterNameList().push_back("TRANSFORM"); + inverseBindMatrixSource.setAccessorCount(jointCount); + inverseBindMatrixSource.prepareToAppendValues(); + + for (int i = 0; i < jointCount; ++i) + { + INode* boneNode = boneINodes[i]; + + Matrix3 bindPose; + int success = skin->GetBoneInitTM(boneNode, bindPose); + assert(success == SKIN_OK); + bindPose.Invert(); + + double bindPoseArray[4][4]; + VisualSceneExporter::matrix3ToDouble4x4(bindPoseArray, bindPose); + inverseBindMatrixSource.appendValues(bindPoseArray); + } + inverseBindMatrixSource.finish(); + + + ISkinContextData* contextData = skin->GetContextInterface(iNode); + int vertexCount = contextData->GetNumPoints(); + + //count weights, excluding the ones that are + int weightsCount = 1; + for (int i = 0; i < vertexCount; ++i) + { + int jointCount = contextData->GetNumAssignedBones(i); + for (int p = 0; p < jointCount; ++p) + { + float weight = contextData->GetBoneWeight(i, p); + if ( !COLLADA::MathUtils::equals(weight, 1.0f) ) + weightsCount++; + } + } + + //export weights source + String weightsId = controllerId + WEIGHTS_SOURCE_ID_SUFFIX; + COLLADA::FloatSource weightsSource(mSW); + weightsSource.setId(weightsId); + weightsSource.setArrayId(weightsId + ARRAY_ID_SUFFIX); + weightsSource.setAccessorStride(1); + weightsSource.getParameterNameList().push_back("WEIGHT"); + weightsSource.setAccessorCount(weightsCount); + weightsSource.prepareToAppendValues(); + + weightsSource.appendValues(1.0); + for (int i = 0; i < vertexCount; ++i) + { + int jointCount = contextData->GetNumAssignedBones(i); + for (int p = 0; p < jointCount; ++p) + { + float weight = contextData->GetBoneWeight(i, p); + if ( !COLLADA::MathUtils::equals(weight, 1.0f) ) + weightsSource.appendValues(weight); + } + } + weightsSource.finish(); + + COLLADA::JointsElement joints(mSW); + joints.getInputList().push_back(COLLADA::Input(COLLADA::JOINT, "#" + jointsId)); + joints.getInputList().push_back(COLLADA::Input(COLLADA::BINDMATRIX, "#" + inverseBindMatrixId)); + joints.add(); + + COLLADA::VertexWeightsElement vertexWeights(mSW); + COLLADA::Input weightInput(COLLADA::WEIGHT, "#" + weightsId); + vertexWeights.getInputList().push_back(COLLADA::Input(COLLADA::JOINT, "#" + jointsId, 0)); + vertexWeights.getInputList().push_back(COLLADA::Input(COLLADA::WEIGHT, "#" + weightsId, 1)); + vertexWeights.setCount(vertexCount); + + vertexWeights.prepareToAppendVCountValues(); + + for (int i = 0; i < vertexCount; ++i) + vertexWeights.appendValues(contextData->GetNumAssignedBones(i)); + + vertexWeights.CloseVCountAndOpenVElement(); + + int currentIndex = 1; + for (int i = 0; i < vertexCount; ++i) + { + int jointCount = contextData->GetNumAssignedBones(i); + for (int p = 0; p < jointCount; ++p) + { + vertexWeights.appendValues(contextData->GetAssignedBone(i, p)); + float weight = contextData->GetBoneWeight(i, p); + if ( !COLLADA::MathUtils::equals(weight, 1.0f) ) + { + vertexWeights.appendValues(currentIndex++); + } + else + { + vertexWeights.appendValues(0); + } + } + } + + + + vertexWeights.finish(); + + +#if 0 + int vertexCount = iskin->GetNumVertices(); + colladaSkin->SetInfluenceCount(vertexCount); + for (int i = 0; i < vertexCount; ++i) + { + FCDSkinControllerVertex* vertex = colladaSkin->GetVertexInfluence(i); + int pairCount = iskin->GetNumAssignedBones(i); + vertex->SetPairCount(pairCount); + for (int p = 0; p < pairCount; ++p) + { + FCDJointWeightPair* pair = vertex->GetPair(p); + pair->weight = iskin->GetBoneWeight(i, p); + pair->jointIndex = iskin->GetAssignedBone(i, p); + } + } + + +#endif + closeSkin(); + } + + + //--------------------------------------------------------------- + void ControllerExporter::exportMorphController( ExportNode* exportNode, MorphController* morphController, const String& controllerId, const String& morphSource ) + { + MorphR3* morpher = morphController->getMorph(); + + + FloatList listOfWeights; + StringList listOfTargetIds; + + String weightsId = controllerId + WEIGHTS_SOURCE_ID_SUFFIX; + + size_t channelBankCount = morpher->chanBank.size(); + for ( size_t i = 0; ichanBank[i]; + + if (!channel.mActive || channel.mNumPoints == 0) + continue; + + INode* targetINode = channel.mConnection; + + listOfWeights.push_back(ConversionFunctors::fromPercent(channel.cblock->GetFloat(morphChannel::cblock_weight_index, mDocumentExporter->getOptions().getAnimationStart()))); + + Control* weightController = channel.cblock->GetController(morphChannel::cblock_weight_index); + mDocumentExporter->getAnimationExporter()->addAnimatedFloat(weightController, weightsId, EMPTY_STRING, (int)i, true, &ConversionFunctors::fromPercent ); + + if ( !targetINode ) + { + MorphControllerHelperGeometry morphControllerHelperGeometry; + morphControllerHelperGeometry.exportNode = exportNode; + morphControllerHelperGeometry.controllerId = controllerId; + morphControllerHelperGeometry.morphController = morphController; + morphControllerHelperGeometry.channelBankindex = i; + + String targetId = ExportSceneGraph::getMorphControllerHelperId(morphControllerHelperGeometry); + listOfTargetIds.push_back(targetId); + } + else + { + ExportNode* targetExportNode = mExportSceneGraph->getExportNode(targetINode); + assert(targetExportNode); + + ExportNode* geometryExportNode = mDocumentExporter->getExportedObjectExportNode(ObjectIdentifier(targetExportNode->getInitialPose())); + assert( geometryExportNode ); +// listOfTargetIds.push_back(geometryExportNode); + listOfTargetIds.push_back(GeometriesExporter::getGeometryId(*geometryExportNode)); + } + } + + openMorph(controllerId, EMPTY_STRING, morphSource); + + //export weights source + String targetId = controllerId + TARGETS_SOURCE_ID_SUFFIX; + COLLADA::IdRefSource targetsSource(mSW); + targetsSource.setId(targetId); + targetsSource.setArrayId(targetId + ARRAY_ID_SUFFIX); + targetsSource.setAccessorStride(1); + targetsSource.getParameterNameList().push_back("MORPH_TARGET"); + targetsSource.setAccessorCount((unsigned long)listOfTargetIds.size()); + targetsSource.prepareToAppendValues(); + + for ( StringList::const_iterator it = listOfTargetIds.begin(); it != listOfTargetIds.end(); ++it) + targetsSource.appendValues(*it); + + targetsSource.finish(); + + + //export weights source + COLLADA::FloatSource weightsSource(mSW); + weightsSource.setId(weightsId); + weightsSource.setArrayId(weightsId + ARRAY_ID_SUFFIX); + weightsSource.setAccessorStride(1); + weightsSource.getParameterNameList().push_back("MORPH_WEIGHT"); + weightsSource.setAccessorCount((unsigned long)listOfWeights.size()); + weightsSource.prepareToAppendValues(); + + for ( FloatList::const_iterator it = listOfWeights.begin(); it != listOfWeights.end(); ++it) + weightsSource.appendValues(*it); + + weightsSource.finish(); + + + COLLADA::TargetsElement targets(mSW); + targets.getInputList().push_back(COLLADA::Input(COLLADA::MORPH_TARGET, "#" + targetId)); + targets.getInputList().push_back(COLLADA::Input(COLLADA::MORPH_WEIGHT, "#" + weightsId)); + targets.add(); + + closeMorph(); + + } + + + void ControllerExporter::determineReferencedJoints(ExportNode* exportNode, SkinController* skinController) + { + ISkin* skin = skinController->getSkin(); + + int jointCount = skin->GetNumBones(); + + ExportNodeSet referencedJoints; + + for (int i = 0; i < jointCount; ++i) + { + // there should not be any null bone. + // the ISkin::GetBone, not GetBoneFlat, function is called here. + INode* boneNode = skin->GetBone(i); + assert(boneNode); + + ExportNode* jointExportNode = mExportSceneGraph->getExportNode(boneNode); + assert(jointExportNode); + + referencedJoints.insert(jointExportNode); + } + + determineSkeletonRoots(referencedJoints, exportNode->getControllerList()); + } + + + + //--------------------------------------------------------------- + void ControllerExporter::determineSkeletonRoots( const ExportNodeSet &referencedJoints, ControllerList * controllerList) + { + for ( ExportNodeSet::const_iterator it = referencedJoints.begin(); it!=referencedJoints.end(); ++it) + { + ExportNode* joint = *it; + if ( !isOneParentInSet(joint, referencedJoints) ) + controllerList->addReferencedJoint(joint); + } + } + + //--------------------------------------------------------------- + bool ControllerExporter::isOneParentInSet( ExportNode *joint, const ExportNodeSet &jointSet ) + { + ExportNode* parentNode = joint->getParent(); + + if ( !parentNode ) + return false; + + if ( jointSet.count(parentNode) != 0 ) + return true; + + return isOneParentInSet(parentNode, jointSet); + } + +} diff --git a/COLLADAMax/src/COLLADAMaxXRefFunctions.cpp b/COLLADAMax/src/COLLADAMaxXRefFunctions.cpp new file mode 100644 index 000000000..0a37530ce --- /dev/null +++ b/COLLADAMax/src/COLLADAMaxXRefFunctions.cpp @@ -0,0 +1,237 @@ +/* + Copyright (c) 2008 NetAllied Systems GmbH + + This file is part of COLLADAMax. + + Portions of the code are: + Copyright (c) 2005-2007 Feeling Software Inc. + Copyright (c) 2005-2007 Sony Computer Entertainment America + + Based on the 3dsMax COLLADA Tools: + Copyright (c) 2005-2006 Autodesk Media Entertainment + + Licensed under the MIT Open Source License, + for details please see LICENSE file or the website + http://www.opensource.org/licenses/mit-license.php +*/ + + +#include "ColladaMaxStableHeaders.h" + +#include "COLLADAMaxXRefFunctions.h" + +#include +#include "COLLADAMaxXRefIncludes.h" + +namespace COLLADAMax +{ + + //--------------------------------------------------------------- + bool XRefFunctions::isXRefObject(Animatable* object) + { +#ifdef MAX_8_OR_NEWER + return IXRefObject8::Is_IXRefObject8(* object); +#else + return (object->SuperClassID() == SYSTEM_CLASS_ID && object->ClassID().PartA() == XREFOBJ_CLASS_ID); +#endif + } + + + //--------------------------------------------------------------- + bool XRefFunctions::isXRefItem(Animatable* object) + { +#ifdef MAX_8_OR_NEWER + return IXRefItem::IsIXRefItem(* object); +#else + +#endif + } + + + //--------------------------------------------------------------- + bool XRefFunctions::isXRefMaterial(Animatable* material) + { +#ifdef MAX_8_OR_NEWER + return IXRefMaterial::Is_IXRefMaterial(*material); +#else + // not supported + (void)material; + return false; +#endif + } + +#if 0 + //--------------------------------------------------------------- + fstring XRefFunctions::GetURL(Animatable* xref) + { + if (!IsXRefObject(xref) && !IsXRefMaterial(xref)) return FS(""); + + fstring maxUrl; +#ifdef USE_MAX_8 + { + IXRefItem* x = IXRefItem::GetInterface(*xref); + maxUrl = (x != NULL) ? x->GetSrcFileName() : emptyFString; + } +#elif USE_MAX_7 + { + IXRefObject* x = (IXRefObject*) xref; + maxUrl = TO_FSTRING(x->GetFileName(FALSE).data()); + } +#endif + + size_t xrefTokenIndex = maxUrl.find(FC(".xreffile")); + if (xrefTokenIndex != fstring::npos) + { + // Remove the ".xreffile.max" suffix. The old extension should still be there. + maxUrl.erase(xrefTokenIndex); + } + + // Replace the extension by .dae + return maxUrl; + } +#endif + +#if 0 + //--------------------------------------------------------------- + bool XRefFunctions::IsXRefCOLLADA(Animatable* xref) + { + // Not performant, but the simplest method is to look at the extension of the filename. + FUUri uri(XRefFunctions::GetURL(xref)); + fstring extension = FUFileManager::GetFileExtension(uri.GetPath()); + return IsEquivalentI(extension, FC("dae")) || IsEquivalentI(extension, FC("xml")); + } +#endif + +#if 0 + //--------------------------------------------------------------- + fm::string XRefFunctions::GetSourceName(Animatable* xref) + { +#if USE_MAX_8 + IXRefItem* x = IXRefItem::GetInterface(* xref); + if (x == NULL) + return ""; + + return fm::string(x->GetSrcItemName()); + +#elif USE_MAX_7 + if (IsXRefObject(xref)) + { + IXRefObject* xobj = (IXRefObject*)xref; + return fm::string(xobj->GetObjName(FALSE).data()); + } + else + { + return "(not xref)"; + } +#endif + } +#endif + + //--------------------------------------------------------------- + Object* XRefFunctions::getXRefObjectSource(Object* xRefObject, Tab< Modifier * > * modifiers) + { + if ( !isXRefObject(xRefObject) ) + return xRefObject; // this is the source +#ifdef MAX_8_OR_NEWER + + IXRefObject8* xRefObjectInterface = IXRefObject8::GetInterface(* xRefObject); + if ( !xRefObjectInterface ) + return 0; + + // resolve nested + Object* source = xRefObjectInterface->GetSourceObject(false, modifiers); + +#else + XRefObject_REDEFINITION* xobj = (XRefObject_REDEFINITION*)xRefObject; + Object* source = xobj->object; + +#endif + return source; + } + + + //--------------------------------------------------------------- + IDerivedObject* XRefFunctions::getXRefItemSource(Object* xRefObject) + { + if ( !isXRefItem(xRefObject) ) + return (IDerivedObject*) xRefObject; // this is the source +#ifdef MAX_8_OR_NEWER + + IXRefItem * xRefObjectInterface = IXRefItem::GetInterface(* xRefObject); + //remove + INodeTab nodes; + xRefObjectInterface->GetNodes(nodes); + int gg = nodes.Count(); + INode* n; + if ( gg > 0) + n = nodes[0]; + + INode* m = n->GetActualINode(); + + INode* bb = xRefObject->GetWorldSpaceObjectNode(); + + if ( !xRefObjectInterface ) + return 0; + + // resolve nested + IDerivedObject* source = (IDerivedObject*) xRefObjectInterface->GetSrcItem(false); + + INode* bb1 = source->GetWorldSpaceObjectNode(); + + + int hh = 5; + +#else + +#endif + return source; + } + + + +#if 0 + //--------------------------------------------------------------- + fm::string XRefFunctions::GetXRefObjectName(Object* xref) + { + if (!IsXRefObject(xref)) return emptyString; // this is the source +#if USE_MAX_8 + + IXRefObject8* xobj = IXRefObject8::GetInterface(*xref); + if (xobj == NULL) return emptyString; + IXRefItem* item = IXRefItem::GetInterface(*xref); + if (item == NULL) return emptyString; + return item->GetSrcItemName(); +#elif USE_MAX_7 + + XRefObject_REDEFINITION* xobj = (XRefObject_REDEFINITION*)xref; + return xobj->xrefObj.data(); +#endif + } +#endif + + //--------------------------------------------------------------- + Mtl* XRefFunctions::getXRefMaterialSource(Mtl* xRefMaterial) + { +#ifdef MAX_8_OR_NEWER + + if (!isXRefMaterial(xRefMaterial)) + { + // this is the source + return xRefMaterial; + } + + IXRefMaterial* xRefMaterialInterface = IXRefMaterial::GetInterface(* xRefMaterial); + if ( !xRefMaterialInterface ) + return 0; + + // resolve nested + Mtl* source = xRefMaterialInterface->GetSourceMaterial(true); + return source; + +#else + // not supported in Max 7 + return xRefMaterial; +#endif + } + +}