diff --git a/CMakeLists.txt b/CMakeLists.txt index 0026dcb7f..83e1be081 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,8 +138,7 @@ SET (PROJECT_VERSION "${ASSIMP_VERSION}") SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" ) -# Needed for openddl_parser config, no use of c++11 at this moment -ADD_DEFINITIONS( -DOPENDDL_NO_USE_CPP11 ) +# Enable C++1 globally set_property( GLOBAL PROPERTY CXX_STANDARD 11 ) # Get the current working branch @@ -161,7 +160,7 @@ EXECUTE_PROCESS( ) IF(NOT GIT_COMMIT_HASH) - SET(GIT_COMMIT_HASH 0) + SET(GIT_COMMIT_HASH 0) ENDIF(NOT GIT_COMMIT_HASH) IF(ASSIMP_DOUBLE_PRECISION) @@ -179,10 +178,10 @@ CONFIGURE_FILE( ) INCLUDE_DIRECTORIES( - ./ - include - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/include + ./ + include + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/include ) LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" ) @@ -192,14 +191,6 @@ SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPO SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") IF( UNIX ) - # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux - IF( ${OPERATING_SYSTEM} MATCHES "Android") - ELSE() - IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux - #ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) - ENDIF() - ENDIF() - # Use GNUInstallDirs for Unix predefined directories INCLUDE(GNUInstallDirs) ENDIF( UNIX ) @@ -212,13 +203,13 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW) SET(LIBSTDC++_LIBRARIES -lstdc++) ELSEIF(MSVC) # enable multi-core compilation with MSVC - add_compile_options(/MP) - if("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)") - add_compile_options( /bigobj ) - endif() + ADD_COMPILE_OPTIONS(/MP) + IF("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)") + ADD_COMPILE_OPTIONS( /bigobj ) + ENDIF() # disable "elements of array '' will be default initialized" warning on MSVC2013 IF(MSVC12) - add_compile_options(/wd4351) + ADD_COMPILE_OPTIONS(/wd4351) ENDIF() ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" ) @@ -229,39 +220,39 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW ) ADD_DEFINITIONS( -U__STRICT_ANSI__ ) ENDIF() -if (IOS) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") -endif() +IF (IOS) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") +ENDIF() -if (ASSIMP_COVERALLS) - MESSAGE(STATUS "Coveralls enabled") - INCLUDE(Coveralls) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") -endif() +IF (ASSIMP_COVERALLS) + MESSAGE(STATUS "Coveralls enabled") + INCLUDE(Coveralls) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") +ENDIF() -if (ASSIMP_WERROR) +IF (ASSIMP_WERROR) MESSAGE(STATUS "Treating warnings as errors") IF (MSVC) - add_compile_options(/WX) + ADD_COMPILE_OPTIONS(/WX) ELSE() SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") ENDIF() -endif() +ENDIF() -if (ASSIMP_ASAN) - MESSAGE(STATUS "AddressSanitizer enabled") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") -endif() +IF (ASSIMP_ASAN) + MESSAGE(STATUS "AddressSanitizer enabled") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +ENDIF() -if (ASSIMP_UBSAN) - MESSAGE(STATUS "Undefined Behavior sanitizer enabled") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") -endif() +IF (ASSIMP_UBSAN) + MESSAGE(STATUS "Undefined Behavior sanitizer enabled") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") +ENDIF() INCLUDE (FindPkgMacros) INCLUDE (PrecompiledHeader) @@ -294,42 +285,42 @@ ENDIF() IF (NOT TARGET uninstall) # add make uninstall capability CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) - add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") + ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") ENDIF() # cmake configuration files CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE) CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE) -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) +INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) FIND_PACKAGE( DirectX ) IF( BUILD_DOCS ) - add_subdirectory(doc) + ADD_SUBDIRECTORY(doc) ENDIF( BUILD_DOCS ) # Look for system installed irrXML IF ( SYSTEM_IRRXML ) - find_package( IrrXML REQUIRED ) + FIND_PACKAGE( IrrXML REQUIRED ) ENDIF( SYSTEM_IRRXML ) # Search for external dependencies, and build them from source if not found # Search for zlib IF ( NOT ASSIMP_BUILD_ZLIB ) - find_package(ZLIB) + FIND_PACKAGE(ZLIB) ENDIF( NOT ASSIMP_BUILD_ZLIB ) IF( NOT ZLIB_FOUND ) - message(STATUS "compiling zlib from souces") + MESSAGE(STATUS "compiling zlib from souces") INCLUDE(CheckIncludeFile) INCLUDE(CheckTypeSize) INCLUDE(CheckFunctionExists) # compile from sources - add_subdirectory(contrib/zlib) + ADD_SUBDIRECTORY(contrib/zlib) SET(ZLIB_FOUND 1) SET(ZLIB_LIBRARIES zlibstatic) SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib) -else(NOT ZLIB_FOUND) +ELSE(NOT ZLIB_FOUND) ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB) SET(ZLIB_LIBRARIES_LINKED -lz) ENDIF(NOT ZLIB_FOUND) @@ -371,7 +362,9 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes") # pick the correct prebuilt library - IF(MSVC14) + IF(MSVC15) + SET(C4D_LIB_POSTFIX "_2017") + ELSEIF(MSVC14) SET(C4D_LIB_POSTFIX "_2015") ELSEIF(MSVC12) SET(C4D_LIB_POSTFIX "_2013") @@ -412,7 +405,7 @@ ADD_SUBDIRECTORY(contrib) ADD_SUBDIRECTORY( code/ ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( WIN32 AND DirectX_D3DX9_LIBRARY ) - option ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} ) + OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} ) IF ( ASSIMP_BUILD_ASSIMP_VIEW ) ADD_SUBDIRECTORY( tools/assimp_view/ ) ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW ) @@ -476,8 +469,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) SET(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") - string(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER") - string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER") + STRING(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER") + STRING(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER") SET(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools") SET(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" ) @@ -507,8 +500,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) SET(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release") ENDIF() SET(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources") - include(CPack) - include(DebSourcePPA) + INCLUDE(CPack) + INCLUDE(DebSourcePPA) ENDIF() if(WIN32) @@ -520,14 +513,16 @@ if(WIN32) SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/") ENDIF() - if(MSVC12) + IF(MSVC12) SET(ASSIMP_MSVC_VERSION "vc120") - elseif(MSVC14) + ELSEIF(MSVC14) SET(ASSIMP_MSVC_VERSION "vc140") + ELSEIF(MSVC15) + SET(ASSIMP_MSVC_VERSION "vc141") ENDIF(MSVC12) - if(MSVC12 OR MSVC14) - add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM) + IF(MSVC12 OR MSVC14 OR MSVC15 ) + ADD_CUSTOM_TARGET(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM) IF(CMAKE_GENERATOR MATCHES "^Visual Studio") ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM) @@ -548,5 +543,5 @@ if(WIN32) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) ENDIF() - ENDIF(MSVC12 OR MSVC14) + ENDIF(MSVC12 OR MSVC14 OR MSVC15 ) ENDIF (WIN32) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index dafe017ef..7ae1a7e63 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -177,8 +177,6 @@ SET( Common_SRCS SkeletonMeshBuilder.cpp SplitByBoneCountProcess.cpp SplitByBoneCountProcess.h - ScaleProcess.cpp - ScaleProcess.h StandardShapes.cpp TargetAnimation.cpp TargetAnimation.h @@ -586,6 +584,8 @@ SET( PostProcessing_SRCS PolyTools.h MakeVerboseFormat.cpp MakeVerboseFormat.h + ScaleProcess.cpp + ScaleProcess.h ) SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS}) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index f3a908dd4..2c9818a16 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -61,6 +61,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include namespace Assimp { namespace FBX { @@ -133,9 +135,7 @@ void Converter::ConvertRootNode() { ConvertNodes( 0L, *out->mRootNode ); } - -void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform ) -{ +void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform ) { const std::vector& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" ); std::vector nodes; @@ -153,14 +153,14 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa } const Object* const object = con->SourceObject(); - if ( !object ) { + if ( nullptr == object ) { FBXImporter::LogWarn( "failed to convert source object for Model link" ); continue; } const Model* const model = dynamic_cast( object ); - if ( model ) { + if ( nullptr != model ) { nodes_chain.clear(); post_nodes_chain.clear(); @@ -174,7 +174,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa ai_assert( nodes_chain.size() ); - const std::string& original_name = FixNodeName( model->Name() ); + std::string original_name = FixNodeName( model->Name() ); // check if any of the nodes in the chain has the name the fbx node // is supposed to have. If there is none, add another node to @@ -189,7 +189,15 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa } if ( !name_carrier ) { + NodeNameCache::const_iterator it( std::find( mNodeNames.begin(), mNodeNames.end(), original_name ) ); + if ( it != mNodeNames.end() ) { + original_name = original_name + std::string( "001" ); + } + + mNodeNames.push_back( original_name ); nodes_chain.push_back( new aiNode( original_name ) ); + } else { + original_name = nodes_chain.back()->mName.C_Str(); } //setup metadata on newest node @@ -250,11 +258,11 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa ConvertNodes( model->ID(), *last_parent, new_abs_transform ); if ( doc.Settings().readLights ) { - ConvertLights( *model ); + ConvertLights( *model, original_name ); } if ( doc.Settings().readCameras ) { - ConvertCameras( *model ); + ConvertCameras( *model, original_name ); } nodes.push_back( nodes_chain.front() ); @@ -278,34 +286,31 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa } -void Converter::ConvertLights( const Model& model ) -{ +void Converter::ConvertLights( const Model& model, const std::string &orig_name ) { const std::vector& node_attrs = model.GetAttributes(); for( const NodeAttribute* attr : node_attrs ) { const Light* const light = dynamic_cast( attr ); if ( light ) { - ConvertLight( model, *light ); + ConvertLight( *light, orig_name ); } } } -void Converter::ConvertCameras( const Model& model ) -{ +void Converter::ConvertCameras( const Model& model, const std::string &orig_name ) { const std::vector& node_attrs = model.GetAttributes(); for( const NodeAttribute* attr : node_attrs ) { const Camera* const cam = dynamic_cast( attr ); if ( cam ) { - ConvertCamera( model, *cam ); + ConvertCamera( *cam, orig_name ); } } } -void Converter::ConvertLight( const Model& model, const Light& light ) -{ +void Converter::ConvertLight( const Light& light, const std::string &orig_name ) { lights.push_back( new aiLight() ); aiLight* const out_light = lights.back(); - out_light->mName.Set( FixNodeName( model.Name() ) ); + out_light->mName.Set( orig_name ); const float intensity = light.Intensity() / 100.0f; const aiVector3D& col = light.Color(); @@ -378,12 +383,12 @@ void Converter::ConvertLight( const Model& model, const Light& light ) } } -void Converter::ConvertCamera( const Model& model, const Camera& cam ) +void Converter::ConvertCamera( const Camera& cam, const std::string &orig_name ) { cameras.push_back( new aiCamera() ); aiCamera* const out_camera = cameras.back(); - out_camera->mName.Set( FixNodeName( model.Name() ) ); + out_camera->mName.Set( orig_name ); out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); @@ -397,6 +402,31 @@ void Converter::ConvertCamera( const Model& model, const Camera& cam ) out_camera->mClipPlaneFar = cam.FarPlane(); } +static bool HasName( NodeNameCache &cache, const std::string &name ) { + NodeNameCache::const_iterator it( std::find( cache.begin(), cache.end(), name ) ); + return it != cache.end(); + +} +void Converter::GetUniqueName( const std::string &name, std::string uniqueName ) { + if ( !HasName( mNodeNames, name ) ) { + uniqueName = name; + return; + } + + int i( 0 ); + std::string newName; + while ( HasName( mNodeNames, newName ) ) { + ++i; + newName.clear(); + newName += name; + std::stringstream ext; + ext << std::setfill( '0' ) << std::setw( 3 ) << i; + newName += ext.str(); + } + uniqueName = newName; + mNodeNames.push_back( uniqueName ); +} + const char* Converter::NameTransformationComp( TransformationComp comp ) { @@ -738,7 +768,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector // not be guaranteed. ai_assert( NeedsComplexTransformationChain( model ) == is_complex ); - const std::string& name = FixNodeName( model.Name() ); + std::string name = FixNodeName( model.Name() ); // now, if we have more than just Translation, Scaling and Rotation, // we need to generate a full node chain to accommodate for assimp's @@ -786,8 +816,10 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector // else, we can just multiply the matrices together aiNode* nd = new aiNode(); output_nodes.push_back( nd ); + std::string uniqueName; + GetUniqueName( name, uniqueName ); - nd->mName.Set( name ); + nd->mName.Set( uniqueName ); for (const auto &transform : chain) { nd->mTransformation = nd->mTransformation * transform; @@ -2005,81 +2037,17 @@ void Converter::ConvertAnimations() } } -void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) { - if ( node_names.find( fixed_name ) == node_names.end() ) { - FBXImporter::LogError( "Cannot rename node " + fixed_name + ", not existing."); - return; - } - - if ( node_names.find( new_name ) != node_names.end() ) { - FBXImporter::LogError( "Cannot rename node " + fixed_name + " to " + new_name +", name already existing." ); - return; - } - - ai_assert( node_names.find( fixed_name ) != node_names.end() ); - ai_assert( node_names.find( new_name ) == node_names.end() ); - - renamed_nodes[ fixed_name ] = new_name; - - const aiString fn( fixed_name ); - - for( aiCamera* cam : cameras ) { - if ( cam->mName == fn ) { - cam->mName.Set( new_name ); - break; - } - } - - for( aiLight* light : lights ) { - if ( light->mName == fn ) { - light->mName.Set( new_name ); - break; - } - } - - for( aiAnimation* anim : animations ) { - for ( unsigned int i = 0; i < anim->mNumChannels; ++i ) { - aiNodeAnim* const na = anim->mChannels[ i ]; - if ( na->mNodeName == fn ) { - na->mNodeName.Set( new_name ); - break; - } - } - } -} - - -std::string Converter::FixNodeName( const std::string& name ) -{ +std::string Converter::FixNodeName( const std::string& name ) { // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if // this causes ambiguities, well possible between empty identifiers, // such as "Model::" and ""). Make sure the behaviour is consistent // across multiple calls to FixNodeName(). if ( name.substr( 0, 7 ) == "Model::" ) { std::string temp = name.substr( 7 ); - - const NodeNameMap::const_iterator it = node_names.find( temp ); - if ( it != node_names.end() ) { - if ( !( *it ).second ) { - return FixNodeName( name + "_" ); - } - } - node_names[ temp ] = true; - - const NameNameMap::const_iterator rit = renamed_nodes.find( temp ); - return rit == renamed_nodes.end() ? temp : ( *rit ).second; + return temp; } - const NodeNameMap::const_iterator it = node_names.find( name ); - if ( it != node_names.end() ) { - if ( ( *it ).second ) { - return FixNodeName( name + "_" ); - } - } - node_names[ name ] = false; - - const NameNameMap::const_iterator rit = renamed_nodes.find( name ); - return rit == renamed_nodes.end() ? name : ( *rit ).second; + return name; } void Converter::ConvertAnimationStack( const AnimationStack& st ) diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 06a6f07a7..60fd04e2c 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -68,6 +68,8 @@ namespace FBX { class Document; +using NodeNameCache = std::vector; + /** * Convert a FBX #Document to #aiScene * @param out Empty scene to be populated @@ -117,16 +119,19 @@ private: void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4()); // ------------------------------------------------------------------------------------------------ - void ConvertLights(const Model& model); + void ConvertLights(const Model& model, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ - void ConvertCameras(const Model& model); + void ConvertCameras(const Model& model, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ - void ConvertLight(const Model& model, const Light& light); + void ConvertLight( const Light& light, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ - void ConvertCamera(const Model& model, const Camera& cam); + void ConvertCamera( const Camera& cam, const std::string &orig_name ); + + // ------------------------------------------------------------------------------------------------ + void GetUniqueName( const std::string &name, std::string uniqueName ); // ------------------------------------------------------------------------------------------------ // this returns unified names usable within assimp identifiers (i.e. no space characters - @@ -258,18 +263,6 @@ private: // convert animation data to aiAnimation et al void ConvertAnimations(); - // ------------------------------------------------------------------------------------------------ - // rename a node already partially converted. fixed_name is a string previously returned by - // FixNodeName, new_name specifies the string FixNodeName should return on all further invocations - // which would previously have returned the old value. - // - // this also updates names in node animations, cameras and light sources and is thus slow. - // - // NOTE: the caller is responsible for ensuring that the new name is unique and does - // not collide with any other identifiers. The best way to ensure this is to only - // append to the old name, which is guaranteed to match these requirements. - void RenameNode(const std::string& fixed_name, const std::string& new_name); - // ------------------------------------------------------------------------------------------------ // takes a fbx node name and returns the identifier to be used in the assimp output scene. // the function is guaranteed to provide consistent results over multiple invocations @@ -281,7 +274,6 @@ private: // XXX: better use multi_map .. typedef std::map > NodeMap; - // ------------------------------------------------------------------------------------------------ void ConvertAnimationStack(const AnimationStack& st); @@ -432,13 +424,7 @@ private: typedef std::map NodeAnimBitMap; NodeAnimBitMap node_anim_chain_bits; - // name -> has had its prefix_stripped? - typedef std::map NodeNameMap; - NodeNameMap node_names; - - typedef std::map NameNameMap; - NameNameMap renamed_nodes; - + NodeNameCache mNodeNames; double anim_fps; aiScene* const out; diff --git a/code/ScaleProcess.cpp b/code/ScaleProcess.cpp index 0f60fbdb4..facc39d7d 100644 --- a/code/ScaleProcess.cpp +++ b/code/ScaleProcess.cpp @@ -88,13 +88,6 @@ void ScaleProcess::Execute( aiScene* pScene ) { void ScaleProcess::traverseNodes( aiNode *node ) { applyScaling( node ); - - /*for ( unsigned int i = 0; i < node->mNumChildren; ++i ) { - aiNode *currentNode = currentNode->mChildren[ i ]; - if ( nullptr != currentNode ) { - traverseNodes( currentNode ); - } - }*/ } void ScaleProcess::applyScaling( aiNode *currentNode ) { diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index ebb6728f3..f6c0833ee 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -537,9 +537,11 @@ enum aiPostProcessSteps /**
This step will perform a global scale of the model. * * Some importers are providing a mechanism to define a scaling unit for the - * model. This post processing step can be used to do so. + * model. This post processing step can be used to do so. You need to get the + * global scaling from your importer settings like in FBX. Use the flag + * AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY from the global property table to configure this. * - * Use #AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY to control this. + * Use #AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY to setup the global scaing factor. */ aiProcess_GlobalScale = 0x8000000, diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index c4d5fe189..ae858bfe8 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -46,12 +46,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Main.h" +#include +#include +#include + const char* AICMD_MSG_INFO_HELP_E = "assimp info [-r] [-v]\n" "\tPrint basic structure of a 3D model\n" "\t-r,--raw: No postprocessing, do a raw import\n" "\t-v,--verbose: Print verbose info such as node transform data\n"; +const std::string TREE_BRANCH_ASCII = "|-"; +const std::string TREE_BRANCH_UTF8 = "\xe2\x94\x9c\xe2\x95\xb4"; +const std::string TREE_STOP_ASCII = "'-"; +const std::string TREE_STOP_UTF8 = "\xe2\x94\x94\xe2\x95\xb4"; +const std::string TREE_CONTINUE_ASCII = "| "; +const std::string TREE_CONTINUE_UTF8 = "\xe2\x94\x82 "; + +// note: by default this is outputing utf-8 text. +// this is well supported on pretty much any linux terminal. +// if this causes problems on some platform, +// put an #ifdef to use the ascii version for that platform. +const std::string TREE_BRANCH = TREE_BRANCH_UTF8; +const std::string TREE_STOP = TREE_STOP_UTF8; +const std::string TREE_CONTINUE = TREE_CONTINUE_UTF8; + // ----------------------------------------------------------------------------------- unsigned int CountNodes(const aiNode* root) @@ -184,46 +203,77 @@ std::string FindPTypes(const aiScene* scene) } // ----------------------------------------------------------------------------------- -void PrintHierarchy(const aiNode* root, unsigned int maxnest, unsigned int maxline, - unsigned int cline, bool verbose, unsigned int cnest=0) -{ - if (cline++ >= maxline || cnest >= maxnest) { - return; +// Prettily print the node graph to stdout +void PrintHierarchy( + const aiNode* node, + const std::string &indent, + bool verbose, + bool last = false, + bool first = true +){ + // tree visualization + std::string branchchar; + if (first) { branchchar = ""; } + else if (last) { branchchar = TREE_STOP; } // "'-" + else { branchchar = TREE_BRANCH; } // "|-" + + // print the indent and the branch character and the name + std::cout << indent << branchchar << node->mName.C_Str(); + + // if there are meshes attached, indicate this + if (node->mNumMeshes) { + std::cout << " (mesh "; + bool sep = false; + for (size_t i=0; i < node->mNumMeshes; ++i) { + unsigned int mesh_index = node->mMeshes[i]; + if (sep) { std::cout << ", "; } + std::cout << mesh_index; + sep = true; + } + std::cout << ")"; } - for(unsigned int i = 0; i < cnest; ++i) { - printf("-- "); - } - printf("\'%s\', meshes: %u\n",root->mName.data,root->mNumMeshes); + // finish the line + std::cout << std::endl; + // in verbose mode, print the transform data as well if (verbose) { - // print the actual transform - //printf(","); + // indent to use + std::string indentadd; + if (last) { indentadd += " "; } + else { indentadd += TREE_CONTINUE; } // "| ".. + if (node->mNumChildren == 0) { indentadd += " "; } + else { indentadd += TREE_CONTINUE; } // .."| " aiVector3D s, r, t; - root->mTransformation.Decompose(s, r, t); + node->mTransformation.Decompose(s, r, t); if (s.x != 1.0 || s.y != 1.0 || s.z != 1.0) { - for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } - printf(" S:[%f %f %f]\n", s.x, s.y, s.z); + std::cout << indent << indentadd; + printf(" S:[%f %f %f]\n", s.x, s.y, s.z); } if (r.x || r.y || r.z) { - for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } - printf(" R:[%f %f %f]\n", r.x, r.y, r.z); + std::cout << indent << indentadd; + printf(" R:[%f %f %f]\n", r.x, r.y, r.z); } if (t.x || t.y || t.z) { - for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } - printf(" T:[%f %f %f]\n", t.x, t.y, t.z); + std::cout << indent << indentadd; + printf(" T:[%f %f %f]\n", t.x, t.y, t.z); } } - //printf("\n"); - for (unsigned int i = 0; i < root->mNumChildren; ++i ) { - PrintHierarchy(root->mChildren[i],maxnest,maxline,cline,verbose,cnest+1); - if(i == root->mNumChildren-1) { - for(unsigned int i = 0; i < cnest; ++i) { - printf(" "); - } - printf("<--\n"); - } + // and recurse + std::string nextIndent; + if (first) { nextIndent = indent; } + else if (last) { nextIndent = indent + " "; } + else { nextIndent = indent + TREE_CONTINUE; } // "| " + for (size_t i = 0; i < node->mNumChildren; ++i) { + bool lastone = (i == node->mNumChildren - 1); + PrintHierarchy( + node->mChildren[i], + nextIndent, + verbose, + lastone, + false + ); } } @@ -406,8 +456,7 @@ int Assimp_Info (const char* const* params, unsigned int num) // node hierarchy printf("\nNode hierarchy:\n"); - unsigned int cline=0; - PrintHierarchy(scene->mRootNode,20,1000,cline,verbose); + PrintHierarchy(scene->mRootNode,"",verbose); printf("\n"); return 0;