Prechádzať zdrojové kódy

Merge branch 'master' of https://github.com/assimp/assimp

Alexander Gessler 10 rokov pred
rodič
commit
a1268bf864

+ 3 - 1
CREDITS

@@ -153,6 +153,8 @@ Ogre Binary format support
 Android JNI asset extraction support
 
 - Richard Steffen
-Contributed X File exporter
 Contributed ExportProperties interface
+Contributed X File exporter
+Contributed Step (stp) exporter
+
 

+ 74 - 124
code/CMakeLists.txt

@@ -157,7 +157,27 @@ IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
 	SOURCE_GROUP( C4D FILES ${C4D_SRCS})
 ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
 
-SET( 3DS_SRCS
+# macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
+# this way selective loaders can be compiled (reduces filesize + compile time)
+MACRO(ADD_ASSIMP_IMPORTER name)
+	OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" TRUE)
+	IF(ASSIMP_BUILD_${name}_IMPORTER)
+		LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
+		SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
+		SET(${name}_SRCS ${ARGN})
+		SOURCE_GROUP(${name} FILES ${ARGN})
+	ELSE()
+		SET(${name}_SRC "")
+		SET(ASSIMP_IMPORTERS_DISABLED "${ASSIMP_IMPORTERS_DISABLED} ${name}")
+		add_definitions(-DASSIMP_BUILD_NO_${name}_IMPORTER)
+	ENDIF()
+ENDMACRO()
+
+SET(ASSIMP_LOADER_SRCS "")
+SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers
+SET(ASSIMP_IMPORTERS_DISABLED "") # disabled list (used to print)
+
+ADD_ASSIMP_IMPORTER(3DS
 	3DSConverter.cpp
 	3DSHelper.h
 	3DSLoader.cpp
@@ -165,49 +185,42 @@ SET( 3DS_SRCS
 	3DSExporter.h
 	3DSExporter.cpp
 )
-SOURCE_GROUP(3DS FILES ${3DS_SRCS})
 
-SET( AC_SRCS
+ADD_ASSIMP_IMPORTER(AC
 	ACLoader.cpp
 	ACLoader.h
 )
-SOURCE_GROUP( AC FILES ${AC_SRCS})
 
-SET( ASE_SRCS
+ADD_ASSIMP_IMPORTER(ASE
 	ASELoader.cpp
 	ASELoader.h
 	ASEParser.cpp
 	ASEParser.h
 )
-SOURCE_GROUP( ASE FILES ${ASE_SRCS})
 
-SET( ASSBIN_SRCS
+ADD_ASSIMP_IMPORTER(ASSBIN
 	AssbinExporter.h
 	AssbinExporter.cpp
 	AssbinLoader.h
 	AssbinLoader.cpp
 )
-SOURCE_GROUP( Assbin FILES ${ASSBIN_SRCS})
 
-SET( ASSXML_SRCS
+ADD_ASSIMP_IMPORTER(ASSXML
 	AssxmlExporter.h
 	AssxmlExporter.cpp
 )
-SOURCE_GROUP( Assxml FILES ${ASSXML_SRCS})
 
-SET( B3D_SRCS
+ADD_ASSIMP_IMPORTER(B3D
 	B3DImporter.cpp
 	B3DImporter.h
 )
-SOURCE_GROUP( B3D FILES ${B3D_SRCS})
 
-SET( BVH_SRCS
+ADD_ASSIMP_IMPORTER(BVH
 	BVHLoader.cpp
 	BVHLoader.h
 )
-SOURCE_GROUP( BVH FILES ${BVH_SRCS})
 
-SET( Collada_SRCS
+ADD_ASSIMP_IMPORTER(COLLADA
 	ColladaHelper.h
 	ColladaLoader.cpp
 	ColladaLoader.h
@@ -216,30 +229,27 @@ SET( Collada_SRCS
 	ColladaExporter.h
 	ColladaExporter.cpp
 )
-SOURCE_GROUP( Collada FILES ${Collada_SRCS})
 
-SET( DXF_SRCS
+ADD_ASSIMP_IMPORTER(DXF
 	DXFLoader.cpp
 	DXFLoader.h
 	DXFHelper.h
 )
-SOURCE_GROUP( DXF FILES ${DXF_SRCS})
 
-SET( CSM_SRCS
+ADD_ASSIMP_IMPORTER(CSM
 	CSMLoader.cpp
 	CSMLoader.h
 )
-SOURCE_GROUP( CSM FILES ${CSM_SRCS})
 
-SET( HMP_SRCS
+ADD_ASSIMP_IMPORTER(HMP
 	HMPFileData.h
 	HMPLoader.cpp
 	HMPLoader.h
 	HalfLifeFileData.h
 )
-SOURCE_GROUP( HMP FILES ${HMP_SRCS})
 
-SET( Irr_SRCS
+#FIXME: allow to set IRRMESH by option
+ADD_ASSIMP_IMPORTER(IRR
 	IRRLoader.cpp
 	IRRLoader.h
 	IRRMeshLoader.cpp
@@ -247,9 +257,8 @@ SET( Irr_SRCS
 	IRRShared.cpp
 	IRRShared.h
 )
-SOURCE_GROUP( Irr FILES ${Irr_SRCS})
 
-SET( LWO_SRCS
+ADD_ASSIMP_IMPORTER(LWO
 	LWOAnimation.cpp
 	LWOAnimation.h
 	LWOBLoader.cpp
@@ -258,53 +267,46 @@ SET( LWO_SRCS
 	LWOLoader.h
 	LWOMaterial.cpp
 )
-SOURCE_GROUP( LWO FILES ${LWO_SRCS})
 
-SET( LWS_SRCS
+ADD_ASSIMP_IMPORTER(LWS
 	LWSLoader.cpp
 	LWSLoader.h
 )
-SOURCE_GROUP( LWS FILES ${LWS_SRCS})
 
-SET( MD2_SRCS
+ADD_ASSIMP_IMPORTER(MD2
 	MD2FileData.h
 	MD2Loader.cpp
 	MD2Loader.h
 	MD2NormalTable.h
 )
-SOURCE_GROUP( MD2 FILES ${MD2_SRCS})
 
-SET( MD3_SRCS
+ADD_ASSIMP_IMPORTER(MD3
 	MD3FileData.h
 	MD3Loader.cpp
 	MD3Loader.h
 )
-SOURCE_GROUP( MD3 FILES ${MD3_SRCS})
 
-SET( MD5_SRCS
+ADD_ASSIMP_IMPORTER(MD5
 	MD5Loader.cpp
 	MD5Loader.h
 	MD5Parser.cpp
 	MD5Parser.h
 )
-SOURCE_GROUP( MD5 FILES ${MD5_SRCS})
 
-SET( MDC_SRCS
+ADD_ASSIMP_IMPORTER(MDC
 	MDCFileData.h
 	MDCLoader.cpp
 	MDCLoader.h
 	MDCNormalTable.h
 )
-SOURCE_GROUP( MDC FILES ${MDC_SRCS})
 
-SET( MDL_SRCS
+ADD_ASSIMP_IMPORTER(MDL
 	MDLDefaultColorMap.h
 	MDLFileData.h
 	MDLLoader.cpp
 	MDLLoader.h
 	MDLMaterialLoader.cpp
 )
-SOURCE_GROUP( MDL FILES ${MDL_SRCS})
 
 SET( MaterialSystem_SRCS
 	MaterialSystem.cpp
@@ -312,25 +314,22 @@ SET( MaterialSystem_SRCS
 )
 SOURCE_GROUP( MaterialSystem FILES ${MaterialSystem_SRCS})
 
-SET( NFF_SRCS
+ADD_ASSIMP_IMPORTER(NFF
 	NFFLoader.cpp
 	NFFLoader.h
 )
-SOURCE_GROUP( NFF FILES ${NFF_SRCS})
 
-SET( NDO_SRCS
+ADD_ASSIMP_IMPORTER(NDO
 	NDOLoader.cpp
 	NDOLoader.h
 )
-SOURCE_GROUP( NDO FILES ${NDO_SRCS})
 
-SET( OFFFormat_SRCS
+ADD_ASSIMP_IMPORTER(OFF
 	OFFLoader.cpp
 	OFFLoader.h
 )
-SOURCE_GROUP( OFFFormat FILES ${OFFFormat_SRCS})
 
-SET( Obj_SRCS
+ADD_ASSIMP_IMPORTER(OBJ
 	ObjFileData.h
 	ObjFileImporter.cpp
 	ObjFileImporter.h
@@ -343,9 +342,8 @@ SET( Obj_SRCS
 	ObjExporter.h
 	ObjExporter.cpp
 )
-SOURCE_GROUP( Obj FILES ${Obj_SRCS})
 
-SET( Ogre_SRCS
+ADD_ASSIMP_IMPORTER(OGRE
 	OgreImporter.h
 	OgreStructs.h
 	OgreParsingUtils.h
@@ -357,16 +355,14 @@ SET( Ogre_SRCS
 	OgreXmlSerializer.cpp
 	OgreMaterial.cpp
 )
-SOURCE_GROUP( Ogre FILES ${Ogre_SRCS})
 
-SET( OpenGEX_SRCS
+ADD_ASSIMP_IMPORTER(OPENGEX
     OpenGEXImporter.cpp
     OpenGEXImporter.h
     OpenGEXStructs.h
 )
-SOURCE_GROUP( OpenGEX FILES ${OpenGEX_SRCS})
 
-SET( Ply_SRCS
+ADD_ASSIMP_IMPORTER(PLY
 	PlyLoader.cpp
 	PlyLoader.h
 	PlyParser.cpp
@@ -374,22 +370,19 @@ SET( Ply_SRCS
 	PlyExporter.cpp
 	PlyExporter.h
 )
-SOURCE_GROUP( Ply FILES ${Ply_SRCS})
 
-SET(MS3D_SRCS
+ADD_ASSIMP_IMPORTER(MS3D
 	MS3DLoader.cpp
 	MS3DLoader.h
 )
-SOURCE_GROUP( MS3D FILES ${MS3D_SRCS})
 
-SET(COB_SRCS
+ADD_ASSIMP_IMPORTER(COB
 	COBLoader.cpp
 	COBLoader.h
 	COBScene.h
 )
-SOURCE_GROUP( COB FILES ${COB_SRCS})
 
-SET(BLENDER_SRCS
+ADD_ASSIMP_IMPORTER(BLEND
 	BlenderLoader.cpp
 	BlenderLoader.h
 	BlenderDNA.cpp
@@ -406,9 +399,8 @@ SET(BLENDER_SRCS
 	BlenderTessellator.h
 	BlenderTessellator.cpp
 )
-SOURCE_GROUP( BLENDER FILES ${BLENDER_SRCS})
 
-SET(IFC_SRCS
+ADD_ASSIMP_IMPORTER(IFC
 	IFCLoader.cpp
 	IFCLoader.h
 	IFCReaderGen.cpp
@@ -427,16 +419,14 @@ SET(IFC_SRCS
 	STEPFileEncoding.cpp
 	STEPFileEncoding.h
 )
-SOURCE_GROUP( IFC FILES ${IFC_SRCS})
 
-SET( XGL_SRCS
+ADD_ASSIMP_IMPORTER(XGL
 	XGLLoader.cpp
 	XGLLoader.h
 )
-SOURCE_GROUP( XGL FILES ${XGL_SRCS})
 
 
-SET(FBX_SRCS
+ADD_ASSIMP_IMPORTER(FBX
 	FBXImporter.cpp
 	FBXCompileConfig.h
 	FBXImporter.h
@@ -462,8 +452,6 @@ SET(FBX_SRCS
 	FBXBinaryTokenizer.cpp
 	FBXDocumentUtil.cpp
 )
-SOURCE_GROUP( FBX FILES ${FBX_SRCS})
-
 
 SET( PostProcessing_SRCS
 	CalcTangentsProcess.cpp
@@ -520,13 +508,12 @@ SET( PostProcessing_SRCS
 )
 SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
 
-SET( Q3D_SRCS
+ADD_ASSIMP_IMPORTER(Q3D
 	Q3DLoader.cpp
 	Q3DLoader.h
 )
-SOURCE_GROUP( Q3D FILES ${Q3D_SRCS})
 
-SET( Q3BSP_SRCS
+ADD_ASSIMP_IMPORTER(Q3BSP
 	Q3BSPFileData.h
 	Q3BSPFileParser.h
 	Q3BSPFileParser.cpp
@@ -535,41 +522,35 @@ SET( Q3BSP_SRCS
 	Q3BSPZipArchive.h
 	Q3BSPZipArchive.cpp
 )
-SOURCE_GROUP( Q3BSP FILES ${Q3BSP_SRCS})
 
-SET( Raw_SRCS
+ADD_ASSIMP_IMPORTER(RAW
 	RawLoader.cpp
 	RawLoader.h
 )
-SOURCE_GROUP( Raw FILES ${Raw_SRCS})
 
-SET( SMD_SRCS
+ADD_ASSIMP_IMPORTER(SMD
 	SMDLoader.cpp
 	SMDLoader.h
 )
-SOURCE_GROUP( SMD FILES ${SMD_SRCS})
 
-SET( STL_SRCS
+ADD_ASSIMP_IMPORTER(STL
 	STLLoader.cpp
 	STLLoader.h
 	STLExporter.h
 	STLExporter.cpp
 )
-SOURCE_GROUP( STL FILES ${STL_SRCS})
 
-SET( Terragen_SRCS
+ADD_ASSIMP_IMPORTER(TERRAGEN
 	TerragenLoader.cpp
 	TerragenLoader.h
 )
-SOURCE_GROUP( Terragen FILES ${Terragen_SRCS})
 
-SET( Unreal_SRCS
+ADD_ASSIMP_IMPORTER(3D
 	UnrealLoader.cpp
 	UnrealLoader.h
 )
-SOURCE_GROUP( Unreal FILES ${Unreal_SRCS})
 
-SET( XFile_SRCS
+ADD_ASSIMP_IMPORTER(X
 	XFileHelper.h
 	XFileImporter.cpp
 	XFileImporter.h
@@ -578,7 +559,12 @@ SET( XFile_SRCS
 	XFileExporter.h
 	XFileExporter.cpp
 )
-SOURCE_GROUP( XFile FILES ${XFile_SRCS})
+
+SET( Step_SRCS
+	StepExporter.h
+	StepExporter.cpp
+)
+SOURCE_GROUP( Step FILES ${Step_SRCS})
 
 SET( Exporter_SRCS
 	Exporter.cpp
@@ -674,6 +660,9 @@ else (UNZIP_FOUND)
 	SET (unzip_compile_SRCS ${unzip_SRCS})
 endif (UNZIP_FOUND)
 
+MESSAGE(STATUS "Enabled formats:${ASSIMP_IMPORTERS_ENABLED}")
+MESSAGE(STATUS "Disabled formats:${ASSIMP_IMPORTERS_DISABLED}")
+
 SET( assimp_src
 	# Assimp Files
 	${Core_SRCS}
@@ -681,50 +670,11 @@ SET( assimp_src
 	${Logging_SRCS}
 	${Exporter_SRCS}
 	${PostProcessing_SRCS}
+	${MaterialSystem_SRCS}
+	${Step_SRCS}
 
 	# Model Support
-	${3DS_SRCS}
-	${AC_SRCS}
-	${ASE_SRCS}
-	${ASSBIN_SRCS}
-	${ASSXML_SRCS}
-	${B3D_SRCS}
-	${BVH_SRCS}
-	${Collada_SRCS}
-	${DXF_SRCS}
-	${CSM_SRCS}
-	${HMP_SRCS}
-	${Irr_SRCS}
-	${LWO_SRCS}
-	${LWS_SRCS}
-	${MD2_SRCS}
-	${MD3_SRCS}
-	${MD5_SRCS}
-	${MDC_SRCS}
-	${MDL_SRCS}
-	${MaterialSystem_SRCS}
-	${NFF_SRCS}
-	${OFFFormat_SRCS}
-	${Obj_SRCS}
-	${Ogre_SRCS}
-    ${OpenGEX_SRCS}
-	${Ply_SRCS}
-	${Q3D_SRCS}
-	${Q3BSP_SRCS}
-	${Raw_SRCS}
-	${SMD_SRCS}
-	${STL_SRCS}
-	${Terragen_SRCS}
-	${Unreal_SRCS}
-	${XFile_SRCS}
-	${Extra_SRCS}
-	${MS3D_SRCS}
-	${COB_SRCS}
-	${BLENDER_SRCS}
-	${NDO_SRCS}
-	${IFC_SRCS}
-	${XGL_SRCS}
-	${FBX_SRCS}
+	${ASSIMP_LOADER_SRCS}
 
 	# Third-party libraries
 	${IrrXML_SRCS}
@@ -732,7 +682,7 @@ SET( assimp_src
 	${unzip_compile_SRCS}
 	${Poly2Tri_SRCS}
 	${Clipper_SRCS}
-    ${openddl_parser_SRCS}
+	${openddl_parser_SRCS}
 	# Necessary to show the headers in the project when using the VC++ generator:
 	${Boost_SRCS}
 

+ 3 - 16
code/ColladaExporter.cpp

@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "Bitmap.h"
 #include "fast_atof.h"
 #include "SceneCombiner.h"
+#include "DefaultIOSystem.h"
 #include "XMLTools.h"
 #include "../include/assimp/IOSystem.hpp"
 #include "../include/assimp/Exporter.hpp"
@@ -67,22 +68,8 @@ namespace Assimp
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
 void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
-	std::string path = "";
-	std::string file = pFile;
-
-	// We need to test both types of folder separators because pIOSystem->getOsSeparator() is not reliable.
-	// Moreover, the path given by some applications is not even consistent with the OS specific type of separator.
-	const char* end_path = std::max(strrchr(pFile, '\\'), strrchr(pFile, '/'));
-
-	if(end_path != NULL) {
-		path = std::string(pFile, end_path + 1 - pFile);
-		file = file.substr(end_path + 1 - pFile, file.npos);
-
-		std::size_t pos = file.find_last_of('.');
-		if(pos != file.npos) {
-			file = file.substr(0, pos);
-		}
-	}
+	std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
+	std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));
 
 	// invoke the exporter 
 	ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file);

+ 27 - 0
code/DefaultIOSystem.cpp

@@ -167,4 +167,31 @@ bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const
 	return !ASSIMP_stricmp(temp1,temp2);
 }
 
+
+std::string DefaultIOSystem::fileName(std::string path)
+{
+	std::string ret = path;
+	std::size_t last = ret.find_last_of("\\/");
+	if (last != std::string::npos) ret = ret.substr(last + 1);
+	return ret;
+}
+
+
+std::string DefaultIOSystem::completeBaseName(std::string path)
+{
+	std::string ret = fileName(path);
+	std::size_t pos = ret.find_last_of('.');
+	if(pos != ret.npos) ret = ret.substr(0, pos);
+	return ret;
+}
+
+
+std::string DefaultIOSystem::absolutePath(std::string path)
+{
+	std::string ret = path;
+	std::size_t last = ret.find_last_of("\\/");
+	if (last != std::string::npos) ret = ret.substr(0, last);
+	return ret;
+}
+
 #undef PATHLIMIT

+ 15 - 0
code/DefaultIOSystem.h

@@ -76,6 +76,21 @@ public:
 	// -------------------------------------------------------------------
 	/** Compare two paths */
 	bool ComparePaths (const char* one, const char* second) const;
+	
+	/** @brief get the file name of a full filepath
+	 * example: /tmp/archive.tar.gz -> archive.tar.gz
+	 */
+	static std::string fileName(std::string path);
+
+	/** @brief get the complete base name of a full filepath
+	 * example: /tmp/archive.tar.gz -> archive.tar
+	 */
+	static std::string completeBaseName(std::string path);
+
+	/** @brief get the path of a full filepath
+	 * example: /tmp/archive.tar.gz -> /tmp/
+	 */
+	static std::string absolutePath(std::string path);
 };
 
 } //!ns Assimp

+ 6 - 1
code/Exporter.cpp

@@ -79,7 +79,8 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
 // Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
 // do not use const, because some exporter need to convert the scene temporary
 void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*); 
+void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
@@ -102,6 +103,10 @@ Exporter::ExportFormatEntry gExporters[] =
 		aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
 #endif
 
+#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
+	Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0),
+#endif
+
 #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
 	Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj, 
 		aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */),

+ 9 - 3
code/OpenGEXImporter.cpp

@@ -223,6 +223,7 @@ OpenGEXImporter::OpenGEXImporter()
 , m_currentNode( NULL )
 , m_currentMesh( NULL )
 , m_currentMaterial( NULL )
+, m_tokenType( Grammar::NoneType )
 , m_nodeStack()
 , m_unresolvedRefStack() {
     // empty
@@ -406,7 +407,12 @@ void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene *pScene ) {
         }
 
         const std::string name( val->getString() );
-        m_currentNode->mName.Set( name.c_str() );
+        if( m_tokenType == Grammar::GeometryNodeToken ) {
+            m_currentNode->mName.Set( name.c_str() );
+        } else if( m_tokenType == Grammar::MaterialToken ) {
+            
+        }
+
     }
 }
 
@@ -462,6 +468,7 @@ void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene
 void OpenGEXImporter::handleGeometryNode( DDLNode *node, aiScene *pScene ) {
     aiNode *newNode = new aiNode;
     pushNode( newNode, pScene );
+    m_tokenType = Grammar::GeometryNodeToken;
     m_currentNode = newNode;
     handleNodes( node, pScene );
     
@@ -768,9 +775,8 @@ static ColorType getColorType( Identifier *id ) {
 void OpenGEXImporter::handleMaterialNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
     m_currentMaterial = new aiMaterial;
     m_materialCache.push_back( m_currentMaterial );
-
+    m_tokenType = Grammar::MaterialToken;
     handleNodes( node, pScene );
-
 }
 
 //------------------------------------------------------------------------------------------------

+ 1 - 0
code/OpenGEXImporter.h

@@ -179,6 +179,7 @@ private:
     VertexContainer m_currentVertices;
     aiMesh *m_currentMesh;
     aiMaterial *m_currentMaterial;
+    int m_tokenType;
     std::vector<aiMaterial*> m_materialCache;
     std::vector<aiNode*> m_nodeStack;
     std::vector<RefInfo*> m_unresolvedRefStack;

+ 20 - 0
code/ProcessHelper.cpp

@@ -94,6 +94,26 @@ void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D&
 	out = min + (max-min)*0.5f;
 }
 
+// -------------------------------------------------------------------------------
+void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max)
+{
+	if (scene->mNumMeshes == 0) return;
+	FindMeshCenter(scene->mMeshes[0], out, min, max);
+	for (unsigned int i = 1; i < scene->mNumMeshes; ++i)
+	{
+		aiVector3D tout, tmin, tmax;
+		FindMeshCenter(scene->mMeshes[i], tout, tmin, tmax);
+		if (min[0] > tmin[0]) min[0] = tmin[0];
+		if (min[1] > tmin[1]) min[1] = tmin[1];
+		if (min[2] > tmin[2]) min[2] = tmin[2];
+		if (max[0] < tmax[0]) max[0] = tmax[0];
+		if (max[1] < tmax[1]) max[1] = tmax[1];
+		if (max[2] < tmax[2]) max[2] = tmax[2];
+	}
+	out = min + (max-min)*0.5f;
+}
+
+
 // -------------------------------------------------------------------------------
 void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min,
 	aiVector3D& max, const aiMatrix4x4& m)

+ 10 - 0
code/ProcessHelper.h

@@ -265,6 +265,16 @@ void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
  *  @param[out] out Center point */
 void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max);
 
+// -------------------------------------------------------------------------------
+/** @brief Helper function to determine the 'real' center of a scene
+ *
+ *  That is the center of its axis-aligned bounding box.
+ *  @param scene Input scene
+ *  @param[out] min Minimum vertex of the scene
+ *  @param[out] max maximum vertex of the scene
+ *  @param[out] out Center point */
+void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max);
+
 
 // -------------------------------------------------------------------------------
 // Helper function to determine the 'real' center of a mesh after applying a given transform

+ 386 - 0
code/StepExporter.cpp

@@ -0,0 +1,386 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the 
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@author: Richard Steffen, 2015
+----------------------------------------------------------------------
+*/
+
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
+#include "StepExporter.h"
+#include "ConvertToLHProcess.h"
+#include "Bitmap.h"
+#include "BaseImporter.h"
+#include "fast_atof.h"
+#include "SceneCombiner.h" 
+#include "DefaultIOSystem.h"
+#include <iostream>
+#include <ctime>
+#include <set>
+#include <map>
+#include <list>
+#include <boost/scoped_ptr.hpp>
+#include "Exceptional.h"
+#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/scene.h"
+#include "../include/assimp/light.h"
+
+//
+#if _MSC_VER > 1500 || (defined __GNUC___)
+#	define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
+#	else
+#	define step_unordered_map map
+#	define step_unordered_multimap multimap
+#endif
+
+#ifdef ASSIMP_STEP_USE_UNORDERED_MULTIMAP
+#	include <unordered_map>
+#	if _MSC_VER > 1600
+#		define step_unordered_map unordered_map
+#		define step_unordered_multimap unordered_multimap
+#	else
+#		define step_unordered_map tr1::unordered_map
+#		define step_unordered_multimap tr1::unordered_multimap
+#	endif
+#endif
+
+typedef std::step_unordered_map<aiVector3D*, int> VectorIndexUMap;
+
+/* Tested with Step viewer v4 from www.ida-step.net */
+
+using namespace Assimp;
+
+namespace Assimp
+{
+
+// ------------------------------------------------------------------------------------------------
+// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
+void ExportSceneStep(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+	std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
+	std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));	
+
+	// create/copy Properties
+	ExportProperties props(*pProperties);
+
+	// invoke the exporter 
+	StepExporter iDoTheExportThing( pScene, pIOSystem, path, file, &props);
+
+	// we're still here - export successfully completed. Write result to the given IOSYstem
+	boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+	if(outfile == NULL) {
+		throw DeadlyExportError("could not open output .stp file: " + std::string(pFile));
+	}
+
+	// XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
+	outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1);
+}
+
+} // end of namespace Assimp
+
+
+namespace {
+	inline uint64_t toIndexHash(int32_t id1, int32_t id2)
+	{
+		// dont wonder that -1/-1 -> hash=-1
+		uint64_t hash = (uint32_t) id1;
+		hash = (hash << 32);
+		hash += (uint32_t) id2;
+		return hash;
+	}
+
+	inline void fromIndexHash(uint64_t hash, int32_t &id1, int32_t &id2)
+	{
+		id1 = (hash & 0xFFFFFFFF00000000) >> 32;
+		id2 = (hash & 0xFFFFFFFF);
+	}
+
+	// Collect world transformations for each node
+	void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) {
+		const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4();
+		trafos[node] = parent * node->mTransformation;
+		for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+			CollectTrafos(node->mChildren[i], trafos);
+		}
+	}
+
+	// Generate a flat list of the meshes (by index) assigned to each node
+	void CollectMeshes(const aiNode* node, std::multimap<const aiNode*, unsigned int>& meshes) {
+		for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
+			meshes.insert(std::make_pair(node, node->mMeshes[i]));
+		}
+		for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+			CollectMeshes(node->mChildren[i], meshes);
+		}
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+// Constructor for a specific scene to export
+StepExporter::StepExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties) : mIOSystem(pIOSystem), mPath(path), mFile(file), mProperties(pProperties)
+{
+	CollectTrafos(pScene->mRootNode, trafos);
+	CollectMeshes(pScene->mRootNode, meshes);
+
+	// make sure that all formatting happens using the standard, C locale and not the user's current locale
+	mOutput.imbue( std::locale("C") );
+
+	mScene = pScene;
+
+	// set up strings
+	endstr = ";\n";
+
+	// start writing
+	WriteFile();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Starts writing the contents
+void StepExporter::WriteFile()
+{
+	// see http://shodhganga.inflibnet.ac.in:8080/jspui/bitstream/10603/14116/11/11_chapter%203.pdf
+	// note, that all realnumber values must be comma separated in x files
+	mOutput.setf(std::ios::fixed);
+	mOutput.precision(16); // precission for double
+	
+	// standard color
+	aiColor4D fColor;
+	fColor.r = 0.8f;
+	fColor.g = 0.8f;
+	fColor.b = 0.8f;
+
+	int ind = 100; // the start index to be used
+	int faceEntryLen = 30; // number of entries for a triangle/face
+	// prepare unique (count triangles and vertices)
+
+	VectorIndexUMap uniqueVerts; // use a map to reduce find complexity to log(n)
+	VectorIndexUMap::iterator it;
+	int countFace = 0;
+
+	for (unsigned int i=0; i<mScene->mNumMeshes; ++i)
+	{
+		aiMesh* mesh = mScene->mMeshes[i];		
+		for (unsigned int j=0; j<mesh->mNumFaces; ++j)
+		{
+			aiFace* face = &(mesh->mFaces[j]);
+
+			if (face->mNumIndices == 3) countFace++;
+		}
+		for (unsigned int j=0; j<mesh->mNumVertices; ++j)
+		{
+			aiVector3D* v = &(mesh->mVertices[j]);
+			it =uniqueVerts.find(v); 
+			if (it == uniqueVerts.end())
+			{
+				uniqueVerts[v] = -1; // first mark the vector as not transformed
+			}
+		}
+	}
+
+	static const unsigned int date_nb_chars = 20;
+	char date_str[date_nb_chars];
+	std::time_t date = std::time(NULL);
+	std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date));
+
+	// write the header	
+	mOutput << "ISO-10303-21" << endstr;
+	mOutput << "HEADER" << endstr;
+	mOutput << "FILE_DESCRIPTION(('STEP AP214'),'1')" << endstr;
+	mOutput << "FILE_NAME('" << mFile << ".stp','" << date_str << "',(' '),(' '),'Spatial InterOp 3D',' ',' ')" << endstr;
+	mOutput << "FILE_SCHEMA(('automotive_design'))" << endstr;
+	mOutput << "ENDSEC" << endstr;
+
+	// write the top of data
+	mOutput << "DATA" << endstr;
+	mOutput << "#1=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION(' ',(";
+	for (int i=0; i<countFace; ++i)
+	{
+		mOutput << "#" << i*faceEntryLen + ind + 2*uniqueVerts.size();
+		if (i!=countFace-1) mOutput << ",";
+	}
+	mOutput << "),#6)" << endstr;
+
+	mOutput << "#2=PRODUCT_DEFINITION_CONTEXT('',#7,'design')" << endstr;
+	mOutput << "#3=APPLICATION_PROTOCOL_DEFINITION('INTERNATIONAL STANDARD','automotive_design',1994,#7)" << endstr;
+	mOutput << "#4=PRODUCT_CATEGORY_RELATIONSHIP('NONE','NONE',#8,#9)" << endstr;
+	mOutput << "#5=SHAPE_DEFINITION_REPRESENTATION(#10,#11)" << endstr;
+	mOutput << "#6= (GEOMETRIC_REPRESENTATION_CONTEXT(3)GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#12))GLOBAL_UNIT_ASSIGNED_CONTEXT((#13,#14,#15))REPRESENTATION_CONTEXT('NONE','WORKSPACE'))" << endstr;
+	mOutput << "#7=APPLICATION_CONTEXT(' ')" << endstr;
+	mOutput << "#8=PRODUCT_CATEGORY('part','NONE')" << endstr;
+	mOutput << "#9=PRODUCT_RELATED_PRODUCT_CATEGORY('detail',' ',(#17))" << endstr;
+	mOutput << "#10=PRODUCT_DEFINITION_SHAPE('NONE','NONE',#18)" << endstr;
+	mOutput << "#11=MANIFOLD_SURFACE_SHAPE_REPRESENTATION('Root',(#16,#19),#6)" << endstr;
+	mOutput << "#12=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.0E-006),#13,'','')" << endstr;
+	mOutput << "#13=(CONVERSION_BASED_UNIT('METRE',#20)LENGTH_UNIT()NAMED_UNIT(#21))" << endstr;
+	mOutput << "#14=(NAMED_UNIT(#22)PLANE_ANGLE_UNIT()SI_UNIT($,.RADIAN.))" << endstr;
+	mOutput << "#15=(NAMED_UNIT(#22)SOLID_ANGLE_UNIT()SI_UNIT($,.STERADIAN.))" << endstr;
+	mOutput << "#16=SHELL_BASED_SURFACE_MODEL('Root',(#29))" << endstr;
+	mOutput << "#17=PRODUCT('Root','Root','Root',(#23))" << endstr;
+	mOutput << "#18=PRODUCT_DEFINITION('NONE','NONE',#24,#2)" << endstr;
+	mOutput << "#19=AXIS2_PLACEMENT_3D('',#25,#26,#27)" << endstr;
+	mOutput << "#20=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.0),#28)" << endstr;
+	mOutput << "#21=DIMENSIONAL_EXPONENTS(1.0,0.0,0.0,0.0,0.0,0.0,0.0)" << endstr;
+	mOutput << "#22=DIMENSIONAL_EXPONENTS(0.0,0.0,0.0,0.0,0.0,0.0,0.0)" << endstr;
+	mOutput << "#23=PRODUCT_CONTEXT('',#7,'mechanical')" << endstr;
+	mOutput << "#24=PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE(' ','NONE',#17,.NOT_KNOWN.)" << endstr;
+	mOutput << "#25=CARTESIAN_POINT('',(0.0,0.0,0.0))" << endstr;
+	mOutput << "#26=DIRECTION('',(0.0,0.0,1.0))" << endstr;
+	mOutput << "#27=DIRECTION('',(1.0,0.0,0.0))" << endstr;	
+	mOutput << "#28= (NAMED_UNIT(#21)LENGTH_UNIT()SI_UNIT(.MILLI.,.METRE.))" << endstr;
+	mOutput << "#29=CLOSED_SHELL('',(";
+	for (int i=0; i<countFace; ++i)
+	{
+		mOutput << "#" << i*faceEntryLen + ind + 2*uniqueVerts.size() + 8;
+		if (i!=countFace-1) mOutput << ",";
+	}
+	mOutput << "))" << endstr;
+
+	// write all the unique transformed CARTESIAN and VERTEX
+	for (MeshesByNodeMap::const_iterator it2 = meshes.begin(); it2 != meshes.end(); it2++)
+	{
+		const aiNode& node = *(*it2).first;
+		unsigned int mesh_idx = (*it2).second;
+
+		const aiMesh* mesh = mScene->mMeshes[mesh_idx];
+		aiMatrix4x4& trafo = trafos[&node];
+		for (unsigned int i = 0; i < mesh->mNumVertices; ++i)
+		{
+			aiVector3D* v = &(mesh->mVertices[i]);
+			it = uniqueVerts.find(v);
+			if (it->second >=0 ) continue;
+			it->second = ind; // this one is new, so set the index (ind)
+			aiVector3D vt = trafo * (*v); // transform the coordinate
+			mOutput << "#" << it->second << "=CARTESIAN_POINT('',(" << vt.x << "," << vt.y << "," << vt.z << "))" << endstr;
+			mOutput << "#" << it->second+1 << "=VERTEX_POINT('',#" << it->second << ")" << endstr;
+			ind += 2;
+		}
+	}
+
+	// write the triangles
+	for (unsigned int i=0; i<mScene->mNumMeshes; ++i)
+	{
+		aiMesh* mesh = mScene->mMeshes[i];		
+		for (unsigned int j=0; j<mesh->mNumFaces; ++j)
+		{
+			aiFace* face = &(mesh->mFaces[j]);
+
+			if (face->mNumIndices != 3) continue;
+	
+			aiVector3D* v1 = &(mesh->mVertices[face->mIndices[0]]);
+			aiVector3D* v2 = &(mesh->mVertices[face->mIndices[1]]);
+			aiVector3D* v3 = &(mesh->mVertices[face->mIndices[2]]);
+			aiVector3D dv12 = *v2 - *v1;
+			aiVector3D dv23 = *v3 - *v2;
+			aiVector3D dv31 = *v1 - *v3;
+			aiVector3D dv13 = *v3 - *v1;
+			dv12.Normalize();
+			dv23.Normalize();
+			dv31.Normalize();
+			dv13.Normalize();
+
+			int pid1 = uniqueVerts.find(v1)->second;
+			int pid2 = uniqueVerts.find(v2)->second;
+			int pid3 = uniqueVerts.find(v3)->second;
+			
+			// mean vertex color for the face if available
+			if (mesh->HasVertexColors(0))
+			{					
+				fColor.r = 0.0;
+				fColor.g = 0.0;
+				fColor.b = 0.0;
+				fColor += mesh->mColors[0][face->mIndices[0]];
+				fColor += mesh->mColors[0][face->mIndices[1]];
+				fColor += mesh->mColors[0][face->mIndices[2]];
+				fColor /= 3.0f;
+			}
+
+			int sid = ind; // the sub index		
+			mOutput << "#" << sid << "=STYLED_ITEM('',(#" << sid+1 << "),#" << sid+8 << ")" << endstr; /* the item that must be referenced in #1 */
+			/* This is the color information of the Triangle */
+			mOutput << "#" << sid+1 << "=PRESENTATION_STYLE_ASSIGNMENT((#" << sid+2 << "))" << endstr;
+			mOutput << "#" << sid+2 << "=SURFACE_STYLE_USAGE(.BOTH.,#" << sid+3 << ")" << endstr;
+			mOutput << "#" << sid+3 << "=SURFACE_SIDE_STYLE('',(#" << sid+4 << "))" << endstr;
+			mOutput << "#" << sid+4 << "=SURFACE_STYLE_FILL_AREA(#" << sid+5 << ")" << endstr;
+			mOutput << "#" << sid+5 << "=FILL_AREA_STYLE('',(#" << sid+6 << "))" << endstr;
+			mOutput << "#" << sid+6 << "=FILL_AREA_STYLE_COLOUR('',#" << sid+7 << ")" << endstr;
+			mOutput << "#" << sid+7 << "=COLOUR_RGB(''," << fColor.r << "," << fColor.g << "," << fColor.b << ")" << endstr;
+
+			/* this is the geometry */
+			mOutput << "#" << sid+8 << "=FACE_SURFACE('',(#" << sid+13 << "),#" << sid+9<< ",.T.)" << endstr; /* the face that must be referenced in 29 */
+
+			/* 2 directions of the plane */
+			mOutput << "#" << sid+9 << "=PLANE('',#" << sid+10 << ")" << endstr;
+			mOutput << "#" << sid+10 << "=AXIS2_PLACEMENT_3D('',#" << pid1 << ", #" << sid+11 << ",#" << sid+12 << ")" << endstr;									
+
+			mOutput << "#" << sid+11 << "=DIRECTION('',(" << dv12.x << "," << dv12.y << "," << dv12.z << "))" << endstr;
+			mOutput << "#" << sid+12 << "=DIRECTION('',(" << dv13.x << "," << dv13.y << "," << dv13.z << "))" << endstr;
+
+			mOutput << "#" << sid+13 << "=FACE_BOUND('',#" << sid+14 << ",.T.)" << endstr;
+			mOutput << "#" << sid+14 << "=EDGE_LOOP('',(#" << sid+15 << ",#" << sid+16 << ",#" << sid+17 << "))" << endstr;
+
+			/* edge loop  */
+			mOutput << "#" << sid+15 << "=ORIENTED_EDGE('',*,*,#" << sid+18 << ",.T.)" << endstr;
+			mOutput << "#" << sid+16 << "=ORIENTED_EDGE('',*,*,#" << sid+19 << ",.T.)" << endstr;
+			mOutput << "#" << sid+17 << "=ORIENTED_EDGE('',*,*,#" << sid+20 << ",.T.)" << endstr;
+
+			/* oriented edges */
+			mOutput << "#" << sid+18 << "=EDGE_CURVE('',#" << pid1+1 << ",#" << pid2+1 << ",#" << sid+21 << ",.F.)" << endstr;
+			mOutput << "#" << sid+19 << "=EDGE_CURVE('',#" << pid2+1 << ",#" << pid3+1 << ",#" << sid+22 << ",.T.)" << endstr;
+			mOutput << "#" << sid+20 << "=EDGE_CURVE('',#" << pid3+1 << ",#" << pid1+1 << ",#" << sid+23 << ",.T.)" << endstr;
+
+			/* 3 lines and 3 vectors for the lines for the 3 edge curves */
+			mOutput << "#" << sid+21 << "=LINE('',#" << pid1 << ",#" << sid+24 << ")" << endstr;
+			mOutput << "#" << sid+22 << "=LINE('',#" << pid2 << ",#" << sid+25 << ")" << endstr;
+			mOutput << "#" << sid+23 << "=LINE('',#" << pid3 << ",#" << sid+26 << ")" << endstr;
+			mOutput << "#" << sid+24 << "=VECTOR('',#" << sid+27 << ",1.0)" << endstr;
+			mOutput << "#" << sid+25 << "=VECTOR('',#" << sid+28 << ",1.0)" << endstr;
+			mOutput << "#" << sid+26 << "=VECTOR('',#" << sid+29 << ",1.0)" << endstr;
+			mOutput << "#" << sid+27 << "=DIRECTION('',(" << dv12.x << "," << dv12.y << "," << dv12.z << "))" << endstr;
+			mOutput << "#" << sid+28 << "=DIRECTION('',(" << dv23.x << "," << dv23.y << "," << dv23.z << "))" << endstr;
+			mOutput << "#" << sid+29 << "=DIRECTION('',(" << dv31.x << "," << dv31.y << "," << dv31.z << "))" << endstr;
+			ind += faceEntryLen; // increase counter
+		}
+	}
+		
+	mOutput << "ENDSEC" << endstr; // end of data section	
+	mOutput << "END-ISO-10303-21" << endstr; // end of file
+}
+
+#endif
+#endif
+

+ 109 - 0
code/StepExporter.h

@@ -0,0 +1,109 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the 
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@author: Richard Steffen, 2014
+
+----------------------------------------------------------------------
+*/
+
+/** @file StepExporter.h
+ * Declares the exporter class to write a scene to a Collada file
+ */
+#ifndef AI_STEPEXPORTER_H_INC
+#define AI_STEPEXPORTER_H_INC
+
+#include "../include/assimp/ai_assert.h"
+#include "../include/assimp/matrix4x4.h"
+#include "../include/assimp/Exporter.hpp"
+#include <sstream>
+
+
+struct aiScene;
+struct aiNode;
+
+namespace Assimp	
+{
+
+/// Helper class to export a given scene to a StepFile.
+/// Note: an StepFile uses a left hand system. Assimp used a right hand system (OpenGL), therefore we have to transform everything
+class StepExporter
+{
+public:
+	/// Constructor for a specific scene to export
+	StepExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties);
+
+protected:
+	/// Starts writing the contents
+	void WriteFile();	
+
+public:
+
+	/// Stringstream to write all output into
+	std::stringstream mOutput;
+
+protected:
+
+	/// hold the properties pointer
+	const ExportProperties* mProperties;	
+
+	/// The IOSystem for output
+	IOSystem* mIOSystem;
+
+	/// Name of the file (without extension) where the scene will be exported
+	std::string mFile;
+
+	/// Path of the directory where the scene will be exported
+	std::string mPath;	
+
+	/// The scene to be written
+	const aiScene* mScene;
+
+	/// current line end string for simple stream insertion
+	std::string endstr;
+
+	/// accumultated transformations for nodes
+	std::map<const aiNode*, aiMatrix4x4> trafos;
+
+	/// map to all meshed of nodes
+	typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
+	MeshesByNodeMap meshes;
+
+};
+
+}
+
+#endif // !! AI_STEPEXPORTER_H_INC

+ 16 - 26
code/XFileExporter.cpp

@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BaseImporter.h"
 #include "fast_atof.h"
 #include "SceneCombiner.h"
-
+#include "DefaultIOSystem.h"
 #include <ctime>
 #include <set>
 #include <boost/scoped_ptr.hpp>
@@ -68,22 +68,8 @@ namespace Assimp
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
 void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
-	std::string path = "";
-	std::string file = pFile;
-
-	// We need to test both types of folder separators because pIOSystem->getOsSeparator() is not reliable.
-	// Moreover, the path given by some applications is not even consistent with the OS specific type of separator.
-	const char* end_path = std::max(strrchr(pFile, '\\'), strrchr(pFile, '/'));
-
-	if(end_path != NULL) {
-		path = std::string(pFile, end_path + 1 - pFile);
-		file = file.substr(end_path + 1 - pFile, file.npos);
-
-		std::size_t pos = file.find_last_of('.');
-		if(pos != file.npos) {
-			file = file.substr(0, pos);
-		}
-	}
+	std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
+	std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));
 
 	// create/copy Properties
 	ExportProperties props(*pProperties);
@@ -118,7 +104,7 @@ XFileExporter::XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const s
 	mSceneOwned = false;
 
 	// set up strings
-	endstr = "\n"; 
+	endstr = "\n";
 
 	// start writing
 	WriteFile();
@@ -326,8 +312,8 @@ void XFileExporter::WriteNode( aiNode* pNode)
 		WriteMesh(mScene->mMeshes[pNode->mMeshes[i]]);
 
 	// recursive call the Nodes
-	for (size_t a = 0; a < pNode->mNumChildren; a++)
-		WriteNode( mScene->mRootNode->mChildren[a]);
+	for (size_t i = 0; i < pNode->mNumChildren; ++i)
+		WriteNode( mScene->mRootNode->mChildren[i]);
 
 	PopTag();
 
@@ -514,12 +500,16 @@ void XFileExporter::WriteMesh(aiMesh* mesh)
 
 std::string XFileExporter::toXFileString(aiString &name)
 {
-	std::string str = std::string(name.C_Str());
-	std::replace(str.begin(), str.end(), '<', '_');
-	std::replace(str.begin(), str.end(), '>', '_');
-	std::replace(str.begin(), str.end(), '{', '_');
-	std::replace(str.begin(), str.end(), '}', '_');
-	std::replace(str.begin(), str.end(), '$', '_');
+	std::string pref = ""; // node name prefix to prevent unexpected start of string
+	std::string str = pref + std::string(name.C_Str());	
+	for (int i=0; i < (int) str.length(); ++i)
+	{
+		if ((str[i] >= '0' && str[i] <= '9') || // 0-9
+			(str[i] >= 'A' && str[i] <= 'Z') || // A-Z
+			(str[i] >= 'a' && str[i] <= 'z')) // a-z
+			continue;
+		str[i] = '_';
+	}
 	return str;
 }
 

+ 0 - 2
code/XFileExporter.h

@@ -128,8 +128,6 @@ protected:
 	/// current line end string for simple stream insertion
 	std::string endstr;
   
-protected:
-
 };
 
 }

+ 12 - 7
contrib/openddlparser/code/Value.cpp

@@ -101,12 +101,11 @@ uint8 Value::getUnsignedInt8() const {
 void Value::setUnsignedInt16( uint16 value ) {
     assert( ddl_unsigned_int16 == m_type );
     ::memcpy( m_data, &value, m_size );
-
 }
+
 uint16 Value::getUnsignedInt16() const {
     assert( ddl_unsigned_int16 == m_type );
     return ( uint8 ) ( *m_data );
-
 }
 
 void Value::setUnsignedInt32( uint32 value ) {
@@ -135,9 +134,15 @@ void Value::setFloat( float value ) {
 }
 
 float Value::getFloat() const {
-    float v;
-    ::memcpy( &v, m_data, m_size );
-    return v;
+    if( m_type == ddl_float ) {
+        float v;
+        ::memcpy( &v, m_data, m_size );
+        return ( float ) v;
+    } else {
+        float tmp;
+        ::memcpy( &tmp, m_data, 4 );
+        return ( float ) tmp;
+    }
 }
 
 void Value::setDouble( double value ) {
@@ -241,7 +246,7 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
             data->m_size = sizeof( int );
             break;
         case Value::ddl_int64:
-            data->m_size = sizeof( long );
+            data->m_size = sizeof( int64 );
             break;
         case Value::ddl_unsigned_int8:
             data->m_size = sizeof( unsigned char );
@@ -250,7 +255,7 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
             data->m_size = sizeof( unsigned int );
             break;
         case Value::ddl_unsigned_int64:
-            data->m_size = sizeof( unsigned long );
+            data->m_size = sizeof( uint64 );
             break;
         case Value::ddl_half:
             data->m_size = sizeof( short );

+ 0 - 4
contrib/openddlparser/include/openddlparser/DDLNode.h

@@ -21,8 +21,6 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------------------------*/
 #pragma once
-#ifndef OPENDDLPARSER_DDLNODE_H_INC
-#define OPENDDLPARSER_DDLNODE_H_INC
 
 #include <openddlparser/OpenDDLCommon.h>
 
@@ -88,5 +86,3 @@ private:
 };
 
 END_ODDLPARSER_NS
-
-#endif // OPENDDLPARSER_DDLNODE_H_INC

+ 11 - 7
contrib/openddlparser/include/openddlparser/OpenDDLCommon.h

@@ -21,14 +21,15 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------------------------*/
 #pragma once
-#ifndef OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
-#define OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
 
 #include <cstddef>
 #include <vector>
 #include <string>
 
 #include <string.h>
+#ifndef _WIN32
+#  include <inttypes.h>
+#endif 
 
 #ifdef _MSC_VER
 #   define TAG_DLL_EXPORT __declspec(dllexport)
@@ -67,11 +68,17 @@ struct DataArrayList;
 typedef char           int8;
 typedef short          int16;
 typedef int            int32;
-typedef long           int64;
 typedef unsigned char  uint8;
 typedef unsigned short uint16;
 typedef unsigned int   uint32;
-typedef unsigned long  uint64;
+
+#ifdef _WIN32
+typedef __int64           int64;
+typedef unsigned __int64  uint64;
+#else
+typedef int64_t           int64;
+typedef uint64_t          uint64;
+#endif
 
 enum NameType {
     GlobalName,
@@ -248,6 +255,3 @@ private:
 };
 
 END_ODDLPARSER_NS
-
-#endif // OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
-

+ 0 - 4
contrib/openddlparser/include/openddlparser/OpenDDLParser.h

@@ -21,8 +21,6 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------------------------*/
 #pragma once
-#ifndef OPENDDLPARSER_OPENDDLPARSER_H_INC
-#define OPENDDLPARSER_OPENDDLPARSER_H_INC
 
 #include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/DDLNode.h>
@@ -127,5 +125,3 @@ private:
 };
 
 END_ODDLPARSER_NS
-
-#endif // OPENDDLPARSER_OPENDDLPARSER_H_INC

+ 0 - 9
contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h

@@ -21,8 +21,6 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------------------------*/
 #pragma once
-#ifndef OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
-#define OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
 
 #include <openddlparser/OpenDDLCommon.h>
 
@@ -124,7 +122,6 @@ bool isInteger( T *in, T *end ) {
 
     bool result( false );
     while( isNotEndOfToken( in, end ) ) {
-        //while( '}' != *in && ',' != *in && !isSpace( *in ) && in != end ) {
         result = isNumeric( *in );
         if( !result ) {
             break;
@@ -147,8 +144,6 @@ bool isFloat( T *in, T *end ) {
     // check for <1>.0f
     bool result( false );
     while( isNotEndOfToken( in, end ) ) {
-
-//    while( !isSpace( *in ) && in != end ) {
         if( *in == '.' ) {
             result = true;
             break;
@@ -169,8 +164,6 @@ bool isFloat( T *in, T *end ) {
 
     // check for 1.<0>f
     while( isNotEndOfToken( in, end ) ) {
-
-//    while( !isSpace( *in ) && in != end && *in != ',' && *in != '}' ) {
         result = isNumeric( *in );
         if( !result ) {
             return false;
@@ -257,5 +250,3 @@ int hex2Decimal( char in ) {
 }
 
 END_ODDLPARSER_NS
-
-#endif // OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC

+ 0 - 4
contrib/openddlparser/include/openddlparser/Value.h

@@ -21,8 +21,6 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------------------------*/
 #pragma once
-#ifndef OPENDDLPARSER_VALUE_H_INC
-#define OPENDDLPARSER_VALUE_H_INC
 
 #include <openddlparser/OpenDDLCommon.h>
 
@@ -101,5 +99,3 @@ struct DLL_ODDLPARSER_EXPORT ValueAllocator {
 };
 
 END_ODDLPARSER_NS
-
-#endif // OPENDDLPARSER_VALUE_H_INC