Merge branch 'master' into umw_dev

pull/1863/head
Kim Kulling 2018-04-08 21:42:10 +02:00 committed by GitHub
commit f096843c45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1374 additions and 547 deletions

View File

@ -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)

View File

@ -35,29 +35,29 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki
__Importers__:
- 3D
- 3DS
- 3MF
- [3DS](https://en.wikipedia.org/wiki/.3ds)
- [3MF](https://en.wikipedia.org/wiki/3D_Manufacturing_Format)
- AC
- AC3D
- [AC3D](https://en.wikipedia.org/wiki/AC3D)
- ACC
- AMJ
- ASE
- ASK
- B3D
- BLEND (Blender)
- BVH
- COB
- [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format))
- [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy)
- CMS
- DAE/Collada
- DXF
- COB
- [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA)
- [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF)
- ENFF
- FBX
- glTF 1.0 + GLB
- glTF 2.0
- [FBX](https://en.wikipedia.org/wiki/FBX)
- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB
- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0)
- HMB
- IFC-STEP
- IRR / IRRMESH
- LWO
- [LWO](https://en.wikipedia.org/wiki/LightWave_3D)
- LWS
- LXO
- MD2
@ -70,10 +70,10 @@ __Importers__:
- MS3D
- NDO
- NFF
- OBJ
- OFF
- OGEX
- PLY
- [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
- [OFF](https://en.wikipedia.org/wiki/OFF_(file_format))
- [OGEX](https://en.wikipedia.org/wiki/Open_Game_Engine_Exchange)
- [PLY](https://en.wikipedia.org/wiki/PLY_(file_format))
- PMX
- PRJ
- Q3O
@ -82,19 +82,19 @@ __Importers__:
- SCN
- SIB
- SMD
- STL
- STP
- [STP](https://en.wikipedia.org/wiki/ISO_10303-21)
- [STL](https://en.wikipedia.org/wiki/STL_(file_format))
- TER
- UC
- VTA
- X
- X3D
- [X3D](https://en.wikipedia.org/wiki/X3D)
- XGL
- ZGL
Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
- C4D (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange)
- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange)
__Exporters__:

View File

@ -34,36 +34,18 @@ if( MSVC )
else()
set(MSVC_PREFIX "vc150")
endif()
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" FORCE)
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
else()
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" FORCE)
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" )
endif()
set( ASSIMP_CXX_FLAGS ) # dynamically linked library
if( WIN32 )
# for visual studio linking, most of the time boost dlls will be used
set( ASSIMP_CXX_FLAGS " -DBOOST_ALL_DYN_LINK -DBOOST_ALL_NO_LIB")
endif()
set( ASSIMP_LINK_FLAGS "" )
set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@")
set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@")
set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX})
set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}@CMAKE_DEBUG_POSTFIX@)
# search for the boost version assimp was compiled with
#set(Boost_USE_MULTITHREAD ON)
#set(Boost_USE_STATIC_LIBS OFF)
#set(Boost_USE_STATIC_RUNTIME OFF)
#find_package(Boost ${ASSIMP_Boost_VERSION} EXACT COMPONENTS thread date_time)
#if(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# set( ASSIMP_INCLUDE_DIRS "${ASSIMP_INCLUDE_DIRS}" ${Boost_INCLUDE_DIRS})
#else(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# message(WARNING "Failed to find Boost ${ASSIMP_Boost_VERSION} necessary for assimp")
#endif(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# the boost version assimp was compiled with
set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@")
# for compatibility with pkg-config
set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}")
@ -74,7 +56,6 @@ MARK_AS_ADVANCED(
ASSIMP_LINK_FLAGS
ASSIMP_INCLUDE_DIRS
ASSIMP_LIBRARIES
ASSIMP_Boost_VERSION
ASSIMP_CFLAGS_OTHER
ASSIMP_LDFLAGS_OTHER
ASSIMP_LIBRARY_SUFFIX

View File

@ -71,7 +71,7 @@ static const aiImporterDesc desc = {
0,
0,
0,
"3ds prj"
"3ds prj 3DS PRJ"
};
@ -127,7 +127,7 @@ Discreet3DSImporter::~Discreet3DSImporter() {
// Returns whether the class can handle the format of the given file.
bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
std::string extension = GetExtension(pFile);
if(extension == "3ds" || extension == "prj" ) {
if(extension == "3ds" || extension == "3DS" || extension == "prj"|| extension == "PRJ" ) {
return true;
}

View File

@ -186,6 +186,8 @@ SET( Common_SRCS
Bitmap.cpp
Version.cpp
CreateAnimMesh.cpp
simd.h
simd.cpp
)
SOURCE_GROUP(Common FILES ${Common_SRCS})

View File

@ -47,11 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
#include "COBLoader.h"
#include "COBScene.h"
#include "ConvertToLHProcess.h"
#include <assimp/StreamReader.h>
#include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h>
#include <assimp/LineSplitter.h>
#include <assimp/TinyFormatter.h>
#include <memory>
@ -105,7 +104,7 @@ COBImporter::~COBImporter()
bool COBImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
const std::string& extension = GetExtension(pFile);
if (extension == "cob" || extension == "scn") {
if (extension == "cob" || extension == "scn" || extension == "COB" || extension == "SCN") {
return true;
}
@ -225,6 +224,9 @@ void COBImporter::InternReadFile( const std::string& pFile,
}
pScene->mRootNode = BuildNodes(*root.get(),scene,pScene);
//flip normals after import
FlipWindingOrderProcess flip;
flip.Execute( pScene );
}
// ------------------------------------------------------------------------------------------------
@ -1299,3 +1301,4 @@ void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const
#endif

View File

@ -190,7 +190,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
// when t1, t2, t3 in same position in UV space, just use default UV direction.
if ( 0 == sx && 0 ==sy && 0 == tx && 0 == ty ) {
if ( sx * ty == sy * tx ) {
sx = 0.0; sy = 1.0;
tx = 1.0; ty = 0.0;
}

View File

@ -98,7 +98,7 @@ void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportPrope
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
//void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
// ------------------------------------------------------------------------------------------------
@ -173,7 +173,7 @@ Exporter::ExportFormatEntry gExporters[] =
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ),
//Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ),
Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ),
#endif
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER

View File

@ -61,6 +61,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <iterator>
#include <vector>
#include <sstream>
#include <iomanip>
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<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" );
std::vector<aiNode*> 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<const Model*>( 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<const NodeAttribute*>& node_attrs = model.GetAttributes();
for( const NodeAttribute* attr : node_attrs ) {
const Light* const light = dynamic_cast<const Light*>( 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<const NodeAttribute*>& node_attrs = model.GetAttributes();
for( const NodeAttribute* attr : node_attrs ) {
const Camera* const cam = dynamic_cast<const Camera*>( 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 )

View File

@ -68,6 +68,8 @@ namespace FBX {
class Document;
using NodeNameCache = std::vector<std::string>;
/**
* 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<std::string, std::vector<const AnimationCurveNode*> > NodeMap;
// ------------------------------------------------------------------------------------------------
void ConvertAnimationStack(const AnimationStack& st);
@ -432,19 +424,11 @@ private:
typedef std::map<std::string, unsigned int> NodeAnimBitMap;
NodeAnimBitMap node_anim_chain_bits;
// name -> has had its prefix_stripped?
typedef std::map<std::string, bool> NodeNameMap;
NodeNameMap node_names;
typedef std::map<std::string, std::string> NameNameMap;
NameNameMap renamed_nodes;
NodeNameCache mNodeNames;
double anim_fps;
aiScene* const out;
const FBX::Document& doc;
std::vector<std::string> mLightNames;
};
}

View File

@ -45,9 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXCommon.h"
#include <assimp/StreamWriter.h> // StreamWriterLE
#include <assimp/Exceptional.h> // DeadlyExportError
#include <assimp/ai_assert.h>
#include <assimp/StringUtils.h> // ai_snprintf
#include <string>
#include <ostream>
#include <sstream> // ostringstream
#include <memory> // shared_ptr
// AddP70<type> helpers... there's no usable pattern here,
@ -145,33 +149,174 @@ void FBX::Node::AddP70time(
}
// public member functions for writing nodes to stream
void FBX::Node::Dump(
std::shared_ptr<Assimp::IOStream> outfile,
bool binary, int indent
) {
if (binary) {
Assimp::StreamWriterLE outstream(outfile);
DumpBinary(outstream);
} else {
std::ostringstream ss;
DumpAscii(ss, indent);
std::string s = ss.str();
outfile->Write(s.c_str(), s.size(), 1);
}
}
void FBX::Node::Dump(
Assimp::StreamWriterLE &outstream,
bool binary, int indent
) {
if (binary) {
DumpBinary(outstream);
} else {
std::ostringstream ss;
DumpAscii(ss, indent);
outstream.PutString(ss.str());
}
}
// public member functions for low-level writing
void FBX::Node::Begin(
Assimp::StreamWriterLE &s,
bool binary, int indent
) {
if (binary) {
BeginBinary(s);
} else {
// assume we're at the correct place to start already
(void)indent;
std::ostringstream ss;
BeginAscii(ss, indent);
s.PutString(ss.str());
}
}
void FBX::Node::DumpProperties(
Assimp::StreamWriterLE& s,
bool binary, int indent
) {
if (binary) {
DumpPropertiesBinary(s);
} else {
std::ostringstream ss;
DumpPropertiesAscii(ss, indent);
s.PutString(ss.str());
}
}
void FBX::Node::EndProperties(
Assimp::StreamWriterLE &s,
bool binary, int indent
) {
EndProperties(s, binary, indent, properties.size());
}
void FBX::Node::EndProperties(
Assimp::StreamWriterLE &s,
bool binary, int indent,
size_t num_properties
) {
if (binary) {
EndPropertiesBinary(s, num_properties);
} else {
// nothing to do
(void)indent;
}
}
void FBX::Node::BeginChildren(
Assimp::StreamWriterLE &s,
bool binary, int indent
) {
if (binary) {
// nothing to do
} else {
std::ostringstream ss;
BeginChildrenAscii(ss, indent);
s.PutString(ss.str());
}
}
void FBX::Node::DumpChildren(
Assimp::StreamWriterLE& s,
bool binary, int indent
) {
if (binary) {
DumpChildrenBinary(s);
} else {
std::ostringstream ss;
DumpChildrenAscii(ss, indent);
s.PutString(ss.str());
}
}
void FBX::Node::End(
Assimp::StreamWriterLE &s,
bool binary, int indent,
bool has_children
) {
if (binary) {
EndBinary(s, has_children);
} else {
std::ostringstream ss;
EndAscii(ss, indent, has_children);
s.PutString(ss.str());
}
}
// public member functions for writing to binary fbx
void FBX::Node::Dump(std::shared_ptr<Assimp::IOStream> outfile)
{
Assimp::StreamWriterLE outstream(outfile);
Dump(outstream);
}
void FBX::Node::Dump(Assimp::StreamWriterLE &s)
void FBX::Node::DumpBinary(Assimp::StreamWriterLE &s)
{
// write header section (with placeholders for some things)
Begin(s);
BeginBinary(s);
// write properties
DumpProperties(s);
DumpPropertiesBinary(s);
// go back and fill in property related placeholders
EndProperties(s, properties.size());
EndPropertiesBinary(s, properties.size());
// write children
DumpChildren(s);
DumpChildrenBinary(s);
// finish, filling in end offset placeholder
End(s, !children.empty());
EndBinary(s, force_has_children || !children.empty());
}
void FBX::Node::Begin(Assimp::StreamWriterLE &s)
// public member functions for writing to ascii fbx
void FBX::Node::DumpAscii(std::ostream &s, int indent)
{
// write name
BeginAscii(s, indent);
// write properties
DumpPropertiesAscii(s, indent);
if (force_has_children || !children.empty()) {
// begin children (with a '{')
BeginChildrenAscii(s, indent + 1);
// write children
DumpChildrenAscii(s, indent + 1);
}
// finish (also closing the children bracket '}')
EndAscii(s, indent, force_has_children || !children.empty());
}
// private member functions for low-level writing to fbx
void FBX::Node::BeginBinary(Assimp::StreamWriterLE &s)
{
// remember start pos so we can come back and write the end pos
this->start_pos = s.Tell();
@ -189,26 +334,14 @@ void FBX::Node::Begin(Assimp::StreamWriterLE &s)
this->property_start = s.Tell();
}
void FBX::Node::DumpProperties(Assimp::StreamWriterLE& s)
void FBX::Node::DumpPropertiesBinary(Assimp::StreamWriterLE& s)
{
for (auto &p : properties) {
p.Dump(s);
p.DumpBinary(s);
}
}
void FBX::Node::DumpChildren(Assimp::StreamWriterLE& s)
{
for (FBX::Node& child : children) {
child.Dump(s);
}
}
void FBX::Node::EndProperties(Assimp::StreamWriterLE &s)
{
EndProperties(s, properties.size());
}
void FBX::Node::EndProperties(
void FBX::Node::EndPropertiesBinary(
Assimp::StreamWriterLE &s,
size_t num_properties
) {
@ -222,7 +355,14 @@ void FBX::Node::EndProperties(
s.Seek(pos);
}
void FBX::Node::End(
void FBX::Node::DumpChildrenBinary(Assimp::StreamWriterLE& s)
{
for (FBX::Node& child : children) {
child.DumpBinary(s);
}
}
void FBX::Node::EndBinary(
Assimp::StreamWriterLE &s,
bool has_children
) {
@ -237,48 +377,192 @@ void FBX::Node::End(
}
// static member functions
void FBX::Node::BeginAscii(std::ostream& s, int indent)
{
s << '\n';
for (int i = 0; i < indent; ++i) { s << '\t'; }
s << name << ": ";
}
// convenience function to create and write a property node,
// holding a single property which is an array of values.
// does not copy the data, so is efficient for large arrays.
void FBX::Node::DumpPropertiesAscii(std::ostream &s, int indent)
{
for (size_t i = 0; i < properties.size(); ++i) {
if (i > 0) { s << ", "; }
properties[i].DumpAscii(s, indent);
}
}
void FBX::Node::BeginChildrenAscii(std::ostream& s, int indent)
{
// only call this if there are actually children
s << " {";
(void)indent;
}
void FBX::Node::DumpChildrenAscii(std::ostream& s, int indent)
{
// children will need a lot of padding and corralling
if (children.size() || force_has_children) {
for (size_t i = 0; i < children.size(); ++i) {
// no compression in ascii files, so skip this node if it exists
if (children[i].name == "EncryptionType") { continue; }
// the child can dump itself
children[i].DumpAscii(s, indent);
}
}
}
void FBX::Node::EndAscii(std::ostream& s, int indent, bool has_children)
{
if (!has_children) { return; } // nothing to do
s << '\n';
for (int i = 0; i < indent; ++i) { s << '\t'; }
s << "}";
}
// private helpers for static member functions
// ascii property node from vector of doubles
void FBX::Node::WritePropertyNodeAscii(
const std::string& name,
const std::vector<double>& v,
Assimp::StreamWriterLE& s,
int indent
){
char buffer[32];
FBX::Node node(name);
node.Begin(s, false, indent);
std::string vsize = std::to_string(v.size());
// *<size> {
s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
// indent + 1
for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
// a: value,value,value,...
s.PutString("a: ");
int count = 0;
for (size_t i = 0; i < v.size(); ++i) {
if (i > 0) { s.PutChar(','); }
int len = ai_snprintf(buffer, sizeof(buffer), "%f", v[i]);
count += len;
if (count > 2048) { s.PutChar('\n'); count = 0; }
if (len < 0 || len > 31) {
// this should never happen
throw DeadlyExportError("failed to convert double to string");
}
for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
}
// }
s.PutChar('\n');
for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
s.PutChar('}'); s.PutChar(' ');
node.End(s, false, indent, false);
}
// ascii property node from vector of int32_t
void FBX::Node::WritePropertyNodeAscii(
const std::string& name,
const std::vector<int32_t>& v,
Assimp::StreamWriterLE& s,
int indent
){
char buffer[32];
FBX::Node node(name);
node.Begin(s, false, indent);
std::string vsize = std::to_string(v.size());
// *<size> {
s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
// indent + 1
for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
// a: value,value,value,...
s.PutString("a: ");
int count = 0;
for (size_t i = 0; i < v.size(); ++i) {
if (i > 0) { s.PutChar(','); }
int len = ai_snprintf(buffer, sizeof(buffer), "%d", v[i]);
count += len;
if (count > 2048) { s.PutChar('\n'); count = 0; }
if (len < 0 || len > 31) {
// this should never happen
throw DeadlyExportError("failed to convert double to string");
}
for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
}
// }
s.PutChar('\n');
for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
s.PutChar('}'); s.PutChar(' ');
node.End(s, false, indent, false);
}
// binary property node from vector of doubles
// TODO: optional zip compression!
void FBX::Node::WritePropertyNode(
void FBX::Node::WritePropertyNodeBinary(
const std::string& name,
const std::vector<double>& v,
Assimp::StreamWriterLE& s
){
Node node(name);
node.Begin(s);
FBX::Node node(name);
node.BeginBinary(s);
s.PutU1('d');
s.PutU4(uint32_t(v.size())); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
s.PutU4(uint32_t(v.size()) * 8); // data size
for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
node.EndProperties(s, 1);
node.End(s, false);
node.EndPropertiesBinary(s, 1);
node.EndBinary(s, false);
}
// convenience function to create and write a property node,
// holding a single property which is an array of values.
// does not copy the data, so is efficient for large arrays.
// binary property node from vector of int32_t
// TODO: optional zip compression!
void FBX::Node::WritePropertyNode(
void FBX::Node::WritePropertyNodeBinary(
const std::string& name,
const std::vector<int32_t>& v,
Assimp::StreamWriterLE& s
){
Node node(name);
node.Begin(s);
FBX::Node node(name);
node.BeginBinary(s);
s.PutU1('i');
s.PutU4(uint32_t(v.size())); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
s.PutU4(uint32_t(v.size()) * 4); // data size
for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
node.EndProperties(s, 1);
node.End(s, false);
node.EndPropertiesBinary(s, 1);
node.EndBinary(s, false);
}
// public static member functions
// convenience function to create and write a property node,
// holding a single property which is an array of values.
// does not copy the data, so is efficient for large arrays.
void FBX::Node::WritePropertyNode(
const std::string& name,
const std::vector<double>& v,
Assimp::StreamWriterLE& s,
bool binary, int indent
){
if (binary) {
FBX::Node::WritePropertyNodeBinary(name, v, s);
} else {
FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
}
}
// convenience function to create and write a property node,
// holding a single property which is an array of values.
// does not copy the data, so is efficient for large arrays.
void FBX::Node::WritePropertyNode(
const std::string& name,
const std::vector<int32_t>& v,
Assimp::StreamWriterLE& s,
bool binary, int indent
){
if (binary) {
FBX::Node::WritePropertyNodeBinary(name, v, s);
} else {
FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
}
}
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -66,14 +66,18 @@ public: // public data members
std::vector<FBX::Property> properties; // node properties
std::vector<FBX::Node> children; // child nodes
// some nodes always pretend they have children...
bool force_has_children = false;
public: // constructors
Node() = default;
Node(const std::string& n) : name(n) {}
Node(const std::string& n, const FBX::Property &p)
// convenience template to construct with properties directly
template <typename... More>
Node(const std::string& n, const More... more)
: name(n)
{ properties.push_back(p); }
Node(const std::string& n, const std::vector<FBX::Property> &pv)
: name(n), properties(pv) {}
{ AddProperties(more...); }
public: // functions to add properties or children
// add a single property to the node
@ -138,19 +142,48 @@ public: // support specifically for dealing with Properties70 nodes
public: // member functions for writing data to a file or stream
// write the full node as binary data to the given file or stream
void Dump(std::shared_ptr<Assimp::IOStream> outfile);
void Dump(Assimp::StreamWriterLE &s);
// write the full node to the given file or stream
void Dump(
std::shared_ptr<Assimp::IOStream> outfile,
bool binary, int indent
);
void Dump(Assimp::StreamWriterLE &s, bool binary, int indent);
// these other functions are for writing data piece by piece.
// they must be used carefully.
// for usage examples see FBXExporter.cpp.
void Begin(Assimp::StreamWriterLE &s);
void DumpProperties(Assimp::StreamWriterLE& s);
void EndProperties(Assimp::StreamWriterLE &s);
void EndProperties(Assimp::StreamWriterLE &s, size_t num_properties);
void DumpChildren(Assimp::StreamWriterLE& s);
void End(Assimp::StreamWriterLE &s, bool has_children);
void Begin(Assimp::StreamWriterLE &s, bool binary, int indent);
void DumpProperties(Assimp::StreamWriterLE& s, bool binary, int indent);
void EndProperties(Assimp::StreamWriterLE &s, bool binary, int indent);
void EndProperties(
Assimp::StreamWriterLE &s, bool binary, int indent,
size_t num_properties
);
void BeginChildren(Assimp::StreamWriterLE &s, bool binary, int indent);
void DumpChildren(Assimp::StreamWriterLE& s, bool binary, int indent);
void End(
Assimp::StreamWriterLE &s, bool binary, int indent,
bool has_children
);
private: // internal functions used for writing
void DumpBinary(Assimp::StreamWriterLE &s);
void DumpAscii(Assimp::StreamWriterLE &s, int indent);
void DumpAscii(std::ostream &s, int indent);
void BeginBinary(Assimp::StreamWriterLE &s);
void DumpPropertiesBinary(Assimp::StreamWriterLE& s);
void EndPropertiesBinary(Assimp::StreamWriterLE &s);
void EndPropertiesBinary(Assimp::StreamWriterLE &s, size_t num_properties);
void DumpChildrenBinary(Assimp::StreamWriterLE& s);
void EndBinary(Assimp::StreamWriterLE &s, bool has_children);
void BeginAscii(std::ostream &s, int indent);
void DumpPropertiesAscii(std::ostream &s, int indent);
void BeginChildrenAscii(std::ostream &s, int indent);
void DumpChildrenAscii(std::ostream &s, int indent);
void EndAscii(std::ostream &s, int indent, bool has_children);
private: // data used for binary dumps
size_t start_pos; // starting position in stream
@ -165,11 +198,12 @@ public: // static member functions
static void WritePropertyNode(
const std::string& name,
const T value,
Assimp::StreamWriterLE& s
Assimp::StreamWriterLE& s,
bool binary, int indent
) {
FBX::Property p(value);
FBX::Node node(name, p);
node.Dump(s);
node.Dump(s, binary, indent);
}
// convenience function to create and write a property node,
@ -178,7 +212,8 @@ public: // static member functions
static void WritePropertyNode(
const std::string& name,
const std::vector<double>& v,
Assimp::StreamWriterLE& s
Assimp::StreamWriterLE& s,
bool binary, int indent
);
// convenience function to create and write a property node,
@ -187,8 +222,34 @@ public: // static member functions
static void WritePropertyNode(
const std::string& name,
const std::vector<int32_t>& v,
Assimp::StreamWriterLE& s,
bool binary, int indent
);
private: // static helper functions
static void WritePropertyNodeAscii(
const std::string& name,
const std::vector<double>& v,
Assimp::StreamWriterLE& s,
int indent
);
static void WritePropertyNodeAscii(
const std::string& name,
const std::vector<int32_t>& v,
Assimp::StreamWriterLE& s,
int indent
);
static void WritePropertyNodeBinary(
const std::string& name,
const std::vector<double>& v,
Assimp::StreamWriterLE& s
);
static void WritePropertyNodeBinary(
const std::string& name,
const std::vector<int32_t>& v,
Assimp::StreamWriterLE& s
);
};

View File

@ -48,7 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
#include <sstream> // stringstream
#include <ostream>
#include <locale>
#include <sstream> // ostringstream
// constructors for single element properties
@ -164,18 +166,18 @@ size_t FBX::Property::size()
}
}
void FBX::Property::Dump(Assimp::StreamWriterLE &s)
void FBX::Property::DumpBinary(Assimp::StreamWriterLE &s)
{
s.PutU1(type);
uint8_t* d;
uint8_t* d = data.data();
size_t N;
switch (type) {
case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(data.data()))); return;
case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(data.data()))); return;
case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(data.data()))); return;
case 'F': s.PutF4(*(reinterpret_cast<float*>(data.data()))); return;
case 'D': s.PutF8(*(reinterpret_cast<double*>(data.data()))); return;
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(data.data()))); return;
case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return;
case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return;
case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return;
case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return;
case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return;
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return;
case 'S':
case 'R':
s.PutU4(uint32_t(data.size()));
@ -187,7 +189,6 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
d = data.data();
for (size_t i = 0; i < N; ++i) {
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
}
@ -198,7 +199,6 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
d = data.data();
for (size_t i = 0; i < N; ++i) {
s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
}
@ -209,7 +209,6 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
d = data.data();
for (size_t i = 0; i < N; ++i) {
s.PutF4((reinterpret_cast<float*>(d))[i]);
}
@ -220,18 +219,146 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
d = data.data();
for (size_t i = 0; i < N; ++i) {
s.PutF8((reinterpret_cast<double*>(d))[i]);
}
return;
default:
std::stringstream err;
std::ostringstream err;
err << "Tried to dump property with invalid type '";
err << type << "'!";
throw DeadlyExportError(err.str());
}
}
void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent)
{
std::ostringstream ss;
ss.imbue(std::locale::classic());
ss.precision(15); // this seems to match official FBX SDK exports
DumpAscii(ss, indent);
outstream.PutString(ss.str());
}
void FBX::Property::DumpAscii(std::ostream& s, int indent)
{
// no writing type... or anything. just shove it into the stream.
uint8_t* d = data.data();
size_t N;
size_t swap = data.size();
size_t count = 0;
switch (type) {
case 'C':
if (*(reinterpret_cast<uint8_t*>(d))) { s << 'T'; }
else { s << 'F'; }
return;
case 'Y': s << *(reinterpret_cast<int16_t*>(d)); return;
case 'I': s << *(reinterpret_cast<int32_t*>(d)); return;
case 'F': s << *(reinterpret_cast<float*>(d)); return;
case 'D': s << *(reinterpret_cast<double*>(d)); return;
case 'L': s << *(reinterpret_cast<int64_t*>(d)); return;
case 'S':
// first search to see if it has "\x00\x01" in it -
// which separates fields which are reversed in the ascii version.
// yeah.
// FBX, yeah.
for (size_t i = 0; i < data.size(); ++i) {
if (data[i] == '\0') {
swap = i;
break;
}
}
case 'R':
s << '"';
// we might as well check this now,
// probably it will never happen
for (size_t i = 0; i < data.size(); ++i) {
char c = data[i];
if (c == '"') {
throw runtime_error("can't handle quotes in property string");
}
}
// first write the SWAPPED member (if any)
for (size_t i = swap + 2; i < data.size(); ++i) {
char c = data[i];
s << c;
}
// then a separator
if (swap != data.size()) {
s << "::";
}
// then the initial member
for (size_t i = 0; i < swap; ++i) {
char c = data[i];
s << c;
}
s << '"';
return;
case 'i':
N = data.size() / 4; // number of elements
s << '*' << N << " {\n";
for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
s << "a: ";
for (size_t i = 0; i < N; ++i) {
if (i > 0) { s << ','; }
if (count++ > 120) { s << '\n'; count = 0; }
s << (reinterpret_cast<int32_t*>(d))[i];
}
s << '\n';
for (int i = 0; i < indent; ++i) { s << '\t'; }
s << "} ";
return;
case 'l':
N = data.size() / 8;
s << '*' << N << " {\n";
for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
s << "a: ";
for (size_t i = 0; i < N; ++i) {
if (i > 0) { s << ','; }
if (count++ > 120) { s << '\n'; count = 0; }
s << (reinterpret_cast<int64_t*>(d))[i];
}
s << '\n';
for (int i = 0; i < indent; ++i) { s << '\t'; }
s << "} ";
return;
case 'f':
N = data.size() / 4;
s << '*' << N << " {\n";
for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
s << "a: ";
for (size_t i = 0; i < N; ++i) {
if (i > 0) { s << ','; }
if (count++ > 120) { s << '\n'; count = 0; }
s << (reinterpret_cast<float*>(d))[i];
}
s << '\n';
for (int i = 0; i < indent; ++i) { s << '\t'; }
s << "} ";
return;
case 'd':
N = data.size() / 8;
s << '*' << N << " {\n";
for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
s << "a: ";
// set precision to something that can handle doubles
s.precision(15);
for (size_t i = 0; i < N; ++i) {
if (i > 0) { s << ','; }
if (count++ > 120) { s << '\n'; count = 0; }
s << (reinterpret_cast<double*>(d))[i];
}
s << '\n';
for (int i = 0; i < indent; ++i) { s << '\t'; }
s << "} ";
return;
default:
std::ostringstream err;
err << "Tried to dump property with invalid type '";
err << type << "'!";
throw runtime_error(err.str());
}
}
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
#include <ostream>
#include <type_traits> // is_void
namespace FBX {
@ -113,7 +114,10 @@ public:
size_t size();
// write this property node as binary data to the given stream
void Dump(Assimp::StreamWriterLE &s);
void DumpBinary(Assimp::StreamWriterLE &s);
void DumpAscii(Assimp::StreamWriterLE &s, int indent=0);
void DumpAscii(std::ostream &s, int indent=0);
// note: make sure the ostream is in classic "C" locale
private:
char type;

View File

@ -66,7 +66,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <array>
#include <unordered_set>
#include <iostream> // endl
// RESOURCES:
// https://code.blender.org/2013/08/fbx-binary-file-format-specification/
@ -89,6 +88,8 @@ namespace FBX {
"\xfa\xbc\xab\x09\xd0\xc8\xd4\x66\xb1\x76\xfb\x83\x1c\xf7\x26\x7e";
const std::string FOOT_MAGIC =
"\xf8\x5a\x8c\x6a\xde\xf5\xd9\x7e\xec\xe9\x0c\xe3\x75\x8f\x29\x0b";
const std::string COMMENT_UNDERLINE =
";------------------------------------------------------------------";
}
using namespace Assimp;
@ -115,7 +116,7 @@ namespace Assimp {
// ---------------------------------------------------------------------
// Worker function for exporting a scene to ASCII FBX.
// Prototyped and registered in Exporter.cpp
/*void ExportSceneFBXA (
void ExportSceneFBXA (
const char* pFile,
IOSystem* pIOSystem,
const aiScene* pScene,
@ -126,7 +127,7 @@ namespace Assimp {
// perform ascii export
exporter.ExportAscii(pFile, pIOSystem);
}*/ // TODO
}
} // end of namespace Assimp
@ -194,27 +195,43 @@ void FBXExporter::ExportAscii (
);
}
// this isn't really necessary,
// but the Autodesk FBX SDK puts a similar comment at the top of the file.
// Theirs declares that the file copyright is owned by Autodesk...
std::stringstream head;
using std::endl;
head << "; FBX " << EXPORT_VERSION_STR << " project file" << endl;
head << "; Created by the Open Asset Import Library (Assimp)" << endl;
head << "; http://assimp.org" << endl;
head << "; -------------------------------------------------" << endl;
head << endl;
const std::string ascii_header = head.str();
outfile->Write(ascii_header.c_str(), ascii_header.size(), 1);
// write the ascii header
WriteAsciiHeader();
// write all the sections
WriteAllNodes();
// make sure the file ends with a newline.
// note: if the file is opened in text mode,
// this should do the right cross-platform thing.
outfile->Write("\n", 1, 1);
// explicitly release file pointer,
// so we don't have to rely on class destruction.
outfile.reset();
}
void FBXExporter::WriteAsciiHeader()
{
// basically just a comment at the top of the file
std::stringstream head;
head << "; FBX " << EXPORT_VERSION_STR << " project file\n";
head << "; Created by the Open Asset Import Library (Assimp)\n";
head << "; http://assimp.org\n";
head << "; -------------------------------------------------\n";
const std::string ascii_header = head.str();
outfile->Write(ascii_header.c_str(), ascii_header.size(), 1);
}
void FBXExporter::WriteAsciiSectionHeader(const std::string& title)
{
StreamWriterLE outstream(outfile);
std::stringstream s;
s << "\n\n; " << title << '\n';
s << FBX::COMMENT_UNDERLINE << "\n";
outstream.PutString(s.str());
}
void FBXExporter::WriteBinaryHeader()
{
// first a specific sequence of 23 bytes, always the same
@ -294,28 +311,39 @@ void FBXExporter::WriteAllNodes ()
//FBXHeaderExtension top-level node
void FBXExporter::WriteHeaderExtension ()
{
if (!binary) {
// no title, follows directly from the top comment
}
FBX::Node n("FBXHeaderExtension");
StreamWriterLE outstream(outfile);
int indent = 0;
// begin node
n.Begin(outstream);
n.Begin(outstream, binary, indent);
// write properties
// (none)
// finish properties
n.EndProperties(outstream, 0);
n.EndProperties(outstream, binary, indent, 0);
// begin children
n.BeginChildren(outstream, binary, indent);
indent = 1;
// write child nodes
FBX::Node::WritePropertyNode(
"FBXHeaderVersion", int32_t(1003), outstream
"FBXHeaderVersion", int32_t(1003), outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"FBXVersion", int32_t(EXPORT_VERSION_INT), outstream
);
FBX::Node::WritePropertyNode(
"EncryptionType", int32_t(0), outstream
"FBXVersion", int32_t(EXPORT_VERSION_INT), outstream, binary, indent
);
if (binary) {
FBX::Node::WritePropertyNode(
"EncryptionType", int32_t(0), outstream, binary, indent
);
}
FBX::Node CreationTimeStamp("CreationTimeStamp");
time_t rawtime;
@ -329,36 +357,50 @@ void FBXExporter::WriteHeaderExtension ()
CreationTimeStamp.AddChild("Minute", int32_t(now->tm_min));
CreationTimeStamp.AddChild("Second", int32_t(now->tm_sec));
CreationTimeStamp.AddChild("Millisecond", int32_t(0));
CreationTimeStamp.Dump(outstream);
CreationTimeStamp.Dump(outstream, binary, indent);
std::stringstream creator;
creator << "Open Asset Import Library (Assimp) " << aiGetVersionMajor()
<< "." << aiGetVersionMinor() << "." << aiGetVersionRevision();
FBX::Node::WritePropertyNode("Creator", creator.str(), outstream);
FBX::Node::WritePropertyNode(
"Creator", creator.str(), outstream, binary, indent
);
FBX::Node sceneinfo("SceneInfo");
//FBX::Node sceneinfo("SceneInfo");
//sceneinfo.AddProperty("GlobalInfo" + FBX::SEPARATOR + "SceneInfo");
// not sure if any of this is actually needed,
// so just write an empty node for now.
sceneinfo.Dump(outstream);
//sceneinfo.Dump(outstream, binary, indent);
indent = 0;
// finish node
n.End(outstream, true);
n.End(outstream, binary, indent, true);
// that's it for FBXHeaderExtension...
if (!binary) { return; }
// but binary files also need top-level FileID, CreationTime, Creator:
std::vector<uint8_t> raw(GENERIC_FILEID.size());
for (size_t i = 0; i < GENERIC_FILEID.size(); ++i) {
raw[i] = uint8_t(GENERIC_FILEID[i]);
}
FBX::Node::WritePropertyNode("FileId", raw, outstream);
FBX::Node::WritePropertyNode("CreationTime", GENERIC_CTIME, outstream);
FBX::Node::WritePropertyNode("Creator", creator.str(), outstream);
FBX::Node::WritePropertyNode(
"FileId", raw, outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"CreationTime", GENERIC_CTIME, outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"Creator", creator.str(), outstream, binary, indent
);
}
void FBXExporter::WriteGlobalSettings ()
{
if (!binary) {
// no title, follows directly from the header extension
}
FBX::Node gs("GlobalSettings");
gs.AddChild("Version", int32_t(1000));
@ -385,11 +427,15 @@ void FBXExporter::WriteGlobalSettings ()
p.AddP70int("CurrentTimeMarker", -1);
gs.AddChild(p);
gs.Dump(outfile);
gs.Dump(outfile, binary, 0);
}
void FBXExporter::WriteDocuments ()
{
if (!binary) {
WriteAsciiSectionHeader("Documents Description");
}
// not sure what the use of multiple documents would be,
// or whether any end-application supports it
FBX::Node docs("Documents");
@ -411,15 +457,19 @@ void FBXExporter::WriteDocuments ()
doc.AddChild("RootNode", int64_t(0));
docs.AddChild(doc);
docs.Dump(outfile);
docs.Dump(outfile, binary, 0);
}
void FBXExporter::WriteReferences ()
{
if (!binary) {
WriteAsciiSectionHeader("Document References");
}
// always empty for now.
// not really sure what this is for.
FBX::Node n("References");
n.Dump(outfile);
n.force_has_children = true;
n.Dump(outfile, binary, 0);
}
@ -468,9 +518,6 @@ size_t count_images(const aiScene* scene) {
}
}
}
//for (auto &s : images) {
// std::cout << "found image: " << s << std::endl;
//}
return images.size();
}
@ -510,6 +557,11 @@ void FBXExporter::WriteDefinitions ()
// determining how many of each type of object there are
// and specifying the base properties to use when otherwise unspecified.
// ascii section header
if (!binary) {
WriteAsciiSectionHeader("Object definitions");
}
// we need to count the objects
int32_t count;
int32_t total_count = 0;
@ -520,7 +572,7 @@ void FBXExporter::WriteDefinitions ()
// GlobalSettings
// this seems to always be here in Maya exports
n = FBX::Node("ObjectType", Property("GlobalSettings"));
n = FBX::Node("ObjectType", "GlobalSettings");
count = 1;
n.AddChild("Count", count);
object_nodes.push_back(n);
@ -531,9 +583,9 @@ void FBXExporter::WriteDefinitions ()
// but no harm seems to come of leaving it out.
count = mScene->mNumAnimations;
if (count) {
n = FBX::Node("ObjectType", Property("AnimationStack"));
n = FBX::Node("ObjectType", "AnimationStack");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate", Property("FbxAnimStack"));
pt = FBX::Node("PropertyTemplate", "FbxAnimStack");
p = FBX::Node("Properties70");
p.AddP70string("Description", "");
p.AddP70time("LocalStart", 0);
@ -553,9 +605,9 @@ void FBXExporter::WriteDefinitions ()
// so there will be one per aiAnimation
count = mScene->mNumAnimations;
if (count) {
n = FBX::Node("ObjectType", Property("AnimationLayer"));
n = FBX::Node("ObjectType", "AnimationLayer");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate", Property("FBXAnimLayer"));
pt = FBX::Node("PropertyTemplate", "FBXAnimLayer");
p = FBX::Node("Properties70");
p.AddP70("Weight", "Number", "", "A", double(100));
p.AddP70bool("Mute", 0);
@ -583,9 +635,9 @@ void FBXExporter::WriteDefinitions ()
count = 1; // TODO: select properly
if (count) {
// FbxSkeleton
n = FBX::Node("ObjectType", Property("NodeAttribute"));
n = FBX::Node("ObjectType", "NodeAttribute");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate", Property("FbxSkeleton"));
pt = FBX::Node("PropertyTemplate", "FbxSkeleton");
p = FBX::Node("Properties70");
p.AddP70color("Color", 0.8, 0.8, 0.8);
p.AddP70double("Size", 33.333333333333);
@ -601,9 +653,9 @@ void FBXExporter::WriteDefinitions ()
// <~~ node heirarchy
count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
if (count) {
n = FBX::Node("ObjectType", Property("Model"));
n = FBX::Node("ObjectType", "Model");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate", Property("FbxNode"));
pt = FBX::Node("PropertyTemplate", "FbxNode");
p = FBX::Node("Properties70");
p.AddP70enum("QuaternionInterpolate", 0);
p.AddP70vector("RotationOffset", 0.0, 0.0, 0.0);
@ -698,9 +750,9 @@ void FBXExporter::WriteDefinitions ()
// <~~ aiMesh
count = mScene->mNumMeshes;
if (count) {
n = FBX::Node("ObjectType", Property("Geometry"));
n = FBX::Node("ObjectType", "Geometry");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate", Property("FbxMesh"));
pt = FBX::Node("PropertyTemplate", "FbxMesh");
p = FBX::Node("Properties70");
p.AddP70color("Color", 0, 0, 0);
p.AddP70vector("BBoxMin", 0, 0, 0);
@ -724,7 +776,7 @@ void FBXExporter::WriteDefinitions ()
count = mScene->mNumMaterials;
if (count) {
bool has_phong = has_phong_mat(mScene);
n = FBX::Node("ObjectType", Property("Material"));
n = FBX::Node("ObjectType", "Material");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate");
if (has_phong) {
@ -771,9 +823,9 @@ void FBXExporter::WriteDefinitions ()
// one for each image file.
count = int32_t(count_images(mScene));
if (count) {
n = FBX::Node("ObjectType", Property("Video"));
n = FBX::Node("ObjectType", "Video");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate", Property("FbxVideo"));
pt = FBX::Node("PropertyTemplate", "FbxVideo");
p = FBX::Node("Properties70");
p.AddP70bool("ImageSequence", 0);
p.AddP70int("ImageSequenceOffset", 0);
@ -800,9 +852,9 @@ void FBXExporter::WriteDefinitions ()
// <~~ aiTexture
count = int32_t(count_textures(mScene));
if (count) {
n = FBX::Node("ObjectType", Property("Texture"));
n = FBX::Node("ObjectType", "Texture");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate", Property("FbxFileTexture"));
pt = FBX::Node("PropertyTemplate", "FbxFileTexture");
p = FBX::Node("Properties70");
p.AddP70enum("TextureTypeUse", 0);
p.AddP70numberA("Texture alpha", 1.0);
@ -829,9 +881,9 @@ void FBXExporter::WriteDefinitions ()
// AnimationCurveNode / FbxAnimCurveNode
count = mScene->mNumAnimations * 3;
if (count) {
n = FBX::Node("ObjectType", Property("AnimationCurveNode"));
n = FBX::Node("ObjectType", "AnimationCurveNode");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate", Property("FbxAnimCurveNode"));
pt = FBX::Node("PropertyTemplate", "FbxAnimCurveNode");
p = FBX::Node("Properties70");
p.AddP70("d", "Compound", "", "");
pt.AddChild(p);
@ -843,7 +895,7 @@ void FBXExporter::WriteDefinitions ()
// AnimationCurve / FbxAnimCurve
count = mScene->mNumAnimations * 9;
if (count) {
n = FBX::Node("ObjectType", Property("AnimationCurve"));
n = FBX::Node("ObjectType", "AnimationCurve");
n.AddChild("Count", count);
object_nodes.push_back(n);
total_count += count;
@ -856,7 +908,7 @@ void FBXExporter::WriteDefinitions ()
if (mesh->HasBones()) { ++count; }
}
if (count) {
n = FBX::Node("ObjectType", Property("Pose"));
n = FBX::Node("ObjectType", "Pose");
n.AddChild("Count", count);
object_nodes.push_back(n);
total_count += count;
@ -865,7 +917,7 @@ void FBXExporter::WriteDefinitions ()
// Deformer
count = int32_t(count_deformers(mScene));
if (count) {
n = FBX::Node("ObjectType", Property("Deformer"));
n = FBX::Node("ObjectType", "Deformer");
n.AddChild("Count", count);
object_nodes.push_back(n);
total_count += count;
@ -874,9 +926,9 @@ void FBXExporter::WriteDefinitions ()
// (template)
count = 0;
if (count) {
n = FBX::Node("ObjectType", Property(""));
n = FBX::Node("ObjectType", "");
n.AddChild("Count", count);
pt = FBX::Node("PropertyTemplate", Property(""));
pt = FBX::Node("PropertyTemplate", "");
p = FBX::Node("Properties70");
pt.AddChild(p);
n.AddChild(pt);
@ -889,7 +941,7 @@ void FBXExporter::WriteDefinitions ()
defs.AddChild("Version", int32_t(100));
defs.AddChild("Count", int32_t(total_count));
for (auto &n : object_nodes) { defs.AddChild(n); }
defs.Dump(outfile);
defs.Dump(outfile, binary, 0);
}
@ -935,14 +987,20 @@ int64_t to_ktime(double ticks, const aiAnimation* anim) {
void FBXExporter::WriteObjects ()
{
if (!binary) {
WriteAsciiSectionHeader("Object properties");
}
// numbers should match those given in definitions! make sure to check
StreamWriterLE outstream(outfile);
FBX::Node object_node("Objects");
object_node.Begin(outstream);
object_node.EndProperties(outstream);
int indent = 0;
object_node.Begin(outstream, binary, indent);
object_node.EndProperties(outstream, binary, indent);
object_node.BeginChildren(outstream, binary, indent);
// geometry (aiMesh)
mesh_uids.clear();
indent = 1;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
// it's all about this mesh
aiMesh* m = mScene->mMeshes[mi];
@ -954,9 +1012,11 @@ void FBXExporter::WriteObjects ()
n.AddProperty(uid);
n.AddProperty(FBX::SEPARATOR + "Geometry");
n.AddProperty("Mesh");
n.Begin(outstream);
n.DumpProperties(outstream);
n.EndProperties(outstream);
n.Begin(outstream, binary, indent);
n.DumpProperties(outstream, binary, indent);
n.EndProperties(outstream, binary, indent);
n.BeginChildren(outstream, binary, indent);
indent = 2;
// output vertex data - each vertex should be unique (probably)
std::vector<double> flattened_vertices;
@ -980,7 +1040,7 @@ void FBXExporter::WriteObjects ()
}
}
FBX::Node::WritePropertyNode(
"Vertices", flattened_vertices, outstream
"Vertices", flattened_vertices, outstream, binary, indent
);
// output polygon data as a flattened array of vertex indices.
@ -996,30 +1056,38 @@ void FBXExporter::WriteObjects ()
);
}
FBX::Node::WritePropertyNode(
"PolygonVertexIndex", polygon_data, outstream
"PolygonVertexIndex", polygon_data, outstream, binary, indent
);
// here could be edges but they're insane.
// it's optional anyway, so let's ignore it.
FBX::Node::WritePropertyNode(
"GeometryVersion", int32_t(124), outstream
"GeometryVersion", int32_t(124), outstream, binary, indent
);
// normals, if any
if (m->HasNormals()) {
FBX::Node normals("LayerElementNormal", Property(int32_t(0)));
normals.Begin(outstream);
normals.DumpProperties(outstream);
normals.EndProperties(outstream);
FBX::Node::WritePropertyNode("Version", int32_t(101), outstream);
FBX::Node::WritePropertyNode("Name", "", outstream);
FBX::Node normals("LayerElementNormal", int32_t(0));
normals.Begin(outstream, binary, indent);
normals.DumpProperties(outstream, binary, indent);
normals.EndProperties(outstream, binary, indent);
normals.BeginChildren(outstream, binary, indent);
indent = 3;
FBX::Node::WritePropertyNode(
"MappingInformationType", "ByPolygonVertex", outstream
"Version", int32_t(101), outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"Name", "", outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"MappingInformationType", "ByPolygonVertex",
outstream, binary, indent
);
// TODO: vertex-normals or indexed normals when appropriate
FBX::Node::WritePropertyNode(
"ReferenceInformationType", "Direct", outstream
"ReferenceInformationType", "Direct",
outstream, binary, indent
);
std::vector<double> normal_data;
normal_data.reserve(3 * polygon_data.size());
@ -1032,10 +1100,13 @@ void FBXExporter::WriteObjects ()
normal_data.push_back(n.z);
}
}
FBX::Node::WritePropertyNode("Normals", normal_data, outstream);
FBX::Node::WritePropertyNode(
"Normals", normal_data, outstream, binary, indent
);
// note: version 102 has a NormalsW also... not sure what it is,
// so we can stick with version 101 for now.
normals.End(outstream, true);
indent = 2;
normals.End(outstream, binary, indent, true);
}
// uvs, if any
@ -1055,19 +1126,27 @@ void FBXExporter::WriteObjects ()
err << " but may be incorrectly interpreted on load.";
DefaultLogger::get()->warn(err.str());
}
FBX::Node uv("LayerElementUV", Property(int32_t(uvi)));
uv.Begin(outstream);
uv.DumpProperties(outstream);
uv.EndProperties(outstream);
FBX::Node::WritePropertyNode("Version", int32_t(101), outstream);
FBX::Node uv("LayerElementUV", int32_t(uvi));
uv.Begin(outstream, binary, indent);
uv.DumpProperties(outstream, binary, indent);
uv.EndProperties(outstream, binary, indent);
uv.BeginChildren(outstream, binary, indent);
indent = 3;
FBX::Node::WritePropertyNode(
"Version", int32_t(101), outstream, binary, indent
);
// it doesn't seem like assimp keeps the uv map name,
// so just leave it blank.
FBX::Node::WritePropertyNode("Name", "", outstream);
FBX::Node::WritePropertyNode(
"MappingInformationType", "ByPolygonVertex", outstream
"Name", "", outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"ReferenceInformationType", "IndexToDirect", outstream
"MappingInformationType", "ByPolygonVertex",
outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"ReferenceInformationType", "IndexToDirect",
outstream, binary, indent
);
std::vector<double> uv_data;
@ -1092,27 +1171,32 @@ void FBXExporter::WriteObjects ()
}
}
}
FBX::Node::WritePropertyNode("UV", uv_data, outstream);
FBX::Node::WritePropertyNode("UVIndex", uv_indices, outstream);
uv.End(outstream, true);
FBX::Node::WritePropertyNode(
"UV", uv_data, outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"UVIndex", uv_indices, outstream, binary, indent
);
indent = 2;
uv.End(outstream, binary, indent, true);
}
// i'm not really sure why this material section exists,
// as the material is linked via "Connections".
// it seems to always have the same "0" value.
FBX::Node mat("LayerElementMaterial", Property(int32_t(0)));
FBX::Node mat("LayerElementMaterial", int32_t(0));
mat.AddChild("Version", int32_t(101));
mat.AddChild("Name", "");
mat.AddChild("MappingInformationType", "AllSame");
mat.AddChild("ReferenceInformationType", "IndexToDirect");
std::vector<int32_t> mat_indices = {0};
mat.AddChild("Materials", mat_indices);
mat.Dump(outstream);
mat.Dump(outstream, binary, indent);
// finally we have the layer specifications,
// which select the normals / UV set / etc to use.
// TODO: handle multiple uv sets correctly?
FBX::Node layer("Layer", Property(int32_t(0)));
FBX::Node layer("Layer", int32_t(0));
layer.AddChild("Version", int32_t(100));
FBX::Node le("LayerElement");
le.AddChild("Type", "LayerElementNormal");
@ -1126,10 +1210,11 @@ void FBXExporter::WriteObjects ()
le.AddChild("Type", "LayerElementUV");
le.AddChild("TypedIndex", int32_t(0));
layer.AddChild(le);
layer.Dump(outstream);
layer.Dump(outstream, binary, indent);
// finish the node record
n.End(outstream, true);
indent = 1;
n.End(outstream, binary, indent, true);
}
// aiMaterial
@ -1273,7 +1358,7 @@ void FBXExporter::WriteObjects ()
n.AddChild(p);
n.Dump(outstream);
n.Dump(outstream, binary, indent);
}
// we need to look up all the images we're using,
@ -1321,7 +1406,7 @@ void FBXExporter::WriteObjects ()
n.AddChild("UseMipMap", int32_t(0));
n.AddChild("Filename", path);
n.AddChild("RelativeFilename", path);
n.Dump(outstream);
n.Dump(outstream, binary, indent);
}
// Textures
@ -1408,14 +1493,12 @@ void FBXExporter::WriteObjects ()
const int64_t texture_uid = generate_uid();
// link the texture to the material
FBX::Node c("C");
c.AddProperties("OP", texture_uid, material_uid, prop_name);
connections.push_back(c);
connections.emplace_back(
"C", "OP", texture_uid, material_uid, prop_name
);
// link the image data to the texture
c = FBX::Node("C");
c.AddProperties("OO", image_uid, texture_uid);
connections.push_back(c);
connections.emplace_back("C", "OO", image_uid, texture_uid);
// now write the actual texture node
FBX::Node tnode("Texture");
@ -1438,11 +1521,11 @@ void FBXExporter::WriteObjects ()
tnode.AddChild("RelativeFilename", texture_path);
tnode.AddChild("ModelUVTranslation", double(0.0), double(0.0));
tnode.AddChild("ModelUVScaling", double(1.0), double(1.0));
tnode.AddChild("Texture_Alpha_Soutce", "None");
tnode.AddChild("Texture_Alpha_Source", "None");
tnode.AddChild(
"Cropping", int32_t(0), int32_t(0), int32_t(0), int32_t(0)
);
tnode.Dump(outstream);
tnode.Dump(outstream, binary, indent);
}
}
@ -1595,12 +1678,10 @@ void FBXExporter::WriteObjects ()
// "acuracy"... this is not a typo....
dnode.AddChild("Link_DeformAcuracy", double(50));
dnode.AddChild("SkinningType", "Linear"); // TODO: other modes?
dnode.Dump(outstream);
dnode.Dump(outstream, binary, indent);
// connect it
FBX::Node c("C");
c.AddProperties("OO", deformer_uid, mesh_uids[mi]);
connections.push_back(c); // TODO: emplace_back
connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
// we will be indexing by vertex...
// but there might be a different number of "vertices"
@ -1703,7 +1784,7 @@ void FBXExporter::WriteObjects ()
// this should be the same as the bone's mOffsetMatrix.
// if it's not the same, the skeleton isn't in the bind pose.
const float epsilon = 1e-5f; // some error is to be expected
const float epsilon = 1e-4f; // some error is to be expected
bool bone_xform_okay = true;
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
not_in_bind_pose.insert(b);
@ -1741,17 +1822,17 @@ void FBXExporter::WriteObjects ()
// there's not really any way around this at the moment.
// done
sdnode.Dump(outstream);
sdnode.Dump(outstream, binary, indent);
// lastly, connect to the parent deformer
c = FBX::Node("C");
c.AddProperties("OO", subdeformer_uid, deformer_uid);
connections.push_back(c); // TODO: emplace_back
connections.emplace_back(
"C", "OO", subdeformer_uid, deformer_uid
);
// we also need to connect the limb node to the subdeformer.
c = FBX::Node("C");
c.AddProperties("OO", node_uids[bone_node], subdeformer_uid);
connections.push_back(c); // TODO: emplace_back
connections.emplace_back(
"C", "OO", node_uids[bone_node], subdeformer_uid
);
}
// if we cannot create a valid FBX file, simply die.
@ -1859,7 +1940,7 @@ void FBXExporter::WriteObjects ()
}
// now write it
bpnode.Dump(outstream);
bpnode.Dump(outstream, binary, indent);
}*/
// TODO: cameras, lights
@ -1918,11 +1999,8 @@ void FBXExporter::WriteObjects ()
// this node absurdly always pretends it has children
// (in this case it does, but just in case...)
asnode.Begin(outstream);
asnode.DumpProperties(outstream);
asnode.EndProperties(outstream);
asnode.DumpChildren(outstream);
asnode.End(outstream, true);
asnode.force_has_children = true;
asnode.Dump(outstream, binary, indent);
// note: animation stacks are not connected to anything
}
@ -1936,16 +2014,13 @@ void FBXExporter::WriteObjects ()
alnode.AddProperties(animlayer_uid, FBX::SEPARATOR + "AnimLayer", "");
// this node absurdly always pretends it has children
alnode.Begin(outstream);
alnode.DumpProperties(outstream);
alnode.EndProperties(outstream);
alnode.DumpChildren(outstream);
alnode.End(outstream, true);
alnode.force_has_children = true;
alnode.Dump(outstream, binary, indent);
// connect to the relevant animstack
FBX::Node c("C");
c.AddProperties("OO", animlayer_uid, animation_stack_uids[ai]);
connections.push_back(c); // TODO: emplace_back
connections.emplace_back(
"C", "OO", animlayer_uid, animation_stack_uids[ai]
);
}
// AnimCurveNode - three per aiNodeAnim
@ -2057,7 +2132,8 @@ void FBXExporter::WriteObjects ()
}
}
object_node.End(outstream, true);
indent = 0;
object_node.End(outstream, binary, indent, true);
}
// convenience map of magic node name strings to FBX properties,
@ -2083,13 +2159,14 @@ const std::map<std::string,std::pair<std::string,char>> transform_types = {
};
// write a single model node to the stream
void WriteModelNode(
void FBXExporter::WriteModelNode(
StreamWriterLE& outstream,
bool binary,
const aiNode* node,
int64_t node_uid,
const std::string& type,
const std::vector<std::pair<std::string,aiVector3D>>& transform_chain,
TransformInheritance inherit_type=TransformInheritance_RSrs
TransformInheritance inherit_type
){
const aiVector3D zero = {0, 0, 0};
const aiVector3D one = {1, 1, 1};
@ -2157,7 +2234,7 @@ void WriteModelNode(
m.AddChild("Shading", Property(true));
m.AddChild("Culling", Property("CullingOff"));
m.Dump(outstream);
m.Dump(outstream, binary, 1);
}
// wrapper for WriteModelNodes to create and pass a blank transform chain
@ -2181,15 +2258,6 @@ void FBXExporter::WriteModelNodes(
// first collapse any expanded transformation chains created by FBX import.
std::string node_name(node->mName.C_Str());
if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
if (node->mNumChildren != 1) {
// this should never happen
std::stringstream err;
err << "FBX transformation node should have exactly 1 child,";
err << " but " << node->mNumChildren << " found";
err << " on node \"" << node_name << "\"!";
throw DeadlyExportError(err.str());
}
aiNode* next_node = node->mChildren[0];
auto pos = node_name.find(MAGIC_NODE_TAG) + MAGIC_NODE_TAG.size() + 1;
std::string type_name = node_name.substr(pos);
auto elem = transform_types.find(type_name);
@ -2223,10 +2291,16 @@ void FBXExporter::WriteModelNodes(
err << elem->second.second;
throw DeadlyExportError(err.str());
}
// now just continue to the next node
WriteModelNodes(
outstream, next_node, parent_uid, limbnodes, transform_chain
);
// now continue on to any child nodes
for (unsigned i = 0; i < node->mNumChildren; ++i) {
WriteModelNodes(
outstream,
node->mChildren[i],
parent_uid,
limbnodes,
transform_chain
);
}
return;
}
@ -2240,9 +2314,7 @@ void FBXExporter::WriteModelNodes(
node_uid = generate_uid();
node_uids[node] = node_uid;
}
FBX::Node c("C");
c.AddProperties("OO", node_uid, parent_uid);
connections.push_back(c);
connections.emplace_back("C", "OO", node_uid, parent_uid);
}
// what type of node is this?
@ -2250,21 +2322,23 @@ void FBXExporter::WriteModelNodes(
// handled later
} else if (node->mNumMeshes == 1) {
// connect to child mesh, which should have been written previously
FBX::Node c("C");
c.AddProperties("OO", mesh_uids[node->mMeshes[0]], node_uid);
connections.push_back(c);
connections.emplace_back(
"C", "OO", mesh_uids[node->mMeshes[0]], node_uid
);
// also connect to the material for the child mesh
c = FBX::Node("C");
c.AddProperties(
"OO",
connections.emplace_back(
"C", "OO",
material_uids[mScene->mMeshes[node->mMeshes[0]]->mMaterialIndex],
node_uid
);
connections.push_back(c);
// write model node
WriteModelNode(outstream, node, node_uid, "Mesh", transform_chain);
WriteModelNode(
outstream, binary, node, node_uid, "Mesh", transform_chain
);
} else if (limbnodes.count(node)) {
WriteModelNode(outstream, node, node_uid, "LimbNode", transform_chain);
WriteModelNode(
outstream, binary, node, node_uid, "LimbNode", transform_chain
);
// we also need to write a nodeattribute to mark it as a skeleton
int64_t node_attribute_uid = generate_uid();
FBX::Node na("NodeAttribute");
@ -2272,14 +2346,14 @@ void FBXExporter::WriteModelNodes(
node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode"
);
na.AddChild("TypeFlags", Property("Skeleton"));
na.Dump(outstream);
na.Dump(outstream, binary, 1);
// and connect them
FBX::Node c("C");
c.AddProperties("OO", node_attribute_uid, node_uid);
connections.push_back(c);
connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
} else {
// generate a null node so we can add children to it
WriteModelNode(outstream, node, node_uid, "Null", transform_chain);
WriteModelNode(
outstream, binary, node, node_uid, "Null", transform_chain
);
}
// if more than one child mesh, make nodes for each mesh
@ -2288,23 +2362,19 @@ void FBXExporter::WriteModelNodes(
// make a new model node
int64_t new_node_uid = generate_uid();
// connect to parent node
FBX::Node c("C");
c.AddProperties("OO", new_node_uid, node_uid);
connections.push_back(c);
connections.emplace_back("C", "OO", new_node_uid, node_uid);
// connect to child mesh, which should have been written previously
c = FBX::Node("C");
c.AddProperties("OO", mesh_uids[node->mMeshes[i]], new_node_uid);
connections.push_back(c);
connections.emplace_back(
"C", "OO", mesh_uids[node->mMeshes[i]], new_node_uid
);
// also connect to the material for the child mesh
c = FBX::Node("C");
c.AddProperties(
"OO",
connections.emplace_back(
"C", "OO",
material_uids[
mScene->mMeshes[node->mMeshes[i]]->mMaterialIndex
],
new_node_uid
);
connections.push_back(c);
// write model node
FBX::Node m("Model");
// take name from mesh name, if it exists
@ -2315,7 +2385,7 @@ void FBXExporter::WriteModelNodes(
FBX::Node p("Properties70");
p.AddP70enum("InheritType", 1);
m.AddChild(p);
m.Dump(outstream);
m.Dump(outstream, binary, 1);
}
}
@ -2344,15 +2414,11 @@ void FBXExporter::WriteAnimationCurveNode(
p.AddP70numberA("d|Y", default_value.y);
p.AddP70numberA("d|Z", default_value.z);
n.AddChild(p);
n.Dump(outstream);
n.Dump(outstream, binary, 1);
// connect to layer
FBX::Node cl("C");
cl.AddProperties("OO", uid, layer_uid);
this->connections.push_back(cl); // TODO: emplace_back
this->connections.emplace_back("C", "OO", uid, layer_uid);
// connect to bone
FBX::Node cb("C");
cb.AddProperties("OP", uid, node_uid, property_name);
this->connections.push_back(cb); // TODO: emplace_back
this->connections.emplace_back("C", "OP", uid, node_uid, property_name);
}
@ -2379,10 +2445,10 @@ void FBXExporter::WriteAnimationCurve(
"KeyAttrRefCount",
std::vector<int32_t>{static_cast<int32_t>(times.size())}
);
n.Dump(outstream);
FBX::Node c("C");
c.AddProperties("OP", curve_uid, curvenode_uid, property_link);
this->connections.push_back(c); // TODO: emplace_back
n.Dump(outstream, binary, 1);
this->connections.emplace_back(
"C", "OP", curve_uid, curvenode_uid, property_link
);
}
@ -2390,13 +2456,18 @@ void FBXExporter::WriteConnections ()
{
// we should have completed the connection graph already,
// so basically just dump it here
if (!binary) {
WriteAsciiSectionHeader("Object connections");
}
// TODO: comments with names in the ascii version
FBX::Node conn("Connections");
StreamWriterLE outstream(outfile);
conn.Begin(outstream);
conn.Begin(outstream, binary, 0);
conn.BeginChildren(outstream, binary, 0);
for (auto &n : connections) {
n.Dump(outstream);
n.Dump(outstream, binary, 1);
}
conn.End(outstream, !connections.empty());
conn.End(outstream, binary, 0, !connections.empty());
connections.clear();
}

View File

@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
#include "FBXExportNode.h" // FBX::Node
#include "FBXCommon.h" // FBX::TransformInheritance
#include <assimp/types.h>
//#include <assimp/material.h>
@ -104,6 +105,9 @@ namespace Assimp
void WriteBinaryHeader();
void WriteBinaryFooter();
// ascii files have a comment at the top
void WriteAsciiHeader();
// WriteAllNodes does the actual export.
// It just calls all the Write<Section> methods below in order.
void WriteAllNodes();
@ -126,6 +130,7 @@ namespace Assimp
// WriteTakes(); // deprecated since at least 2015 (fbx 7.4)
// helpers
void WriteAsciiSectionHeader(const std::string& title);
void WriteModelNodes(
Assimp::StreamWriterLE& s,
const aiNode* node,
@ -139,6 +144,15 @@ namespace Assimp
const std::unordered_set<const aiNode*>& limbnodes,
std::vector<std::pair<std::string,aiVector3D>>& transform_chain
);
void WriteModelNode( // nor this
StreamWriterLE& s,
bool binary,
const aiNode* node,
int64_t node_uid,
const std::string& type,
const std::vector<std::pair<std::string,aiVector3D>>& xfm_chain,
FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs
);
void WriteAnimationCurveNode(
StreamWriterLE& outstream,
int64_t uid,

View File

@ -42,22 +42,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Stuff to deal with aiScene::mPrivate
*/
#pragma once
#ifndef AI_SCENEPRIVATE_H_INCLUDED
#define AI_SCENEPRIVATE_H_INCLUDED
#include <assimp/ai_assert.h>
#include <assimp/scene.h>
namespace Assimp {
namespace Assimp {
// Forward declarations
class Importer;
struct ScenePrivateData {
ScenePrivateData()
: mOrigImporter()
, mPPStepsApplied()
, mIsCopy()
{}
: mOrigImporter( nullptr )
, mPPStepsApplied( 0 )
, mIsCopy( false ) {
// empty
}
// Importer that originally loaded the scene though the C-API
// If set, this object is owned by this private data instance.
@ -75,14 +78,24 @@ struct ScenePrivateData {
};
// Access private data stored in the scene
inline ScenePrivateData* ScenePriv(aiScene* in) {
inline
ScenePrivateData* ScenePriv(aiScene* in) {
ai_assert( nullptr != in );
if ( nullptr == in ) {
return nullptr;
}
return static_cast<ScenePrivateData*>(in->mPrivate);
}
inline const ScenePrivateData* ScenePriv(const aiScene* in) {
inline
const ScenePrivateData* ScenePriv(const aiScene* in) {
ai_assert( nullptr != in );
if ( nullptr == in ) {
return nullptr;
}
return static_cast<const ScenePrivateData*>(in->mPrivate);
}
}
} // Namespace Assimp
#endif
#endif // AI_SCENEPRIVATE_H_INCLUDED

View File

@ -316,11 +316,9 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
std::string path = tex.C_Str();
if (path.size() > 0) {
if (path[0] != '*') {
std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
if (it != mTexturesByPath.end()) {
texture = mAsset->textures.Get(it->second);
}
std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
if (it != mTexturesByPath.end()) {
texture = mAsset->textures.Get(it->second);
}
if (!texture) {

78
code/simd.cpp 100644
View File

@ -0,0 +1,78 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2018, 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.
---------------------------------------------------------------------------
*/
#include "simd.h"
namespace Assimp {
bool CPUSupportsSSE2() {
#if defined(__x86_64__) || defined(_M_X64)
//* x86_64 always has SSE2 instructions */
return true;
#elif defined(__GNUC__) && defined(i386)
// for GCC x86 we check cpuid
unsigned int d;
__asm__(
"pushl %%ebx\n\t"
"cpuid\n\t"
"popl %%ebx\n\t"
: "=d" ( d )
:"a" ( 1 ) );
return ( d & 0x04000000 ) != 0;
#elif (defined(_MSC_VER) && defined(_M_IX86))
// also check cpuid for MSVC x86
unsigned int d;
__asm {
xor eax, eax
inc eax
push ebx
cpuid
pop ebx
mov d, edx
}
return ( d & 0x04000000 ) != 0;
#else
return false;
#endif
}
} // Namespace Assimp

53
code/simd.h 100644
View File

@ -0,0 +1,53 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2018, 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.
---------------------------------------------------------------------------
*/
#pragma once
#include <assimp/defs.h>
namespace Assimp {
/// @brief Checks if the platform supports SSE2 optimization
/// @return true, if SSE2 is supported. false if SSE2 is not supported.
bool ASSIMP_API CPUSupportsSSE2();
} // Namespace Assimp

View File

@ -283,7 +283,6 @@ public:
return *this;
}
private:
// ---------------------------------------------------------------------
/** Generic read method. ByteSwap::Swap(T*) *must* be defined */
template <typename T>
@ -300,6 +299,7 @@ private:
return f;
}
private:
// ---------------------------------------------------------------------
void InternBegin() {
if (!stream) {

View File

@ -203,6 +203,12 @@ public:
Put(n);
}
// ---------------------------------------------------------------------
/** Write a single character to the stream */
void PutChar(char c) {
Put(c);
}
// ---------------------------------------------------------------------
/** Write an aiString to the stream */
void PutString(const aiString& s)
@ -249,8 +255,6 @@ public:
cursor = new_cursor;
}
private:
// ---------------------------------------------------------------------
/** Generic write method. ByteSwap::Swap(T*) *must* be defined */
template <typename T>

View File

@ -53,6 +53,7 @@ endif()
LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib )
SET( COMMON
unit/utSimd.cpp
unit/utIOSystem.cpp
unit/utIOStreamBuffer.cpp
unit/utIssues.cpp

View File

@ -45,5 +45,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace ::Assimp;
AbstractImportExportBase::~AbstractImportExportBase() {
// empty
// empty
}

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2018, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -106,4 +104,4 @@ TEST_F( utAnim, aiAnimationTest ) {
ok = false;
}
EXPECT_TRUE( ok );
}
}

View File

@ -0,0 +1,62 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2018, 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.
---------------------------------------------------------------------------
*/
#include "UnitTestPCH.h"
#include "simd.h"
using namespace ::Assimp;
class utSimd : public ::testing::Test {
protected:
// empty
};
TEST_F( utSimd, SSE2SupportedTest ) {
bool isSupported;
isSupported = CPUSupportsSSE2();
if ( isSupported ) {
std::cout << "Supported" << std::endl;
} else {
std::cout << "Not supported" << std::endl;
}
}

View File

@ -46,12 +46,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Main.h"
#include <cstdio>
#include <iostream>
#include <string>
const char* AICMD_MSG_INFO_HELP_E =
"assimp info <file> [-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;

View File

@ -560,6 +560,30 @@ void CGLView::Enable_Textures(const bool pEnable)
}
}
void CGLView::Enable_Axes(const bool pEnable){
if(pEnable)
{
this->mAxesEnabled = true;
}
else
{
this->mAxesEnabled = false;
}
}
void CGLView::Enable_Reload_Textures(const bool pEnable)
{
if(pEnable)
{
this->mReloadTexturesEnabled = true;
// this->mScene->ImportTextures(this->mScene->pScenePath);
}
else
{
this->mReloadTexturesEnabled = false;
}
}
/********************************************************************/
/*********************** Override functions ************************/
/********************************************************************/
@ -609,6 +633,7 @@ void CGLView::drawCoordSystem() {
// Z, -Z
qglColor(QColor(Qt::blue)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, 100000.0);
qglColor(QColor(Qt::yellow)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, -100000.0);
qglColor(QColor(Qt::white));
glEnd();
}
@ -629,7 +654,10 @@ void CGLView::paintGL()
if ( mLightingEnabled ) {
glDisable( GL_LIGHTING );///TODO: display list
}
drawCoordSystem();
if (this->mAxesEnabled == true)
{
drawCoordSystem();
}
glDisable(GL_COLOR_MATERIAL);
if(mLightingEnabled) glEnable(GL_LIGHTING);

View File

@ -75,7 +75,9 @@ private:
};
public:
bool mAxesEnabled = true;
// Textures
bool mReloadTexturesEnabled = false; // If true then textures will reload when the window is activated.
/// \enum ELightType
/// Type of light source.
enum class ELightType { Directional, Point, Spot };
@ -155,7 +157,6 @@ private:
GLdouble mCamera_Viewport_AspectRatio;///< Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height).
// Lighting
bool mLightingEnabled = false;///< If true then OpenGL lighting is enabled (glEnable(GL_LIGHTING)), if false - disabled.
// Textures
///TODO: map is goooood, but not for case when one image can be used in different materials with difference in: texture transformation, targeting of the
/// texture (ambient or emission, or even height map), texture properties.
QMap<QString, GLuint> mTexture_IDMap;///< Map image filenames to textures ID's.
@ -306,6 +307,12 @@ public:
/// \param [in] pEnable - if true then enable textures, false - disable textures.
void Enable_Textures(const bool pEnable);
void Enable_Axes(const bool pEnable);
/// \fn void Enable_Textures(const bool pEnable)
/// Control textures drawing.
/// \param [in] pEnable - if true then enable textures, false - disable textures.
void Enable_Reload_Textures(const bool pEnable);
/********************************************************************/
/******************** Lighting control functions ********************/
/********************************************************************/

View File

@ -48,6 +48,7 @@ QTime time_begin = QTime::currentTime();
ui->cbxLighting->setChecked(true); mGLView->Lighting_Enable();
ui->cbxBBox->setChecked(false); mGLView->Enable_SceneBBox(false);
ui->cbxTextures->setChecked(true); mGLView->Enable_Textures(true);
ui->cbxReloadTextures->setChecked(true); mGLView->Enable_Reload_Textures(false);
//
// Fill info labels
//
@ -194,6 +195,13 @@ GLfloat step;
/********************************************************************/
/********************** Constructor/Destructor **********************/
/********************************************************************/
bool MainWindow::event(QEvent *e)
{
if (e->type() == QEvent::WindowActivate && this->mGLView->mReloadTexturesEnabled == true) {
qInfo() << "Window Activated";
}
return QWidget::event(e);
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow),
@ -364,6 +372,18 @@ void MainWindow::on_cbxBBox_clicked(bool checked)
mGLView->updateGL();
}
void MainWindow::on_cbxDrawAxes_clicked(bool checked)
{
mGLView->Enable_Axes(checked);
mGLView->updateGL();
}
void MainWindow::on_cbxReloadTextures_clicked(bool checked)
{
mGLView->Enable_Reload_Textures(checked);
mGLView->updateGL();
}
void MainWindow::on_cbxTextures_clicked(bool checked)
{
mGLView->Enable_Textures(checked);

View File

@ -90,7 +90,7 @@ protected:
/// \param [in] pEvent - pointer to event data.
void keyPressEvent(QKeyEvent* pEvent) override;
bool event(QEvent*);
public:
/********************************************************************/
@ -133,4 +133,6 @@ private slots:
void on_lstCamera_clicked(const QModelIndex &index);
void on_cbxBBox_clicked(bool checked);
void on_cbxTextures_clicked(bool checked);
void on_cbxDrawAxes_clicked(bool checked);
void on_cbxReloadTextures_clicked(bool checked);
};

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>641</width>
<height>734</height>
<height>778</height>
</rect>
</property>
<property name="windowTitle">
@ -501,6 +501,23 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="cbxDrawAxes">
<property name="text">
<string>Show Axes</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="cbxReloadTextures">
<property name="text">
<string>Live Reload Textures</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
@ -513,4 +530,7 @@
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
<slots>
<signal>installEventFilter()</signal>
</slots>
</ui>