Merge branch 'master' into review
commit
3e45acbf4e
|
@ -12,6 +12,8 @@ build
|
|||
bin/
|
||||
lib/
|
||||
|
||||
# QtCreator
|
||||
CMakeLists.txt.user
|
||||
|
||||
# Generated
|
||||
assimp.pc
|
||||
|
@ -38,6 +40,7 @@ tools/assimp_cmd/Makefile
|
|||
|
||||
# Tests
|
||||
test/results
|
||||
test/readlinetest*
|
||||
|
||||
# Python
|
||||
__pycache__
|
||||
|
|
258
CHANGES
258
CHANGES
|
@ -1,6 +1,264 @@
|
|||
----------------------------------------------------------------------
|
||||
CHANGELOG
|
||||
----------------------------------------------------------------------
|
||||
4.1.0 (2017-12):
|
||||
- FEATURES:
|
||||
- Export 3MF ( experimental )
|
||||
- Import / Export glTF 2
|
||||
- Introduce new zib-lib to eb able to export zip-archives
|
||||
- FIXES/HOUSEKEEPING:
|
||||
- Added missing include to stdlib.h and remove load library call
|
||||
- Fix install for builds with MSVC compiler and NMake.
|
||||
- Update list of supported file formats.
|
||||
- Add TriLib to the official list of supported ports.
|
||||
- Re-enabling PACK_STRUCT for MDL files.
|
||||
- Use std.::unique_ptr
|
||||
- Update D3MFExporter.h
|
||||
- Update MD3Loader.cpp, using index
|
||||
- Fix all warnings on MSVC14
|
||||
- Copy assimp dll to unit folder on windows
|
||||
- Update jvm port supported formats
|
||||
- Add support for building Mac OS X Framework bundles
|
||||
- Check for nullptr dereferencing before copying scene data
|
||||
- Update ValidateDataStructure.h, typo
|
||||
- Enable data structure validation in cases where it doesn't cause failures
|
||||
- Remove some dead assignments
|
||||
- fast_atof: Silence some uninitialized variable warnings
|
||||
- Check for area test if the face is a triangle.
|
||||
- Set mNumUVComponents to 0 when deleting texture coordinate sets
|
||||
- Only scale the root node because this will rescale all children nodes as well.
|
||||
- Issue 1514: Fix frame pointer arithmetic
|
||||
- Prevent failing stringstream to crash the export process
|
||||
- powf -> pow
|
||||
- add Defines.h to include folder for install.
|
||||
- Android:
|
||||
- Fix android build
|
||||
- Fix assimp for cross compile for android
|
||||
- Use define for D_FILE_OFFSET_BITS only for not-android systems.
|
||||
- FBX:
|
||||
- Fix handling with embedded textures
|
||||
- FBX 7500 Binary reading
|
||||
- Remove dead assignment
|
||||
- Fix export of deleted meshes; Add LazyDict::Remove method
|
||||
- Log an error instead of letting the fbx-importer crash. ( issue 213 )
|
||||
- Replace bad pointer casting with memcpy
|
||||
- Remove useless const qualifier from return value
|
||||
- Add explicit instantiation of log_prefix so other FBX source files can see it
|
||||
- add missing inversion of postrotation matrix for fbx.
|
||||
- FIReader: Silence uninitialized variable warning
|
||||
- Update version check in FBX reader to check for version >= 7500
|
||||
- Use actual min/max of anim keys when start/stop time is missing
|
||||
- GLTF1:
|
||||
- Fix output of glTF 1 version string
|
||||
- Fix delete / delete[] mismatch in glTFAsset
|
||||
- Don’t ignore rgba(1,1,1,1) color properties
|
||||
- glTF2 primitives fixes
|
||||
- Don’t ignore rgba(1,1,1,1) color properties
|
||||
- Fix delete / delete[] mismatch in glTFAsset
|
||||
- Remove KHR_binary_glTF code
|
||||
- glTF nodes can only hold one mesh. this simply assigns to and check’s a Node’s Mesh
|
||||
- version in glb header is stored as uint32_t
|
||||
- GLTF2:
|
||||
- node name conflict fix
|
||||
- Fix transform matrices multiplication order
|
||||
- Preserve node names when importing
|
||||
- Add support for tangents in import
|
||||
- Fix typo on gltf2 camera parameters
|
||||
- Moved byteStride from accessor to bufferView
|
||||
- Implemented reading binary glTF2 (glb) files
|
||||
- Fix signed/unsigned warning
|
||||
- Add postprocess step for scaling
|
||||
- Fix shininess to roughness conversion
|
||||
- Prefer “BLEND” over “MASK” as an alphaMode default
|
||||
- Approximate specularity / glossiness in metallicRoughness materials
|
||||
- Diffuse color and diffuse texture import and export improvements
|
||||
- Addressed some mismatched news/deletes caused by the new glTF2 sources.
|
||||
- Fix delete / delete[] mismatches in glTF2 importer
|
||||
- use correct name of exporter to gltf2
|
||||
- Fix possible infinite loop when exporting to gltf2
|
||||
- Fix glTF2::Asset::FindUniqueID() when the input string is >= 256 chars
|
||||
- Fix glTF2 alphaMode storage and reading
|
||||
- Fix glTF 2.0 multi-primitive support
|
||||
- Load gltf .bin files from correct directory
|
||||
- Add support for importing both glTF and glTF2 files
|
||||
- ampler improvements; Add new LazyDict method
|
||||
- Changes to GLTF2 materials
|
||||
- Remove Light, Technique references
|
||||
- Start removing materials common, and adding pbrSpecularGlossiness
|
||||
- Use !ObjectEmpty() vs. MemberCount() > 0
|
||||
- Working read, import, export, and write of gltf2 (pbr) material
|
||||
- Check in gltf2 models to test directory
|
||||
- Remove un-needed test models
|
||||
- Start managing and importing gltf2 pbr materials
|
||||
- Update glTF2 Asset to use indexes
|
||||
- Duplicate gltfImporter as gltf2Importer; Include glTF2 importer in CMake List
|
||||
- glTF2: Fix animation export
|
||||
- use opacity for diffuse alpha + alphaMode
|
||||
- STL:
|
||||
- Restore import of multi mesh binary STLs
|
||||
- Blender:
|
||||
- Silence warning about uninitialized member
|
||||
- MDLImporter:
|
||||
- Don't take address of packed struct member
|
||||
- assimp_cmd:
|
||||
- Fix strict-aliasing warnings
|
||||
- Open3DGC:
|
||||
- Fix strict-aliasing warnings
|
||||
- Add assertions to silence static analyzer warnings
|
||||
- Remove redundant const qualifiers from return types
|
||||
- Fix some uninitialized variable warnings
|
||||
- Remove OPEN3DGC and compression references
|
||||
- unzip:
|
||||
- Remove dead assignment
|
||||
- Bail on bad compression method
|
||||
- Fix possibly uninitialized variables
|
||||
- clipper:
|
||||
- Add assertion to silence a static analyzer warning
|
||||
- OpenDDLExport:
|
||||
- Reduce scope of a variable
|
||||
- Remove dead variable
|
||||
- Remove dead assignment
|
||||
- Fix another potential memory leak
|
||||
- X3DImporter:
|
||||
- Add assertions to silence static analyzer warnings
|
||||
- Add missing unittest
|
||||
- Workaround for buggy Android NDK (issue #1361)
|
||||
- TerragenLoader:
|
||||
- Remove unused variable
|
||||
- SIBImporter:
|
||||
- Add assertions to silence static analyzer warnings
|
||||
- IFC:
|
||||
- Remove dead code
|
||||
- Add explicit instantiation of log_prefix so IFCMaterial.cpp can see it
|
||||
- PLY:
|
||||
- Remove dead assignment and reduce scope of a variable
|
||||
- fix vertex attribute lookup.
|
||||
- OpenGEX:
|
||||
- Add assertion to silence a static analyzer warning
|
||||
- Fix for TextureFile with number in file name
|
||||
- Return early when element is TextureFile
|
||||
- NFF:
|
||||
- Add assertions to silence static analyzer warnings
|
||||
- Split up some complicated assignments
|
||||
- Raw: Fix misleading indentation warning
|
||||
- Reduce scope of a variable
|
||||
- LWO
|
||||
- Reduce scope of a variable
|
||||
- IRRLoader:
|
||||
- Fix confusing boolean casting
|
||||
- AssbinExporter:
|
||||
- Add assertion to silence a static analyzer warning
|
||||
- ASE:
|
||||
- Add assertion to silence a static analyzer warning
|
||||
- AMFImporter:
|
||||
- Add assertion to silence a static analyzer warning
|
||||
- Add a block
|
||||
- OptimizeGraph:
|
||||
- Fix possible null pointer dereference
|
||||
- RemoveRedundantMaterials:
|
||||
- Add assertion to silence a static analyzer warning
|
||||
- ImproveCacheLocality:
|
||||
- Add assertion to silence a static analyzer warning
|
||||
- RemoveRedundantMaterials:
|
||||
- Set pointer to nullptr after deleting it
|
||||
- Travis:
|
||||
- Disable unit tests in scan-build config
|
||||
- Move slower builds earlier to improve parallelization
|
||||
- Add static analysis to build
|
||||
- Remove unused branch rule for travis.
|
||||
- Add Clang UBSan build configuration
|
||||
- Treat warnings as errors, without typos this time
|
||||
- Unittests:
|
||||
- Add VS-based source groups for the unittests.
|
||||
- Collada:
|
||||
- export <library_animations> tag
|
||||
- Update ColladaExporter.cpp
|
||||
- Silence uninitialized variable warning
|
||||
- Add support for line strip primitives
|
||||
- Obj Wavefront:
|
||||
- check in exporting against out-of-bounds-access .
|
||||
- Issue 1351: use correct name for obj-meshname export for groups.
|
||||
- fix mem-lead: face will be not released in case of an error.
|
||||
- Anatoscope obj exporter nomtl
|
||||
- Raise exception when obj file contains invalid face indices
|
||||
- Added alternative displacement texture token in OBJ MTL material.
|
||||
- Obj: rename attribute from exporter.
|
||||
- Fix OBJ discarding all material names if the material library is missing
|
||||
- Step:
|
||||
- use correct lookup for utf32
|
||||
- MD2:
|
||||
- Fix MD2 frames containing garbage
|
||||
- STL
|
||||
- add missing const.
|
||||
- Fix memory-alignment bug.
|
||||
- Fix issue 104: deal with more solids in one STL file.
|
||||
- CMake
|
||||
- Fix issue 213: use correct include folder for assimp
|
||||
- Doxygen
|
||||
- Fix issue 1513: put irrXML onto exclucde list for doxygen run
|
||||
- PyAssimp:
|
||||
- Search for libassimp.so in LD_LIBRARY_PATH if available.
|
||||
- Fix operator precedence issue in header check
|
||||
- Split setup.py into multiple lines
|
||||
- Detect if Anaconda and fixed 3d_viewer for Python 3
|
||||
- created a python3 version of the 3dviewer and fixed the / = float in py3
|
||||
- Blender:
|
||||
- Fix invalid access to mesh array when the array is empty.
|
||||
- Fix short overflow.
|
||||
- Silence warning about inline function which is declared but not defined
|
||||
- JAssimp
|
||||
- Changed license header for IHMC contributions from Apache 2.0 to BSD
|
||||
- Add Node metadata to the Jassmip Java API
|
||||
- Added supported for custom IO Systems in Java. Implemented ClassLoader IO System
|
||||
- Added a link to pure jvm assimp port
|
||||
- Clang sanitizer:
|
||||
- Undefined Behavior sanitizer
|
||||
- Fixed a divide by zero error in IFCBoolean that was latent, but nevertheless a bug
|
||||
- B3DImporter:
|
||||
- Replace bad pointer casting with memcpy
|
||||
- AppVeyor:
|
||||
- Cleanup and Addition of VS 2017 and running Tests
|
||||
- Fixed File Size reported as 0 in tests that use temporary files
|
||||
- x86 isn't a valid VS platform. Win32 it is, then.
|
||||
- Replaced the worker image name, which doesn't work as generator name, with a manually created generator name.
|
||||
- Cleaned up appveyor setup, added VS 2017 to the build matrix and attempted to add running of tests.
|
||||
- Treat warnings as errors on Appveyor
|
||||
- Disable warning 4351 on MSVC 2013
|
||||
- OpenGEXImporter:
|
||||
- Copy materials to scene
|
||||
- Store RefInfo in unique_ptr so they get automatically cleaned up
|
||||
- Fix IOStream leak
|
||||
- Store ChildInfo in unique_ptr so they get automatically cleaned up
|
||||
- improve logging to be able to detect error-prone situations.
|
||||
- AMFImporter:
|
||||
- Fix memory leak
|
||||
- UnrealLoader:
|
||||
- Fix IOStream leak
|
||||
- Upgrade RapidJSON to get rid of a clang warning
|
||||
- zlib:
|
||||
- Update zlib contribution
|
||||
- Removed unnecessary files from zlib contribution
|
||||
- Replaced unsigned long for the crc table to z_crc_t, to match what is returned by get-crc_table
|
||||
- MakeVerboseFormat:
|
||||
- Fix delete / delete[] mismatches in MakeVerboseFormat
|
||||
- MaterialSystem:
|
||||
- Fix out-of-bounds read in MaterialSystem unit test
|
||||
- SIB:
|
||||
- Added support for SIB models from Silo 2.5
|
||||
- AssbinExporter:
|
||||
- Fix strict aliasing violation
|
||||
- Add Write specialization for aiColor3D
|
||||
- DefaultLogger:
|
||||
- Whitespace cleanup to fix GCC misleading indentation warning
|
||||
- MDP:
|
||||
- Fix encoding issues.
|
||||
- PreTransformVertices:
|
||||
- fix name lost in mesh and nodes when load with flag
|
||||
- C4D:
|
||||
- Fixes for C4D importer
|
||||
- Unzip:
|
||||
- Latest greatest.
|
||||
|
||||
4.0.1 (2017-07-28)
|
||||
- FIXES/HOUSEKEEPING:
|
||||
- fix version test.
|
||||
|
|
150
CMakeLists.txt
150
CMakeLists.txt
|
@ -110,7 +110,6 @@ if (WIN32)
|
|||
endif()
|
||||
|
||||
IF(MSVC)
|
||||
SET (CMAKE_PREFIX_PATH "D:\\libs\\devil")
|
||||
OPTION( ASSIMP_INSTALL_PDB
|
||||
"Install MSVC debug files."
|
||||
ON
|
||||
|
@ -139,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
|
||||
|
@ -162,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)
|
||||
|
@ -180,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" )
|
||||
|
@ -193,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 )
|
||||
|
@ -213,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" )
|
||||
|
@ -230,34 +220,39 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW )
|
|||
ADD_DEFINITIONS( -U__STRICT_ANSI__ )
|
||||
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 (IOS)
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
|
||||
ENDIF()
|
||||
|
||||
if (ASSIMP_WERROR)
|
||||
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)
|
||||
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)
|
||||
|
@ -290,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 sources")
|
||||
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)
|
||||
|
@ -367,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")
|
||||
|
@ -408,39 +405,14 @@ 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 )
|
||||
ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
|
||||
|
||||
ADD_SUBDIRECTORY( tools/assimp_cmd/ )
|
||||
|
||||
# Check dependencies for assimp_qt_viewer.
|
||||
# Why here? Maybe user do not want Qt viewer and have no Qt.
|
||||
# Why assimp_qt_viewer/CMakeLists.txt still contain similar check?
|
||||
# Because viewer can be build independently of Assimp.
|
||||
FIND_PACKAGE(Qt5Widgets QUIET)
|
||||
FIND_PACKAGE(DevIL QUIET)
|
||||
FIND_PACKAGE(OpenGL QUIET)
|
||||
IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
|
||||
ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
|
||||
ELSE()
|
||||
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
|
||||
IF (NOT Qt5_FOUND)
|
||||
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5")
|
||||
ENDIF (NOT Qt5_FOUND)
|
||||
|
||||
IF (NOT IL_FOUND)
|
||||
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL")
|
||||
ENDIF (NOT IL_FOUND)
|
||||
|
||||
IF (NOT OPENGL_FOUND)
|
||||
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL")
|
||||
ENDIF (NOT OPENGL_FOUND)
|
||||
|
||||
MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}")
|
||||
ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
|
||||
ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
|
||||
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
|
||||
|
||||
IF ( ASSIMP_BUILD_SAMPLES)
|
||||
|
@ -460,7 +432,7 @@ INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTAL
|
|||
|
||||
IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
|
||||
# Packing information
|
||||
SET(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}")
|
||||
SET(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}.{ASSIMP_VERSION_MINOR}")
|
||||
SET(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.")
|
||||
SET(CPACK_PACKAGE_VENDOR "https://github.com/assimp")
|
||||
SET(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}")
|
||||
|
@ -472,8 +444,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}" )
|
||||
|
@ -490,8 +462,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
|
|||
SET(CPACK_DEBIAN_PACKAGE_SECTION "libs" )
|
||||
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}")
|
||||
SET(CPACK_DEBIAN_PACKAGE_SUGGESTS)
|
||||
SET(CPACK_DEBIAN_PACKAGE_NAME "assimp")
|
||||
SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging)
|
||||
set(cPACK_DEBIAN_PACKAGE_NAME "assimp")
|
||||
SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/gtest contrib/zlib workspaces test doc obj samples packaging)
|
||||
SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force)
|
||||
SET(CPACK_DEBIAN_CHANGELOG)
|
||||
execute_process(COMMAND lsb_release -is
|
||||
|
@ -503,8 +475,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)
|
||||
|
@ -516,14 +488,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)
|
||||
|
@ -544,5 +518,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)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# How to contribute
|
||||
|
||||
If you want to contribute, follow these steps:
|
||||
|
||||
- First, create your own clone of assimp.
|
||||
- When you want to fix a bug or add a new feature, create a branch on your own fork following [these instructions](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
|
||||
- Push it to your fork of the repository and open a pull request.
|
||||
- A pull request will start our continuous integration service, which checks if the build works for Linux and Windows.
|
||||
It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fail, fix it and the tests will be restarted automatically.
|
||||
- At the end, we will perform a code review and merge your branch to the master branch.
|
17
CREDITS
17
CREDITS
|
@ -157,12 +157,27 @@ Contributed ExportProperties interface
|
|||
Contributed X File exporter
|
||||
Contributed Step (stp) exporter
|
||||
|
||||
- Thomas Iorns (mesilliac)
|
||||
Initial FBX Export support
|
||||
|
||||
For a more detailed list just check: https://github.com/assimp/assimp/network/members
|
||||
|
||||
Patreons:
|
||||
|
||||
========
|
||||
Patreons
|
||||
========
|
||||
|
||||
Huge thanks to our Patreons!
|
||||
|
||||
- migenius
|
||||
- Marcus
|
||||
- Cort
|
||||
- elect
|
||||
- Steffen
|
||||
|
||||
|
||||
===================
|
||||
Commercial Sponsors
|
||||
===================
|
||||
|
||||
- MyDidimo (mydidimo.com): Sponsored development of FBX Export support
|
||||
|
|
3
INSTALL
3
INSTALL
|
@ -42,3 +42,6 @@ For Windows:
|
|||
1. Open a command prompt
|
||||
2. cmake CMakeLists.txt
|
||||
2. Open your default IDE and build it
|
||||
|
||||
For iOS:
|
||||
Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS
|
||||
|
|
46
Readme.md
46
Readme.md
|
@ -32,32 +32,32 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki
|
|||
|
||||
#### Supported file formats ####
|
||||
|
||||
A full list [is here](http://assimp.org/main_features_formats.html).
|
||||
__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__:
|
||||
|
||||
|
@ -109,6 +109,8 @@ __Exporters__:
|
|||
- STEP
|
||||
- glTF 1.0 (partial)
|
||||
- glTF 2.0 (partial)
|
||||
- 3MF ( experimental )
|
||||
- FBX ( experimental )
|
||||
|
||||
### Building ###
|
||||
Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
|
||||
|
@ -138,8 +140,6 @@ Open Asset Import Library is implemented in C++. The directory structure is:
|
|||
/tools Tools (old assimp viewer, command line `assimp`)
|
||||
/samples A small number of samples to illustrate possible
|
||||
use cases for Assimp
|
||||
/workspaces Build environments for vc,xcode,... (deprecated,
|
||||
CMake has superseeded all legacy build options!)
|
||||
|
||||
|
||||
### Where to get help ###
|
||||
|
|
|
@ -32,6 +32,9 @@ install:
|
|||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
|
||||
- if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
|
||||
- cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%"
|
||||
- set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
|
||||
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe
|
||||
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe
|
||||
|
||||
cache:
|
||||
- code\assimp.dir\%CONFIGURATION%
|
||||
|
@ -50,6 +53,7 @@ build:
|
|||
project: Assimp.sln
|
||||
|
||||
after_build:
|
||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss
|
||||
- 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\*
|
||||
|
||||
test_script:
|
||||
|
|
|
@ -10,10 +10,7 @@
|
|||
# ASSIMP_LIBRARY_DIRS - link directories
|
||||
# ASSIMP_LIBRARIES - libraries to link plugins with
|
||||
# ASSIMP_Boost_VERSION - the boost version assimp was compiled with
|
||||
get_filename_component(_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
get_filename_component(_PREFIX "${_PREFIX}" PATH)
|
||||
get_filename_component(_PREFIX "${_PREFIX}" PATH)
|
||||
get_filename_component(ASSIMP_ROOT_DIR "${_PREFIX}" PATH)
|
||||
get_filename_component(ASSIMP_ROOT_DIR "@CMAKE_INSTALL_PREFIX@" REALPATH)
|
||||
|
||||
if( MSVC )
|
||||
# in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix
|
||||
|
@ -34,36 +31,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 +53,6 @@ MARK_AS_ADVANCED(
|
|||
ASSIMP_LINK_FLAGS
|
||||
ASSIMP_INCLUDE_DIRS
|
||||
ASSIMP_LIBRARIES
|
||||
ASSIMP_Boost_VERSION
|
||||
ASSIMP_CFLAGS_OTHER
|
||||
ASSIMP_LDFLAGS_OTHER
|
||||
ASSIMP_LIBRARY_SUFFIX
|
||||
|
|
|
@ -72,7 +72,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
|
|||
unsigned int idx( NotSet );
|
||||
for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
|
||||
{
|
||||
std::string s = mScene->mMaterials[i].mName;
|
||||
std::string &s = mScene->mMaterials[i].mName;
|
||||
for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) {
|
||||
*it = static_cast< char >( ::tolower( *it ) );
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
|
|||
else if ( (*a) >= mScene->mMaterials.size())
|
||||
{
|
||||
(*a) = idx;
|
||||
DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material");
|
||||
ASSIMP_LOG_WARN("Material index overflow in 3DS file. Using default material");
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
|
|||
sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f);
|
||||
mScene->mMaterials.push_back(sMat);
|
||||
|
||||
DefaultLogger::get()->info("3DS: Generating default material");
|
||||
ASSIMP_LOG_INFO("3DS: Generating default material");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,12 +147,12 @@ void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh)
|
|||
{
|
||||
if ((*i).mIndices[a] >= sMesh.mPositions.size())
|
||||
{
|
||||
DefaultLogger::get()->warn("3DS: Vertex index overflow)");
|
||||
ASSIMP_LOG_WARN("3DS: Vertex index overflow)");
|
||||
(*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1;
|
||||
}
|
||||
if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size())
|
||||
{
|
||||
DefaultLogger::get()->warn("3DS: Texture coordinate index overflow)");
|
||||
ASSIMP_LOG_WARN("3DS: Texture coordinate index overflow)");
|
||||
(*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1;
|
||||
}
|
||||
}
|
||||
|
@ -204,8 +204,9 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
|
|||
mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
|
||||
|
||||
// Setup the texture mapping mode
|
||||
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
|
||||
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
|
||||
int mapMode = static_cast<int>(texture.mMapMode);
|
||||
mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
|
||||
mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
|
||||
|
||||
// Mirroring - double the scaling values
|
||||
// FIXME: this is not really correct ...
|
||||
|
@ -313,7 +314,8 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
|
|||
case D3DS::Discreet3DS::Blinn :
|
||||
eShading = aiShadingMode_Blinn; break;
|
||||
}
|
||||
mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
|
||||
int eShading_ = static_cast<int>(eShading);
|
||||
mat.AddProperty<int>(&eShading_, 1, AI_MATKEY_SHADING_MODEL);
|
||||
|
||||
// DIFFUSE texture
|
||||
if( oldMat.sTexDiffuse.mMapName.length() > 0)
|
||||
|
@ -497,7 +499,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
|
|||
pvCurrent->x *= -1.f;
|
||||
t2->x *= -1.f;
|
||||
}
|
||||
DefaultLogger::get()->info("3DS: Flipping mesh X-Axis");
|
||||
ASSIMP_LOG_INFO("3DS: Flipping mesh X-Axis");
|
||||
}
|
||||
|
||||
// Handle pivot point
|
||||
|
@ -573,11 +575,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
|
|||
pcIn->aTargetPositionKeys.size() > 1)
|
||||
{
|
||||
aiAnimation* anim = pcSOut->mAnimations[0];
|
||||
ai_assert(NULL != anim);
|
||||
ai_assert(nullptr != anim);
|
||||
|
||||
if (pcIn->aCameraRollKeys.size() > 1)
|
||||
{
|
||||
DefaultLogger::get()->debug("3DS: Converting camera roll track ...");
|
||||
ASSIMP_LOG_DEBUG("3DS: Converting camera roll track ...");
|
||||
|
||||
// Camera roll keys - in fact they're just rotations
|
||||
// around the camera's z axis. The angles are given
|
||||
|
@ -597,7 +599,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
|
|||
#if 0
|
||||
if (pcIn->aTargetPositionKeys.size() > 1)
|
||||
{
|
||||
DefaultLogger::get()->debug("3DS: Converting target track ...");
|
||||
ASSIMP_LOG_DEBUG("3DS: Converting target track ...");
|
||||
|
||||
// Camera or spot light - need to convert the separate
|
||||
// target position channel to our representation
|
||||
|
@ -743,7 +745,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
|
|||
// | | | | |
|
||||
// MESH_0 MESH_1 MESH_2 ... MESH_N CAMERA_0 ....
|
||||
//
|
||||
DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
|
||||
ASSIMP_LOG_WARN("No hierarchy information has been found in the file. ");
|
||||
|
||||
pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes +
|
||||
static_cast<unsigned int>(mScene->mCameras.size() + mScene->mLights.size());
|
||||
|
|
|
@ -184,7 +184,7 @@ void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScen
|
|||
} // end of namespace Assimp
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* scene)
|
||||
Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, const aiScene* scene)
|
||||
: scene(scene)
|
||||
, writer(outfile)
|
||||
{
|
||||
|
@ -381,7 +381,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type
|
|||
|
||||
// TODO: handle embedded textures properly
|
||||
if (path.data[0] == '*') {
|
||||
DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
|
||||
ASSIMP_LOG_ERROR("Ignoring embedded texture for export: " + std::string(path.C_Str()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace Assimp
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
class Discreet3DSExporter {
|
||||
public:
|
||||
Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* pScene);
|
||||
Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, const aiScene* pScene);
|
||||
~Discreet3DSExporter();
|
||||
|
||||
private:
|
||||
|
|
|
@ -71,7 +71,7 @@ static const aiImporterDesc desc = {
|
|||
0,
|
||||
0,
|
||||
0,
|
||||
"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 == "prj") {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -258,8 +258,9 @@ void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut)
|
|||
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize())
|
||||
throw DeadlyImportError("Chunk is too large");
|
||||
|
||||
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit())
|
||||
DefaultLogger::get()->error("3DS: Chunk overflow");
|
||||
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) {
|
||||
ASSIMP_LOG_ERROR("3DS: Chunk overflow");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -320,7 +321,7 @@ void Discreet3DSImporter::ParseEditorChunk()
|
|||
// print the version number
|
||||
char buff[10];
|
||||
ASSIMP_itoa10(buff,stream->GetI2());
|
||||
DefaultLogger::get()->info(std::string("3DS file format version: ") + buff);
|
||||
ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff);
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
@ -349,7 +350,7 @@ void Discreet3DSImporter::ParseObjectChunk()
|
|||
case Discreet3DS::CHUNK_MAT_MATERIAL:
|
||||
|
||||
// Add a new material to the list
|
||||
mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + std::to_string(mScene->mMaterials.size()))));
|
||||
mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + to_string(mScene->mMaterials.size()))));
|
||||
ParseMaterialChunk();
|
||||
break;
|
||||
|
||||
|
@ -361,7 +362,7 @@ void Discreet3DSImporter::ParseObjectChunk()
|
|||
if (is_qnan(mClrAmbient.r))
|
||||
{
|
||||
// We failed to read the ambient base color.
|
||||
DefaultLogger::get()->error("3DS: Failed to read ambient base color");
|
||||
ASSIMP_LOG_ERROR("3DS: Failed to read ambient base color");
|
||||
mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f;
|
||||
}
|
||||
break;
|
||||
|
@ -463,7 +464,7 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
|
|||
if (len < 1e-5) {
|
||||
|
||||
// There are some files with lookat == position. Don't know why or whether it's ok or not.
|
||||
DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector");
|
||||
ASSIMP_LOG_ERROR("3DS: Unable to read proper camera look-at vector");
|
||||
camera->mLookAt = aiVector3D(0.0,1.0,0.0);
|
||||
|
||||
}
|
||||
|
@ -629,9 +630,9 @@ void Discreet3DSImporter::SkipTCBInfo()
|
|||
if (!flags) {
|
||||
// Currently we can't do anything with these values. They occur
|
||||
// quite rare, so it wouldn't be worth the effort implementing
|
||||
// them. 3DS ist not really suitable for complex animations,
|
||||
// them. 3DS is not really suitable for complex animations,
|
||||
// so full support is not required.
|
||||
DefaultLogger::get()->warn("3DS: Skipping TCB animation info");
|
||||
ASSIMP_LOG_WARN("3DS: Skipping TCB animation info");
|
||||
}
|
||||
|
||||
if (flags & Discreet3DS::KEY_USE_TENS) {
|
||||
|
@ -732,7 +733,6 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|||
|
||||
// If object name is DUMMY, take this one instead
|
||||
if (mCurrentNode->mName == "$$$DUMMY") {
|
||||
//DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object");
|
||||
mCurrentNode->mName = std::string(sz);
|
||||
break;
|
||||
}
|
||||
|
@ -743,7 +743,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|||
|
||||
if ( Discreet3DS::CHUNK_TRACKINFO != parent)
|
||||
{
|
||||
DefaultLogger::get()->warn("3DS: Skipping pivot subchunk for non usual object");
|
||||
ASSIMP_LOG_WARN("3DS: Skipping pivot subchunk for non usual object");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +805,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|||
{
|
||||
// roll keys are accepted for cameras only
|
||||
if (parent != Discreet3DS::CHUNK_TRACKCAMERA) {
|
||||
DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object");
|
||||
ASSIMP_LOG_WARN("3DS: Ignoring roll track for non-camera object");
|
||||
break;
|
||||
}
|
||||
bool sortKeys = false;
|
||||
|
@ -845,7 +845,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|||
// CAMERA FOV KEYFRAME
|
||||
case Discreet3DS::CHUNK_TRACKFOV:
|
||||
{
|
||||
DefaultLogger::get()->error("3DS: Skipping FOV animation track. "
|
||||
ASSIMP_LOG_ERROR("3DS: Skipping FOV animation track. "
|
||||
"This is not supported");
|
||||
}
|
||||
break;
|
||||
|
@ -985,7 +985,7 @@ void Discreet3DSImporter::ParseFaceChunk()
|
|||
}
|
||||
}
|
||||
if (0xcdcdcdcd == idx) {
|
||||
DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz);
|
||||
ASSIMP_LOG_ERROR_F( "3DS: Unknown material: ", sz);
|
||||
}
|
||||
|
||||
// Now continue and read all material indices
|
||||
|
@ -995,7 +995,7 @@ void Discreet3DSImporter::ParseFaceChunk()
|
|||
|
||||
// check range
|
||||
if (fidx >= mMesh.mFaceMaterials.size()) {
|
||||
DefaultLogger::get()->error("3DS: Invalid face index in face material list");
|
||||
ASSIMP_LOG_ERROR("3DS: Invalid face index in face material list");
|
||||
}
|
||||
else mMesh.mFaceMaterials[fidx] = idx;
|
||||
}}
|
||||
|
@ -1110,7 +1110,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|||
|
||||
if (!cnt) {
|
||||
// This may not be, we use the default name instead
|
||||
DefaultLogger::get()->error("3DS: Empty material name");
|
||||
ASSIMP_LOG_ERROR("3DS: Empty material name");
|
||||
}
|
||||
else mScene->mMaterials.back().mName = std::string(sz,cnt);
|
||||
}
|
||||
|
@ -1123,7 +1123,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|||
ParseColorChunk(pc);
|
||||
if (is_qnan(pc->r)) {
|
||||
// color chunk is invalid. Simply ignore it
|
||||
DefaultLogger::get()->error("3DS: Unable to read DIFFUSE chunk");
|
||||
ASSIMP_LOG_ERROR("3DS: Unable to read DIFFUSE chunk");
|
||||
pc->r = pc->g = pc->b = 1.0f;
|
||||
}}
|
||||
break;
|
||||
|
@ -1135,7 +1135,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|||
ParseColorChunk(pc);
|
||||
if (is_qnan(pc->r)) {
|
||||
// color chunk is invalid. Simply ignore it
|
||||
DefaultLogger::get()->error("3DS: Unable to read SPECULAR chunk");
|
||||
ASSIMP_LOG_ERROR("3DS: Unable to read SPECULAR chunk");
|
||||
pc->r = pc->g = pc->b = 1.0f;
|
||||
}}
|
||||
break;
|
||||
|
@ -1147,7 +1147,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|||
ParseColorChunk(pc);
|
||||
if (is_qnan(pc->r)) {
|
||||
// color chunk is invalid. Simply ignore it
|
||||
DefaultLogger::get()->error("3DS: Unable to read AMBIENT chunk");
|
||||
ASSIMP_LOG_ERROR("3DS: Unable to read AMBIENT chunk");
|
||||
pc->r = pc->g = pc->b = 0.0f;
|
||||
}}
|
||||
break;
|
||||
|
@ -1159,7 +1159,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|||
ParseColorChunk(pc);
|
||||
if (is_qnan(pc->r)) {
|
||||
// color chunk is invalid. Simply ignore it
|
||||
DefaultLogger::get()->error("3DS: Unable to read EMISSIVE chunk");
|
||||
ASSIMP_LOG_ERROR("3DS: Unable to read EMISSIVE chunk");
|
||||
pc->r = pc->g = pc->b = 0.0f;
|
||||
}}
|
||||
break;
|
||||
|
@ -1293,7 +1293,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
|
|||
pcOut->mScaleU = stream->GetF4();
|
||||
if (0.0f == pcOut->mScaleU)
|
||||
{
|
||||
DefaultLogger::get()->warn("Texture coordinate scaling in the x direction is zero. Assuming 1.");
|
||||
ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1.");
|
||||
pcOut->mScaleU = 1.0f;
|
||||
}
|
||||
break;
|
||||
|
@ -1302,7 +1302,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
|
|||
pcOut->mScaleV = stream->GetF4();
|
||||
if (0.0f == pcOut->mScaleV)
|
||||
{
|
||||
DefaultLogger::get()->warn("Texture coordinate scaling in the y direction is zero. Assuming 1.");
|
||||
ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1.");
|
||||
pcOut->mScaleV = 1.0f;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -45,6 +45,11 @@ namespace Assimp {
|
|||
namespace D3MF {
|
||||
|
||||
namespace XmlTag {
|
||||
// Meta-data
|
||||
static const std::string meta = "metadata";
|
||||
static const std::string meta_name = "name";
|
||||
|
||||
// Model-data specific tags
|
||||
static const std::string model = "model";
|
||||
static const std::string model_unit = "unit";
|
||||
static const std::string metadata = "metadata";
|
||||
|
@ -62,6 +67,8 @@ namespace XmlTag {
|
|||
static const std::string v2 = "v2";
|
||||
static const std::string v3 = "v3";
|
||||
static const std::string id = "id";
|
||||
static const std::string pid = "pid";
|
||||
static const std::string p1 = "p1";
|
||||
static const std::string name = "name";
|
||||
static const std::string type = "type";
|
||||
static const std::string build = "build";
|
||||
|
@ -69,6 +76,14 @@ namespace XmlTag {
|
|||
static const std::string objectid = "objectid";
|
||||
static const std::string transform = "transform";
|
||||
|
||||
// Material definitions
|
||||
static const std::string basematerials = "basematerials";
|
||||
static const std::string basematerials_id = "id";
|
||||
static const std::string basematerials_base = "base";
|
||||
static const std::string basematerials_name = "name";
|
||||
static const std::string basematerials_displaycolor = "displaycolor";
|
||||
|
||||
// Meta info tags
|
||||
static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
|
||||
static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
|
||||
static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
|
||||
|
@ -83,7 +98,6 @@ namespace XmlTag {
|
|||
static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
|
||||
static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
|
||||
static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
|
||||
|
||||
}
|
||||
|
||||
} // Namespace D3MF
|
||||
|
|
|
@ -85,7 +85,7 @@ static const aiImporterDesc desc = {
|
|||
#define AI_AC_SKIP_TO_NEXT_TOKEN() \
|
||||
if (!SkipSpaces(&buffer)) \
|
||||
{ \
|
||||
DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ static const aiImporterDesc desc = {
|
|||
{ \
|
||||
if (IsLineEnd( *buffer )) \
|
||||
{ \
|
||||
DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); \
|
||||
out = "ERROR"; \
|
||||
break; \
|
||||
} \
|
||||
|
@ -120,7 +120,7 @@ static const aiImporterDesc desc = {
|
|||
{ \
|
||||
if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \
|
||||
{ \
|
||||
DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " name " was expected."); \
|
||||
continue; \
|
||||
} \
|
||||
buffer += name_length+1; \
|
||||
|
@ -217,7 +217,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
|
|||
light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i",static_cast<unsigned int>(mLights->size())-1);
|
||||
obj.name = std::string( light->mName.data );
|
||||
|
||||
DefaultLogger::get()->debug("AC3D: Light source encountered");
|
||||
ASSIMP_LOG_DEBUG("AC3D: Light source encountered");
|
||||
obj.type = Object::Light;
|
||||
}
|
||||
else if (!ASSIMP_strincmp(buffer,"group",5))
|
||||
|
@ -307,12 +307,12 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
|
|||
{
|
||||
if (!GetNextLine())
|
||||
{
|
||||
DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet");
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet");
|
||||
break;
|
||||
}
|
||||
else if (!IsNumeric(*buffer))
|
||||
{
|
||||
DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet");
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet");
|
||||
--buffer; // make sure the line is processed a second time
|
||||
break;
|
||||
}
|
||||
|
@ -338,8 +338,8 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
|
|||
// example writes no surf chunks
|
||||
if (!Q3DWorkAround)
|
||||
{
|
||||
DefaultLogger::get()->warn("AC3D: SURF token was expected");
|
||||
DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled");
|
||||
ASSIMP_LOG_WARN("AC3D: SURF token was expected");
|
||||
ASSIMP_LOG_DEBUG("Continuing with Quick3D Workaround enabled");
|
||||
}
|
||||
--buffer; // make sure the line is processed a second time
|
||||
// break; --- see fix notes above
|
||||
|
@ -384,7 +384,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
|
|||
{
|
||||
if(!GetNextLine())
|
||||
{
|
||||
DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete");
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: surface references are incomplete");
|
||||
break;
|
||||
}
|
||||
surf.entries.push_back(Surface::SurfaceEntry());
|
||||
|
@ -405,7 +405,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
|
|||
}
|
||||
}
|
||||
}
|
||||
DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected");
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: \'kids\' line was expected");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -478,7 +478,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
|||
therefore: if no surfaces are defined return point data only
|
||||
*/
|
||||
|
||||
DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, "
|
||||
ASSIMP_LOG_INFO("AC3D: No surfaces defined in object definition, "
|
||||
"a point list is returned");
|
||||
|
||||
meshes.push_back(new aiMesh());
|
||||
|
@ -519,12 +519,12 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
|||
unsigned int idx = (*it).mat;
|
||||
if (idx >= needMat.size())
|
||||
{
|
||||
DefaultLogger::get()->error("AC3D: material index is out of range");
|
||||
ASSIMP_LOG_ERROR("AC3D: material index is out of range");
|
||||
idx = 0;
|
||||
}
|
||||
if ((*it).entries.empty())
|
||||
{
|
||||
DefaultLogger::get()->warn("AC3D: surface her zero vertex references");
|
||||
ASSIMP_LOG_WARN("AC3D: surface her zero vertex references");
|
||||
}
|
||||
|
||||
// validate all vertex indices to make sure we won't crash here
|
||||
|
@ -533,7 +533,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
|||
{
|
||||
if ((*it2).first >= object.vertices.size())
|
||||
{
|
||||
DefaultLogger::get()->warn("AC3D: Invalid vertex reference");
|
||||
ASSIMP_LOG_WARN("AC3D: Invalid vertex reference");
|
||||
(*it2).first = 0;
|
||||
}
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
|||
|
||||
if ((*it).flags & 0xf)
|
||||
{
|
||||
DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown");
|
||||
ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown");
|
||||
(*it).flags &= ~(0xf);
|
||||
}
|
||||
|
||||
|
@ -712,7 +712,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
|||
if (object.subDiv) {
|
||||
if (configEvalSubdivision) {
|
||||
std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
|
||||
DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name);
|
||||
ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: "+object.name);
|
||||
|
||||
std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL);
|
||||
div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true);
|
||||
|
@ -721,7 +721,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
|||
// previous meshes are deleted vy Subdivide().
|
||||
}
|
||||
else {
|
||||
DefaultLogger::get()->info("AC3D: Letting the subdivision surface untouched due to my configuration: "
|
||||
ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: "
|
||||
+object.name);
|
||||
}
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
|
|||
unsigned int version = HexDigitToDecimal( buffer[4] );
|
||||
char msg[3];
|
||||
ASSIMP_itoa10(msg,3,version);
|
||||
DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg);
|
||||
ASSIMP_LOG_INFO_F("AC3D file format version: ", msg);
|
||||
|
||||
std::vector<Material> materials;
|
||||
materials.reserve(5);
|
||||
|
@ -857,7 +857,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
if (materials.empty())
|
||||
{
|
||||
DefaultLogger::get()->warn("AC3D: No material has been found");
|
||||
ASSIMP_LOG_WARN("AC3D: No material has been found");
|
||||
materials.push_back(Material());
|
||||
}
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ casu_cres:
|
|||
if(!skipped_before[sk_idx])
|
||||
{
|
||||
skipped_before[sk_idx] = true;
|
||||
LogWarning("Skipping node \"" + nn + "\" in " + pParentNodeName + ".");
|
||||
ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -358,18 +358,6 @@ private:
|
|||
/************** Functions: LOG set *************/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn void LogInfo(const std::string& pMessage)
|
||||
/// Short variant for calling \ref DefaultLogger::get()->info()
|
||||
void LogInfo(const std::string& pMessage) { DefaultLogger::get()->info(pMessage); }
|
||||
|
||||
/// \fn void LogWarning(const std::string& pMessage)
|
||||
/// Short variant for calling \ref DefaultLogger::get()->warn()
|
||||
void LogWarning(const std::string& pMessage) { DefaultLogger::get()->warn(pMessage); }
|
||||
|
||||
/// \fn void LogError(const std::string& pMessage)
|
||||
/// Short variant for calling \ref DefaultLogger::get()->error()
|
||||
void LogError(const std::string& pMessage) { DefaultLogger::get()->error(pMessage); }
|
||||
|
||||
/***********************************************/
|
||||
/************** Functions: XML set *************/
|
||||
/***********************************************/
|
||||
|
|
|
@ -71,7 +71,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
}
|
||||
|
||||
/// \def MACRO_ATTRREAD_CHECK_REF
|
||||
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
|
||||
/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
|
||||
/// "continue" will called.
|
||||
/// \param [in] pAttrName - attribute name.
|
||||
/// \param [out] pVarName - output variable name.
|
||||
|
@ -84,7 +84,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
}
|
||||
|
||||
/// \def MACRO_ATTRREAD_CHECK_RET
|
||||
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
|
||||
/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
|
||||
/// If result was read then "continue" will called.
|
||||
/// \param [in] pAttrName - attribute name.
|
||||
/// \param [out] pVarName - output variable name.
|
||||
|
@ -130,7 +130,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
} while(false)
|
||||
|
||||
/// \def MACRO_NODECHECK_READCOMP_F
|
||||
/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "float".
|
||||
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "float".
|
||||
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
|
||||
/// \param [in] pNodeName - node name.
|
||||
/// \param [in, out] pReadFlag - read flag.
|
||||
|
@ -147,7 +147,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
}
|
||||
|
||||
/// \def MACRO_NODECHECK_READCOMP_U32
|
||||
/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
|
||||
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
|
||||
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
|
||||
/// \param [in] pNodeName - node name.
|
||||
/// \param [in, out] pReadFlag - read flag.
|
||||
|
|
|
@ -99,7 +99,7 @@ CAMFImporter_NodeElement* ne;
|
|||
ParseHelper_Node_Exit();
|
||||
// check that all components was defined
|
||||
if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
|
||||
// check if <a> is absent. Then manualy add "a == 1".
|
||||
// check if <a> is absent. Then manually add "a == 1".
|
||||
if(!read_flag[3]) als.Color.a = 1;
|
||||
|
||||
}// if(!mReader->isEmptyElement())
|
||||
|
|
|
@ -156,10 +156,11 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string&
|
|||
TextureConverted_Index = 0;
|
||||
for(const SPP_Texture& tex_convd: mTexture_Converted)
|
||||
{
|
||||
if(tex_convd.ID == TextureConverted_ID)
|
||||
return TextureConverted_Index;
|
||||
else
|
||||
TextureConverted_Index++;
|
||||
if ( tex_convd.ID == TextureConverted_ID ) {
|
||||
return TextureConverted_Index;
|
||||
} else {
|
||||
++TextureConverted_Index;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -769,7 +770,7 @@ std::list<aiNode*> ch_node;
|
|||
// find referenced object
|
||||
if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID);
|
||||
|
||||
// create node for apllying transformation
|
||||
// create node for applying transformation
|
||||
t_node = new aiNode;
|
||||
t_node->mParent = con_node;
|
||||
// apply transformation
|
||||
|
|
|
@ -200,7 +200,7 @@ void ASEImporter::InternReadFile( const std::string& pFile,
|
|||
ConvertMeshes(*i,avOutMeshes);
|
||||
}
|
||||
if (tookNormals) {
|
||||
DefaultLogger::get()->debug("ASE: Taking normals from the file. Use "
|
||||
ASSIMP_LOG_DEBUG("ASE: Taking normals from the file. Use "
|
||||
"the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you "
|
||||
"experience problems");
|
||||
}
|
||||
|
@ -297,15 +297,15 @@ void ASEImporter::BuildAnimations(const std::vector<BaseNode*>& nodes)
|
|||
|
||||
// TODO: Implement Bezier & TCB support
|
||||
if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) {
|
||||
DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
|
||||
ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. "
|
||||
"This is not supported.");
|
||||
}
|
||||
if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) {
|
||||
DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. "
|
||||
ASSIMP_LOG_WARN("ASE: Rotation controller uses Bezier/TCB keys. "
|
||||
"This is not supported.");
|
||||
}
|
||||
if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK) {
|
||||
DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
|
||||
ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. "
|
||||
"This is not supported.");
|
||||
}
|
||||
|
||||
|
@ -583,7 +583,7 @@ void ASEImporter::AddNodes (const std::vector<BaseNode*>& nodes,
|
|||
node->mTransformation = mParentAdjust*snode->mTransform;
|
||||
|
||||
// Add sub nodes - prevent stack overflow due to recursive parenting
|
||||
if (node->mName != node->mParent->mName) {
|
||||
if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName ) {
|
||||
AddNodes(nodes,node,node->mName.data,snode->mTransform);
|
||||
}
|
||||
|
||||
|
@ -624,7 +624,7 @@ void ASEImporter::AddNodes (const std::vector<BaseNode*>& nodes,
|
|||
node->mNumChildren++;
|
||||
|
||||
// What we did is so great, it is at least worth a debug message
|
||||
DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")");
|
||||
ASSIMP_LOG_DEBUG("ASE: Generating separate target node ("+snode->mName+")");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -947,7 +947,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
// validate the material index of the mesh
|
||||
if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) {
|
||||
mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1;
|
||||
DefaultLogger::get()->warn("Material index is out of range");
|
||||
ASSIMP_LOG_WARN("Material index is out of range");
|
||||
}
|
||||
|
||||
// If the material the mesh is assigned to is consisting of submeshes, split it
|
||||
|
@ -957,11 +957,11 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
|
||||
std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[vSubMaterials.size()];
|
||||
|
||||
// build a list of all faces per submaterial
|
||||
// build a list of all faces per sub-material
|
||||
for (unsigned int i = 0; i < mesh.mFaces.size();++i) {
|
||||
// check range
|
||||
if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) {
|
||||
DefaultLogger::get()->warn("Submaterial index is out of range");
|
||||
ASSIMP_LOG_WARN("Submaterial index is out of range");
|
||||
|
||||
// use the last material instead
|
||||
aiSplit[vSubMaterials.size()-1].push_back(i);
|
||||
|
|
|
@ -151,7 +151,7 @@ void Parser::LogWarning(const char* szWarn)
|
|||
#endif
|
||||
|
||||
// output the warning to the logger ...
|
||||
DefaultLogger::get()->warn(szTemp);
|
||||
ASSIMP_LOG_WARN(szTemp);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -167,7 +167,7 @@ void Parser::LogInfo(const char* szWarn)
|
|||
#endif
|
||||
|
||||
// output the information to the logger ...
|
||||
DefaultLogger::get()->info(szTemp);
|
||||
ASSIMP_LOG_INFO(szTemp);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -267,7 +267,9 @@ void Parser::Parse()
|
|||
// at the file extension (ASE, ASK, ASC)
|
||||
// *************************************************************
|
||||
|
||||
if (fmt)iFileFormat = fmt;
|
||||
if ( fmt ) {
|
||||
iFileFormat = fmt;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// main scene information
|
||||
|
@ -427,28 +429,25 @@ void Parser::ParseLV1SoftSkinBlock()
|
|||
// Reserve enough storage
|
||||
vert.mBoneWeights.reserve(numWeights);
|
||||
|
||||
for (unsigned int w = 0; w < numWeights;++w)
|
||||
{
|
||||
std::string bone;
|
||||
std::string bone;
|
||||
for (unsigned int w = 0; w < numWeights;++w) {
|
||||
bone.clear();
|
||||
ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
|
||||
|
||||
// Find the bone in the mesh's list
|
||||
std::pair<int,ai_real> me;
|
||||
me.first = -1;
|
||||
|
||||
for (unsigned int n = 0; n < curMesh->mBones.size();++n)
|
||||
{
|
||||
if (curMesh->mBones[n].mName == bone)
|
||||
{
|
||||
for (unsigned int n = 0; n < curMesh->mBones.size();++n) {
|
||||
if (curMesh->mBones[n].mName == bone) {
|
||||
me.first = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (-1 == me.first)
|
||||
{
|
||||
if (-1 == me.first) {
|
||||
// We don't have this bone yet, so add it to the list
|
||||
me.first = (int)curMesh->mBones.size();
|
||||
curMesh->mBones.push_back(ASE::Bone(bone));
|
||||
me.first = static_cast<int>( curMesh->mBones.size() );
|
||||
curMesh->mBones.push_back( ASE::Bone( bone ) );
|
||||
}
|
||||
ParseLV4MeshFloat( me.second );
|
||||
|
||||
|
@ -745,6 +744,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
|||
// empty the texture won't be used later.
|
||||
// ***********************************************************
|
||||
bool parsePath = true;
|
||||
std::string temp;
|
||||
while (true)
|
||||
{
|
||||
if ('*' == *filePtr)
|
||||
|
@ -753,12 +753,12 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
|||
// type of map
|
||||
if (TokenMatch(filePtr,"MAP_CLASS" ,9))
|
||||
{
|
||||
std::string temp;
|
||||
temp.clear();
|
||||
if(!ParseString(temp,"*MAP_CLASS"))
|
||||
SkipToNextToken();
|
||||
if (temp != "Bitmap" && temp != "Normal Bump")
|
||||
{
|
||||
DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
|
||||
ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp);
|
||||
parsePath = false;
|
||||
}
|
||||
continue;
|
||||
|
@ -773,7 +773,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
|||
{
|
||||
// Files with 'None' as map name are produced by
|
||||
// an Maja to ASE exporter which name I forgot ..
|
||||
DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
|
||||
ASSIMP_LOG_WARN("ASE: Skipping invalid map entry");
|
||||
map.mMapName = "";
|
||||
}
|
||||
|
||||
|
@ -1072,7 +1072,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
|
|||
( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET))
|
||||
{
|
||||
|
||||
DefaultLogger::get()->error("ASE: Found target animation channel "
|
||||
ASSIMP_LOG_ERROR("ASE: Found target animation channel "
|
||||
"but the node is neither a camera nor a spot light");
|
||||
anim = NULL;
|
||||
}
|
||||
|
@ -1098,7 +1098,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
|
|||
if (!anim || anim == &mesh.mTargetAnim)
|
||||
{
|
||||
// Target animation channels may have no rotation channels
|
||||
DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
|
||||
ASSIMP_LOG_ERROR("ASE: Ignoring scaling channel in target animation");
|
||||
SkipSection();
|
||||
}
|
||||
else ParseLV3ScaleAnimationBlock(*anim);
|
||||
|
@ -1112,7 +1112,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
|
|||
if (!anim || anim == &mesh.mTargetAnim)
|
||||
{
|
||||
// Target animation channels may have no rotation channels
|
||||
DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
|
||||
ASSIMP_LOG_ERROR("ASE: Ignoring rotation channel in target animation");
|
||||
SkipSection();
|
||||
}
|
||||
else ParseLV3RotAnimationBlock(*anim);
|
||||
|
@ -1295,12 +1295,14 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh)
|
|||
{
|
||||
mode = 2;
|
||||
}
|
||||
else DefaultLogger::get()->error("ASE: Ignoring target transform, "
|
||||
"this is no spot light or target camera");
|
||||
else {
|
||||
ASSIMP_LOG_ERROR("ASE: Ignoring target transform, "
|
||||
"this is no spot light or target camera");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
|
||||
ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp);
|
||||
// mode = 0
|
||||
}
|
||||
continue;
|
||||
|
@ -1916,7 +1918,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
|
|||
else if (index == face.mIndices[2])
|
||||
index = 2;
|
||||
else {
|
||||
DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
|
||||
ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
|
||||
continue;
|
||||
}
|
||||
// We'll renormalize later
|
||||
|
@ -1928,7 +1930,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
|
|||
ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
|
||||
|
||||
if (faceIdx >= sMesh.mFaces.size()) {
|
||||
DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
|
||||
ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_FACENORMAL section");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -427,7 +427,7 @@ public:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
//! Construct a parser from a given input file which is
|
||||
//! guaranted to be terminated with zero.
|
||||
//! guaranteed to be terminated with zero.
|
||||
//! @param szFile Input file
|
||||
//! @param fileFormatDefault Assumed file format version. If the
|
||||
//! file format is specified in the file the new value replaces
|
||||
|
|
|
@ -146,7 +146,7 @@ private:
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ReportSceneNotFoundError() {
|
||||
DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
|
||||
ASSIMP_LOG_ERROR("Unable to find the Assimp::Importer for this aiScene. "
|
||||
"The C-API does not accept scenes produced by the C++ API and vice versa");
|
||||
|
||||
ai_assert(false);
|
||||
|
|
|
@ -614,7 +614,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
|
|||
if (!DefaultLogger::isNullLogger()) {
|
||||
char dmp[128];
|
||||
ai_snprintf(dmp, 128, "B3D file format version: %i",version);
|
||||
DefaultLogger::get()->info(dmp);
|
||||
ASSIMP_LOG_INFO(dmp);
|
||||
}
|
||||
|
||||
while( ChunkSize() ){
|
||||
|
|
|
@ -199,6 +199,7 @@ aiNode* BVHLoader::ReadNode()
|
|||
Node& internNode = mNodes.back();
|
||||
|
||||
// now read the node's contents
|
||||
std::string siteToken;
|
||||
while( 1)
|
||||
{
|
||||
std::string token = GetNextToken();
|
||||
|
@ -218,7 +219,8 @@ aiNode* BVHLoader::ReadNode()
|
|||
else if( token == "End")
|
||||
{
|
||||
// The real symbol is "End Site". Second part comes in a separate token
|
||||
std::string siteToken = GetNextToken();
|
||||
siteToken.clear();
|
||||
siteToken = GetNextToken();
|
||||
if( siteToken != "Site")
|
||||
ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." );
|
||||
|
||||
|
@ -262,21 +264,18 @@ aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
|
|||
aiNode* node = new aiNode( "EndSite_" + pParentName);
|
||||
|
||||
// now read the node's contents. Only possible entry is "OFFSET"
|
||||
while( 1)
|
||||
{
|
||||
std::string token = GetNextToken();
|
||||
std::string token;
|
||||
while( 1) {
|
||||
token.clear();
|
||||
token = GetNextToken();
|
||||
|
||||
// end node's offset
|
||||
if( token == "OFFSET")
|
||||
{
|
||||
if( token == "OFFSET") {
|
||||
ReadNodeOffset( node);
|
||||
}
|
||||
else if( token == "}")
|
||||
{
|
||||
} else if( token == "}") {
|
||||
// we're done with the end node
|
||||
break;
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
// everything else is a parse error
|
||||
ThrowException( format() << "Unknown keyword \"" << token << "\"." );
|
||||
}
|
||||
|
@ -296,8 +295,10 @@ void BVHLoader::ReadNodeOffset( aiNode* pNode)
|
|||
offset.z = GetNextTokenAsFloat();
|
||||
|
||||
// build a transformation matrix from it
|
||||
pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
|
||||
0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x,
|
||||
0.0f, 1.0f, 0.0f, offset.y,
|
||||
0.0f, 0.0f, 1.0f, offset.z,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -64,23 +64,24 @@ using namespace Assimp;
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
BaseImporter::BaseImporter()
|
||||
: m_progress()
|
||||
{
|
||||
: m_progress() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
BaseImporter::~BaseImporter()
|
||||
{
|
||||
BaseImporter::~BaseImporter() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file and returns the imported data.
|
||||
aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler)
|
||||
{
|
||||
aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) {
|
||||
m_progress = pImp->GetProgressHandler();
|
||||
if (nullptr == m_progress) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ai_assert(m_progress);
|
||||
|
||||
// Gather configuration properties for this run
|
||||
|
@ -100,8 +101,8 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
|
|||
} catch( const std::exception& err ) {
|
||||
// extract error description
|
||||
m_ErrorText = err.what();
|
||||
DefaultLogger::get()->error(m_ErrorText);
|
||||
return NULL;
|
||||
ASSIMP_LOG_ERROR(m_ErrorText);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// return what we gathered from the import.
|
||||
|
@ -115,13 +116,12 @@ void BaseImporter::SetupProperties(const Importer* /*pImp*/)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
|
||||
{
|
||||
void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
||||
const aiImporterDesc* desc = GetInfo();
|
||||
ai_assert(desc != NULL);
|
||||
ai_assert(desc != nullptr);
|
||||
|
||||
const char* ext = desc->mFileExtensions;
|
||||
ai_assert(ext != NULL);
|
||||
ai_assert(ext != nullptr );
|
||||
|
||||
const char* last = ext;
|
||||
do {
|
||||
|
@ -145,12 +145,13 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
|
|||
unsigned int searchBytes /* = 200 */,
|
||||
bool tokensSol /* false */)
|
||||
{
|
||||
ai_assert( NULL != tokens );
|
||||
ai_assert( nullptr != tokens );
|
||||
ai_assert( 0 != numTokens );
|
||||
ai_assert( 0 != searchBytes);
|
||||
|
||||
if (!pIOHandler)
|
||||
if ( nullptr == pIOHandler ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
|
||||
if (pStream.get() ) {
|
||||
|
@ -178,16 +179,24 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
|
|||
}
|
||||
*cur2 = '\0';
|
||||
|
||||
for (unsigned int i = 0; i < numTokens;++i) {
|
||||
ai_assert(NULL != tokens[i]);
|
||||
const char* r = strstr(buffer,tokens[i]);
|
||||
std::string token;
|
||||
for (unsigned int i = 0; i < numTokens; ++i ) {
|
||||
ai_assert( nullptr != tokens[i] );
|
||||
const size_t len( strlen( tokens[ i ] ) );
|
||||
token.clear();
|
||||
const char *ptr( tokens[ i ] );
|
||||
for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) {
|
||||
token.push_back( tolower( *ptr ) );
|
||||
++ptr;
|
||||
}
|
||||
const char* r = strstr( buffer, token.c_str() );
|
||||
if( !r ) {
|
||||
continue;
|
||||
}
|
||||
// We got a match, either we don't care where it is, or it happens to
|
||||
// be in the beginning of the file / line
|
||||
if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
|
||||
DefaultLogger::get()->debug(std::string("Found positive match for header keyword: ") + tokens[i]);
|
||||
ASSIMP_LOG_DEBUG_F( "Found positive match for header keyword: ", tokens[i] );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +252,8 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
|
|||
/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
|
||||
const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
|
||||
{
|
||||
ai_assert(size <= 16 && _magic);
|
||||
ai_assert( size <= 16 );
|
||||
ai_assert( _magic );
|
||||
|
||||
if (!pIOHandler) {
|
||||
return false;
|
||||
|
@ -313,7 +323,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
|
|||
|
||||
// UTF 8 with BOM
|
||||
if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
|
||||
DefaultLogger::get()->debug("Found UTF-8 BOM ...");
|
||||
ASSIMP_LOG_DEBUG("Found UTF-8 BOM ...");
|
||||
|
||||
std::copy(data.begin()+3,data.end(),data.begin());
|
||||
data.resize(data.size()-3);
|
||||
|
@ -332,7 +342,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
|
|||
|
||||
// UTF 32 LE with BOM
|
||||
if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
|
||||
DefaultLogger::get()->debug("Found UTF-32 BOM ...");
|
||||
ASSIMP_LOG_DEBUG("Found UTF-32 BOM ...");
|
||||
|
||||
std::vector<char> output;
|
||||
int *ptr = (int*)&data[ 0 ];
|
||||
|
@ -352,7 +362,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
|
|||
|
||||
// UTF 16 LE with BOM
|
||||
if(*((uint16_t*)&data.front()) == 0xFEFF) {
|
||||
DefaultLogger::get()->debug("Found UTF-16 BOM ...");
|
||||
ASSIMP_LOG_DEBUG("Found UTF-16 BOM ...");
|
||||
|
||||
std::vector<unsigned char> output;
|
||||
utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
|
||||
|
@ -377,16 +387,14 @@ void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
|
|||
data[j] = ((unsigned char) data[++i] + 0x40);
|
||||
} else {
|
||||
std::stringstream stream;
|
||||
|
||||
stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
|
||||
|
||||
DefaultLogger::get()->error(stream.str());
|
||||
ASSIMP_LOG_ERROR( stream.str() );
|
||||
|
||||
data[j++] = data[i++];
|
||||
data[j] = data[i];
|
||||
}
|
||||
} else {
|
||||
DefaultLogger::get()->error("UTF8 code but only one character remaining");
|
||||
ASSIMP_LOG_ERROR("UTF8 code but only one character remaining");
|
||||
|
||||
data[j] = data[i];
|
||||
}
|
||||
|
@ -402,7 +410,7 @@ void BaseImporter::TextFileToBuffer(IOStream* stream,
|
|||
std::vector<char>& data,
|
||||
TextFileMode mode)
|
||||
{
|
||||
ai_assert(NULL != stream);
|
||||
ai_assert(nullptr != stream);
|
||||
|
||||
const size_t fileSize = stream->FileSize();
|
||||
if (mode == FORBID_EMPTY) {
|
||||
|
@ -463,14 +471,14 @@ struct Assimp::BatchData {
|
|||
, pImporter( nullptr )
|
||||
, next_id(0xffff)
|
||||
, validate( validate ) {
|
||||
ai_assert( NULL != pIO );
|
||||
ai_assert( nullptr != pIO );
|
||||
|
||||
pImporter = new Importer();
|
||||
pImporter->SetIOHandler( pIO );
|
||||
}
|
||||
|
||||
~BatchData() {
|
||||
pImporter->SetIOHandler( NULL ); /* get pointer back into our possession */
|
||||
pImporter->SetIOHandler( nullptr ); /* get pointer back into our possession */
|
||||
delete pImporter;
|
||||
}
|
||||
|
||||
|
@ -496,9 +504,8 @@ struct Assimp::BatchData {
|
|||
typedef std::list<LoadRequest>::iterator LoadReqIt;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BatchLoader::BatchLoader(IOSystem* pIO, bool validate )
|
||||
{
|
||||
ai_assert(NULL != pIO);
|
||||
BatchLoader::BatchLoader(IOSystem* pIO, bool validate ) {
|
||||
ai_assert(nullptr != pIO);
|
||||
|
||||
m_data = new BatchData( pIO, validate );
|
||||
}
|
||||
|
@ -564,7 +571,7 @@ aiScene* BatchLoader::GetImport( unsigned int which )
|
|||
return sc;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -587,13 +594,13 @@ void BatchLoader::LoadAll()
|
|||
|
||||
if (!DefaultLogger::isNullLogger())
|
||||
{
|
||||
DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
|
||||
DefaultLogger::get()->info("File: " + (*it).file);
|
||||
ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%");
|
||||
ASSIMP_LOG_INFO_F("File: ", (*it).file);
|
||||
}
|
||||
m_data->pImporter->ReadFile((*it).file,pp);
|
||||
(*it).scene = m_data->pImporter->GetOrphanedScene();
|
||||
(*it).loaded = true;
|
||||
|
||||
DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%");
|
||||
ASSIMP_LOG_INFO("%%% END EXTERNAL FILE %%%");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ void BaseProcess::ExecuteOnScene( Importer* pImp)
|
|||
|
||||
// extract error description
|
||||
pImp->Pimpl()->mErrorString = err.what();
|
||||
DefaultLogger::get()->error(pImp->Pimpl()->mErrorString);
|
||||
ASSIMP_LOG_ERROR(pImp->Pimpl()->mErrorString);
|
||||
|
||||
// and kill the partially imported data
|
||||
delete pImp->Pimpl()->mScene;
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
#include "BlenderCustomData.h"
|
||||
#include "BlenderDNA.h"
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
/**
|
||||
* @brief read/convert of Structure array to memory
|
||||
*/
|
||||
template<typename T>
|
||||
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
|
||||
for (size_t i = 0; i < cnt; ++i) {
|
||||
T read;
|
||||
s.Convert(read, db);
|
||||
*p = read;
|
||||
p++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief pointer to function read memory for n CustomData types
|
||||
*/
|
||||
typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
|
||||
typedef ElemBase * (*PCreate)(const size_t cnt);
|
||||
typedef void(*PDestroy)(ElemBase *);
|
||||
|
||||
#define IMPL_STRUCT_READ(ty) \
|
||||
bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
|
||||
return read<ty>(db.dna[#ty], dynamic_cast<ty *>(v), cnt, db); \
|
||||
}
|
||||
|
||||
#define IMPL_STRUCT_CREATE(ty) \
|
||||
ElemBase *create##ty(const size_t cnt) { \
|
||||
return new ty[cnt]; \
|
||||
}
|
||||
|
||||
#define IMPL_STRUCT_DESTROY(ty) \
|
||||
void destroy##ty(ElemBase *pE) { \
|
||||
ty *p = dynamic_cast<ty *>(pE); \
|
||||
delete[]p; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief helper macro to define Structure functions
|
||||
*/
|
||||
#define IMPL_STRUCT(ty) \
|
||||
IMPL_STRUCT_READ(ty) \
|
||||
IMPL_STRUCT_CREATE(ty) \
|
||||
IMPL_STRUCT_DESTROY(ty)
|
||||
|
||||
// supported structures for CustomData
|
||||
IMPL_STRUCT(MVert)
|
||||
IMPL_STRUCT(MEdge)
|
||||
IMPL_STRUCT(MFace)
|
||||
IMPL_STRUCT(MTFace)
|
||||
IMPL_STRUCT(MTexPoly)
|
||||
IMPL_STRUCT(MLoopUV)
|
||||
IMPL_STRUCT(MLoopCol)
|
||||
IMPL_STRUCT(MPoly)
|
||||
IMPL_STRUCT(MLoop)
|
||||
|
||||
/**
|
||||
* @brief describes the size of data and the read function to be used for single CustomerData.type
|
||||
*/
|
||||
struct CustomDataTypeDescription {
|
||||
PRead Read; ///< function to read one CustomData type element
|
||||
PCreate Create; ///< function to allocate n type elements
|
||||
PDestroy Destroy;
|
||||
|
||||
CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy)
|
||||
: Read(read)
|
||||
, Create(create)
|
||||
, Destroy(destroy)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief helper macro to define Structure type specific CustomDataTypeDescription
|
||||
* @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
|
||||
*/
|
||||
#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
|
||||
CustomDataTypeDescription{&read##ty, &create##ty, &destroy##ty}
|
||||
|
||||
/**
|
||||
* @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type
|
||||
*/
|
||||
#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
|
||||
CustomDataTypeDescription{nullptr, nullptr, nullptr}
|
||||
|
||||
/**
|
||||
* @brief descriptors for data pointed to from CustomDataLayer.data
|
||||
* @note some of the CustomData uses already well defined Structures
|
||||
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
|
||||
* use a special readfunction for that cases
|
||||
*/
|
||||
std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
|
||||
}};
|
||||
|
||||
|
||||
bool isValidCustomDataType(const int cdtype) {
|
||||
return cdtype >= 0 && cdtype < CD_NUMTYPES;
|
||||
}
|
||||
|
||||
bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
|
||||
if (!isValidCustomDataType(cdtype)) {
|
||||
throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index"));
|
||||
}
|
||||
|
||||
const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
|
||||
if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
|
||||
// allocate cnt elements and parse them from file
|
||||
out.reset(cdtd.Create(cnt), cdtd.Destroy);
|
||||
return cdtd.Read(out.get(), cnt, db);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
|
||||
for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
|
||||
if (it->get()->type == cdtype && name == it->get()->name) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ElemBase * getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name)
|
||||
{
|
||||
const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
|
||||
if (pLayer && pLayer->data) {
|
||||
return pLayer->data.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderScene.h"
|
||||
#include <memory>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
/* CustomData.type from Blender (2.79b) */
|
||||
enum CustomDataType {
|
||||
CD_AUTO_FROM_NAME = -1,
|
||||
CD_MVERT = 0,
|
||||
#ifdef DNA_DEPRECATED
|
||||
CD_MSTICKY = 1, /* DEPRECATED */
|
||||
#endif
|
||||
CD_MDEFORMVERT = 2,
|
||||
CD_MEDGE = 3,
|
||||
CD_MFACE = 4,
|
||||
CD_MTFACE = 5,
|
||||
CD_MCOL = 6,
|
||||
CD_ORIGINDEX = 7,
|
||||
CD_NORMAL = 8,
|
||||
/* CD_POLYINDEX = 9, */
|
||||
CD_PROP_FLT = 10,
|
||||
CD_PROP_INT = 11,
|
||||
CD_PROP_STR = 12,
|
||||
CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
|
||||
CD_ORCO = 14,
|
||||
CD_MTEXPOLY = 15,
|
||||
CD_MLOOPUV = 16,
|
||||
CD_MLOOPCOL = 17,
|
||||
CD_TANGENT = 18,
|
||||
CD_MDISPS = 19,
|
||||
CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */
|
||||
/* CD_ID_MCOL = 21, */
|
||||
CD_TEXTURE_MLOOPCOL = 22,
|
||||
CD_CLOTH_ORCO = 23,
|
||||
CD_RECAST = 24,
|
||||
|
||||
/* BMESH ONLY START */
|
||||
CD_MPOLY = 25,
|
||||
CD_MLOOP = 26,
|
||||
CD_SHAPE_KEYINDEX = 27,
|
||||
CD_SHAPEKEY = 28,
|
||||
CD_BWEIGHT = 29,
|
||||
CD_CREASE = 30,
|
||||
CD_ORIGSPACE_MLOOP = 31,
|
||||
CD_PREVIEW_MLOOPCOL = 32,
|
||||
CD_BM_ELEM_PYPTR = 33,
|
||||
/* BMESH ONLY END */
|
||||
|
||||
CD_PAINT_MASK = 34,
|
||||
CD_GRID_PAINT_MASK = 35,
|
||||
CD_MVERT_SKIN = 36,
|
||||
CD_FREESTYLE_EDGE = 37,
|
||||
CD_FREESTYLE_FACE = 38,
|
||||
CD_MLOOPTANGENT = 39,
|
||||
CD_TESSLOOPNORMAL = 40,
|
||||
CD_CUSTOMLOOPNORMAL = 41,
|
||||
|
||||
CD_NUMTYPES = 42
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief check if given cdtype is valid (ie >= 0 and < CD_NUMTYPES)
|
||||
* @param[in] cdtype to check
|
||||
* @return true when valid
|
||||
*/
|
||||
bool isValidCustomDataType(const int cdtype);
|
||||
|
||||
/**
|
||||
* @brief returns CustomDataLayer ptr for given cdtype and name
|
||||
* @param[in] customdata CustomData to search for wanted layer
|
||||
* @param[in] cdtype to search for
|
||||
* @param[in] name to search for
|
||||
* @return CustomDataLayer * or nullptr if not found
|
||||
*/
|
||||
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief returns CustomDataLayer data ptr for given cdtype and name
|
||||
* @param[in] customdata CustomData to search for wanted layer
|
||||
* @param[in] cdtype to search for
|
||||
* @param[in] name to search for
|
||||
* @return * to struct data or nullptr if not found
|
||||
*/
|
||||
const ElemBase * getCustomDataLayerData(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
|
||||
}
|
||||
}
|
|
@ -58,12 +58,11 @@ using namespace Assimp::Formatter;
|
|||
|
||||
static bool match4(StreamReaderAny& stream, const char* string) {
|
||||
ai_assert( nullptr != string );
|
||||
char tmp[] = {
|
||||
(const char)(stream).GetI1(),
|
||||
(const char)(stream).GetI1(),
|
||||
(const char)(stream).GetI1(),
|
||||
(const char)(stream).GetI1()
|
||||
};
|
||||
char tmp[4];
|
||||
tmp[ 0 ] = ( stream ).GetI1();
|
||||
tmp[ 1 ] = ( stream ).GetI1();
|
||||
tmp[ 2 ] = ( stream ).GetI1();
|
||||
tmp[ 3 ] = ( stream ).GetI1();
|
||||
return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
|
||||
}
|
||||
|
||||
|
@ -211,8 +210,7 @@ void DNAParser::Parse ()
|
|||
s.size = offset;
|
||||
}
|
||||
|
||||
DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(),
|
||||
" structures with totally ",fields," fields"));
|
||||
ASSIMP_LOG_DEBUG_F( "BlenderDNA: Got ", dna.structures.size()," structures with totally ",fields," fields");
|
||||
|
||||
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
|
||||
dna.DumpToFile();
|
||||
|
@ -229,12 +227,12 @@ void DNAParser::Parse ()
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void DNA :: DumpToFile()
|
||||
{
|
||||
// we dont't bother using the VFS here for this is only for debugging.
|
||||
// we don't bother using the VFS here for this is only for debugging.
|
||||
// (and all your bases are belong to us).
|
||||
|
||||
std::ofstream f("dna.txt");
|
||||
if (f.fail()) {
|
||||
DefaultLogger::get()->error("Could not dump dna to dna.txt");
|
||||
ASSIMP_LOG_ERROR("Could not dump dna to dna.txt");
|
||||
return;
|
||||
}
|
||||
f << "Field format: type name offset size" << "\n";
|
||||
|
@ -249,7 +247,7 @@ void DNA :: DumpToFile()
|
|||
}
|
||||
f << std::flush;
|
||||
|
||||
DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
|
||||
ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -368,7 +366,7 @@ void SectionParser :: Next()
|
|||
}
|
||||
|
||||
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
|
||||
DefaultLogger::get()->debug(current.id);
|
||||
ASSIMP_LOG_DEBUG(current.id);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ enum ErrorPolicy {
|
|||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Represents a data structure in a BLEND file. A Structure defines n fields
|
||||
* and their locatios and encodings the input stream. Usually, every
|
||||
* and their locations and encodings the input stream. Usually, every
|
||||
* Structure instance pertains to one equally-named data structure in the
|
||||
* BlenderScene.h header. This class defines various utilities to map a
|
||||
* binary `blob` read from the file to such a structure instance with
|
||||
|
@ -309,6 +309,28 @@ public:
|
|||
void ReadField(T& out, const char* name,
|
||||
const FileDatabase& db) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
/**
|
||||
* @brief field parsing for dynamic vectors
|
||||
* @param[in] out vector of struct to be filled
|
||||
* @param[in] name of field
|
||||
* @param[in] db to access the file, dna, ...
|
||||
* @return true when read was successful
|
||||
*/
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
bool ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const;
|
||||
|
||||
/**
|
||||
* @brief parses raw customdata
|
||||
* @param[in] out shared_ptr to be filled
|
||||
* @param[in] cdtype customdata type to read
|
||||
* @param[in] name of field ptr
|
||||
* @param[in] db to access the file, dna, ...
|
||||
* @return true when read was successful
|
||||
*/
|
||||
template <int error_policy>
|
||||
bool ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const;
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
@ -381,7 +403,7 @@ template <> struct Structure :: _defaultInitializer<ErrorPolicy_Warn> {
|
|||
|
||||
template <typename T>
|
||||
void operator ()(T& out, const char* reason = "<add reason>") {
|
||||
DefaultLogger::get()->warn(reason);
|
||||
ASSIMP_LOG_WARN(reason);
|
||||
|
||||
// ... and let the show go on
|
||||
_defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out);
|
||||
|
@ -663,7 +685,7 @@ public:
|
|||
/** Check whether a specific item is in the cache.
|
||||
* @param s Data type of the item
|
||||
* @param out Output pointer. Unchanged if the
|
||||
* cache doens't know the item yet.
|
||||
* cache doesn't know the item yet.
|
||||
* @param ptr Item address to look for. */
|
||||
template <typename T> void get (
|
||||
const Structure& s,
|
||||
|
@ -803,6 +825,17 @@ private:
|
|||
FileDatabase& db;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief read CustomData's data to ptr to mem
|
||||
* @param[out] out memory ptr to set
|
||||
* @param[in] cdtype to read
|
||||
* @param[in] cnt cnt of elements to read
|
||||
* @param[in] db to read elements from
|
||||
* @return true when ok
|
||||
*/
|
||||
bool readCustomData(std::shared_ptr<ElemBase> &out, int cdtype, size_t cnt, const FileDatabase &db);
|
||||
|
||||
|
||||
} // end Blend
|
||||
} // end Assimp
|
||||
|
||||
|
|
|
@ -307,6 +307,108 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
|
|||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// field parsing for raw untyped data (like CustomDataLayer.data)
|
||||
template <int error_policy>
|
||||
bool Structure::ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const {
|
||||
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
|
||||
Pointer ptrval;
|
||||
const Field* f;
|
||||
try {
|
||||
f = &(*this)[name];
|
||||
|
||||
// sanity check, should never happen if the genblenddna script is right
|
||||
if (!(f->flags & FieldFlag_Pointer)) {
|
||||
throw Error((Formatter::format(), "Field `", name, "` of structure `",
|
||||
this->name, "` ought to be a pointer"));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f->offset);
|
||||
Convert(ptrval, db);
|
||||
// actually it is meaningless on which Structure the Convert is called
|
||||
// because the `Pointer` argument triggers a special implementation.
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out, e.what());
|
||||
out.reset();
|
||||
}
|
||||
|
||||
bool readOk = true;
|
||||
if (ptrval.val) {
|
||||
// get block for ptr
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
|
||||
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
|
||||
// read block->num instances of given type to out
|
||||
readOk = readCustomData(out, cdtype, block->num, db);
|
||||
}
|
||||
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
|
||||
return readOk;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
bool Structure::ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const {
|
||||
out.clear();
|
||||
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
|
||||
Pointer ptrval;
|
||||
const Field* f;
|
||||
try {
|
||||
f = &(*this)[name];
|
||||
|
||||
// sanity check, should never happen if the genblenddna script is right
|
||||
if (!(f->flags & FieldFlag_Pointer)) {
|
||||
throw Error((Formatter::format(), "Field `", name, "` of structure `",
|
||||
this->name, "` ought to be a pointer"));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f->offset);
|
||||
Convert(ptrval, db);
|
||||
// actually it is meaningless on which Structure the Convert is called
|
||||
// because the `Pointer` argument triggers a special implementation.
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out, e.what());
|
||||
out.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (ptrval.val) {
|
||||
// find the file block the pointer is pointing to
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
|
||||
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
|
||||
// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
|
||||
// I really ought to improve StreamReader to work with 64 bit indices exclusively.
|
||||
|
||||
const Structure& s = db.dna[f->type];
|
||||
for (size_t i = 0; i < block->num; ++i) {
|
||||
TOUT<T> p(new T);
|
||||
s.Convert(*p, db);
|
||||
out.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
|
||||
|
@ -468,9 +570,7 @@ template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shar
|
|||
// this might happen if DNA::RegisterConverters hasn't been called so far
|
||||
// or if the target type is not contained in `our` DNA.
|
||||
out.reset();
|
||||
DefaultLogger::get()->warn((Formatter::format(),
|
||||
"Failed to find a converter for the `",s.name,"` structure"
|
||||
));
|
||||
ASSIMP_LOG_WARN_F( "Failed to find a converter for the `",s.name,"` structure" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -502,7 +602,7 @@ const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrv
|
|||
{
|
||||
// the file blocks appear in list sorted by
|
||||
// with ascending base addresses so we can run a
|
||||
// binary search to locate the pointee quickly.
|
||||
// binary search to locate the pointer quickly.
|
||||
|
||||
// NOTE: Blender seems to distinguish between side-by-side
|
||||
// data (stored in the same data block) and far pointers,
|
||||
|
|
|
@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "BlenderIntermediate.h"
|
||||
#include "BlenderModifier.h"
|
||||
#include "BlenderBMesh.h"
|
||||
#include "BlenderCustomData.h"
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
|
@ -327,12 +328,12 @@ void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file)
|
|||
ss.Convert(out,file);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
DefaultLogger::get()->info((format(),
|
||||
ASSIMP_LOG_INFO_F(
|
||||
"(Stats) Fields read: " ,file.stats().fields_read,
|
||||
", pointers resolved: " ,file.stats().pointers_resolved,
|
||||
", cache hits: " ,file.stats().cache_hits,
|
||||
", cached objects: " ,file.stats().cached_objects
|
||||
));
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1021,6 +1022,32 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
}
|
||||
}
|
||||
|
||||
// TODO should we create the TextureUVMapping map in Convert<Material> to prevent redundant processing?
|
||||
|
||||
// create texture <-> uvname mapping for all materials
|
||||
// key is texture number, value is data *
|
||||
typedef std::map<uint32_t, const MLoopUV *> TextureUVMapping;
|
||||
// key is material number, value is the TextureUVMapping for the material
|
||||
typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
|
||||
MaterialTextureUVMappings matTexUvMappings;
|
||||
const uint32_t maxMat = static_cast<const uint32_t>(mesh->mat.size());
|
||||
for (uint32_t m = 0; m < maxMat; ++m) {
|
||||
// get material by index
|
||||
const std::shared_ptr<Material> pMat = mesh->mat[m];
|
||||
TextureUVMapping texuv;
|
||||
const uint32_t maxTex = sizeof(pMat->mtex) / sizeof(pMat->mtex[0]);
|
||||
for (uint32_t t = 0; t < maxTex; ++t) {
|
||||
if (pMat->mtex[t] && pMat->mtex[t]->uvname[0]) {
|
||||
// get the CustomData layer for given uvname and correct type
|
||||
const ElemBase *pLoop = getCustomDataLayerData(mesh->ldata, CD_MLOOPUV, pMat->mtex[t]->uvname);
|
||||
if (pLoop) {
|
||||
texuv.insert(std::make_pair(t, dynamic_cast<const MLoopUV *>(pLoop)));
|
||||
}
|
||||
}
|
||||
}
|
||||
matTexUvMappings.insert(std::make_pair(m, texuv));
|
||||
}
|
||||
|
||||
// collect texture coordinates, they're stored in a separate per-face buffer
|
||||
if (mesh->mtface || mesh->mloopuv) {
|
||||
if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
|
||||
|
@ -1028,8 +1055,17 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
}
|
||||
for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
|
||||
ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
|
||||
|
||||
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
|
||||
const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
|
||||
if (itMatTexUvMapping == matTexUvMappings.end()) {
|
||||
// default behaviour like before
|
||||
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
|
||||
}
|
||||
else {
|
||||
// create texture coords for every mapped tex
|
||||
for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) {
|
||||
(*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices];
|
||||
}
|
||||
}
|
||||
(*it)->mNumFaces = (*it)->mNumVertices = 0;
|
||||
}
|
||||
|
||||
|
@ -1051,13 +1087,34 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
|
||||
const aiFace& f = out->mFaces[out->mNumFaces++];
|
||||
|
||||
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
|
||||
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
|
||||
const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
|
||||
vo->x = uv.uv[0];
|
||||
vo->y = uv.uv[1];
|
||||
const auto itMatTexUvMapping = matTexUvMappings.find(v.mat_nr);
|
||||
if (itMatTexUvMapping == matTexUvMappings.end()) {
|
||||
// old behavior
|
||||
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
|
||||
for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) {
|
||||
const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
|
||||
vo->x = uv.uv[0];
|
||||
vo->y = uv.uv[1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// create textureCoords for every mapped tex
|
||||
for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) {
|
||||
const MLoopUV *tm = itMatTexUvMapping->second[m];
|
||||
aiVector3D* vo = &out->mTextureCoords[m][out->mNumVertices];
|
||||
uint32_t j = 0;
|
||||
for (; j < f.mNumIndices; ++j, ++vo) {
|
||||
const MLoopUV& uv = tm[v.loopstart + j];
|
||||
vo->x = uv.uv[0];
|
||||
vo->y = uv.uv[1];
|
||||
}
|
||||
// only update written mNumVertices in last loop
|
||||
// TODO why must the numVertices be incremented here?
|
||||
if (m == itMatTexUvMapping->second.size() - 1) {
|
||||
out->mNumVertices += j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,34 +70,6 @@ static const fpCreateModifier creators[] = {
|
|||
NULL // sentinel
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// just testing out some new macros to simplify logging
|
||||
#define ASSIMP_LOG_WARN_F(string,...)\
|
||||
DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__))
|
||||
|
||||
#define ASSIMP_LOG_ERROR_F(string,...)\
|
||||
DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
|
||||
|
||||
#define ASSIMP_LOG_DEBUG_F(string,...)\
|
||||
DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
|
||||
|
||||
#define ASSIMP_LOG_INFO_F(string,...)\
|
||||
DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
|
||||
|
||||
|
||||
#define ASSIMP_LOG_WARN(string)\
|
||||
DefaultLogger::get()->warn(string)
|
||||
|
||||
#define ASSIMP_LOG_ERROR(string)\
|
||||
DefaultLogger::get()->error(string)
|
||||
|
||||
#define ASSIMP_LOG_DEBUG(string)\
|
||||
DefaultLogger::get()->debug(string)
|
||||
|
||||
#define ASSIMP_LOG_INFO(string)\
|
||||
DefaultLogger::get()->info(string)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
struct SharedModifierData : ElemBase
|
||||
{
|
||||
|
|
|
@ -47,53 +47,57 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define INCLUDED_AI_BLEND_MODIFIER_H
|
||||
|
||||
#include "BlenderIntermediate.h"
|
||||
#include <assimp/TinyFormatter.h>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/** Dummy base class for all blender modifiers. Modifiers are reused between imports, so
|
||||
* they should be stateless and not try to cache model data. */
|
||||
/**
|
||||
* Dummy base class for all blender modifiers. Modifiers are reused between imports, so
|
||||
* they should be stateless and not try to cache model data.
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class BlenderModifier
|
||||
{
|
||||
class BlenderModifier {
|
||||
public:
|
||||
/**
|
||||
* The class destructor, virtual.
|
||||
*/
|
||||
virtual ~BlenderModifier() {
|
||||
// empty
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// --------------------
|
||||
/** Check if *this* modifier is active, given a ModifierData& block.*/
|
||||
/**
|
||||
* Check if *this* modifier is active, given a ModifierData& block.
|
||||
*/
|
||||
virtual bool IsActive( const ModifierData& /*modin*/) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
/** Apply the modifier to a given output node. The original data used
|
||||
/**
|
||||
* Apply the modifier to a given output node. The original data used
|
||||
* to construct the node is given as well. Not called unless IsActive()
|
||||
* was called and gave positive response. */
|
||||
* was called and gave positive response.
|
||||
*/
|
||||
virtual void DoIt(aiNode& /*out*/,
|
||||
ConversionData& /*conv_data*/,
|
||||
const ElemBase& orig_modifier,
|
||||
const Scene& /*in*/,
|
||||
const Object& /*orig_object*/
|
||||
) {
|
||||
DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type));
|
||||
ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: ",orig_modifier.dna_type );
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/** Manage all known modifiers and instance and apply them if necessary */
|
||||
/**
|
||||
* Manage all known modifiers and instance and apply them if necessary
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class BlenderModifierShowcase
|
||||
{
|
||||
class BlenderModifierShowcase {
|
||||
public:
|
||||
|
||||
// --------------------
|
||||
/** Apply all requested modifiers provided we support them. */
|
||||
void ApplyModifiers(aiNode& out,
|
||||
|
@ -103,25 +107,18 @@ public:
|
|||
);
|
||||
|
||||
private:
|
||||
|
||||
TempArray< std::vector,BlenderModifier > cached_modifiers;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// MODIFIERS
|
||||
|
||||
|
||||
// MODIFIERS /////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/** Mirror modifier. Status: implemented. */
|
||||
/**
|
||||
* Mirror modifier. Status: implemented.
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class BlenderModifier_Mirror : public BlenderModifier
|
||||
{
|
||||
class BlenderModifier_Mirror : public BlenderModifier {
|
||||
public:
|
||||
|
||||
// --------------------
|
||||
virtual bool IsActive( const ModifierData& modin);
|
||||
|
||||
|
@ -137,8 +134,7 @@ public:
|
|||
// -------------------------------------------------------------------------------------------
|
||||
/** Subdivision modifier. Status: dummy. */
|
||||
// -------------------------------------------------------------------------------------------
|
||||
class BlenderModifier_Subdivision : public BlenderModifier
|
||||
{
|
||||
class BlenderModifier_Subdivision : public BlenderModifier {
|
||||
public:
|
||||
|
||||
// --------------------
|
||||
|
@ -153,6 +149,7 @@ public:
|
|||
) ;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
#endif // !INCLUDED_AI_BLEND_MODIFIER_H
|
||||
|
|
|
@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "BlenderScene.h"
|
||||
#include "BlenderSceneGen.h"
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderCustomData.h"
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
|
@ -116,7 +117,7 @@ template <> void Structure :: Convert<MTex> (
|
|||
ReadField<ErrorPolicy_Igno>(temp,"projy",db);
|
||||
dest.projy = static_cast<Assimp::Blender::MTex::Projection>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(temp,"projz",db);
|
||||
dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
|
||||
dest.projz = static_cast<Assimp::Blender::MTex::Projection>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);
|
||||
|
@ -481,6 +482,12 @@ template <> void Structure :: Convert<Mesh> (
|
|||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
|
||||
|
||||
ReadField<ErrorPolicy_Igno>(dest.vdata, "vdata", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.edata, "edata", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fdata, "fdata", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pdata, "pdata", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.ldata, "ldata", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
|
@ -786,6 +793,42 @@ template <> void Structure :: Convert<Image> (
|
|||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure::Convert<CustomData>(
|
||||
CustomData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.typemap, "typemap", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pad_i1, "pad_i1", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.totlayer, "totlayer", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.maxlayer, "maxlayer", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.totsize, "totsize", db);
|
||||
ReadFieldPtrVector<ErrorPolicy_Warn>(dest.layers, "*layers", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure::Convert<CustomDataLayer>(
|
||||
CustomDataLayer& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
ReadField<ErrorPolicy_Fail>(dest.type, "type", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.offset, "offset", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.flag, "flag", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active, "active", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active_rnd, "active_rnd", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active_clone, "active_clone", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active_mask, "active_mask", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.uid, "uid", db);
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.name, "name", db);
|
||||
ReadCustomDataPtr<ErrorPolicy_Fail>(dest.data, dest.type, "*data", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
void DNA::RegisterConverters() {
|
||||
|
||||
|
@ -822,6 +865,8 @@ void DNA::RegisterConverters() {
|
|||
converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
|
||||
converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
|
||||
converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
|
||||
converters["CustomData"] = DNA::FactoryPair(&Structure::Allocate<CustomData>, &Structure::Convert<CustomData>);
|
||||
converters["CustomDataLayer"] = DNA::FactoryPair(&Structure::Allocate<CustomDataLayer>, &Structure::Convert<CustomDataLayer>);
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
|
|
@ -157,10 +157,16 @@ struct World : ElemBase {
|
|||
// -------------------------------------------------------------------------------
|
||||
struct MVert : ElemBase {
|
||||
float co[3] FAIL;
|
||||
float no[3] FAIL;
|
||||
float no[3] FAIL; // readed as short and divided through / 32767.f
|
||||
char flag;
|
||||
int mat_nr WARN;
|
||||
int bweight;
|
||||
|
||||
MVert() : ElemBase()
|
||||
, flag(0)
|
||||
, mat_nr(0)
|
||||
, bweight(0)
|
||||
{}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
@ -369,6 +375,73 @@ struct Material : ElemBase {
|
|||
std::shared_ptr<MTex> mtex[18];
|
||||
};
|
||||
|
||||
/*
|
||||
CustomDataLayer 104
|
||||
|
||||
int type 0 4
|
||||
int offset 4 4
|
||||
int flag 8 4
|
||||
int active 12 4
|
||||
int active_rnd 16 4
|
||||
int active_clone 20 4
|
||||
int active_mask 24 4
|
||||
int uid 28 4
|
||||
char name 32 64
|
||||
void *data 96 8
|
||||
*/
|
||||
struct CustomDataLayer : ElemBase {
|
||||
int type;
|
||||
int offset;
|
||||
int flag;
|
||||
int active;
|
||||
int active_rnd;
|
||||
int active_clone;
|
||||
int active_mask;
|
||||
int uid;
|
||||
char name[64];
|
||||
std::shared_ptr<ElemBase> data; // must be converted to real type according type member
|
||||
|
||||
CustomDataLayer()
|
||||
: ElemBase()
|
||||
, type(0)
|
||||
, offset(0)
|
||||
, flag(0)
|
||||
, active(0)
|
||||
, active_rnd(0)
|
||||
, active_clone(0)
|
||||
, active_mask(0)
|
||||
, uid(0)
|
||||
, data(nullptr)
|
||||
{
|
||||
memset(name, 0, sizeof name);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
CustomData 208
|
||||
|
||||
CustomDataLayer *layers 0 8
|
||||
int typemap 8 168
|
||||
int pad_i1 176 4
|
||||
int totlayer 180 4
|
||||
int maxlayer 184 4
|
||||
int totsize 188 4
|
||||
BLI_mempool *pool 192 8
|
||||
CustomDataExternal *external 200 8
|
||||
*/
|
||||
struct CustomData : ElemBase {
|
||||
vector<std::shared_ptr<struct CustomDataLayer> > layers;
|
||||
int typemap[42]; // CD_NUMTYPES
|
||||
int pad_i1;
|
||||
int totlayer;
|
||||
int maxlayer;
|
||||
int totsize;
|
||||
/*
|
||||
std::shared_ptr<BLI_mempool> pool;
|
||||
std::shared_ptr<CustomDataExternal> external;
|
||||
*/
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Mesh : ElemBase {
|
||||
ID id FAIL;
|
||||
|
@ -398,6 +471,12 @@ struct Mesh : ElemBase {
|
|||
vector<MCol> mcol;
|
||||
|
||||
vector< std::shared_ptr<Material> > mat FAIL;
|
||||
|
||||
struct CustomData vdata;
|
||||
struct CustomData edata;
|
||||
struct CustomData fdata;
|
||||
struct CustomData pdata;
|
||||
struct CustomData ldata;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
|
|
@ -248,6 +248,17 @@ template <> void Structure :: Convert<Image> (
|
|||
) const
|
||||
;
|
||||
|
||||
template <> void Structure::Convert<CustomData>(
|
||||
CustomData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure::Convert<CustomDataLayer>(
|
||||
CustomDataLayer& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define INCLUDED_AI_BLEND_TESSELLATOR_H
|
||||
|
||||
// Use these to toggle between GLU Tessellate or poly2tri
|
||||
// Note (acg) keep GLU Tesselate disabled by default - if it is turned on,
|
||||
// Note (acg) keep GLU Tessellate disabled by default - if it is turned on,
|
||||
// assimp needs to be linked against GLU, which is currently not yet
|
||||
// made configurable in CMake and potentially not wanted by most users
|
||||
// as it requires a Gl environment.
|
||||
|
|
|
@ -72,6 +72,7 @@ SET( PUBLIC_HEADERS
|
|||
${HEADER_PATH}/matrix4x4.h
|
||||
${HEADER_PATH}/matrix4x4.inl
|
||||
${HEADER_PATH}/mesh.h
|
||||
${HEADER_PATH}/pbrmaterial.h
|
||||
${HEADER_PATH}/postprocess.h
|
||||
${HEADER_PATH}/quaternion.h
|
||||
${HEADER_PATH}/quaternion.inl
|
||||
|
@ -176,8 +177,6 @@ SET( Common_SRCS
|
|||
SkeletonMeshBuilder.cpp
|
||||
SplitByBoneCountProcess.cpp
|
||||
SplitByBoneCountProcess.h
|
||||
ScaleProcess.cpp
|
||||
ScaleProcess.h
|
||||
StandardShapes.cpp
|
||||
TargetAnimation.cpp
|
||||
TargetAnimation.h
|
||||
|
@ -187,6 +186,8 @@ SET( Common_SRCS
|
|||
Bitmap.cpp
|
||||
Version.cpp
|
||||
CreateAnimMesh.cpp
|
||||
simd.h
|
||||
simd.cpp
|
||||
)
|
||||
SOURCE_GROUP(Common FILES ${Common_SRCS})
|
||||
|
||||
|
@ -207,8 +208,15 @@ OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_
|
|||
# macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
|
||||
# this way selective loaders can be compiled (reduces filesize + compile time)
|
||||
MACRO(ADD_ASSIMP_IMPORTER name)
|
||||
OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT})
|
||||
IF(ASSIMP_BUILD_${name}_IMPORTER)
|
||||
IF (ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT)
|
||||
set(ASSIMP_IMPORTER_ENABLED TRUE)
|
||||
IF (DEFINED ASSIMP_BUILD_${name}_IMPORTER AND NOT ASSIMP_BUILD_${name}_IMPORTER)
|
||||
set(ASSIMP_IMPORTER_ENABLED FALSE)
|
||||
ENDIF ()
|
||||
ELSE ()
|
||||
set(ASSIMP_IMPORTER_ENABLED ${ASSIMP_BUILD_${name}_IMPORTER})
|
||||
ENDIF ()
|
||||
IF (ASSIMP_IMPORTER_ENABLED)
|
||||
LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
|
||||
SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
|
||||
SET(${name}_SRCS ${ARGN})
|
||||
|
@ -461,6 +469,8 @@ ADD_ASSIMP_IMPORTER( BLEND
|
|||
BlenderBMesh.cpp
|
||||
BlenderTessellator.h
|
||||
BlenderTessellator.cpp
|
||||
BlenderCustomData.h
|
||||
BlenderCustomData.cpp
|
||||
)
|
||||
|
||||
ADD_ASSIMP_IMPORTER( IFC
|
||||
|
@ -484,9 +494,9 @@ ADD_ASSIMP_IMPORTER( IFC
|
|||
)
|
||||
if (ASSIMP_BUILD_IFC_IMPORTER)
|
||||
if (MSVC)
|
||||
set_source_files_properties(IFCReaderGen1.cpp IFCReaderGen2.cpp PROPERTIES COMPILE_FLAGS "/bigobj")
|
||||
set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "/bigobj")
|
||||
elseif(CMAKE_COMPILER_IS_MINGW)
|
||||
set_source_files_properties(IFCReaderGen1.cpp IFCReaderGen2.cpp PROPERTIES COMPILE_FLAGS "-O2 -Wa,-mbig-obj")
|
||||
set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "-O2 -Wa,-mbig-obj")
|
||||
endif()
|
||||
endif (ASSIMP_BUILD_IFC_IMPORTER)
|
||||
|
||||
|
@ -522,6 +532,13 @@ ADD_ASSIMP_IMPORTER( FBX
|
|||
FBXDeformer.cpp
|
||||
FBXBinaryTokenizer.cpp
|
||||
FBXDocumentUtil.cpp
|
||||
FBXExporter.h
|
||||
FBXExporter.cpp
|
||||
FBXExportNode.h
|
||||
FBXExportNode.cpp
|
||||
FBXExportProperty.h
|
||||
FBXExportProperty.cpp
|
||||
FBXCommon.h
|
||||
)
|
||||
|
||||
SET( PostProcessing_SRCS
|
||||
|
@ -578,6 +595,8 @@ SET( PostProcessing_SRCS
|
|||
PolyTools.h
|
||||
MakeVerboseFormat.cpp
|
||||
MakeVerboseFormat.h
|
||||
ScaleProcess.cpp
|
||||
ScaleProcess.h
|
||||
)
|
||||
SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
|
||||
|
||||
|
@ -641,7 +660,7 @@ ADD_ASSIMP_IMPORTER( X
|
|||
XFileExporter.cpp
|
||||
)
|
||||
|
||||
ADD_ASSIMP_IMPORTER(X3D
|
||||
ADD_ASSIMP_IMPORTER( X3D
|
||||
X3DExporter.cpp
|
||||
X3DExporter.hpp
|
||||
X3DImporter.cpp
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -151,7 +150,7 @@ void COBImporter::InternReadFile( const std::string& pFile,
|
|||
ThrowException("Could not found magic id: `Caligari`");
|
||||
}
|
||||
|
||||
DefaultLogger::get()->info("File format tag: "+std::string(head+9,6));
|
||||
ASSIMP_LOG_INFO_F("File format tag: ",std::string(head+9,6));
|
||||
if (head[16]!='L') {
|
||||
ThrowException("File is big-endian, which is not supported");
|
||||
}
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -301,7 +303,7 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill
|
|||
}
|
||||
std::unique_ptr<const Material> defmat;
|
||||
if(!min) {
|
||||
DefaultLogger::get()->debug(format()<<"Could not resolve material index "
|
||||
ASSIMP_LOG_DEBUG(format()<<"Could not resolve material index "
|
||||
<<reflist.first<<" - creating default material for this slot");
|
||||
|
||||
defmat.reset(min=new Material());
|
||||
|
@ -473,7 +475,7 @@ void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo
|
|||
|
||||
// we can recover if the chunk size was specified.
|
||||
if(nfo.size != static_cast<unsigned int>(-1)) {
|
||||
DefaultLogger::get()->error(error);
|
||||
ASSIMP_LOG_ERROR(error);
|
||||
|
||||
// (HACK) - our current position in the stream is the beginning of the
|
||||
// head line of the next chunk. That's fine, but the caller is going
|
||||
|
@ -485,46 +487,6 @@ void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo
|
|||
else ThrowException(error);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void COBImporter::LogWarn_Ascii(const LineSplitter& splitter, const format& message) {
|
||||
LogWarn_Ascii(message << " [at line "<< splitter.get_index()<<"]");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void COBImporter::LogError_Ascii(const LineSplitter& splitter, const format& message) {
|
||||
LogError_Ascii(message << " [at line "<< splitter.get_index()<<"]");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void COBImporter::LogInfo_Ascii(const LineSplitter& splitter, const format& message) {
|
||||
LogInfo_Ascii(message << " [at line "<< splitter.get_index()<<"]");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& message) {
|
||||
LogDebug_Ascii(message << " [at line "<< splitter.get_index()<<"]");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void COBImporter::LogWarn_Ascii(const Formatter::format& message) {
|
||||
DefaultLogger::get()->warn(std::string("COB: ")+=message);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void COBImporter::LogError_Ascii(const Formatter::format& message) {
|
||||
DefaultLogger::get()->error(std::string("COB: ")+=message);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void COBImporter::LogInfo_Ascii(const Formatter::format& message) {
|
||||
DefaultLogger::get()->info(std::string("COB: ")+=message);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void COBImporter::LogDebug_Ascii(const Formatter::format& message) {
|
||||
DefaultLogger::get()->debug(std::string("COB: ")+=message);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void COBImporter::ReadBasicNodeInfo_Ascii(Node& msh, LineSplitter& splitter, const ChunkInfo& /*nfo*/)
|
||||
{
|
||||
|
@ -574,8 +536,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
|
|||
|
||||
++splitter;
|
||||
if (!splitter.match_start("mat# ")) {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Expected `mat#` line in `Mat1` chunk "<<nfo.id);
|
||||
ASSIMP_LOG_WARN_F( "Expected `mat#` line in `Mat1` chunk ", nfo.id );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -587,8 +548,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
|
|||
++splitter;
|
||||
|
||||
if (!splitter.match_start("shader: ")) {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Expected `mat#` line in `Mat1` chunk "<<nfo.id);
|
||||
ASSIMP_LOG_WARN_F( "Expected `mat#` line in `Mat1` chunk ", nfo.id);
|
||||
return;
|
||||
}
|
||||
std::string shader = std::string(splitter[1]);
|
||||
|
@ -601,14 +561,12 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
|
|||
mat.shader = Material::PHONG;
|
||||
}
|
||||
else if (shader != "flat") {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Unknown value for `shader` in `Mat1` chunk "<<nfo.id);
|
||||
ASSIMP_LOG_WARN_F( "Unknown value for `shader` in `Mat1` chunk ", nfo.id );
|
||||
}
|
||||
|
||||
++splitter;
|
||||
if (!splitter.match_start("rgb ")) {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Expected `rgb` line in `Mat1` chunk "<<nfo.id);
|
||||
ASSIMP_LOG_WARN_F( "Expected `rgb` line in `Mat1` chunk ", nfo.id);
|
||||
}
|
||||
|
||||
const char* rgb = splitter[1];
|
||||
|
@ -616,8 +574,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
|
|||
|
||||
++splitter;
|
||||
if (!splitter.match_start("alpha ")) {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Expected `alpha` line in `Mat1` chunk "<<nfo.id);
|
||||
ASSIMP_LOG_WARN_F( "Expected `alpha` line in `Mat1` chunk ", nfo.id);
|
||||
}
|
||||
|
||||
const char* tokens[10];
|
||||
|
@ -638,8 +595,7 @@ void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const Chunk
|
|||
}
|
||||
++splitter;
|
||||
if (!splitter.match_start("Units ")) {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Expected `Units` line in `Unit` chunk "<<nfo.id);
|
||||
ASSIMP_LOG_WARN_F( "Expected `Units` line in `Unit` chunk ", nfo.id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -650,13 +606,12 @@ void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const Chunk
|
|||
const unsigned int t=strtoul10(splitter[1]);
|
||||
|
||||
nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
|
||||
LogWarn_Ascii(splitter,format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
|
||||
ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id)
|
||||
,1.f):units[t];
|
||||
return;
|
||||
}
|
||||
}
|
||||
LogWarn_Ascii(splitter,format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
|
||||
<<nfo.parent_id<<" which does not exist");
|
||||
ASSIMP_LOG_WARN_F( "`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -690,15 +645,13 @@ void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const Chunk
|
|||
msh.ltype = Light::SPOT;
|
||||
}
|
||||
else {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Unknown kind of light source in `Lght` chunk "<<nfo.id<<" : "<<*splitter);
|
||||
ASSIMP_LOG_WARN_F( "Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter );
|
||||
msh.ltype = Light::SPOT;
|
||||
}
|
||||
|
||||
++splitter;
|
||||
if (!splitter.match_start("color ")) {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Expected `color` line in `Lght` chunk "<<nfo.id);
|
||||
ASSIMP_LOG_WARN_F( "Expected `color` line in `Lght` chunk ", nfo.id );
|
||||
}
|
||||
|
||||
const char* rgb = splitter[1];
|
||||
|
@ -706,16 +659,14 @@ void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const Chunk
|
|||
|
||||
SkipSpaces(&rgb);
|
||||
if (strncmp(rgb,"cone angle",10)) {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Expected `cone angle` entity in `color` line in `Lght` chunk "<<nfo.id);
|
||||
ASSIMP_LOG_WARN_F( "Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id );
|
||||
}
|
||||
SkipSpaces(rgb+10,&rgb);
|
||||
msh.angle = fast_atof(&rgb);
|
||||
|
||||
SkipSpaces(&rgb);
|
||||
if (strncmp(rgb,"inner angle",11)) {
|
||||
LogWarn_Ascii(splitter,format()<<
|
||||
"Expected `inner angle` entity in `color` line in `Lght` chunk "<<nfo.id);
|
||||
ASSIMP_LOG_WARN_F( "Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
|
||||
}
|
||||
SkipSpaces(rgb+11,&rgb);
|
||||
msh.inner_angle = fast_atof(&rgb);
|
||||
|
@ -826,7 +777,7 @@ void COBImporter::ReadPolH_Ascii(Scene& out, LineSplitter& splitter, const Chunk
|
|||
|
||||
for(unsigned int cur = 0; cur < cnt && ++splitter ;++cur) {
|
||||
if (splitter.match_start("Hole")) {
|
||||
LogWarn_Ascii(splitter,"Skipping unsupported `Hole` line");
|
||||
ASSIMP_LOG_WARN( "Skipping unsupported `Hole` line" );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -886,7 +837,7 @@ void COBImporter::ReadBitM_Ascii(Scene& /*out*/, LineSplitter& splitter, const C
|
|||
|
||||
const unsigned int head = strtoul10((++splitter)[1]);
|
||||
if (head != sizeof(Bitmap::BitmapHeader)) {
|
||||
LogWarn_Ascii(splitter,"Unexpected ThumbNailHdrSize, skipping this chunk");
|
||||
ASSIMP_LOG_WARN("Unexpected ThumbNailHdrSize, skipping this chunk");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -933,7 +884,7 @@ void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkIn
|
|||
|
||||
// we can recover if the chunk size was specified.
|
||||
if(nfo.size != static_cast<unsigned int>(-1)) {
|
||||
DefaultLogger::get()->error(error);
|
||||
ASSIMP_LOG_ERROR(error);
|
||||
reader.IncPtr(nfo.size);
|
||||
}
|
||||
else ThrowException(error);
|
||||
|
@ -1140,7 +1091,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const
|
|||
mat.type = Material::METAL;
|
||||
break;
|
||||
default:
|
||||
LogError_Ascii(format("Unrecognized shader type in `Mat1` chunk with id ")<<nfo.id);
|
||||
ASSIMP_LOG_ERROR_F( "Unrecognized shader type in `Mat1` chunk with id ", nfo.id );
|
||||
mat.type = Material::FLAT;
|
||||
}
|
||||
|
||||
|
@ -1155,7 +1106,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const
|
|||
mat.autofacet = Material::SMOOTH;
|
||||
break;
|
||||
default:
|
||||
LogError_Ascii(format("Unrecognized faceting mode in `Mat1` chunk with id ")<<nfo.id);
|
||||
ASSIMP_LOG_ERROR_F( "Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id );
|
||||
mat.autofacet = Material::FACETED;
|
||||
}
|
||||
mat.autofacet_angle = static_cast<float>(reader.GetI1());
|
||||
|
@ -1287,15 +1238,13 @@ void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const
|
|||
if (nd->id == nfo.parent_id) {
|
||||
const unsigned int t=reader.GetI2();
|
||||
nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
|
||||
LogWarn_Ascii(format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
|
||||
ASSIMP_LOG_WARN_F(t," is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id)
|
||||
,1.f):units[t];
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
LogWarn_Ascii(format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
|
||||
<<nfo.parent_id<<" which does not exist");
|
||||
ASSIMP_LOG_WARN_F( "`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif // ASSIMP_BUILD_NO_COB_IMPORTER
|
||||
|
|
|
@ -77,10 +77,7 @@ class COBImporter : public BaseImporter
|
|||
public:
|
||||
COBImporter();
|
||||
~COBImporter();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// --------------------
|
||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
|
||||
bool checkSig) const;
|
||||
|
@ -115,15 +112,11 @@ private:
|
|||
* @param stream Stream to read from. */
|
||||
void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Conversion to Assimp output format
|
||||
|
||||
aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
|
||||
|
||||
private:
|
||||
|
||||
// ASCII file support
|
||||
|
||||
void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
|
||||
|
@ -142,19 +135,6 @@ private:
|
|||
void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
|
||||
|
||||
|
||||
// ASCII file logging stuff to add proper line numbers to messages
|
||||
|
||||
static void LogWarn_Ascii (const LineSplitter& splitter, const Formatter::format& message);
|
||||
static void LogError_Ascii(const LineSplitter& splitter, const Formatter::format& message);
|
||||
static void LogInfo_Ascii (const LineSplitter& splitter, const Formatter::format& message);
|
||||
static void LogDebug_Ascii(const LineSplitter& splitter, const Formatter::format& message);
|
||||
|
||||
static void LogWarn_Ascii (const Formatter::format& message);
|
||||
static void LogError_Ascii (const Formatter::format& message);
|
||||
static void LogInfo_Ascii (const Formatter::format& message);
|
||||
static void LogDebug_Ascii (const Formatter::format& message);
|
||||
|
||||
|
||||
// Binary file support
|
||||
|
||||
void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);
|
||||
|
|
|
@ -233,7 +233,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
if (TokenMatchI(buffer, "DROPOUT", 7)) {
|
||||
// seems this is invalid marker data; at least the doc says it's possible
|
||||
DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)");
|
||||
ASSIMP_LOG_WARN("CSM: Encountered invalid marker data (DROPOUT)");
|
||||
}
|
||||
else {
|
||||
aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
|
||||
|
|
|
@ -95,7 +95,7 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
|
|||
{
|
||||
ai_assert( NULL != pScene );
|
||||
|
||||
DefaultLogger::get()->debug("CalcTangentsProcess begin");
|
||||
ASSIMP_LOG_DEBUG("CalcTangentsProcess begin");
|
||||
|
||||
bool bHas = false;
|
||||
for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
|
||||
|
@ -103,9 +103,9 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
|
|||
}
|
||||
|
||||
if ( bHas ) {
|
||||
DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated");
|
||||
ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated");
|
||||
} else {
|
||||
DefaultLogger::get()->debug("CalcTangentsProcess finished");
|
||||
ASSIMP_LOG_DEBUG("CalcTangentsProcess finished");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,19 +126,19 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
|||
// are undefined.
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
|
||||
{
|
||||
DefaultLogger::get()->info("Tangents are undefined for line and point meshes");
|
||||
ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes");
|
||||
return false;
|
||||
}
|
||||
|
||||
// what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
|
||||
if( pMesh->mNormals == NULL)
|
||||
{
|
||||
DefaultLogger::get()->error("Failed to compute tangents; need normals");
|
||||
ASSIMP_LOG_ERROR("Failed to compute tangents; need normals");
|
||||
return false;
|
||||
}
|
||||
if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
|
||||
{
|
||||
DefaultLogger::get()->error((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
|
||||
ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1269,7 +1269,8 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
|
|||
|
||||
mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
|
||||
PushTag();
|
||||
|
||||
|
||||
std::string node_idstr;
|
||||
for (size_t a = 0; a < anim->mNumChannels; ++a) {
|
||||
const aiNodeAnim * nodeAnim = anim->mChannels[a];
|
||||
|
||||
|
@ -1277,7 +1278,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
|
|||
if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
|
||||
|
||||
{
|
||||
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input");
|
||||
node_idstr.clear();
|
||||
node_idstr += nodeAnim->mNodeName.data;
|
||||
node_idstr += std::string( "_matrix-input" );
|
||||
|
||||
std::vector<ai_real> frames;
|
||||
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
|
||||
|
@ -1289,12 +1292,14 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
|
|||
}
|
||||
|
||||
{
|
||||
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output");
|
||||
node_idstr.clear();
|
||||
|
||||
node_idstr += nodeAnim->mNodeName.data;
|
||||
node_idstr += std::string("_matrix-output");
|
||||
|
||||
std::vector<ai_real> keyframes;
|
||||
keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
|
||||
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
|
||||
|
||||
aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue;
|
||||
aiMatrix4x4 ScalingM; // identity
|
||||
ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z;
|
||||
|
@ -1361,7 +1366,6 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
|
|||
PopTag();
|
||||
mOutput << startstr << "</source>" << endstr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (size_t a = 0; a < anim->mNumChannels; ++a) {
|
||||
|
|
|
@ -189,7 +189,7 @@ protected:
|
|||
{}
|
||||
};
|
||||
|
||||
// summarize a material in an convinient way.
|
||||
// summarize a material in an convenient way.
|
||||
struct Material
|
||||
{
|
||||
std::string name;
|
||||
|
|
|
@ -47,13 +47,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
|
||||
|
||||
#include "ColladaLoader.h"
|
||||
#include "ColladaParser.h"
|
||||
|
||||
#include <assimp/anim.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/Defines.h>
|
||||
|
||||
#include "ColladaParser.h"
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <assimp/SkeletonMeshBuilder.h>
|
||||
|
@ -63,7 +65,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "math.h"
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <assimp/Defines.h>
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Formatter;
|
||||
|
@ -131,6 +132,7 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
|
|||
{
|
||||
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
|
||||
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
|
||||
useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,0) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -292,7 +294,7 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
|
|||
nd = FindNode(pParser.mRootNode, nodeInst.mNode);
|
||||
}
|
||||
if (!nd)
|
||||
DefaultLogger::get()->error("Collada: Unable to resolve reference to instanced node " + nodeInst.mNode);
|
||||
ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
|
||||
|
||||
else {
|
||||
// attach this node to the list of children
|
||||
|
@ -309,7 +311,7 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler
|
|||
std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
|
||||
if (it != table.mMap.end()) {
|
||||
if (it->second.mType != Collada::IT_Texcoord)
|
||||
DefaultLogger::get()->error("Collada: Unexpected effect input mapping");
|
||||
ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
|
||||
|
||||
sampler.mUVId = it->second.mSet;
|
||||
}
|
||||
|
@ -325,7 +327,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
|
|||
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
|
||||
if( srcLightIt == pParser.mLightLibrary.end())
|
||||
{
|
||||
DefaultLogger::get()->warn("Collada: Unable to find light for ID \"" + lid.mLight + "\". Skipping.");
|
||||
ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"" , lid.mLight , "\". Skipping.");
|
||||
continue;
|
||||
}
|
||||
const Collada::Light* srcLight = &srcLightIt->second;
|
||||
|
@ -393,14 +395,14 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
|
|||
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
|
||||
if( srcCameraIt == pParser.mCameraLibrary.end())
|
||||
{
|
||||
DefaultLogger::get()->warn("Collada: Unable to find camera for ID \"" + cid.mCamera + "\". Skipping.");
|
||||
ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"" , cid.mCamera , "\". Skipping.");
|
||||
continue;
|
||||
}
|
||||
const Collada::Camera* srcCamera = &srcCameraIt->second;
|
||||
|
||||
// orthographic cameras not yet supported in Assimp
|
||||
if (srcCamera->mOrtho) {
|
||||
DefaultLogger::get()->warn("Collada: Orthographic cameras are not supported.");
|
||||
ASSIMP_LOG_WARN("Collada: Orthographic cameras are not supported.");
|
||||
}
|
||||
|
||||
// now fill our ai data structure
|
||||
|
@ -470,7 +472,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
|||
|
||||
if( !srcMesh)
|
||||
{
|
||||
DefaultLogger::get()->warn( format() << "Collada: Unable to find geometry for ID \"" << mid.mMeshOrController << "\". Skipping." );
|
||||
ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
|
@ -499,7 +501,8 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
|||
}
|
||||
else
|
||||
{
|
||||
DefaultLogger::get()->warn( format() << "Collada: No material specified for subgroup <" << submesh.mMaterial << "> in geometry <" << mid.mMeshOrController << ">." );
|
||||
ASSIMP_LOG_WARN_F( "Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
|
||||
mid.mMeshOrController, ">." );
|
||||
if( !mid.mMaterials.empty() )
|
||||
meshMaterial = mid.mMaterials.begin()->second.mMatName;
|
||||
}
|
||||
|
@ -872,7 +875,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|||
if( bnode)
|
||||
bone->mName.Set( FindNameForNode( bnode));
|
||||
else
|
||||
DefaultLogger::get()->warn( format() << "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"" << bone->mName.data << "\"." );
|
||||
ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." );
|
||||
|
||||
// and insert bone
|
||||
dstMesh->mBones[boneCount++] = bone;
|
||||
|
@ -953,7 +956,7 @@ void ColladaLoader::StoreSceneMaterials( aiScene* pScene)
|
|||
// Stores all animations
|
||||
void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser)
|
||||
{
|
||||
// recursivly collect all animations from the collada scene
|
||||
// recursively collect all animations from the collada scene
|
||||
StoreAnimations( pScene, pParser, &pParser.mAnims, "");
|
||||
|
||||
// catch special case: many animations with the same length, each affecting only a single node.
|
||||
|
@ -1120,6 +1123,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
continue;
|
||||
|
||||
// now check all channels if they affect the current node
|
||||
std::string targetID, subElement;
|
||||
for( std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
|
||||
cit != pSrcAnim->mChannels.end(); ++cit)
|
||||
{
|
||||
|
@ -1146,7 +1150,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
}
|
||||
if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
|
||||
continue;
|
||||
std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
|
||||
|
||||
targetID.clear();
|
||||
targetID = srcChannel.mTarget.substr( 0, slashPos);
|
||||
if( targetID != srcNode->mID)
|
||||
continue;
|
||||
|
||||
|
@ -1159,7 +1165,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
|
||||
entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1);
|
||||
|
||||
std::string subElement = srcChannel.mTarget.substr( dotPos+1);
|
||||
subElement.clear();
|
||||
subElement = srcChannel.mTarget.substr( dotPos+1);
|
||||
if( subElement == "ANGLE")
|
||||
entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle
|
||||
else if( subElement == "X")
|
||||
|
@ -1169,9 +1176,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
else if( subElement == "Z")
|
||||
entry.mSubElement = 2;
|
||||
else
|
||||
DefaultLogger::get()->warn( format() << "Unknown anim subelement <" << subElement << ">. Ignoring" );
|
||||
} else
|
||||
{
|
||||
ASSIMP_LOG_WARN_F( "Unknown anim subelement <", subElement, ">. Ignoring" );
|
||||
} else {
|
||||
// no subelement following, transformId is remaining string
|
||||
entry.mTransformId = srcChannel.mTarget.substr( slashPos+1);
|
||||
}
|
||||
|
@ -1180,7 +1186,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
if (bracketPos != std::string::npos)
|
||||
{
|
||||
entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1);
|
||||
std::string subElement = srcChannel.mTarget.substr(bracketPos);
|
||||
subElement.clear();
|
||||
subElement = srcChannel.mTarget.substr(bracketPos);
|
||||
|
||||
if (subElement == "(0)(0)")
|
||||
entry.mSubElement = 0;
|
||||
|
@ -1214,7 +1221,6 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
entry.mSubElement = 14;
|
||||
else if (subElement == "(3)(3)")
|
||||
entry.mSubElement = 15;
|
||||
|
||||
}
|
||||
|
||||
// determine which transform step is affected by this channel
|
||||
|
@ -1400,7 +1406,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
anims.push_back( dstAnim);
|
||||
} else
|
||||
{
|
||||
DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
|
||||
ASSIMP_LOG_WARN( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
|
||||
}
|
||||
|
||||
if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
|
||||
|
@ -1555,7 +1561,7 @@ void ColladaLoader::AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
|
|||
}
|
||||
}
|
||||
if (-1 == map) {
|
||||
DefaultLogger::get()->warn("Collada: unable to determine UV channel for texture");
|
||||
ASSIMP_LOG_WARN("Collada: unable to determine UV channel for texture");
|
||||
map = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1592,7 +1598,7 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
|
|||
break;
|
||||
|
||||
default:
|
||||
DefaultLogger::get()->warn("Collada: Unrecognized shading mode, using gouraud shading");
|
||||
ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading");
|
||||
shadeMode = aiShadingMode_Gouraud;
|
||||
break;
|
||||
}
|
||||
|
@ -1651,9 +1657,10 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
|
|||
}
|
||||
|
||||
// add textures, if given
|
||||
if( !effect.mTexAmbient.mName.empty())
|
||||
/* It is merely a lightmap */
|
||||
AddTexture( mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
|
||||
if (!effect.mTexAmbient.mName.empty()) {
|
||||
// It is merely a light-map
|
||||
AddTexture(mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
|
||||
}
|
||||
|
||||
if( !effect.mTexEmissive.mName.empty())
|
||||
AddTexture( mat, pParser, effect, effect.mTexEmissive, aiTextureType_EMISSIVE);
|
||||
|
@ -1681,8 +1688,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
|
|||
{
|
||||
newMats.reserve(pParser.mMaterialLibrary.size());
|
||||
|
||||
for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); matIt != pParser.mMaterialLibrary.end(); ++matIt)
|
||||
{
|
||||
for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin();
|
||||
matIt != pParser.mMaterialLibrary.end(); ++matIt) {
|
||||
const Collada::Material& material = matIt->second;
|
||||
// a material is only a reference to an effect
|
||||
ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find( material.mEffect);
|
||||
|
@ -1746,11 +1753,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
|
|||
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
|
||||
if( imIt == pParser.mImageLibrary.end())
|
||||
{
|
||||
//missing texture should not stop the conversion
|
||||
//throw DeadlyImportError( format() <<
|
||||
// "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
|
||||
|
||||
DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\".");
|
||||
ASSIMP_LOG_WARN_F("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\".");
|
||||
|
||||
//set default texture file name
|
||||
result.Set(name + ".jpg");
|
||||
|
@ -1769,7 +1772,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
|
|||
|
||||
// setup format hint
|
||||
if (imIt->second.mEmbeddedFormat.length() > 3) {
|
||||
DefaultLogger::get()->warn("Collada: texture format hint is too long, truncating to 3 characters");
|
||||
ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
|
||||
}
|
||||
strncpy(tex->achFormatHint,imIt->second.mEmbeddedFormat.c_str(),3);
|
||||
|
||||
|
@ -1781,7 +1784,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
|
|||
|
||||
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
|
||||
// In FBX files textures are now stored internally by Assimp with their filename included
|
||||
// Now Assimp can lookup thru the loaded textures after all data is processed
|
||||
// Now Assimp can lookup through the loaded textures after all data is processed
|
||||
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
|
||||
// This may occur on this case too, it has to be studied
|
||||
// setup texture reference string
|
||||
|
@ -1805,7 +1808,7 @@ void ColladaLoader::ConvertPath (aiString& ss)
|
|||
{
|
||||
// TODO: collada spec, p 22. Handle URI correctly.
|
||||
// For the moment we're just stripping the file:// away to make it work.
|
||||
// Windoes doesn't seem to be able to find stuff like
|
||||
// Windows doesn't seem to be able to find stuff like
|
||||
// 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg'
|
||||
if (0 == strncmp(ss.data,"file://",7))
|
||||
{
|
||||
|
@ -1816,10 +1819,13 @@ void ColladaLoader::ConvertPath (aiString& ss)
|
|||
|
||||
// Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
|
||||
// I need to filter it without destroying linux paths starting with "/somewhere"
|
||||
if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' )
|
||||
{
|
||||
ss.length--;
|
||||
memmove( ss.data, ss.data+1, ss.length);
|
||||
#if defined( _MSC_VER )
|
||||
if( ss.data[0] == '/' && isalpha( (unsigned char) ss.data[1]) && ss.data[2] == ':' ) {
|
||||
#else
|
||||
if (ss.data[ 0 ] == '/' && isalpha( ss.data[ 1 ] ) && ss.data[ 2 ] == ':') {
|
||||
#endif
|
||||
--ss.length;
|
||||
::memmove( ss.data, ss.data+1, ss.length);
|
||||
ss.data[ss.length] = 0;
|
||||
}
|
||||
|
||||
|
@ -1869,9 +1875,9 @@ const std::string& ColladaLoader::ReadString( const Collada::Accessor& pAccessor
|
|||
void ColladaLoader::CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const
|
||||
{
|
||||
poNodes.push_back( pNode);
|
||||
|
||||
for( size_t a = 0; a < pNode->mNumChildren; ++a)
|
||||
CollectNodes( pNode->mChildren[a], poNodes);
|
||||
for (size_t a = 0; a < pNode->mNumChildren; ++a) {
|
||||
CollectNodes(pNode->mChildren[a], poNodes);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -1913,6 +1919,11 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
|
|||
// The name must be unique for proper node-bone association.
|
||||
std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
|
||||
{
|
||||
// If explicitly requested, just use the collada name.
|
||||
if (useColladaName) {
|
||||
return pNode->mName;
|
||||
}
|
||||
|
||||
// Now setup the name of the assimp node. The collada name might not be
|
||||
// unique, so we use the collada ID.
|
||||
if (!pNode->mID.empty())
|
||||
|
|
|
@ -248,6 +248,7 @@ protected:
|
|||
|
||||
bool noSkeletonMesh;
|
||||
bool ignoreUpDirection;
|
||||
bool useColladaName;
|
||||
|
||||
/** Used by FindNameForNode() to generate unique node names */
|
||||
unsigned int mNodeNameCounter;
|
||||
|
|
|
@ -152,22 +152,22 @@ void ColladaParser::ReadContents()
|
|||
|
||||
if (!::strncmp(version,"1.5",3)) {
|
||||
mFormat = FV_1_5_n;
|
||||
DefaultLogger::get()->debug("Collada schema version is 1.5.n");
|
||||
ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n");
|
||||
}
|
||||
else if (!::strncmp(version,"1.4",3)) {
|
||||
mFormat = FV_1_4_n;
|
||||
DefaultLogger::get()->debug("Collada schema version is 1.4.n");
|
||||
ASSIMP_LOG_DEBUG("Collada schema version is 1.4.n");
|
||||
}
|
||||
else if (!::strncmp(version,"1.3",3)) {
|
||||
mFormat = FV_1_3_n;
|
||||
DefaultLogger::get()->debug("Collada schema version is 1.3.n");
|
||||
ASSIMP_LOG_DEBUG("Collada schema version is 1.3.n");
|
||||
}
|
||||
}
|
||||
|
||||
ReadStructure();
|
||||
} else
|
||||
{
|
||||
DefaultLogger::get()->debug( format() << "Ignoring global element <" << mReader->getNodeName() << ">." );
|
||||
ASSIMP_LOG_DEBUG_F( "Ignoring global element <", mReader->getNodeName(), ">." );
|
||||
SkipElement();
|
||||
}
|
||||
} else
|
||||
|
@ -222,6 +222,7 @@ void ColladaParser::ReadStructure()
|
|||
}
|
||||
|
||||
PostProcessRootAnimations();
|
||||
PostProcessControllers();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -360,6 +361,21 @@ void ColladaParser::ReadAnimationClipLibrary()
|
|||
}
|
||||
}
|
||||
|
||||
void ColladaParser::PostProcessControllers()
|
||||
{
|
||||
for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it)
|
||||
{
|
||||
std::string meshId = it->second.mMeshId;
|
||||
ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId);
|
||||
while(findItr != mControllerLibrary.end()) {
|
||||
meshId = findItr->second.mMeshId;
|
||||
findItr = mControllerLibrary.find(meshId);
|
||||
}
|
||||
|
||||
it->second.mMeshId = meshId;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Re-build animations from animation clip library, if present, otherwise combine single-channel animations
|
||||
void ColladaParser::PostProcessRootAnimations()
|
||||
|
@ -968,13 +984,13 @@ void ColladaParser::ReadImage( Collada::Image& pImage)
|
|||
// they're not skipped.
|
||||
int attrib = TestAttribute("array_index");
|
||||
if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
|
||||
DefaultLogger::get()->warn("Collada: Ignoring texture array index");
|
||||
ASSIMP_LOG_WARN("Collada: Ignoring texture array index");
|
||||
continue;
|
||||
}
|
||||
|
||||
attrib = TestAttribute("mip_index");
|
||||
if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
|
||||
DefaultLogger::get()->warn("Collada: Ignoring MIP map layer");
|
||||
ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -995,7 +1011,7 @@ void ColladaParser::ReadImage( Collada::Image& pImage)
|
|||
// embedded image. get format
|
||||
const int attrib = TestAttribute("format");
|
||||
if (-1 == attrib)
|
||||
DefaultLogger::get()->warn("Collada: Unknown image file format");
|
||||
ASSIMP_LOG_WARN("Collada: Unknown image file format");
|
||||
else pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib);
|
||||
|
||||
const char* data = GetTextContent();
|
||||
|
@ -1574,7 +1590,7 @@ void ColladaParser::ReadSamplerProperties( Sampler& out )
|
|||
out.mOp = aiTextureOp_Multiply;
|
||||
|
||||
else {
|
||||
DefaultLogger::get()->warn("Collada: Unsupported MAYA texture blend mode");
|
||||
ASSIMP_LOG_WARN("Collada: Unsupported MAYA texture blend mode");
|
||||
}
|
||||
TestClosing( "blend_mode");
|
||||
}
|
||||
|
@ -2525,7 +2541,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
|
|||
if( pInput.mIndex == 0)
|
||||
pMesh->mPositions.push_back( aiVector3D( obj[0], obj[1], obj[2]));
|
||||
else
|
||||
DefaultLogger::get()->error("Collada: just one vertex position stream supported");
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
|
||||
break;
|
||||
case IT_Normal:
|
||||
// pad to current vertex count if necessary
|
||||
|
@ -2536,7 +2552,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
|
|||
if( pInput.mIndex == 0)
|
||||
pMesh->mNormals.push_back( aiVector3D( obj[0], obj[1], obj[2]));
|
||||
else
|
||||
DefaultLogger::get()->error("Collada: just one vertex normal stream supported");
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
|
||||
break;
|
||||
case IT_Tangent:
|
||||
// pad to current vertex count if necessary
|
||||
|
@ -2547,7 +2563,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
|
|||
if( pInput.mIndex == 0)
|
||||
pMesh->mTangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
|
||||
else
|
||||
DefaultLogger::get()->error("Collada: just one vertex tangent stream supported");
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
|
||||
break;
|
||||
case IT_Bitangent:
|
||||
// pad to current vertex count if necessary
|
||||
|
@ -2558,7 +2574,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
|
|||
if( pInput.mIndex == 0)
|
||||
pMesh->mBitangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
|
||||
else
|
||||
DefaultLogger::get()->error("Collada: just one vertex bitangent stream supported");
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
|
||||
break;
|
||||
case IT_Texcoord:
|
||||
// up to 4 texture coord sets are fine, ignore the others
|
||||
|
@ -2574,7 +2590,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
|
|||
pMesh->mNumUVComponents[pInput.mIndex]=3;
|
||||
} else
|
||||
{
|
||||
DefaultLogger::get()->error("Collada: too many texture coordinate sets. Skipping.");
|
||||
ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
|
||||
}
|
||||
break;
|
||||
case IT_Color:
|
||||
|
@ -2594,7 +2610,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
|
|||
pMesh->mColors[pInput.mIndex].push_back(result);
|
||||
} else
|
||||
{
|
||||
DefaultLogger::get()->error("Collada: too many vertex color sets. Skipping.");
|
||||
ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2723,7 +2739,7 @@ void ColladaParser::ReadSceneNode( Node* pNode)
|
|||
{
|
||||
const char* s = mReader->getAttributeValue(attrId);
|
||||
if (s[0] != '#')
|
||||
DefaultLogger::get()->error("Collada: Unresolved reference format of camera");
|
||||
ASSIMP_LOG_ERROR("Collada: Unresolved reference format of camera");
|
||||
else
|
||||
pNode->mPrimaryCamera = s+1;
|
||||
}
|
||||
|
@ -2736,7 +2752,7 @@ void ColladaParser::ReadSceneNode( Node* pNode)
|
|||
{
|
||||
const char* s = mReader->getAttributeValue(attrID);
|
||||
if (s[0] != '#')
|
||||
DefaultLogger::get()->error("Collada: Unresolved reference format of node");
|
||||
ASSIMP_LOG_ERROR("Collada: Unresolved reference format of node");
|
||||
else
|
||||
{
|
||||
pNode->mNodeInstances.push_back(NodeInstance());
|
||||
|
@ -2754,7 +2770,7 @@ void ColladaParser::ReadSceneNode( Node* pNode)
|
|||
// Reference to a light, name given in 'url' attribute
|
||||
int attrID = TestAttribute("url");
|
||||
if (-1 == attrID)
|
||||
DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_light> element");
|
||||
ASSIMP_LOG_WARN("Collada: Expected url attribute in <instance_light> element");
|
||||
else
|
||||
{
|
||||
const char* url = mReader->getAttributeValue( attrID);
|
||||
|
@ -2770,7 +2786,7 @@ void ColladaParser::ReadSceneNode( Node* pNode)
|
|||
// Reference to a camera, name given in 'url' attribute
|
||||
int attrID = TestAttribute("url");
|
||||
if (-1 == attrID)
|
||||
DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_camera> element");
|
||||
ASSIMP_LOG_WARN("Collada: Expected url attribute in <instance_camera> element");
|
||||
else
|
||||
{
|
||||
const char* url = mReader->getAttributeValue( attrID);
|
||||
|
@ -2857,7 +2873,7 @@ void ColladaParser::ReadMaterialVertexInputBinding( Collada::SemanticMappingTabl
|
|||
tbl.mMap[s] = vn;
|
||||
}
|
||||
else if( IsElement( "bind")) {
|
||||
DefaultLogger::get()->warn("Collada: Found unsupported <bind> element");
|
||||
ASSIMP_LOG_WARN("Collada: Found unsupported <bind> element");
|
||||
}
|
||||
}
|
||||
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
||||
|
@ -2976,10 +2992,9 @@ void ColladaParser::ReportWarning(const char* msg,...)
|
|||
ai_assert(iLen > 0);
|
||||
|
||||
va_end(args);
|
||||
DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen));
|
||||
ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer,iLen));
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Skips all data until the end node of the current element
|
||||
void ColladaParser::SkipElement()
|
||||
|
@ -3090,7 +3105,7 @@ const char* ColladaParser::TestTextContent()
|
|||
// read contents of the element
|
||||
if( !mReader->read() )
|
||||
return NULL;
|
||||
if( mReader->getNodeType() != irr::io::EXN_TEXT)
|
||||
if( mReader->getNodeType() != irr::io::EXN_TEXT && mReader->getNodeType() != irr::io::EXN_CDATA)
|
||||
return NULL;
|
||||
|
||||
// skip leading whitespace
|
||||
|
@ -3174,7 +3189,7 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
|
|||
Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& semantic)
|
||||
{
|
||||
if ( semantic.empty() ) {
|
||||
DefaultLogger::get()->warn( format() << "Vertex input type is empty." );
|
||||
ASSIMP_LOG_WARN("Vertex input type is empty." );
|
||||
return IT_Invalid;
|
||||
}
|
||||
|
||||
|
@ -3193,7 +3208,7 @@ Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& semanti
|
|||
else if( semantic == "TANGENT" || semantic == "TEXTANGENT")
|
||||
return IT_Tangent;
|
||||
|
||||
DefaultLogger::get()->warn( format() << "Unknown vertex input type \"" << semantic << "\". Ignoring." );
|
||||
ASSIMP_LOG_WARN_F( "Unknown vertex input type \"", semantic, "\". Ignoring." );
|
||||
return IT_Invalid;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,9 @@ namespace Assimp
|
|||
/** Reads the animation clip library */
|
||||
void ReadAnimationClipLibrary();
|
||||
|
||||
/** Unwrap controllers dependency hierarchy */
|
||||
void PostProcessControllers();
|
||||
|
||||
/** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */
|
||||
void PostProcessRootAnimations();
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
|
|||
for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
|
||||
if (!mesh->mTextureCoords[m])return m;
|
||||
|
||||
DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found");
|
||||
ASSIMP_LOG_ERROR("Unable to compute UV coordinates, no free UV slot found");
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
|
@ -384,13 +384,13 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
|
||||
{
|
||||
DefaultLogger::get()->error("Mapping type currently not implemented");
|
||||
ASSIMP_LOG_ERROR("Mapping type currently not implemented");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ComputeUVMappingProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("GenUVCoordsProcess begin");
|
||||
ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin");
|
||||
char buffer[1024];
|
||||
|
||||
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
|
||||
|
@ -418,7 +418,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
|
|||
TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
|
||||
MappingTypeToString(mapping));
|
||||
|
||||
DefaultLogger::get()->info(buffer);
|
||||
ASSIMP_LOG_INFO(buffer);
|
||||
}
|
||||
|
||||
if (aiTextureMapping_OTHER == mapping)
|
||||
|
@ -485,7 +485,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
|
|||
}
|
||||
if (m && idx != outIdx)
|
||||
{
|
||||
DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to "
|
||||
ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to "
|
||||
"this material have equal numbers of UV channels. The UV index stored in "
|
||||
"the material structure does therefore not apply for all meshes. ");
|
||||
}
|
||||
|
@ -502,5 +502,5 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
|
|||
}
|
||||
}
|
||||
}
|
||||
DefaultLogger::get()->debug("GenUVCoordsProcess finished");
|
||||
ASSIMP_LOG_DEBUG("GenUVCoordsProcess finished");
|
||||
}
|
||||
|
|
|
@ -85,18 +85,20 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene)
|
|||
{
|
||||
// Check for an existent root node to proceed
|
||||
ai_assert(pScene->mRootNode != NULL);
|
||||
DefaultLogger::get()->debug("MakeLeftHandedProcess begin");
|
||||
ASSIMP_LOG_DEBUG("MakeLeftHandedProcess begin");
|
||||
|
||||
// recursively convert all the nodes
|
||||
ProcessNode( pScene->mRootNode, aiMatrix4x4());
|
||||
|
||||
// process the meshes accordingly
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
|
||||
ProcessMesh( pScene->mMeshes[a]);
|
||||
for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
|
||||
ProcessMesh( pScene->mMeshes[ a ] );
|
||||
}
|
||||
|
||||
// process the materials accordingly
|
||||
for( unsigned int a = 0; a < pScene->mNumMaterials; ++a)
|
||||
ProcessMaterial( pScene->mMaterials[a]);
|
||||
for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a ) {
|
||||
ProcessMaterial( pScene->mMaterials[ a ] );
|
||||
}
|
||||
|
||||
// transform all animation channels as well
|
||||
for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
|
||||
|
@ -108,7 +110,7 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene)
|
|||
ProcessAnimation( nodeAnim);
|
||||
}
|
||||
}
|
||||
DefaultLogger::get()->debug("MakeLeftHandedProcess finished");
|
||||
ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -136,8 +138,11 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts a single mesh to left handed coordinates.
|
||||
void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh)
|
||||
{
|
||||
void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
|
||||
if ( nullptr == pMesh ) {
|
||||
ASSIMP_LOG_ERROR( "Nullptr to mesh found." );
|
||||
return;
|
||||
}
|
||||
// mirror positions, normals and stuff along the Z axis
|
||||
for( size_t a = 0; a < pMesh->mNumVertices; ++a)
|
||||
{
|
||||
|
@ -173,8 +178,12 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts a single material to left handed coordinates.
|
||||
void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
|
||||
{
|
||||
void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) {
|
||||
if ( nullptr == _mat ) {
|
||||
ASSIMP_LOG_ERROR( "Nullptr to aiMaterial found." );
|
||||
return;
|
||||
}
|
||||
|
||||
aiMaterial* mat = (aiMaterial*)_mat;
|
||||
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
|
||||
aiMaterialProperty* prop = mat->mProperties[a];
|
||||
|
@ -183,7 +192,6 @@ void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
|
|||
if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) {
|
||||
ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
|
||||
aiVector3D* pff = (aiVector3D*)prop->mData;
|
||||
|
||||
pff->z *= -1.f;
|
||||
}
|
||||
}
|
||||
|
@ -237,13 +245,13 @@ bool FlipUVsProcess::IsActive( unsigned int pFlags) const
|
|||
// Executes the post processing step on the given imported data.
|
||||
void FlipUVsProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("FlipUVsProcess begin");
|
||||
ASSIMP_LOG_DEBUG("FlipUVsProcess begin");
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
ProcessMesh(pScene->mMeshes[i]);
|
||||
|
||||
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
||||
ProcessMaterial(pScene->mMaterials[i]);
|
||||
DefaultLogger::get()->debug("FlipUVsProcess finished");
|
||||
ASSIMP_LOG_DEBUG("FlipUVsProcess finished");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -254,7 +262,7 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
|
|||
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
|
||||
aiMaterialProperty* prop = mat->mProperties[a];
|
||||
if( !prop ) {
|
||||
DefaultLogger::get()->debug( "Property is null" );
|
||||
ASSIMP_LOG_DEBUG( "Property is null" );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -311,10 +319,10 @@ bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
|
|||
// Executes the post processing step on the given imported data.
|
||||
void FlipWindingOrderProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
|
||||
ASSIMP_LOG_DEBUG("FlipWindingOrderProcess begin");
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
ProcessMesh(pScene->mMeshes[i]);
|
||||
DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
|
||||
ASSIMP_LOG_DEBUG("FlipWindingOrderProcess finished");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -49,8 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/IOStream.hpp>
|
||||
#include <assimp/Exporter.hpp>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/Exceptional.h>
|
||||
|
||||
#include "3MFXmlTags.h"
|
||||
#include "D3MFOpcPackage.h"
|
||||
|
||||
|
@ -116,6 +117,7 @@ bool D3MFExporter::exportArchive( const char *file ) {
|
|||
if ( nullptr == m_zipArchive ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ok |= exportContentTypes();
|
||||
ok |= export3DModel();
|
||||
ok |= exportRelations();
|
||||
|
@ -126,7 +128,6 @@ bool D3MFExporter::exportArchive( const char *file ) {
|
|||
return ok;
|
||||
}
|
||||
|
||||
|
||||
bool D3MFExporter::exportContentTypes() {
|
||||
mContentOutput.clear();
|
||||
|
||||
|
@ -153,7 +154,11 @@ bool D3MFExporter::exportRelations() {
|
|||
mRelOutput << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">";
|
||||
|
||||
for ( size_t i = 0; i < mRelations.size(); ++i ) {
|
||||
mRelOutput << "<Relationship Target=\"/" << mRelations[ i ]->target << "\" ";
|
||||
if ( mRelations[ i ]->target[ 0 ] == '/' ) {
|
||||
mRelOutput << "<Relationship Target=\"" << mRelations[ i ]->target << "\" ";
|
||||
} else {
|
||||
mRelOutput << "<Relationship Target=\"/" << mRelations[ i ]->target << "\" ";
|
||||
}
|
||||
mRelOutput << "Id=\"" << mRelations[i]->id << "\" ";
|
||||
mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />";
|
||||
mRelOutput << std::endl;
|
||||
|
@ -177,6 +182,10 @@ bool D3MFExporter::export3DModel() {
|
|||
mModelOutput << "<" << XmlTag::resources << ">";
|
||||
mModelOutput << std::endl;
|
||||
|
||||
writeMetaData();
|
||||
|
||||
writeBaseMaterials();
|
||||
|
||||
writeObjects();
|
||||
|
||||
|
||||
|
@ -203,6 +212,63 @@ void D3MFExporter::writeHeader() {
|
|||
mModelOutput << std::endl;
|
||||
}
|
||||
|
||||
void D3MFExporter::writeMetaData() {
|
||||
if ( nullptr == mScene->mMetaData ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned int numMetaEntries( mScene->mMetaData->mNumProperties );
|
||||
if ( 0 == numMetaEntries ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const aiString *key = nullptr;
|
||||
const aiMetadataEntry *entry(nullptr);
|
||||
for ( size_t i = 0; i < numMetaEntries; ++i ) {
|
||||
mScene->mMetaData->Get( i, key, entry );
|
||||
std::string k( key->C_Str() );
|
||||
aiString value;
|
||||
mScene->mMetaData->Get( k, value );
|
||||
mModelOutput << "<" << XmlTag::meta << " " << XmlTag::meta_name << "=\"" << key->C_Str() << "\">";
|
||||
mModelOutput << value.C_Str();
|
||||
mModelOutput << "</" << XmlTag::meta << ">" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void D3MFExporter::writeBaseMaterials() {
|
||||
mModelOutput << "<basematerials id=\"1\">\n";
|
||||
std::string strName, hexDiffuseColor , tmp;
|
||||
for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) {
|
||||
aiMaterial *mat = mScene->mMaterials[ i ];
|
||||
aiString name;
|
||||
if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) {
|
||||
strName = "basemat_" + to_string( i );
|
||||
} else {
|
||||
strName = name.C_Str();
|
||||
}
|
||||
aiColor4D color;
|
||||
if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) {
|
||||
hexDiffuseColor.clear();
|
||||
tmp.clear();
|
||||
hexDiffuseColor = "#";
|
||||
|
||||
tmp = DecimalToHexa( color.r );
|
||||
hexDiffuseColor += tmp;
|
||||
tmp = DecimalToHexa( color.g );
|
||||
hexDiffuseColor += tmp;
|
||||
tmp = DecimalToHexa( color.b );
|
||||
hexDiffuseColor += tmp;
|
||||
tmp = DecimalToHexa( color.a );
|
||||
hexDiffuseColor += tmp;
|
||||
} else {
|
||||
hexDiffuseColor = "#FFFFFFFF";
|
||||
}
|
||||
|
||||
mModelOutput << "<base name=\""+strName+"\" "+" displaycolor=\""+hexDiffuseColor+"\" />\n";
|
||||
}
|
||||
mModelOutput << "</basematerials>\n";
|
||||
}
|
||||
|
||||
void D3MFExporter::writeObjects() {
|
||||
if ( nullptr == mScene->mRootNode ) {
|
||||
return;
|
||||
|
@ -242,7 +308,9 @@ void D3MFExporter::writeMesh( aiMesh *mesh ) {
|
|||
}
|
||||
mModelOutput << "</" << XmlTag::vertices << ">" << std::endl;
|
||||
|
||||
writeFaces( mesh );
|
||||
const unsigned int matIdx( mesh->mMaterialIndex );
|
||||
|
||||
writeFaces( mesh, matIdx );
|
||||
|
||||
mModelOutput << "</" << XmlTag::mesh << ">" << std::endl;
|
||||
}
|
||||
|
@ -252,7 +320,7 @@ void D3MFExporter::writeVertex( const aiVector3D &pos ) {
|
|||
mModelOutput << std::endl;
|
||||
}
|
||||
|
||||
void D3MFExporter::writeFaces( aiMesh *mesh ) {
|
||||
void D3MFExporter::writeFaces( aiMesh *mesh, unsigned int matIdx ) {
|
||||
if ( nullptr == mesh ) {
|
||||
return;
|
||||
}
|
||||
|
@ -264,7 +332,8 @@ void D3MFExporter::writeFaces( aiMesh *mesh ) {
|
|||
for ( unsigned int i = 0; i < mesh->mNumFaces; ++i ) {
|
||||
aiFace ¤tFace = mesh->mFaces[ i ];
|
||||
mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[ 0 ] << "\" v2=\""
|
||||
<< currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] << "\"/>";
|
||||
<< currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ]
|
||||
<< "\" pid=\"1\" p1=\""+to_string(matIdx)+"\" />";
|
||||
mModelOutput << std::endl;
|
||||
}
|
||||
mModelOutput << "</" << XmlTag::triangles << ">";
|
||||
|
|
|
@ -76,10 +76,12 @@ public:
|
|||
|
||||
protected:
|
||||
void writeHeader();
|
||||
void writeMetaData();
|
||||
void writeBaseMaterials();
|
||||
void writeObjects();
|
||||
void writeMesh( aiMesh *mesh );
|
||||
void writeVertex( const aiVector3D &pos );
|
||||
void writeFaces( aiMesh *mesh );
|
||||
void writeFaces( aiMesh *mesh, unsigned int matIdx );
|
||||
void writeBuild();
|
||||
void exportContentTyp( const std::string &filename );
|
||||
void writeModelToArchive( const std::string &folder, const std::string &modelName );
|
||||
|
|
|
@ -61,14 +61,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <unzip.h>
|
||||
#include <assimp/irrXMLWrapper.h>
|
||||
#include "3MFXmlTags.h"
|
||||
#include <assimp/fast_atof.h>
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
namespace Assimp {
|
||||
namespace D3MF {
|
||||
|
||||
class XmlSerializer {
|
||||
public:
|
||||
using MatArray = std::vector<aiMaterial*>;
|
||||
using MatId2MatArray = std::map<unsigned int, std::vector<unsigned int>>;
|
||||
|
||||
XmlSerializer(XmlReader* xmlReader)
|
||||
: xmlReader(xmlReader) {
|
||||
: mMeshes()
|
||||
, mMatArray()
|
||||
, mActiveMatGroup( 99999999 )
|
||||
, mMatId2MatArray()
|
||||
, xmlReader(xmlReader){
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -77,14 +87,24 @@ public:
|
|||
}
|
||||
|
||||
void ImportXml(aiScene* scene) {
|
||||
if ( nullptr == scene ) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene->mRootNode = new aiNode();
|
||||
std::vector<aiNode*> children;
|
||||
|
||||
std::string nodeName;
|
||||
while(ReadToEndElement(D3MF::XmlTag::model)) {
|
||||
if(xmlReader->getNodeName() == D3MF::XmlTag::object) {
|
||||
nodeName = xmlReader->getNodeName();
|
||||
if( nodeName == D3MF::XmlTag::object) {
|
||||
children.push_back(ReadObject(scene));
|
||||
} else if(xmlReader->getNodeName() == D3MF::XmlTag::build) {
|
||||
|
||||
} else if( nodeName == D3MF::XmlTag::build) {
|
||||
//
|
||||
} else if ( nodeName == D3MF::XmlTag::basematerials ) {
|
||||
ReadBaseMaterials();
|
||||
} else if ( nodeName == D3MF::XmlTag::meta ) {
|
||||
ReadMetadata();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,31 +112,47 @@ public:
|
|||
scene->mRootNode->mName.Set( "3MF" );
|
||||
}
|
||||
|
||||
scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
|
||||
// import the metadata
|
||||
if ( !mMetaData.empty() ) {
|
||||
const size_t numMeta( mMetaData.size() );
|
||||
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>( numMeta ) );
|
||||
for ( size_t i = 0; i < numMeta; ++i ) {
|
||||
aiString val( mMetaData[ i ].value );
|
||||
scene->mMetaData->Set(static_cast<unsigned int>( i ), mMetaData[ i ].name, val );
|
||||
}
|
||||
}
|
||||
|
||||
// import the meshes
|
||||
scene->mNumMeshes = static_cast<unsigned int>( mMeshes.size());
|
||||
scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
|
||||
std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes);
|
||||
|
||||
std::copy(meshes.begin(), meshes.end(), scene->mMeshes);
|
||||
// import the materials
|
||||
scene->mNumMaterials = static_cast<unsigned int>( mMatArray.size() );
|
||||
if ( 0 != scene->mNumMaterials ) {
|
||||
scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ];
|
||||
std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials );
|
||||
}
|
||||
|
||||
// create the scenegraph
|
||||
scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
|
||||
scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
|
||||
|
||||
std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
|
||||
}
|
||||
|
||||
private:
|
||||
aiNode* ReadObject(aiScene* scene)
|
||||
{
|
||||
aiNode* ReadObject(aiScene* scene) {
|
||||
std::unique_ptr<aiNode> node(new aiNode());
|
||||
|
||||
std::vector<unsigned long> meshIds;
|
||||
|
||||
const char *attrib( nullptr );
|
||||
std::string name, type;
|
||||
attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() );
|
||||
attrib = xmlReader->getAttributeValue( D3MF::XmlTag::id.c_str() );
|
||||
if ( nullptr != attrib ) {
|
||||
name = attrib;
|
||||
}
|
||||
attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() );
|
||||
attrib = xmlReader->getAttributeValue( D3MF::XmlTag::type.c_str() );
|
||||
if ( nullptr != attrib ) {
|
||||
type = attrib;
|
||||
}
|
||||
|
@ -124,19 +160,16 @@ private:
|
|||
node->mParent = scene->mRootNode;
|
||||
node->mName.Set(name);
|
||||
|
||||
size_t meshIdx = meshes.size();
|
||||
size_t meshIdx = mMeshes.size();
|
||||
|
||||
while(ReadToEndElement(D3MF::XmlTag::object))
|
||||
{
|
||||
if(xmlReader->getNodeName() == D3MF::XmlTag::mesh)
|
||||
{
|
||||
while(ReadToEndElement(D3MF::XmlTag::object)) {
|
||||
if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) {
|
||||
auto mesh = ReadMesh();
|
||||
|
||||
mesh->mName.Set(name);
|
||||
meshes.push_back(mesh);
|
||||
mMeshes.push_back(mesh);
|
||||
meshIds.push_back(static_cast<unsigned long>(meshIdx));
|
||||
meshIdx++;
|
||||
|
||||
++meshIdx;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,19 +180,14 @@ private:
|
|||
std::copy(meshIds.begin(), meshIds.end(), node->mMeshes);
|
||||
|
||||
return node.release();
|
||||
|
||||
}
|
||||
|
||||
aiMesh* ReadMesh() {
|
||||
aiMesh *ReadMesh() {
|
||||
aiMesh* mesh = new aiMesh();
|
||||
while(ReadToEndElement(D3MF::XmlTag::mesh))
|
||||
{
|
||||
if(xmlReader->getNodeName() == D3MF::XmlTag::vertices)
|
||||
{
|
||||
while(ReadToEndElement(D3MF::XmlTag::mesh)) {
|
||||
if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) {
|
||||
ImportVertices(mesh);
|
||||
}
|
||||
else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles)
|
||||
{
|
||||
} else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) {
|
||||
ImportTriangles(mesh);
|
||||
}
|
||||
}
|
||||
|
@ -167,14 +195,25 @@ private:
|
|||
return mesh;
|
||||
}
|
||||
|
||||
void ImportVertices(aiMesh* mesh)
|
||||
{
|
||||
std::vector<aiVector3D> vertices;
|
||||
void ReadMetadata() {
|
||||
const std::string name = xmlReader->getAttributeValue( D3MF::XmlTag::meta_name.c_str() );
|
||||
xmlReader->read();
|
||||
const std::string value = xmlReader->getNodeData();
|
||||
|
||||
while(ReadToEndElement(D3MF::XmlTag::vertices))
|
||||
{
|
||||
if(xmlReader->getNodeName() == D3MF::XmlTag::vertex)
|
||||
{
|
||||
if ( name.empty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
MetaEntry entry;
|
||||
entry.name = name;
|
||||
entry.value = value;
|
||||
mMetaData.push_back( entry );
|
||||
}
|
||||
|
||||
void ImportVertices(aiMesh* mesh) {
|
||||
std::vector<aiVector3D> vertices;
|
||||
while(ReadToEndElement(D3MF::XmlTag::vertices)) {
|
||||
if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) {
|
||||
vertices.push_back(ReadVertex());
|
||||
}
|
||||
}
|
||||
|
@ -182,11 +221,9 @@ private:
|
|||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||
|
||||
std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
|
||||
|
||||
}
|
||||
|
||||
aiVector3D ReadVertex()
|
||||
{
|
||||
aiVector3D ReadVertex() {
|
||||
aiVector3D vertex;
|
||||
|
||||
vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr);
|
||||
|
@ -196,16 +233,18 @@ private:
|
|||
return vertex;
|
||||
}
|
||||
|
||||
void ImportTriangles(aiMesh* mesh)
|
||||
{
|
||||
void ImportTriangles(aiMesh* mesh) {
|
||||
std::vector<aiFace> faces;
|
||||
|
||||
|
||||
while(ReadToEndElement(D3MF::XmlTag::triangles))
|
||||
{
|
||||
if(xmlReader->getNodeName() == D3MF::XmlTag::triangle)
|
||||
{
|
||||
while(ReadToEndElement(D3MF::XmlTag::triangles)) {
|
||||
const std::string nodeName( xmlReader->getNodeName() );
|
||||
if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) {
|
||||
faces.push_back(ReadTriangle());
|
||||
const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::p1.c_str() ) );
|
||||
if ( nullptr != pidToken ) {
|
||||
int matIdx( std::atoi( pidToken ) );
|
||||
mesh->mMaterialIndex = matIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,8 +255,7 @@ private:
|
|||
std::copy(faces.begin(), faces.end(), mesh->mFaces);
|
||||
}
|
||||
|
||||
aiFace ReadTriangle()
|
||||
{
|
||||
aiFace ReadTriangle() {
|
||||
aiFace face;
|
||||
|
||||
face.mNumIndices = 3;
|
||||
|
@ -229,45 +267,150 @@ private:
|
|||
return face;
|
||||
}
|
||||
|
||||
private:
|
||||
bool ReadToStartElement(const std::string& startTag)
|
||||
{
|
||||
while(xmlReader->read())
|
||||
{
|
||||
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && xmlReader->getNodeName() == startTag)
|
||||
{
|
||||
return true;
|
||||
void ReadBaseMaterials() {
|
||||
std::vector<unsigned int> MatIdArray;
|
||||
const char *baseMaterialId( xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_id.c_str() ) );
|
||||
if ( nullptr != baseMaterialId ) {
|
||||
unsigned int id = std::atoi( baseMaterialId );
|
||||
const size_t newMatIdx( mMatArray.size() );
|
||||
if ( id != mActiveMatGroup ) {
|
||||
mActiveMatGroup = id;
|
||||
MatId2MatArray::const_iterator it( mMatId2MatArray.find( id ) );
|
||||
if ( mMatId2MatArray.end() == it ) {
|
||||
MatIdArray.clear();
|
||||
mMatId2MatArray[ id ] = MatIdArray;
|
||||
} else {
|
||||
MatIdArray = it->second;
|
||||
}
|
||||
}
|
||||
else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END &&
|
||||
xmlReader->getNodeName() == startTag)
|
||||
{
|
||||
MatIdArray.push_back( static_cast<unsigned int>( newMatIdx ) );
|
||||
mMatId2MatArray[ mActiveMatGroup ] = MatIdArray;
|
||||
}
|
||||
|
||||
while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) {
|
||||
mMatArray.push_back( readMaterialDef() );
|
||||
}
|
||||
}
|
||||
|
||||
bool parseColor( const char *color, aiColor4D &diffuse ) {
|
||||
if ( nullptr == color ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t len( strlen( color ) );
|
||||
if ( 9 != len ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *buf( color );
|
||||
if ( '#' != *buf ) {
|
||||
return false;
|
||||
}
|
||||
++buf;
|
||||
char comp[ 3 ] = { 0,0,'\0' };
|
||||
|
||||
comp[ 0 ] = *buf;
|
||||
++buf;
|
||||
comp[ 1 ] = *buf;
|
||||
++buf;
|
||||
diffuse.r = static_cast<ai_real>( strtol( comp, NULL, 16 ) );
|
||||
|
||||
|
||||
comp[ 0 ] = *buf;
|
||||
++buf;
|
||||
comp[ 1 ] = *buf;
|
||||
++buf;
|
||||
diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
|
||||
|
||||
comp[ 0 ] = *buf;
|
||||
++buf;
|
||||
comp[ 1 ] = *buf;
|
||||
++buf;
|
||||
diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
|
||||
|
||||
comp[ 0 ] = *buf;
|
||||
++buf;
|
||||
comp[ 1 ] = *buf;
|
||||
++buf;
|
||||
diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void assignDiffuseColor( aiMaterial *mat ) {
|
||||
const char *color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() );
|
||||
aiColor4D diffuse;
|
||||
if ( parseColor( color, diffuse ) ) {
|
||||
mat->AddProperty<aiColor4D>( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
|
||||
}
|
||||
|
||||
}
|
||||
aiMaterial *readMaterialDef() {
|
||||
aiMaterial *mat( nullptr );
|
||||
const char *name( nullptr );
|
||||
const std::string nodeName( xmlReader->getNodeName() );
|
||||
if ( nodeName == D3MF::XmlTag::basematerials_base ) {
|
||||
name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() );
|
||||
std::string stdMatName;
|
||||
aiString matName;
|
||||
std::string strId( to_string( mActiveMatGroup ) );
|
||||
stdMatName += "id";
|
||||
stdMatName += strId;
|
||||
stdMatName += "_";
|
||||
if ( nullptr != name ) {
|
||||
stdMatName += std::string( name );
|
||||
} else {
|
||||
stdMatName += "basemat";
|
||||
}
|
||||
matName.Set( stdMatName );
|
||||
|
||||
mat = new aiMaterial;
|
||||
mat->AddProperty( &matName, AI_MATKEY_NAME );
|
||||
|
||||
assignDiffuseColor( mat );
|
||||
}
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
private:
|
||||
bool ReadToStartElement(const std::string& startTag) {
|
||||
while(xmlReader->read()) {
|
||||
const std::string &nodeName( xmlReader->getNodeName() );
|
||||
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && nodeName == startTag) {
|
||||
return true;
|
||||
} else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == startTag) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadToEndElement(const std::string& closeTag)
|
||||
{
|
||||
while(xmlReader->read())
|
||||
{
|
||||
bool ReadToEndElement(const std::string& closeTag) {
|
||||
while(xmlReader->read()) {
|
||||
const std::string &nodeName( xmlReader->getNodeName() );
|
||||
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||
return true;
|
||||
}
|
||||
else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END
|
||||
&& xmlReader->getNodeName() == closeTag)
|
||||
{
|
||||
} else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == closeTag) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
|
||||
ASSIMP_LOG_ERROR("unexpected EOF, expected closing <" + closeTag + "> tag");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::vector<aiMesh*> meshes;
|
||||
struct MetaEntry {
|
||||
std::string name;
|
||||
std::string value;
|
||||
};
|
||||
std::vector<MetaEntry> mMetaData;
|
||||
std::vector<aiMesh*> mMeshes;
|
||||
MatArray mMatArray;
|
||||
unsigned int mActiveMatGroup;
|
||||
MatId2MatArray mMatId2MatArray;
|
||||
XmlReader* xmlReader;
|
||||
};
|
||||
|
||||
|
@ -288,7 +431,6 @@ static const aiImporterDesc desc = {
|
|||
Extension.c_str()
|
||||
};
|
||||
|
||||
|
||||
D3MFImporter::D3MFImporter()
|
||||
: BaseImporter() {
|
||||
// empty
|
||||
|
@ -298,14 +440,19 @@ D3MFImporter::~D3MFImporter() {
|
|||
// empty
|
||||
}
|
||||
|
||||
bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
|
||||
const std::string extension = GetExtension(pFile);
|
||||
bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const {
|
||||
const std::string extension( GetExtension( filename ) );
|
||||
if(extension == Extension ) {
|
||||
return true;
|
||||
} else if ( !extension.length() || checkSig ) {
|
||||
if (nullptr == pIOHandler ) {
|
||||
return true;
|
||||
if ( nullptr == pIOHandler ) {
|
||||
return false;
|
||||
}
|
||||
if ( !D3MF::D3MFOpcPackage::isZipArchive( pIOHandler, filename ) ) {
|
||||
return false;
|
||||
}
|
||||
D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename );
|
||||
return opcPackage.validate();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -319,8 +466,8 @@ const aiImporterDesc *D3MFImporter::GetInfo() const {
|
|||
return &desc;
|
||||
}
|
||||
|
||||
void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
|
||||
D3MF::D3MFOpcPackage opcPackage(pIOHandler, pFile);
|
||||
void D3MFImporter::InternReadFile( const std::string &filename, aiScene *pScene, IOSystem *pIOHandler ) {
|
||||
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
|
||||
|
||||
std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream()));
|
||||
std::unique_ptr<D3MF::XmlReader> xmlReader(irr::io::createIrrXMLReader(xmlStream.get()));
|
||||
|
|
|
@ -247,13 +247,13 @@ private:
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor.
|
||||
D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile)
|
||||
: m_ZipFileHandle(NULL)
|
||||
: m_ZipFileHandle( nullptr )
|
||||
, m_ArchiveMap() {
|
||||
if (! rFile.empty()) {
|
||||
zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
|
||||
|
||||
m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
|
||||
if(m_ZipFileHandle != NULL) {
|
||||
if(m_ZipFileHandle != nullptr ) {
|
||||
mapArchive();
|
||||
}
|
||||
}
|
||||
|
@ -267,32 +267,32 @@ D3MFZipArchive::~D3MFZipArchive() {
|
|||
}
|
||||
m_ArchiveMap.clear();
|
||||
|
||||
if(m_ZipFileHandle != NULL) {
|
||||
if(m_ZipFileHandle != nullptr) {
|
||||
unzClose(m_ZipFileHandle);
|
||||
m_ZipFileHandle = NULL;
|
||||
m_ZipFileHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns true, if the archive is already open.
|
||||
bool D3MFZipArchive::isOpen() const {
|
||||
return (m_ZipFileHandle != NULL);
|
||||
return (m_ZipFileHandle != nullptr );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns true, if the filename is part of the archive.
|
||||
bool D3MFZipArchive::Exists(const char* pFile) const {
|
||||
ai_assert(pFile != NULL);
|
||||
ai_assert(pFile != nullptr );
|
||||
|
||||
bool exist = false;
|
||||
if ( pFile == nullptr ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pFile != NULL) {
|
||||
std::string rFile(pFile);
|
||||
std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
|
||||
|
||||
if(it != m_ArchiveMap.end()) {
|
||||
exist = true;
|
||||
}
|
||||
std::string filename(pFile);
|
||||
std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(filename);
|
||||
bool exist( false );
|
||||
if(it != m_ArchiveMap.end()) {
|
||||
exist = true;
|
||||
}
|
||||
|
||||
return exist;
|
||||
|
@ -434,8 +434,8 @@ public:
|
|||
|
||||
std::vector<OpcPackageRelationshipPtr> m_relationShips;
|
||||
};
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
|
||||
: mRootStream(nullptr)
|
||||
, mZipArchive() {
|
||||
|
@ -460,28 +460,19 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
|
|||
if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) {
|
||||
rootFile = rootFile.substr( 1 );
|
||||
if ( rootFile[ 0 ] == '/' ) {
|
||||
// deal with zipbug
|
||||
// deal with zip-bug
|
||||
rootFile = rootFile.substr( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
DefaultLogger::get()->debug(rootFile);
|
||||
ASSIMP_LOG_DEBUG(rootFile);
|
||||
|
||||
mRootStream = mZipArchive->Open(rootFile.c_str());
|
||||
ai_assert( mRootStream != nullptr );
|
||||
if ( nullptr == mRootStream ) {
|
||||
throw DeadlyExportError( "Cannot open rootfile in archive : " + rootFile );
|
||||
throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile );
|
||||
}
|
||||
|
||||
// const size_t size = zipArchive->FileSize();
|
||||
// m_Data.resize( size );
|
||||
|
||||
// const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size );
|
||||
// if ( readSize != size )
|
||||
// {
|
||||
// m_Data.clear();
|
||||
// return false;
|
||||
// }
|
||||
mZipArchive->Close( fileStream );
|
||||
|
||||
} else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
|
||||
|
@ -498,6 +489,25 @@ IOStream* D3MFOpcPackage::RootStream() const {
|
|||
return mRootStream;
|
||||
}
|
||||
|
||||
static const std::string ModelRef = "3D/3dmodel.model";
|
||||
|
||||
bool D3MFOpcPackage::validate() {
|
||||
if ( nullptr == mRootStream || nullptr == mZipArchive ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mZipArchive->Exists( ModelRef.c_str() );
|
||||
}
|
||||
|
||||
bool D3MFOpcPackage::isZipArchive( IOSystem* pIOHandler, const std::string& rFile ) {
|
||||
D3MF::D3MFZipArchive ar( pIOHandler, rFile );
|
||||
if ( !ar.isOpen() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
|
||||
std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
|
||||
std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
|
||||
|
@ -508,14 +518,14 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
|
|||
return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
|
||||
});
|
||||
|
||||
if(itr == reader.m_relationShips.end())
|
||||
throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
|
||||
if ( itr == reader.m_relationShips.end() ) {
|
||||
throw DeadlyImportError( "Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE );
|
||||
}
|
||||
|
||||
return (*itr)->target;
|
||||
}
|
||||
|
||||
} // Namespace D3MF
|
||||
|
||||
} // Namespace Assimp
|
||||
|
||||
#endif //ASSIMP_BUILD_NO_3MF_IMPORTER
|
||||
|
|
|
@ -51,8 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace Assimp {
|
||||
namespace D3MF {
|
||||
|
||||
typedef irr::io::IrrXMLReader XmlReader;
|
||||
typedef std::shared_ptr<XmlReader> XmlReaderPtr;
|
||||
using XmlReader = irr::io::IrrXMLReader ;
|
||||
using XmlReaderPtr = std::shared_ptr<XmlReader> ;
|
||||
|
||||
struct OpcPackageRelationship {
|
||||
std::string id;
|
||||
|
@ -64,9 +64,11 @@ class D3MFZipArchive;
|
|||
|
||||
class D3MFOpcPackage {
|
||||
public:
|
||||
D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile);
|
||||
D3MFOpcPackage( IOSystem* pIOHandler, const std::string& rFile );
|
||||
~D3MFOpcPackage();
|
||||
IOStream* RootStream() const;
|
||||
bool validate();
|
||||
static bool isZipArchive( IOSystem* pIOHandler, const std::string& rFile );
|
||||
|
||||
protected:
|
||||
std::string ReadPackageRootRelationship(IOStream* stream);
|
||||
|
@ -76,7 +78,7 @@ private:
|
|||
std::unique_ptr<D3MFZipArchive> mZipArchive;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // Namespace D3MF
|
||||
} // Namespace Assimp
|
||||
|
||||
#endif // D3MFOPCPACKAGE_H
|
||||
|
|
|
@ -146,7 +146,7 @@ public:
|
|||
for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
|
||||
|
||||
splitter++;
|
||||
DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
|
||||
ASSIMP_LOG_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
|
||||
}
|
||||
} catch(std::logic_error&) {
|
||||
ai_assert(!splitter);
|
||||
|
@ -169,7 +169,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
LineSplitter splitter;
|
||||
int groupcode;
|
||||
std::string value;
|
||||
|
|
|
@ -119,9 +119,18 @@ DXFImporter::~DXFImporter()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool DXFImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
|
||||
{
|
||||
return SimpleExtensionCheck(pFile,"dxf");
|
||||
bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const {
|
||||
const std::string& extension = GetExtension( pFile );
|
||||
if ( extension == "dxf" ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( extension.empty() || checkSig ) {
|
||||
static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" };
|
||||
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4, 32 );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -191,7 +200,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
// comments
|
||||
else if (reader.Is(999)) {
|
||||
DefaultLogger::get()->info("DXF Comment: " + reader.Value());
|
||||
ASSIMP_LOG_INFO_F("DXF Comment: ", reader.Value());
|
||||
}
|
||||
|
||||
// don't read past the official EOF sign
|
||||
|
@ -203,7 +212,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
|
|||
++reader;
|
||||
}
|
||||
if (!eof) {
|
||||
DefaultLogger::get()->warn("DXF: EOF reached, but did not encounter DXF EOF marker");
|
||||
ASSIMP_LOG_WARN("DXF: EOF reached, but did not encounter DXF EOF marker");
|
||||
}
|
||||
|
||||
ConvertMeshes(pScene,output);
|
||||
|
@ -220,7 +229,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
|
|||
void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output)
|
||||
{
|
||||
// the process of resolving all the INSERT statements can grow the
|
||||
// polycount excessively, so log the original number.
|
||||
// poly-count excessively, so log the original number.
|
||||
// XXX Option to import blocks as separate nodes?
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
|
||||
|
@ -232,16 +241,14 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output)
|
|||
}
|
||||
}
|
||||
|
||||
DefaultLogger::get()->debug((Formatter::format("DXF: Unexpanded polycount is "),
|
||||
icount,", vertex count is ",vcount
|
||||
));
|
||||
ASSIMP_LOG_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount);
|
||||
}
|
||||
|
||||
if (! output.blocks.size() ) {
|
||||
throw DeadlyImportError("DXF: no data blocks loaded");
|
||||
}
|
||||
|
||||
DXF::Block* entities = 0;
|
||||
DXF::Block* entities( nullptr );
|
||||
|
||||
// index blocks by name
|
||||
DXF::BlockMap blocks_by_name;
|
||||
|
@ -366,9 +373,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
|
|||
// first check if the referenced blocks exists ...
|
||||
const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name);
|
||||
if (it == blocks_by_name.end()) {
|
||||
DefaultLogger::get()->error((Formatter::format("DXF: Failed to resolve block reference: "),
|
||||
insert.name,"; skipping"
|
||||
));
|
||||
ASSIMP_LOG_ERROR_F("DXF: Failed to resolve block reference: ", insert.name,"; skipping" );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -388,7 +393,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
|
|||
|
||||
// XXX rotation currently ignored - I didn't find an appropriate sample model.
|
||||
if (insert.angle != 0.f) {
|
||||
DefaultLogger::get()->warn("DXF: BLOCK rotation not currently implemented");
|
||||
ASSIMP_LOG_WARN("DXF: BLOCK rotation not currently implemented");
|
||||
}
|
||||
|
||||
for (aiVector3D& v : pl_out->positions) {
|
||||
|
@ -401,7 +406,6 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/)
|
||||
{
|
||||
|
@ -428,7 +432,6 @@ void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/)
|
|||
pScene->mMaterials[0] = pcMat;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/)
|
||||
{
|
||||
|
@ -439,9 +442,7 @@ void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/)
|
|||
if (1 == pScene->mNumMeshes) {
|
||||
pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ];
|
||||
pScene->mRootNode->mMeshes[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ];
|
||||
for (unsigned int m = 0; m < pScene->mRootNode->mNumChildren;++m) {
|
||||
aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode();
|
||||
|
@ -456,22 +457,17 @@ void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/)
|
|||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DXFImporter::SkipSection(DXF::LineReader& reader)
|
||||
{
|
||||
void DXFImporter::SkipSection(DXF::LineReader& reader) {
|
||||
for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DXFImporter::ParseHeader(DXF::LineReader& reader, DXF::FileData& /*output*/)
|
||||
{
|
||||
void DXFImporter::ParseHeader(DXF::LineReader& reader, DXF::FileData& ) {
|
||||
for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output)
|
||||
{
|
||||
void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) {
|
||||
while( !reader.End() && !reader.Is(0,"ENDSEC")) {
|
||||
if (reader.Is(0,"BLOCK")) {
|
||||
ParseBlock(++reader,output);
|
||||
|
@ -480,15 +476,11 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output)
|
|||
++reader;
|
||||
}
|
||||
|
||||
DefaultLogger::get()->debug((Formatter::format("DXF: got "),
|
||||
output.blocks.size()," entries in BLOCKS"
|
||||
));
|
||||
ASSIMP_LOG_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" );
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output)
|
||||
{
|
||||
void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) {
|
||||
// push a new block onto the stack.
|
||||
output.blocks.push_back( DXF::Block() );
|
||||
DXF::Block& block = output.blocks.back();
|
||||
|
@ -518,7 +510,7 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output)
|
|||
|
||||
// XXX is this a valid case?
|
||||
if (reader.Is(0,"INSERT")) {
|
||||
DefaultLogger::get()->warn("DXF: INSERT within a BLOCK not currently supported; skipping");
|
||||
ASSIMP_LOG_WARN("DXF: INSERT within a BLOCK not currently supported; skipping");
|
||||
for( ;!reader.End() && !reader.Is(0,"ENDBLK"); ++reader);
|
||||
break;
|
||||
}
|
||||
|
@ -532,7 +524,6 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
|
||||
{
|
||||
|
@ -562,19 +553,16 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
|
|||
++reader;
|
||||
}
|
||||
|
||||
DefaultLogger::get()->debug((Formatter::format("DXF: got "),
|
||||
block.lines.size()," polylines and ", block.insertions.size() ," inserted blocks in ENTITIES"
|
||||
));
|
||||
ASSIMP_LOG_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(),
|
||||
" inserted blocks in ENTITIES" );
|
||||
}
|
||||
|
||||
|
||||
void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output)
|
||||
{
|
||||
output.blocks.back().insertions.push_back( DXF::InsertBlock() );
|
||||
DXF::InsertBlock& bl = output.blocks.back().insertions.back();
|
||||
|
||||
while( !reader.End() && !reader.Is(0)) {
|
||||
|
||||
switch(reader.GroupCode())
|
||||
{
|
||||
// name of referenced block
|
||||
|
@ -619,8 +607,7 @@ void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output)
|
|||
#define DXF_POLYLINE_FLAG_POLYFACEMESH 0x40
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
|
||||
{
|
||||
void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) {
|
||||
output.blocks.back().lines.push_back( std::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
|
||||
DXF::PolyLine& line = *output.blocks.back().lines.back();
|
||||
|
||||
|
@ -673,16 +660,15 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
|
|||
//}
|
||||
|
||||
if (vguess && line.positions.size() != vguess) {
|
||||
DefaultLogger::get()->warn((Formatter::format("DXF: unexpected vertex count in polymesh: "),
|
||||
line.positions.size(),", expected ", vguess
|
||||
));
|
||||
ASSIMP_LOG_WARN_F("DXF: unexpected vertex count in polymesh: ",
|
||||
line.positions.size(),", expected ", vguess );
|
||||
}
|
||||
|
||||
if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH ) {
|
||||
if (line.positions.size() < 3 || line.indices.size() < 3) {
|
||||
DefaultLogger::get()->warn("DXF: not enough vertices for polymesh; ignoring");
|
||||
output.blocks.back().lines.pop_back();
|
||||
return;
|
||||
ASSIMP_LOG_WARN("DXF: not enough vertices for polymesh; ignoring");
|
||||
output.blocks.back().lines.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
// if these numbers are wrong, parsing might have gone wild.
|
||||
|
@ -690,13 +676,11 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
|
|||
// to set the 71 and 72 fields, respectively, to valid values.
|
||||
// So just fire a warning.
|
||||
if (iguess && line.counts.size() != iguess) {
|
||||
DefaultLogger::get()->warn((Formatter::format("DXF: unexpected face count in polymesh: "),
|
||||
line.counts.size(),", expected ", iguess
|
||||
));
|
||||
ASSIMP_LOG_WARN_F( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess );
|
||||
}
|
||||
}
|
||||
else if (!line.indices.size() && !line.counts.size()) {
|
||||
// a polyline - so there are no indices yet.
|
||||
// a poly-line - so there are no indices yet.
|
||||
size_t guess = line.positions.size() + (line.flags & DXF_POLYLINE_FLAG_CLOSED ? 1 : 0);
|
||||
line.indices.reserve(guess);
|
||||
|
||||
|
@ -738,10 +722,10 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
|
|||
{
|
||||
case 8:
|
||||
// layer to which the vertex belongs to - assume that
|
||||
// this is always the layer the top-level polyline
|
||||
// this is always the layer the top-level poly-line
|
||||
// entity resides on as well.
|
||||
if(reader.Value() != line.layer) {
|
||||
DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
|
||||
ASSIMP_LOG_WARN("DXF: expected vertex to be part of a poly-face but the 0x128 flag isn't set");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -760,7 +744,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
|
|||
case 73:
|
||||
case 74:
|
||||
if (cnti == 4) {
|
||||
DefaultLogger::get()->warn("DXF: more than 4 indices per face not supported; ignoring");
|
||||
ASSIMP_LOG_WARN("DXF: more than 4 indices per face not supported; ignoring");
|
||||
break;
|
||||
}
|
||||
indices[cnti++] = reader.ValueAsUnsignedInt();
|
||||
|
@ -776,7 +760,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
|
|||
}
|
||||
|
||||
if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH && !(flags & DXF_VERTEX_FLAG_PART_OF_POLYFACE)) {
|
||||
DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
|
||||
ASSIMP_LOG_WARN("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
|
||||
}
|
||||
|
||||
if (cnti) {
|
||||
|
@ -784,14 +768,13 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
|
|||
for (unsigned int i = 0; i < cnti; ++i) {
|
||||
// IMPORTANT NOTE: POLYMESH indices are ONE-BASED
|
||||
if (indices[i] == 0) {
|
||||
DefaultLogger::get()->warn("DXF: invalid vertex index, indices are one-based.");
|
||||
ASSIMP_LOG_WARN("DXF: invalid vertex index, indices are one-based.");
|
||||
--line.counts.back();
|
||||
continue;
|
||||
}
|
||||
line.indices.push_back(indices[i]-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
line.positions.push_back(out);
|
||||
line.colors.push_back(clr);
|
||||
}
|
||||
|
@ -901,7 +884,7 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output)
|
|||
|
||||
// sanity checks to see if we got something meaningful
|
||||
if ((b[1] && !b[0]) || !b[2] || !b[3]) {
|
||||
DefaultLogger::get()->warn("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring");
|
||||
ASSIMP_LOG_WARN("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring");
|
||||
output.blocks.back().lines.pop_back();
|
||||
return;
|
||||
}
|
||||
|
@ -917,4 +900,3 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output)
|
|||
}
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_DXF_IMPORTER
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ void DeboneProcess::SetupProperties(const Importer* pImp)
|
|||
// Executes the post processing step on the given imported data.
|
||||
void DeboneProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("DeboneProcess begin");
|
||||
ASSIMP_LOG_DEBUG("DeboneProcess begin");
|
||||
|
||||
if(!pScene->mNumMeshes) {
|
||||
return;
|
||||
|
@ -148,9 +148,7 @@ void DeboneProcess::Execute( aiScene* pScene)
|
|||
}
|
||||
|
||||
if(!DefaultLogger::isNullLogger()) {
|
||||
char buffer[1024];
|
||||
::ai_snprintf(buffer,1024,"Removed %u bones. Input bones: %u. Output bones: %u",in-out,in,out);
|
||||
DefaultLogger::get()->info(buffer);
|
||||
ASSIMP_LOG_INFO_F("Removed %u bones. Input bones:", in - out, ". Output bones: ", out);
|
||||
}
|
||||
|
||||
// and destroy the source mesh. It should be completely contained inside the new submeshes
|
||||
|
@ -173,7 +171,7 @@ void DeboneProcess::Execute( aiScene* pScene)
|
|||
UpdateNode( pScene->mRootNode);
|
||||
}
|
||||
|
||||
DefaultLogger::get()->debug("DeboneProcess end");
|
||||
ASSIMP_LOG_DEBUG("DeboneProcess end");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -209,7 +207,7 @@ bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh)
|
|||
if(vertexBones[vid]!=cUnowned) {
|
||||
if(vertexBones[vid]==i) //double entry
|
||||
{
|
||||
DefaultLogger::get()->warn("Encountered double entry in bone weights");
|
||||
ASSIMP_LOG_WARN("Encountered double entry in bone weights");
|
||||
}
|
||||
else //TODO: track attraction in order to break tie
|
||||
{
|
||||
|
@ -281,7 +279,7 @@ void DeboneProcess::SplitMesh( const aiMesh* pMesh, std::vector< std::pair< aiMe
|
|||
if(vertexBones[vid]!=cUnowned) {
|
||||
if(vertexBones[vid]==i) //double entry
|
||||
{
|
||||
//DefaultLogger::get()->warn("Encountered double entry in bone weights");
|
||||
ASSIMP_LOG_WARN("Encountered double entry in bone weights");
|
||||
}
|
||||
else //TODO: track attraction in order to break tie
|
||||
{
|
||||
|
|
|
@ -76,11 +76,11 @@ bool DefaultIOSystem::Exists( const char* pFile) const
|
|||
#ifdef _WIN32
|
||||
wchar_t fileName16[PATHLIMIT];
|
||||
|
||||
bool isUnicode = IsTextUnicode(pFile, strlen(pFile), NULL);
|
||||
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
|
||||
if (isUnicode) {
|
||||
|
||||
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
|
||||
struct _stat64 filestat;
|
||||
struct __stat64 filestat;
|
||||
if (0 != _wstat64(fileName16, &filestat)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
|
|||
FILE* file;
|
||||
#ifdef _WIN32
|
||||
wchar_t fileName16[PATHLIMIT];
|
||||
bool isUnicode = IsTextUnicode(strFile, strlen(strFile), NULL );
|
||||
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
|
||||
if (isUnicode) {
|
||||
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
|
||||
std::string mode8(strMode);
|
||||
|
@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
|
|||
{
|
||||
ai_assert(in && _out);
|
||||
#if defined( _MSC_VER ) || defined( __MINGW32__ )
|
||||
bool isUnicode = IsTextUnicode(in, strlen(in), NULL);
|
||||
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
|
||||
if (isUnicode) {
|
||||
wchar_t out16[PATHLIMIT];
|
||||
wchar_t in16[PATHLIMIT];
|
||||
|
@ -170,7 +170,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
|
|||
if (!ret) {
|
||||
// preserve the input path, maybe someone else is able to fix
|
||||
// the path before it is accessed (e.g. our file system filter)
|
||||
DefaultLogger::get()->warn("Invalid path: " + std::string(in));
|
||||
ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
|
||||
strcpy(_out, in);
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
|
|||
if (!ret) {
|
||||
// preserve the input path, maybe someone else is able to fix
|
||||
// the path before it is accessed (e.g. our file system filter)
|
||||
DefaultLogger::get()->warn("Invalid path: " + std::string(in));
|
||||
ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
|
||||
strcpy(_out, in);
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
|
|||
if(!ret) {
|
||||
// preserve the input path, maybe someone else is able to fix
|
||||
// the path before it is accessed (e.g. our file system filter)
|
||||
DefaultLogger::get()->warn("Invalid path: "+std::string(in));
|
||||
ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
|
||||
strcpy(_out,in);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
* @brief Implementation of DefaultLogger (and Logger)
|
||||
*/
|
||||
|
||||
|
||||
// Default log streams
|
||||
#include "Win32DebugLogStream.h"
|
||||
#include "StdOStreamLogStream.h"
|
||||
|
@ -62,8 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
# include <thread>
|
||||
# include <mutex>
|
||||
|
||||
std::mutex loggerMutex;
|
||||
std::mutex loggerMutex;
|
||||
#endif
|
||||
|
||||
namespace Assimp {
|
||||
|
@ -76,22 +74,19 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Represents a log-stream + its error severity
|
||||
struct LogStreamInfo
|
||||
{
|
||||
unsigned int m_uiErrorSeverity;
|
||||
LogStream *m_pStream;
|
||||
struct LogStreamInfo {
|
||||
unsigned int m_uiErrorSeverity;
|
||||
LogStream *m_pStream;
|
||||
|
||||
// Constructor
|
||||
LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
|
||||
m_uiErrorSeverity( uiErrorSev ),
|
||||
m_pStream( pStream )
|
||||
{
|
||||
m_pStream( pStream ) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Destructor
|
||||
~LogStreamInfo()
|
||||
{
|
||||
~LogStreamInfo() {
|
||||
delete m_pStream;
|
||||
}
|
||||
};
|
||||
|
@ -109,7 +104,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
|
|||
#ifdef WIN32
|
||||
return new Win32DebugLogStream();
|
||||
#else
|
||||
return NULL;
|
||||
return nullptr;
|
||||
#endif
|
||||
|
||||
// Platform-independent default streams
|
||||
|
@ -118,7 +113,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
|
|||
case aiDefaultLogStream_STDOUT:
|
||||
return new StdOStreamLogStream(std::cout);
|
||||
case aiDefaultLogStream_FILE:
|
||||
return (name && *name ? new FileLogStream(name,io) : NULL);
|
||||
return (name && *name ? new FileLogStream(name,io) : nullptr );
|
||||
default:
|
||||
// We don't know this default log stream, so raise an assertion
|
||||
ai_assert(false);
|
||||
|
@ -134,34 +129,38 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
|
|||
Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
|
||||
LogSeverity severity /*= NORMAL*/,
|
||||
unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
|
||||
IOSystem* io /*= NULL*/)
|
||||
{
|
||||
IOSystem* io /*= NULL*/) {
|
||||
// enter the mutex here to avoid concurrency problems
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
std::lock_guard<std::mutex> lock(loggerMutex);
|
||||
#endif
|
||||
|
||||
if (m_pLogger && !isNullLogger() )
|
||||
if ( m_pLogger && !isNullLogger() ) {
|
||||
delete m_pLogger;
|
||||
}
|
||||
|
||||
m_pLogger = new DefaultLogger( severity );
|
||||
|
||||
// Attach default log streams
|
||||
// Stream the log to the MSVC debugger?
|
||||
if (defStreams & aiDefaultLogStream_DEBUGGER)
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER));
|
||||
if ( defStreams & aiDefaultLogStream_DEBUGGER ) {
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) );
|
||||
}
|
||||
|
||||
// Stream the log to COUT?
|
||||
if (defStreams & aiDefaultLogStream_STDOUT)
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT));
|
||||
if ( defStreams & aiDefaultLogStream_STDOUT ) {
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) );
|
||||
}
|
||||
|
||||
// Stream the log to CERR?
|
||||
if (defStreams & aiDefaultLogStream_STDERR)
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR));
|
||||
if ( defStreams & aiDefaultLogStream_STDERR ) {
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) );
|
||||
}
|
||||
|
||||
// Stream the log to a file
|
||||
if (defStreams & aiDefaultLogStream_FILE && name && *name)
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io));
|
||||
if ( defStreams & aiDefaultLogStream_FILE && name && *name ) {
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) );
|
||||
}
|
||||
|
||||
return m_pLogger;
|
||||
}
|
||||
|
@ -200,7 +199,6 @@ void Logger::warn(const char* message) {
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
void Logger::error(const char* message) {
|
||||
|
||||
// SECURITY FIX: see above
|
||||
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
|
||||
return;
|
||||
|
@ -209,23 +207,24 @@ void Logger::error(const char* message) {
|
|||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
void DefaultLogger::set( Logger *logger )
|
||||
{
|
||||
void DefaultLogger::set( Logger *logger ) {
|
||||
// enter the mutex here to avoid concurrency problems
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
std::lock_guard<std::mutex> lock(loggerMutex);
|
||||
#endif
|
||||
|
||||
if (!logger)logger = &s_pNullLogger;
|
||||
if (m_pLogger && !isNullLogger() )
|
||||
if ( nullptr == logger ) {
|
||||
logger = &s_pNullLogger;
|
||||
}
|
||||
if ( nullptr != m_pLogger && !isNullLogger() ) {
|
||||
delete m_pLogger;
|
||||
}
|
||||
|
||||
DefaultLogger::m_pLogger = logger;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
bool DefaultLogger::isNullLogger()
|
||||
{
|
||||
bool DefaultLogger::isNullLogger() {
|
||||
return m_pLogger == &s_pNullLogger;
|
||||
}
|
||||
|
||||
|
@ -236,8 +235,7 @@ Logger *DefaultLogger::get() {
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Kills the only instance
|
||||
void DefaultLogger::kill()
|
||||
{
|
||||
void DefaultLogger::kill() {
|
||||
// enter the mutex here to avoid concurrency problems
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
std::lock_guard<std::mutex> lock(loggerMutex);
|
||||
|
@ -252,10 +250,10 @@ void DefaultLogger::kill()
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Debug message
|
||||
void DefaultLogger::OnDebug( const char* message )
|
||||
{
|
||||
if ( m_Severity == Logger::NORMAL )
|
||||
return;
|
||||
void DefaultLogger::OnDebug( const char* message ) {
|
||||
if ( m_Severity == Logger::NORMAL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
|
@ -266,8 +264,7 @@ void DefaultLogger::OnDebug( const char* message )
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Logs an info
|
||||
void DefaultLogger::OnInfo( const char* message )
|
||||
{
|
||||
void DefaultLogger::OnInfo( const char* message ){
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message );
|
||||
|
@ -277,8 +274,7 @@ void DefaultLogger::OnInfo( const char* message )
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Logs a warning
|
||||
void DefaultLogger::OnWarn( const char* message )
|
||||
{
|
||||
void DefaultLogger::OnWarn( const char* message ) {
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message );
|
||||
|
@ -288,8 +284,7 @@ void DefaultLogger::OnWarn( const char* message )
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Logs an error
|
||||
void DefaultLogger::OnError( const char* message )
|
||||
{
|
||||
void DefaultLogger::OnError( const char* message ) {
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[ Size ];
|
||||
ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
|
||||
|
@ -299,10 +294,10 @@ void DefaultLogger::OnError( const char* message )
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Will attach a new stream
|
||||
bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
|
||||
{
|
||||
if (!pStream)
|
||||
bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) {
|
||||
if ( nullptr == pStream ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 == severity) {
|
||||
severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
|
||||
|
@ -312,8 +307,7 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
|
|||
it != m_StreamArray.end();
|
||||
++it )
|
||||
{
|
||||
if ( (*it)->m_pStream == pStream )
|
||||
{
|
||||
if ( (*it)->m_pStream == pStream ) {
|
||||
(*it)->m_uiErrorSeverity |= severity;
|
||||
return true;
|
||||
}
|
||||
|
@ -326,34 +320,31 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Detach a stream
|
||||
bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
|
||||
{
|
||||
if (!pStream)
|
||||
bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) {
|
||||
if ( nullptr == pStream ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 == severity) {
|
||||
severity = SeverityAll;
|
||||
}
|
||||
|
||||
for ( StreamIt it = m_StreamArray.begin();
|
||||
it != m_StreamArray.end();
|
||||
++it )
|
||||
{
|
||||
if ( (*it)->m_pStream == pStream )
|
||||
{
|
||||
bool res( false );
|
||||
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
|
||||
if ( (*it)->m_pStream == pStream ) {
|
||||
(*it)->m_uiErrorSeverity &= ~severity;
|
||||
if ( (*it)->m_uiErrorSeverity == 0 )
|
||||
{
|
||||
if ( (*it)->m_uiErrorSeverity == 0 ) {
|
||||
// don't delete the underlying stream 'cause the caller gains ownership again
|
||||
(**it).m_pStream = NULL;
|
||||
(**it).m_pStream = nullptr;
|
||||
delete *it;
|
||||
m_StreamArray.erase( it );
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return res;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
@ -361,15 +352,13 @@ bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
|
|||
DefaultLogger::DefaultLogger(LogSeverity severity)
|
||||
: Logger ( severity )
|
||||
, noRepeatMsg (false)
|
||||
, lastLen( 0 )
|
||||
{
|
||||
, lastLen( 0 ) {
|
||||
lastMsg[0] = '\0';
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Destructor
|
||||
DefaultLogger::~DefaultLogger()
|
||||
{
|
||||
DefaultLogger::~DefaultLogger() {
|
||||
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
|
||||
// also frees the underlying stream, we are its owner.
|
||||
delete *it;
|
||||
|
@ -378,9 +367,8 @@ DefaultLogger::~DefaultLogger()
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Writes message to stream
|
||||
void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev )
|
||||
{
|
||||
ai_assert(NULL != message);
|
||||
void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) {
|
||||
ai_assert(nullptr != message);
|
||||
|
||||
// Check whether this is a repeated message
|
||||
if (! ::strncmp( message,lastMsg, lastLen-1))
|
||||
|
|
|
@ -93,29 +93,27 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) {
|
|||
}
|
||||
}
|
||||
|
||||
char stringBuffer[128];
|
||||
::ai_snprintf(stringBuffer, 128, "EmbedTexturesProcess finished. Embedded %u textures.", embeddedTexturesCount);
|
||||
DefaultLogger::get()->info(stringBuffer);
|
||||
ASSIMP_LOG_INFO_F("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." );
|
||||
}
|
||||
|
||||
bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
|
||||
uint32_t imageSize = 0;
|
||||
std::string imagePath = path;
|
||||
std::streampos imageSize = 0;
|
||||
std::string imagePath = path;
|
||||
|
||||
// Test path directly
|
||||
std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
|
||||
if ((imageSize = file.tellg()) == -1u) {
|
||||
DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder.");
|
||||
if ((imageSize = file.tellg()) == std::streampos(-1)) {
|
||||
ASSIMP_LOG_WARN_F("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder.");
|
||||
|
||||
// Test path in root path
|
||||
imagePath = mRootPath + path;
|
||||
file.open(imagePath, std::ios::binary | std::ios::ate);
|
||||
if ((imageSize = file.tellg()) == -1u) {
|
||||
if ((imageSize = file.tellg()) == std::streampos(-1)) {
|
||||
// Test path basename in root path
|
||||
imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
|
||||
file.open(imagePath, std::ios::binary | std::ios::ate);
|
||||
if ((imageSize = file.tellg()) == -1u) {
|
||||
DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + ".");
|
||||
if ((imageSize = file.tellg()) == std::streampos(-1)) {
|
||||
ASSIMP_LOG_ERROR_F("EmbedTexturesProcess: Unable to embed texture: ", path, ".");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +132,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
|
|||
// Add the new texture
|
||||
auto pTexture = new aiTexture();
|
||||
pTexture->mHeight = 0; // Means that this is still compressed
|
||||
pTexture->mWidth = imageSize;
|
||||
pTexture->mWidth = static_cast<uint32_t>(imageSize);
|
||||
pTexture->pcData = imageContent;
|
||||
|
||||
auto extension = path.substr(path.find_last_of('.') + 1u);
|
||||
|
|
|
@ -62,6 +62,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
|
|||
#include "JoinVerticesProcess.h"
|
||||
#include "MakeVerboseFormat.h"
|
||||
#include "ConvertToLHProcess.h"
|
||||
#include "PretransformVertices.h"
|
||||
#include <assimp/Exceptional.h>
|
||||
#include "ScenePrivate.h"
|
||||
#include <memory>
|
||||
|
@ -97,6 +98,8 @@ void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportPropert
|
|||
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
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 ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -151,9 +154,9 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
|
||||
Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
|
||||
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
|
||||
Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
|
||||
Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2,
|
||||
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
|
||||
Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2,
|
||||
Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2,
|
||||
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
|
||||
#endif
|
||||
|
||||
|
@ -169,6 +172,11 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ),
|
||||
Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
|
||||
Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
|
||||
#endif
|
||||
|
@ -301,7 +309,8 @@ bool IsVerboseFormat(const aiScene* pScene) {
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) {
|
||||
aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
|
||||
unsigned int pPreprocessing, const ExportProperties* pProperties) {
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// when they create scenes from scratch, users will likely create them not in verbose
|
||||
|
@ -355,7 +364,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
|
|||
}
|
||||
|
||||
if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
|
||||
DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
|
||||
ASSIMP_LOG_DEBUG("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
|
||||
|
||||
MakeVerboseFormatProcess proc;
|
||||
proc.Execute(scenecopy.get());
|
||||
|
@ -389,6 +398,11 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
|
|||
}
|
||||
}
|
||||
|
||||
bool exportPointCloud(false);
|
||||
if (nullptr != pProperties) {
|
||||
exportPointCloud = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
|
||||
}
|
||||
|
||||
// dispatch other processes
|
||||
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
|
||||
BaseProcess* const p = pimpl->mPostProcessingSteps[a];
|
||||
|
@ -397,7 +411,9 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
|
|||
&& !dynamic_cast<FlipUVsProcess*>(p)
|
||||
&& !dynamic_cast<FlipWindingOrderProcess*>(p)
|
||||
&& !dynamic_cast<MakeLeftHandedProcess*>(p)) {
|
||||
|
||||
if (dynamic_cast<PretransformVertices*>(p) && exportPointCloud) {
|
||||
continue;
|
||||
}
|
||||
p->Execute(scenecopy.get());
|
||||
}
|
||||
}
|
||||
|
@ -433,7 +449,6 @@ const char* Exporter::GetErrorString() const {
|
|||
return pimpl->mError.c_str();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Exporter::FreeBlob() {
|
||||
delete pimpl->blob;
|
||||
|
@ -462,7 +477,7 @@ size_t Exporter::GetExportFormatCount() const {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const {
|
||||
if (index >= GetExportFormatCount()) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return from static storage if the requested index is built-in.
|
||||
|
@ -487,7 +502,8 @@ aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Exporter::UnregisterExporter(const char* id) {
|
||||
for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
|
||||
for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin();
|
||||
it != pimpl->mExporters.end(); ++it) {
|
||||
if (!strcmp((*it).mDescription.id,id)) {
|
||||
pimpl->mExporters.erase(it);
|
||||
break;
|
||||
|
@ -523,8 +539,7 @@ bool ExportProperties::SetPropertyFloat(const char* szName, ai_real iValue) {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Set a configuration property
|
||||
bool ExportProperties :: SetPropertyString(const char* szName, const std::string& value)
|
||||
{
|
||||
bool ExportProperties::SetPropertyString(const char* szName, const std::string& value) {
|
||||
return SetGenericProperty<std::string>(mStringProperties, szName,value);
|
||||
}
|
||||
|
||||
|
|
|
@ -448,8 +448,8 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
|
|||
/*Result ignored*/ ReadByte(input, cursor, input + length);
|
||||
const uint32_t version = ReadWord(input, cursor, input + length);
|
||||
const bool is64bits = version >= 7500;
|
||||
while (cursor < input + length)
|
||||
{
|
||||
const char *end = input + length;
|
||||
while (cursor < end ) {
|
||||
if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file FBXCommon.h
|
||||
* Some useful constants and enums for dealing with FBX files.
|
||||
*/
|
||||
#ifndef AI_FBXCOMMON_H_INC
|
||||
#define AI_FBXCOMMON_H_INC
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
|
||||
namespace FBX
|
||||
{
|
||||
const std::string NULL_RECORD = { // 13 null bytes
|
||||
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'
|
||||
}; // who knows why
|
||||
const std::string SEPARATOR = {'\x00', '\x01'}; // for use inside strings
|
||||
const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
|
||||
const int64_t SECOND = 46186158000; // FBX's kTime unit
|
||||
|
||||
// rotation order. We'll probably use EulerXYZ for everything
|
||||
enum RotOrder {
|
||||
RotOrder_EulerXYZ = 0,
|
||||
RotOrder_EulerXZY,
|
||||
RotOrder_EulerYZX,
|
||||
RotOrder_EulerYXZ,
|
||||
RotOrder_EulerZXY,
|
||||
RotOrder_EulerZYX,
|
||||
|
||||
RotOrder_SphericXYZ,
|
||||
|
||||
RotOrder_MAX // end-of-enum sentinel
|
||||
};
|
||||
|
||||
// transformation inheritance method. Most of the time RSrs
|
||||
enum TransformInheritance {
|
||||
TransformInheritance_RrSs = 0,
|
||||
TransformInheritance_RSrs,
|
||||
TransformInheritance_Rrs,
|
||||
|
||||
TransformInheritance_MAX // end-of-enum sentinel
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#endif // AI_FBXCOMMON_H_INC
|
|
@ -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,15 +135,14 @@ 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;
|
||||
nodes.reserve( conns.size() );
|
||||
|
||||
std::vector<aiNode*> nodes_chain;
|
||||
std::vector<aiNode*> post_nodes_chain;
|
||||
|
||||
try {
|
||||
for( const Connection* con : conns ) {
|
||||
|
@ -152,15 +153,16 @@ 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();
|
||||
|
||||
aiMatrix4x4 new_abs_transform = parent_transform;
|
||||
|
||||
|
@ -168,11 +170,11 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
|||
// assimp (or rather: the complicated transformation chain that
|
||||
// is employed by fbx) means that we may need multiple aiNode's
|
||||
// to represent a fbx node's transformation.
|
||||
GenerateTransformationNodeChain( *model, nodes_chain );
|
||||
GenerateTransformationNodeChain( *model, nodes_chain, post_nodes_chain );
|
||||
|
||||
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
|
||||
|
@ -187,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
|
||||
|
@ -213,15 +223,46 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
|||
// attach geometry
|
||||
ConvertModel( *model, *nodes_chain.back(), new_abs_transform );
|
||||
|
||||
// attach sub-nodes
|
||||
ConvertNodes( model->ID(), *nodes_chain.back(), new_abs_transform );
|
||||
// check if there will be any child nodes
|
||||
const std::vector<const Connection*>& child_conns
|
||||
= doc.GetConnectionsByDestinationSequenced( model->ID(), "Model" );
|
||||
|
||||
// if so, link the geometric transform inverse nodes
|
||||
// before we attach any child nodes
|
||||
if (child_conns.size()) {
|
||||
for( aiNode* postnode : post_nodes_chain ) {
|
||||
ai_assert( postnode );
|
||||
|
||||
if ( last_parent != &parent ) {
|
||||
last_parent->mNumChildren = 1;
|
||||
last_parent->mChildren = new aiNode*[ 1 ];
|
||||
last_parent->mChildren[ 0 ] = postnode;
|
||||
}
|
||||
|
||||
postnode->mParent = last_parent;
|
||||
last_parent = postnode;
|
||||
|
||||
new_abs_transform *= postnode->mTransformation;
|
||||
}
|
||||
} else {
|
||||
// free the nodes we allocated as we don't need them
|
||||
Util::delete_fun<aiNode> deleter;
|
||||
std::for_each(
|
||||
post_nodes_chain.begin(),
|
||||
post_nodes_chain.end(),
|
||||
deleter
|
||||
);
|
||||
}
|
||||
|
||||
// attach sub-nodes (if any)
|
||||
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() );
|
||||
|
@ -240,38 +281,36 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
|||
Util::delete_fun<aiNode> deleter;
|
||||
std::for_each( nodes.begin(), nodes.end(), deleter );
|
||||
std::for_each( nodes_chain.begin(), nodes_chain.end(), deleter );
|
||||
std::for_each( post_nodes_chain.begin(), post_nodes_chain.end(), deleter );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
|
@ -344,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();
|
||||
|
||||
|
@ -363,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 )
|
||||
{
|
||||
|
@ -396,6 +460,12 @@ const char* Converter::NameTransformationComp( TransformationComp comp )
|
|||
return "GeometricRotation";
|
||||
case TransformationComp_GeometricTranslation:
|
||||
return "GeometricTranslation";
|
||||
case TransformationComp_GeometricScalingInverse:
|
||||
return "GeometricScalingInverse";
|
||||
case TransformationComp_GeometricRotationInverse:
|
||||
return "GeometricRotationInverse";
|
||||
case TransformationComp_GeometricTranslationInverse:
|
||||
return "GeometricTranslationInverse";
|
||||
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
|
||||
default:
|
||||
break;
|
||||
|
@ -437,6 +507,12 @@ const char* Converter::NameTransformationCompProperty( TransformationComp comp )
|
|||
return "GeometricRotation";
|
||||
case TransformationComp_GeometricTranslation:
|
||||
return "GeometricTranslation";
|
||||
case TransformationComp_GeometricScalingInverse:
|
||||
return "GeometricScalingInverse";
|
||||
case TransformationComp_GeometricRotationInverse:
|
||||
return "GeometricRotationInverse";
|
||||
case TransformationComp_GeometricTranslationInverse:
|
||||
return "GeometricTranslationInverse";
|
||||
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
|
||||
break;
|
||||
}
|
||||
|
@ -548,17 +624,25 @@ bool Converter::NeedsComplexTransformationChain( const Model& model )
|
|||
bool ok;
|
||||
|
||||
const float zero_epsilon = 1e-6f;
|
||||
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
|
||||
for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) {
|
||||
const TransformationComp comp = static_cast< TransformationComp >( i );
|
||||
|
||||
if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ||
|
||||
comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) {
|
||||
if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool scale_compare = ( comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling );
|
||||
|
||||
const aiVector3D& v = PropertyGet<aiVector3D>( props, NameTransformationCompProperty( comp ), ok );
|
||||
if ( ok && v.SquareLength() > zero_epsilon ) {
|
||||
return true;
|
||||
if ( ok && scale_compare ) {
|
||||
if ( (v - all_ones).SquareLength() > zero_epsilon ) {
|
||||
return true;
|
||||
}
|
||||
} else if ( ok ) {
|
||||
if ( v.SquareLength() > zero_epsilon ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -570,7 +654,7 @@ std::string Converter::NameTransformationChainNode( const std::string& name, Tra
|
|||
return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp );
|
||||
}
|
||||
|
||||
void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes )
|
||||
void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes )
|
||||
{
|
||||
const PropertyTable& props = model.Props();
|
||||
const Model::RotOrder rot = model.RotationOrder();
|
||||
|
@ -582,20 +666,21 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
|
|||
|
||||
// generate transformation matrices for all the different transformation components
|
||||
const float zero_epsilon = 1e-6f;
|
||||
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
|
||||
bool is_complex = false;
|
||||
|
||||
const aiVector3D& PreRotation = PropertyGet<aiVector3D>( props, "PreRotation", ok );
|
||||
if ( ok && PreRotation.SquareLength() > zero_epsilon ) {
|
||||
is_complex = true;
|
||||
|
||||
GetRotationMatrix( rot, PreRotation, chain[ TransformationComp_PreRotation ] );
|
||||
GetRotationMatrix( Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[ TransformationComp_PreRotation ] );
|
||||
}
|
||||
|
||||
const aiVector3D& PostRotation = PropertyGet<aiVector3D>( props, "PostRotation", ok );
|
||||
if ( ok && PostRotation.SquareLength() > zero_epsilon ) {
|
||||
is_complex = true;
|
||||
|
||||
GetRotationMatrix( rot, PostRotation, chain[ TransformationComp_PostRotation ] );
|
||||
GetRotationMatrix( Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[ TransformationComp_PostRotation ] );
|
||||
}
|
||||
|
||||
const aiVector3D& RotationPivot = PropertyGet<aiVector3D>( props, "RotationPivot", ok );
|
||||
|
@ -634,7 +719,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
|
|||
}
|
||||
|
||||
const aiVector3D& Scaling = PropertyGet<aiVector3D>( props, "Lcl Scaling", ok );
|
||||
if ( ok && std::fabs( Scaling.SquareLength() - 1.0f ) > zero_epsilon ) {
|
||||
if ( ok && (Scaling - all_ones).SquareLength() > zero_epsilon ) {
|
||||
aiMatrix4x4::Scaling( Scaling, chain[ TransformationComp_Scaling ] );
|
||||
}
|
||||
|
||||
|
@ -644,18 +729,38 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
|
|||
}
|
||||
|
||||
const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>( props, "GeometricScaling", ok );
|
||||
if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) {
|
||||
if ( ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon ) {
|
||||
is_complex = true;
|
||||
aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] );
|
||||
aiVector3D GeometricScalingInverse = GeometricScaling;
|
||||
bool canscale = true;
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) {
|
||||
GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
|
||||
} else {
|
||||
FBXImporter::LogError( "cannot invert geometric scaling matrix with a 0.0 scale component" );
|
||||
canscale = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (canscale) {
|
||||
aiMatrix4x4::Scaling( GeometricScalingInverse, chain[ TransformationComp_GeometricScalingInverse ] );
|
||||
}
|
||||
}
|
||||
|
||||
const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>( props, "GeometricRotation", ok );
|
||||
if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) {
|
||||
is_complex = true;
|
||||
GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotation ] );
|
||||
GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotationInverse ] );
|
||||
chain[ TransformationComp_GeometricRotationInverse ].Inverse();
|
||||
}
|
||||
|
||||
const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>( props, "GeometricTranslation", ok );
|
||||
if ( ok && GeometricTranslation.SquareLength() > zero_epsilon ) {
|
||||
is_complex = true;
|
||||
aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] );
|
||||
aiMatrix4x4::Translation( -GeometricTranslation, chain[ TransformationComp_GeometricTranslationInverse ] );
|
||||
}
|
||||
|
||||
// is_complex needs to be consistent with NeedsComplexTransformationChain()
|
||||
|
@ -663,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
|
||||
|
@ -690,10 +795,18 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
|
|||
}
|
||||
|
||||
aiNode* nd = new aiNode();
|
||||
output_nodes.push_back( nd );
|
||||
|
||||
nd->mName.Set( NameTransformationChainNode( name, comp ) );
|
||||
nd->mTransformation = chain[ i ];
|
||||
|
||||
// geometric inverses go in a post-node chain
|
||||
if ( comp == TransformationComp_GeometricScalingInverse ||
|
||||
comp == TransformationComp_GeometricRotationInverse ||
|
||||
comp == TransformationComp_GeometricTranslationInverse
|
||||
) {
|
||||
post_output_nodes.push_back( nd );
|
||||
} else {
|
||||
output_nodes.push_back( nd );
|
||||
}
|
||||
}
|
||||
|
||||
ai_assert( output_nodes.size() );
|
||||
|
@ -703,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;
|
||||
|
@ -759,7 +874,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
|
|||
|
||||
const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo );
|
||||
if ( mesh ) {
|
||||
const std::vector<unsigned int>& indices = ConvertMesh( *mesh, model, node_global_transform );
|
||||
const std::vector<unsigned int>& indices = ConvertMesh( *mesh, model, node_global_transform, nd);
|
||||
std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) );
|
||||
}
|
||||
else {
|
||||
|
@ -776,7 +891,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
|
|||
}
|
||||
|
||||
std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform )
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd)
|
||||
{
|
||||
std::vector<unsigned int> temp;
|
||||
|
||||
|
@ -800,17 +915,17 @@ std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, cons
|
|||
const MatIndexArray::value_type base = mindices[ 0 ];
|
||||
for( MatIndexArray::value_type index : mindices ) {
|
||||
if ( index != base ) {
|
||||
return ConvertMeshMultiMaterial( mesh, model, node_global_transform );
|
||||
return ConvertMeshMultiMaterial( mesh, model, node_global_transform, nd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// faster code-path, just copy the data
|
||||
temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform ) );
|
||||
temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform, nd) );
|
||||
return temp;
|
||||
}
|
||||
|
||||
aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
|
||||
aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd)
|
||||
{
|
||||
aiMesh* const out_mesh = new aiMesh();
|
||||
meshes.push_back( out_mesh );
|
||||
|
@ -825,15 +940,19 @@ aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
|
|||
if ( name.length() ) {
|
||||
out_mesh->mName.Set( name );
|
||||
}
|
||||
else
|
||||
{
|
||||
out_mesh->mName = nd.mName;
|
||||
}
|
||||
|
||||
return out_mesh;
|
||||
}
|
||||
|
||||
unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform )
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd)
|
||||
{
|
||||
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||
aiMesh* const out_mesh = SetupEmptyMesh( mesh );
|
||||
aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
|
||||
|
||||
const std::vector<aiVector3D>& vertices = mesh.GetVertices();
|
||||
const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
|
||||
|
@ -957,7 +1076,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con
|
|||
}
|
||||
|
||||
std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform )
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd)
|
||||
{
|
||||
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||
ai_assert( mindices.size() );
|
||||
|
@ -968,7 +1087,7 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
|
|||
for( MatIndexArray::value_type index : mindices ) {
|
||||
if ( had.find( index ) == had.end() ) {
|
||||
|
||||
indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform ) );
|
||||
indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform, nd) );
|
||||
had.insert( index );
|
||||
}
|
||||
}
|
||||
|
@ -978,9 +1097,10 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
|
|||
|
||||
unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
|
||||
MatIndexArray::value_type index,
|
||||
const aiMatrix4x4& node_global_transform )
|
||||
const aiMatrix4x4& node_global_transform,
|
||||
aiNode& nd)
|
||||
{
|
||||
aiMesh* const out_mesh = SetupEmptyMesh( mesh );
|
||||
aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
|
||||
|
||||
const MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||
const std::vector<aiVector3D>& vertices = mesh.GetVertices();
|
||||
|
@ -1406,6 +1526,46 @@ unsigned int Converter::ConvertVideo( const Video& video )
|
|||
return static_cast<unsigned int>( textures.size() - 1 );
|
||||
}
|
||||
|
||||
aiString Converter::GetTexturePath(const Texture* tex)
|
||||
{
|
||||
aiString path;
|
||||
path.Set(tex->RelativeFilename());
|
||||
|
||||
const Video* media = tex->Media();
|
||||
if (media != nullptr) {
|
||||
bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
|
||||
unsigned int index;
|
||||
|
||||
VideoMap::const_iterator it = textures_converted.find(media);
|
||||
if (it != textures_converted.end()) {
|
||||
index = (*it).second;
|
||||
textureReady = true;
|
||||
}
|
||||
else {
|
||||
if (media->ContentLength() > 0) {
|
||||
index = ConvertVideo(*media);
|
||||
textures_converted[media] = index;
|
||||
textureReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
|
||||
if (doc.Settings().useLegacyEmbeddedTextureNaming) {
|
||||
if (textureReady) {
|
||||
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
|
||||
// In FBX files textures are now stored internally by Assimp with their filename included
|
||||
// Now Assimp can lookup through the loaded textures after all data is processed
|
||||
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
|
||||
// This may occur on this case too, it has to be studied
|
||||
path.data[0] = '*';
|
||||
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& textures,
|
||||
const std::string& propName,
|
||||
aiTextureType target, const MeshGeometry* const mesh )
|
||||
|
@ -1418,41 +1578,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
|
|||
const Texture* const tex = ( *it ).second;
|
||||
if ( tex != 0 )
|
||||
{
|
||||
aiString path;
|
||||
path.Set( tex->RelativeFilename() );
|
||||
|
||||
const Video* media = tex->Media();
|
||||
if (media != 0) {
|
||||
bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
|
||||
unsigned int index;
|
||||
|
||||
VideoMap::const_iterator it = textures_converted.find(media);
|
||||
if (it != textures_converted.end()) {
|
||||
index = (*it).second;
|
||||
textureReady = true;
|
||||
}
|
||||
else {
|
||||
if (media->ContentLength() > 0) {
|
||||
index = ConvertVideo(*media);
|
||||
textures_converted[media] = index;
|
||||
textureReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
|
||||
if (doc.Settings().useLegacyEmbeddedTextureNaming) {
|
||||
if (textureReady) {
|
||||
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
|
||||
// In FBX files textures are now stored internally by Assimp with their filename included
|
||||
// Now Assimp can lookup thru the loaded textures after all data is processed
|
||||
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
|
||||
// This may occur on this case too, it has to be studied
|
||||
path.data[0] = '*';
|
||||
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiString path = GetTexturePath(tex);
|
||||
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
|
||||
|
||||
aiUVTransform uvTrafo;
|
||||
|
@ -1559,9 +1685,8 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
|
|||
}
|
||||
|
||||
void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
|
||||
const std::string& propName,
|
||||
aiTextureType target, const MeshGeometry* const mesh )
|
||||
{
|
||||
const std::string& propName,
|
||||
aiTextureType target, const MeshGeometry* const mesh ) {
|
||||
LayeredTextureMap::const_iterator it = layeredTextures.find( propName );
|
||||
if ( it == layeredTextures.end() ) {
|
||||
return;
|
||||
|
@ -1577,9 +1702,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu
|
|||
|
||||
const Texture* const tex = ( *it ).second->getTexture(texIndex);
|
||||
|
||||
aiString path;
|
||||
path.Set( tex->RelativeFilename() );
|
||||
|
||||
aiString path = GetTexturePath(tex);
|
||||
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex );
|
||||
|
||||
aiUVTransform uvTrafo;
|
||||
|
@ -1805,11 +1928,11 @@ void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyT
|
|||
|
||||
// TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes:
|
||||
const aiColor3D& Transparent = GetColorPropertyFactored( props, "TransparentColor", "TransparencyFactor", ok );
|
||||
float CalculatedOpacity = 1.0;
|
||||
float CalculatedOpacity = 1.0f;
|
||||
if ( ok ) {
|
||||
out_mat->AddProperty( &Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT );
|
||||
// as calculated by FBX SDK 2017:
|
||||
CalculatedOpacity = 1.0 - ((Transparent.r + Transparent.g + Transparent.b) / 3.0);
|
||||
CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f);
|
||||
}
|
||||
|
||||
// use of TransparencyFactor is inconsistent.
|
||||
|
@ -1923,81 +2046,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 )
|
||||
|
@ -2209,8 +2268,7 @@ void Converter::GenerateNodeAnimations( std::vector<aiNodeAnim*>& node_anims,
|
|||
|
||||
has_any = true;
|
||||
|
||||
if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation &&
|
||||
comp != TransformationComp_GeometricScaling && comp != TransformationComp_GeometricRotation && comp != TransformationComp_GeometricTranslation )
|
||||
if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation )
|
||||
{
|
||||
has_complex = true;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -82,7 +84,10 @@ public:
|
|||
* The different parts that make up the final local transformation of a fbx-node
|
||||
*/
|
||||
enum TransformationComp {
|
||||
TransformationComp_Translation = 0,
|
||||
TransformationComp_GeometricScalingInverse = 0,
|
||||
TransformationComp_GeometricRotationInverse,
|
||||
TransformationComp_GeometricTranslationInverse,
|
||||
TransformationComp_Translation,
|
||||
TransformationComp_RotationOffset,
|
||||
TransformationComp_RotationPivot,
|
||||
TransformationComp_PreRotation,
|
||||
|
@ -114,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 -
|
||||
|
@ -153,7 +161,7 @@ private:
|
|||
/**
|
||||
* note: memory for output_nodes will be managed by the caller
|
||||
*/
|
||||
void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes);
|
||||
void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SetupNodeMetadata(const Model& model, aiNode& nd);
|
||||
|
@ -164,23 +172,23 @@ private:
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
|
||||
std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform);
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiMesh* SetupEmptyMesh(const MeshGeometry& mesh);
|
||||
aiMesh* SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform);
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
||||
const aiMatrix4x4& node_global_transform);
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
||||
MatIndexArray::value_type index,
|
||||
const aiMatrix4x4& node_global_transform);
|
||||
const aiMatrix4x4& node_global_transform, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
|
||||
|
@ -220,6 +228,10 @@ private:
|
|||
// Video -> aiTexture
|
||||
unsigned int ConvertVideo(const Video& video);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// convert embedded texture if necessary and return actual texture path
|
||||
aiString GetTexturePath(const Texture* tex);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
|
||||
const std::string& propName,
|
||||
|
@ -255,18 +267,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
|
||||
|
@ -278,7 +278,6 @@ private:
|
|||
// XXX: better use multi_map ..
|
||||
typedef std::map<std::string, std::vector<const AnimationCurveNode*> > NodeMap;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertAnimationStack(const AnimationStack& st);
|
||||
|
||||
|
@ -429,13 +428,7 @@ 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;
|
||||
|
|
|
@ -214,7 +214,7 @@ const Object* LazyObject::Get(bool dieOnError)
|
|||
|
||||
// note: the error message is already formatted, so raw logging is ok
|
||||
if(!DefaultLogger::isNullLogger()) {
|
||||
DefaultLogger::get()->error(ex.what());
|
||||
ASSIMP_LOG_ERROR(ex.what());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -575,11 +575,11 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
|
|||
ai_assert( count != 0 );
|
||||
ai_assert( count <= MAX_CLASSNAMES);
|
||||
|
||||
size_t lenghts[MAX_CLASSNAMES];
|
||||
size_t lengths[MAX_CLASSNAMES];
|
||||
|
||||
const size_t c = count;
|
||||
for (size_t i = 0; i < c; ++i) {
|
||||
lenghts[ i ] = strlen(classnames[i]);
|
||||
lengths[ i ] = strlen(classnames[i]);
|
||||
}
|
||||
|
||||
std::vector<const Connection*> temp;
|
||||
|
@ -597,7 +597,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
|
|||
|
||||
for (size_t i = 0; i < c; ++i) {
|
||||
ai_assert(classnames[i]);
|
||||
if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lenghts[i] && !strncmp(classnames[i],obtype,lenghts[i])) {
|
||||
if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lengths[i] && !strncmp(classnames[i],obtype,lengths[i])) {
|
||||
obtype = NULL;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ void DOMError(const std::string& message, const Element* element /*= NULL*/)
|
|||
void DOMWarning(const std::string& message, const Token& token)
|
||||
{
|
||||
if(DefaultLogger::get()) {
|
||||
DefaultLogger::get()->warn(Util::AddTokenText("FBX-DOM",message,&token));
|
||||
ASSIMP_LOG_WARN(Util::AddTokenText("FBX-DOM",message,&token));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ void DOMWarning(const std::string& message, const Element* element /*= NULL*/)
|
|||
return;
|
||||
}
|
||||
if(DefaultLogger::get()) {
|
||||
DefaultLogger::get()->warn("FBX-DOM: " + message);
|
||||
ASSIMP_LOG_WARN("FBX-DOM: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
|
|||
}
|
||||
}
|
||||
|
||||
if(!Properties70) {
|
||||
if(!Properties70 || !Properties70->Compound()) {
|
||||
if(!no_warn) {
|
||||
DOMWarning("property table (Properties70) not found",&element);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,568 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#include "FBXExportNode.h"
|
||||
#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,
|
||||
// so all are defined as separate functions.
|
||||
// Even "animatable" properties are often completely different
|
||||
// from the standard (nonanimated) property definition,
|
||||
// so they are specified with an 'A' suffix.
|
||||
|
||||
void FBX::Node::AddP70int(
|
||||
const std::string& name, int32_t value
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "int", "Integer", "", value);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70bool(
|
||||
const std::string& name, bool value
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "bool", "", "", int32_t(value));
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70double(
|
||||
const std::string& name, double value
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "double", "Number", "", value);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70numberA(
|
||||
const std::string& name, double value
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "Number", "", "A", value);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70color(
|
||||
const std::string& name, double r, double g, double b
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "ColorRGB", "Color", "", r, g, b);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70colorA(
|
||||
const std::string& name, double r, double g, double b
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "Color", "", "A", r, g, b);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70vector(
|
||||
const std::string& name, double x, double y, double z
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "Vector3D", "Vector", "", x, y, z);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70vectorA(
|
||||
const std::string& name, double x, double y, double z
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "Vector", "", "A", x, y, z);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70string(
|
||||
const std::string& name, const std::string& value
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "KString", "", "", value);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70enum(
|
||||
const std::string& name, int32_t value
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "enum", "", "", value);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
void FBX::Node::AddP70time(
|
||||
const std::string& name, int64_t value
|
||||
) {
|
||||
FBX::Node n("P");
|
||||
n.AddProperties(name, "KTime", "Time", "", value);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
|
||||
// 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::DumpBinary(Assimp::StreamWriterLE &s)
|
||||
{
|
||||
// write header section (with placeholders for some things)
|
||||
BeginBinary(s);
|
||||
|
||||
// write properties
|
||||
DumpPropertiesBinary(s);
|
||||
|
||||
// go back and fill in property related placeholders
|
||||
EndPropertiesBinary(s, properties.size());
|
||||
|
||||
// write children
|
||||
DumpChildrenBinary(s);
|
||||
|
||||
// finish, filling in end offset placeholder
|
||||
EndBinary(s, force_has_children || !children.empty());
|
||||
}
|
||||
|
||||
|
||||
// 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();
|
||||
|
||||
// placeholders for end pos and property section info
|
||||
s.PutU4(0); // end pos
|
||||
s.PutU4(0); // number of properties
|
||||
s.PutU4(0); // total property section length
|
||||
|
||||
// node name
|
||||
s.PutU1(uint8_t(name.size())); // length of node name
|
||||
s.PutString(name); // node name as raw bytes
|
||||
|
||||
// property data comes after here
|
||||
this->property_start = s.Tell();
|
||||
}
|
||||
|
||||
void FBX::Node::DumpPropertiesBinary(Assimp::StreamWriterLE& s)
|
||||
{
|
||||
for (auto &p : properties) {
|
||||
p.DumpBinary(s);
|
||||
}
|
||||
}
|
||||
|
||||
void FBX::Node::EndPropertiesBinary(
|
||||
Assimp::StreamWriterLE &s,
|
||||
size_t num_properties
|
||||
) {
|
||||
if (num_properties == 0) { return; }
|
||||
size_t pos = s.Tell();
|
||||
ai_assert(pos > property_start);
|
||||
size_t property_section_size = pos - property_start;
|
||||
s.Seek(start_pos + 4);
|
||||
s.PutU4(uint32_t(num_properties));
|
||||
s.PutU4(uint32_t(property_section_size));
|
||||
s.Seek(pos);
|
||||
}
|
||||
|
||||
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
|
||||
) {
|
||||
// if there were children, add a null record
|
||||
if (has_children) { s.PutString(FBX::NULL_RECORD); }
|
||||
|
||||
// now go back and write initial pos
|
||||
this->end_pos = s.Tell();
|
||||
s.Seek(start_pos);
|
||||
s.PutU4(uint32_t(end_pos));
|
||||
s.Seek(end_pos);
|
||||
}
|
||||
|
||||
|
||||
void FBX::Node::BeginAscii(std::ostream& s, int indent)
|
||||
{
|
||||
s << '\n';
|
||||
for (int i = 0; i < indent; ++i) { s << '\t'; }
|
||||
s << name << ": ";
|
||||
}
|
||||
|
||||
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::WritePropertyNodeBinary(
|
||||
const std::string& name,
|
||||
const std::vector<double>& v,
|
||||
Assimp::StreamWriterLE& 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.EndPropertiesBinary(s, 1);
|
||||
node.EndBinary(s, false);
|
||||
}
|
||||
|
||||
// binary property node from vector of int32_t
|
||||
// TODO: optional zip compression!
|
||||
void FBX::Node::WritePropertyNodeBinary(
|
||||
const std::string& name,
|
||||
const std::vector<int32_t>& v,
|
||||
Assimp::StreamWriterLE& 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.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
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file FBXExportNode.h
|
||||
* Declares the FBX::Node helper class for fbx export.
|
||||
*/
|
||||
#ifndef AI_FBXEXPORTNODE_H_INC
|
||||
#define AI_FBXEXPORTNODE_H_INC
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#include "FBXExportProperty.h"
|
||||
|
||||
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace FBX {
|
||||
class Node;
|
||||
}
|
||||
|
||||
class FBX::Node
|
||||
{
|
||||
public: // public data members
|
||||
// TODO: accessors
|
||||
std::string name; // node name
|
||||
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) {}
|
||||
|
||||
// convenience template to construct with properties directly
|
||||
template <typename... More>
|
||||
Node(const std::string& n, const More... more)
|
||||
: name(n)
|
||||
{ AddProperties(more...); }
|
||||
|
||||
public: // functions to add properties or children
|
||||
// add a single property to the node
|
||||
template <typename T>
|
||||
void AddProperty(T value) {
|
||||
properties.emplace_back(value);
|
||||
}
|
||||
|
||||
// convenience function to add multiple properties at once
|
||||
template <typename T, typename... More>
|
||||
void AddProperties(T value, More... more) {
|
||||
properties.emplace_back(value);
|
||||
AddProperties(more...);
|
||||
}
|
||||
void AddProperties() {}
|
||||
|
||||
// add a child node directly
|
||||
void AddChild(const Node& node) { children.push_back(node); }
|
||||
|
||||
// convenience function to add a child node with a single property
|
||||
template <typename... More>
|
||||
void AddChild(
|
||||
const std::string& name,
|
||||
More... more
|
||||
) {
|
||||
FBX::Node c(name);
|
||||
c.AddProperties(more...);
|
||||
children.push_back(c);
|
||||
}
|
||||
|
||||
public: // support specifically for dealing with Properties70 nodes
|
||||
|
||||
// it really is simpler to make these all separate functions.
|
||||
// the versions with 'A' suffixes are for animatable properties.
|
||||
// those often follow a completely different format internally in FBX.
|
||||
void AddP70int(const std::string& name, int32_t value);
|
||||
void AddP70bool(const std::string& name, bool value);
|
||||
void AddP70double(const std::string& name, double value);
|
||||
void AddP70numberA(const std::string& name, double value);
|
||||
void AddP70color(const std::string& name, double r, double g, double b);
|
||||
void AddP70colorA(const std::string& name, double r, double g, double b);
|
||||
void AddP70vector(const std::string& name, double x, double y, double z);
|
||||
void AddP70vectorA(const std::string& name, double x, double y, double z);
|
||||
void AddP70string(const std::string& name, const std::string& value);
|
||||
void AddP70enum(const std::string& name, int32_t value);
|
||||
void AddP70time(const std::string& name, int64_t value);
|
||||
|
||||
// template for custom P70 nodes.
|
||||
// anything that doesn't fit in the above can be created manually.
|
||||
template <typename... More>
|
||||
void AddP70(
|
||||
const std::string& name,
|
||||
const std::string& type,
|
||||
const std::string& type2,
|
||||
const std::string& flags,
|
||||
More... more
|
||||
) {
|
||||
Node n("P");
|
||||
n.AddProperties(name, type, type2, flags, more...);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
public: // member functions for writing data to a file or stream
|
||||
|
||||
// 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, 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
|
||||
size_t end_pos; // ending position in stream
|
||||
size_t property_start; // starting position of property section
|
||||
|
||||
public: // static member functions
|
||||
|
||||
// convenience function to create a node with a single property,
|
||||
// and write it to the stream.
|
||||
template <typename T>
|
||||
static void WritePropertyNode(
|
||||
const std::string& name,
|
||||
const T value,
|
||||
Assimp::StreamWriterLE& s,
|
||||
bool binary, int indent
|
||||
) {
|
||||
FBX::Property p(value);
|
||||
FBX::Node node(name, p);
|
||||
node.Dump(s, binary, 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.
|
||||
static void WritePropertyNode(
|
||||
const std::string& name,
|
||||
const std::vector<double>& v,
|
||||
Assimp::StreamWriterLE& s,
|
||||
bool binary, int 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.
|
||||
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
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#endif // AI_FBXEXPORTNODE_H_INC
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#include "FBXExportProperty.h"
|
||||
|
||||
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||
#include <assimp/Exceptional.h> // DeadlyExportError
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <locale>
|
||||
#include <sstream> // ostringstream
|
||||
|
||||
|
||||
// constructors for single element properties
|
||||
|
||||
FBX::Property::Property(bool v)
|
||||
: type('C'), data(1)
|
||||
{
|
||||
data = {uint8_t(v)};
|
||||
}
|
||||
|
||||
FBX::Property::Property(int16_t v) : type('Y'), data(2)
|
||||
{
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<int16_t*>(d))[0] = v;
|
||||
}
|
||||
|
||||
FBX::Property::Property(int32_t v) : type('I'), data(4)
|
||||
{
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<int32_t*>(d))[0] = v;
|
||||
}
|
||||
|
||||
FBX::Property::Property(float v) : type('F'), data(4)
|
||||
{
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<float*>(d))[0] = v;
|
||||
}
|
||||
|
||||
FBX::Property::Property(double v) : type('D'), data(8)
|
||||
{
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<double*>(d))[0] = v;
|
||||
}
|
||||
|
||||
FBX::Property::Property(int64_t v) : type('L'), data(8)
|
||||
{
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<int64_t*>(d))[0] = v;
|
||||
}
|
||||
|
||||
|
||||
// constructors for array-type properties
|
||||
|
||||
FBX::Property::Property(const char* c, bool raw)
|
||||
: Property(std::string(c), raw)
|
||||
{}
|
||||
|
||||
// strings can either be saved as "raw" (R) data, or "string" (S) data
|
||||
FBX::Property::Property(const std::string& s, bool raw)
|
||||
: type(raw ? 'R' : 'S'), data(s.size())
|
||||
{
|
||||
for (size_t i = 0; i < s.size(); ++i) {
|
||||
data[i] = uint8_t(s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
FBX::Property::Property(const std::vector<uint8_t>& r)
|
||||
: type('R'), data(r)
|
||||
{}
|
||||
|
||||
FBX::Property::Property(const std::vector<int32_t>& va)
|
||||
: type('i'), data(4*va.size())
|
||||
{
|
||||
int32_t* d = reinterpret_cast<int32_t*>(data.data());
|
||||
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||
}
|
||||
|
||||
FBX::Property::Property(const std::vector<int64_t>& va)
|
||||
: type('l'), data(8*va.size())
|
||||
{
|
||||
int64_t* d = reinterpret_cast<int64_t*>(data.data());
|
||||
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||
}
|
||||
|
||||
FBX::Property::Property(const std::vector<float>& va)
|
||||
: type('f'), data(4*va.size())
|
||||
{
|
||||
float* d = reinterpret_cast<float*>(data.data());
|
||||
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||
}
|
||||
|
||||
FBX::Property::Property(const std::vector<double>& va)
|
||||
: type('d'), data(8*va.size())
|
||||
{
|
||||
double* d = reinterpret_cast<double*>(data.data());
|
||||
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||
}
|
||||
|
||||
FBX::Property::Property(const aiMatrix4x4& vm)
|
||||
: type('d'), data(8*16)
|
||||
{
|
||||
double* d = reinterpret_cast<double*>(data.data());
|
||||
for (unsigned int c = 0; c < 4; ++c) {
|
||||
for (unsigned int r = 0; r < 4; ++r) {
|
||||
d[4*c+r] = vm[r][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// public member functions
|
||||
|
||||
size_t FBX::Property::size()
|
||||
{
|
||||
switch (type) {
|
||||
case 'C': case 'Y': case 'I': case 'F': case 'D': case 'L':
|
||||
return data.size() + 1;
|
||||
case 'S': case 'R':
|
||||
return data.size() + 5;
|
||||
case 'i': case 'd':
|
||||
return data.size() + 13;
|
||||
default:
|
||||
throw DeadlyExportError("Requested size on property of unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
void FBX::Property::DumpBinary(Assimp::StreamWriterLE &s)
|
||||
{
|
||||
s.PutU1(type);
|
||||
uint8_t* d = data.data();
|
||||
size_t N;
|
||||
switch (type) {
|
||||
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()));
|
||||
for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
|
||||
return;
|
||||
case 'i':
|
||||
N = data.size() / 4;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
case 'l':
|
||||
N = data.size() / 8;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
case 'f':
|
||||
N = data.size() / 4;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutF4((reinterpret_cast<float*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
case 'd':
|
||||
N = data.size() / 8;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutF8((reinterpret_cast<double*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
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
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file FBXExportProperty.h
|
||||
* Declares the FBX::Property helper class for fbx export.
|
||||
*/
|
||||
#ifndef AI_FBXEXPORTPROPERTY_H_INC
|
||||
#define AI_FBXEXPORTPROPERTY_H_INC
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
|
||||
#include <assimp/types.h> // aiMatrix4x4
|
||||
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <type_traits> // is_void
|
||||
|
||||
namespace FBX {
|
||||
class Property;
|
||||
}
|
||||
|
||||
/** FBX::Property
|
||||
*
|
||||
* Holds a value of any of FBX's recognized types,
|
||||
* each represented by a particular one-character code.
|
||||
* C : 1-byte uint8, usually 0x00 or 0x01 to represent boolean false and true
|
||||
* Y : 2-byte int16
|
||||
* I : 4-byte int32
|
||||
* F : 4-byte float
|
||||
* D : 8-byte double
|
||||
* L : 8-byte int64
|
||||
* i : array of int32
|
||||
* f : array of float
|
||||
* d : array of double
|
||||
* l : array of int64
|
||||
* b : array of 1-byte booleans (0x00 or 0x01)
|
||||
* S : string (array of 1-byte char)
|
||||
* R : raw data (array of bytes)
|
||||
*/
|
||||
class FBX::Property
|
||||
{
|
||||
public:
|
||||
// constructors for basic types.
|
||||
// all explicit to avoid accidental typecasting
|
||||
explicit Property(bool v);
|
||||
// TODO: determine if there is actually a byte type,
|
||||
// or if this always means <bool>. 'C' seems to imply <char>,
|
||||
// so possibly the above was intended to represent both.
|
||||
explicit Property(int16_t v);
|
||||
explicit Property(int32_t v);
|
||||
explicit Property(float v);
|
||||
explicit Property(double v);
|
||||
explicit Property(int64_t v);
|
||||
// strings can either be stored as 'R' (raw) or 'S' (string) type
|
||||
explicit Property(const char* c, bool raw=false);
|
||||
explicit Property(const std::string& s, bool raw=false);
|
||||
explicit Property(const std::vector<uint8_t>& r);
|
||||
explicit Property(const std::vector<int32_t>& va);
|
||||
explicit Property(const std::vector<int64_t>& va);
|
||||
explicit Property(const std::vector<double>& va);
|
||||
explicit Property(const std::vector<float>& va);
|
||||
explicit Property(const aiMatrix4x4& vm);
|
||||
|
||||
// this will catch any type not defined above,
|
||||
// so that we don't accidentally convert something we don't want.
|
||||
// for example (const char*) --> (bool)... seriously wtf C++
|
||||
template <class T>
|
||||
explicit Property(T v) : type('X') {
|
||||
static_assert(std::is_void<T>::value, "TRIED TO CREATE FBX PROPERTY WITH UNSUPPORTED TYPE, CHECK YOUR PROPERTY INSTANTIATION");
|
||||
} // note: no line wrap so it appears verbatim on the compiler error
|
||||
|
||||
// the size of this property node in a binary file, in bytes
|
||||
size_t size();
|
||||
|
||||
// write this property node as binary data to the given stream
|
||||
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;
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#endif // AI_FBXEXPORTPROPERTY_H_INC
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file FBXExporter.h
|
||||
* Declares the exporter class to write a scene to an fbx file
|
||||
*/
|
||||
#ifndef AI_FBXEXPORTER_H_INC
|
||||
#define AI_FBXEXPORTER_H_INC
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#include "FBXExportNode.h" // FBX::Node
|
||||
#include "FBXCommon.h" // FBX::TransformInheritance
|
||||
|
||||
#include <assimp/types.h>
|
||||
//#include <assimp/material.h>
|
||||
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||
#include <assimp/Exceptional.h> // DeadlyExportError
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <memory> // shared_ptr
|
||||
#include <sstream> // stringstream
|
||||
|
||||
struct aiScene;
|
||||
struct aiNode;
|
||||
//struct aiMaterial;
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
class IOSystem;
|
||||
class IOStream;
|
||||
class ExportProperties;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Helper class to export a given scene to an FBX file. */
|
||||
// ---------------------------------------------------------------------
|
||||
class FBXExporter
|
||||
{
|
||||
public:
|
||||
/// Constructor for a specific scene to export
|
||||
FBXExporter(const aiScene* pScene, const ExportProperties* pProperties);
|
||||
|
||||
// call one of these methods to export
|
||||
void ExportBinary(const char* pFile, IOSystem* pIOSystem);
|
||||
void ExportAscii(const char* pFile, IOSystem* pIOSystem);
|
||||
|
||||
private:
|
||||
bool binary; // whether current export is in binary or ascii format
|
||||
const aiScene* mScene; // the scene to export
|
||||
const ExportProperties* mProperties; // currently unused
|
||||
std::shared_ptr<IOStream> outfile; // file to write to
|
||||
|
||||
std::vector<FBX::Node> connections; // connection storage
|
||||
|
||||
std::vector<int64_t> mesh_uids;
|
||||
std::vector<int64_t> material_uids;
|
||||
std::map<const aiNode*,int64_t> node_uids;
|
||||
|
||||
// this crude unique-ID system is actually fine
|
||||
int64_t last_uid = 999999;
|
||||
int64_t generate_uid() { return ++last_uid; }
|
||||
|
||||
// binary files have a specific header and footer,
|
||||
// in addition to the actual data
|
||||
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();
|
||||
|
||||
// Methods to write individual sections.
|
||||
// The order here matches the order inside an FBX file.
|
||||
// Each method corresponds to a top-level FBX section,
|
||||
// except WriteHeader which also includes some binary-only sections
|
||||
// and WriteFooter which is binary data only.
|
||||
void WriteHeaderExtension();
|
||||
// WriteFileId(); // binary-only, included in WriteHeader
|
||||
// WriteCreationTime(); // binary-only, included in WriteHeader
|
||||
// WriteCreator(); // binary-only, included in WriteHeader
|
||||
void WriteGlobalSettings();
|
||||
void WriteDocuments();
|
||||
void WriteReferences();
|
||||
void WriteDefinitions();
|
||||
void WriteObjects();
|
||||
void WriteConnections();
|
||||
// WriteTakes(); // deprecated since at least 2015 (fbx 7.4)
|
||||
|
||||
// helpers
|
||||
void WriteAsciiSectionHeader(const std::string& title);
|
||||
void WriteModelNodes(
|
||||
Assimp::StreamWriterLE& s,
|
||||
const aiNode* node,
|
||||
int64_t parent_uid,
|
||||
const std::unordered_set<const aiNode*>& limbnodes
|
||||
);
|
||||
void WriteModelNodes( // usually don't call this directly
|
||||
StreamWriterLE& s,
|
||||
const aiNode* node,
|
||||
int64_t parent_uid,
|
||||
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,
|
||||
std::string name, // "T", "R", or "S"
|
||||
aiVector3D default_value,
|
||||
std::string property_name, // "Lcl Translation" etc
|
||||
int64_t animation_layer_uid,
|
||||
int64_t node_uid
|
||||
);
|
||||
void WriteAnimationCurve(
|
||||
StreamWriterLE& outstream,
|
||||
double default_value,
|
||||
const std::vector<int64_t>& times,
|
||||
const std::vector<float>& values,
|
||||
int64_t curvenode_id,
|
||||
const std::string& property_link // "d|X", "d|Y", etc
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#endif // AI_FBXEXPORTER_H_INC
|
|
@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "FBXProperties.h"
|
||||
#include <assimp/ByteSwapper.h>
|
||||
|
||||
#include <algorithm> // std::transform
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
|
@ -82,11 +84,12 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
|
|||
|
||||
std::string templateName;
|
||||
|
||||
const char* const sh = shading.c_str();
|
||||
if(!strcmp(sh,"phong")) {
|
||||
// lower-case shading because Blender (for example) writes "Phong"
|
||||
std::transform(shading.begin(), shading.end(), shading.begin(), ::tolower);
|
||||
if(shading == "phong") {
|
||||
templateName = "Material.FbxSurfacePhong";
|
||||
}
|
||||
else if(!strcmp(sh,"lambert")) {
|
||||
else if(shading == "lambert") {
|
||||
templateName = "Material.FbxSurfaceLambert";
|
||||
}
|
||||
else {
|
||||
|
@ -299,7 +302,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
|
|||
}
|
||||
|
||||
if(Content) {
|
||||
//this field is ommited when the embedded texture is already loaded, let's ignore if it's not found
|
||||
//this field is omitted when the embedded texture is already loaded, let's ignore if it's not found
|
||||
try {
|
||||
const Token& token = GetRequiredToken(*Content, 0);
|
||||
const char* data = token.begin();
|
||||
|
|
|
@ -79,14 +79,13 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
Geometry::~Geometry()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
const Skin* Geometry::DeformerSkin() const {
|
||||
return skin;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
||||
: Geometry(id, element,name, doc)
|
||||
|
@ -186,9 +185,8 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
MeshGeometry::~MeshGeometry()
|
||||
{
|
||||
|
||||
MeshGeometry::~MeshGeometry() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -308,7 +306,6 @@ void MeshGeometry::ReadLayerElement(const Scope& layerElement)
|
|||
<< type << ", index: " << typedIndex);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source)
|
||||
{
|
||||
|
@ -412,7 +409,6 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Lengthy utility function to read and resolve a FBX vertex data array - that is, the
|
||||
// output is in polygon vertex order. This logic is used for reading normals, UVs, colors,
|
||||
|
@ -428,16 +424,19 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
const std::vector<unsigned int>& mapping_offsets,
|
||||
const std::vector<unsigned int>& mappings)
|
||||
{
|
||||
bool isDirect = ReferenceInformationType == "Direct";
|
||||
bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
|
||||
|
||||
// fall-back to direct data if there is no index data element
|
||||
if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) {
|
||||
isDirect = true;
|
||||
isIndexToDirect = false;
|
||||
}
|
||||
|
||||
// handle permutations of Mapping and Reference type - it would be nice to
|
||||
// deal with this more elegantly and with less redundancy, but right
|
||||
// now it seems unavoidable.
|
||||
if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") {
|
||||
if ( !HasElement( source, indexDataElementName ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (MappingInformationType == "ByVertice" && isDirect) {
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
|
@ -450,14 +449,11 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") {
|
||||
else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
data_out.resize(vertex_count);
|
||||
if ( !HasElement( source, indexDataElementName ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> uvIndices;
|
||||
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
|
||||
|
@ -472,7 +468,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") {
|
||||
else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
|
@ -485,7 +481,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
|
||||
data_out.swap(tempData);
|
||||
}
|
||||
else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") {
|
||||
else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
|
@ -499,9 +495,14 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
return;
|
||||
}
|
||||
|
||||
const T empty;
|
||||
unsigned int next = 0;
|
||||
for(int i : uvIndices) {
|
||||
if (static_cast<size_t>(i) >= tempData.size()) {
|
||||
if ( -1 == i ) {
|
||||
data_out[ next++ ] = empty;
|
||||
continue;
|
||||
}
|
||||
if (static_cast<size_t>(i) >= tempData.size()) {
|
||||
DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
|
||||
}
|
||||
|
||||
|
@ -528,7 +529,6 @@ void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, c
|
|||
m_mappings);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
|
||||
const std::string& MappingInformationType,
|
||||
|
@ -543,7 +543,6 @@ void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope
|
|||
m_mappings);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, const Scope& source,
|
||||
const std::string& MappingInformationType,
|
||||
|
|
|
@ -68,7 +68,6 @@ private:
|
|||
const Skin* skin;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<int> MatIndexArray;
|
||||
|
||||
|
||||
|
@ -95,8 +94,8 @@ public:
|
|||
* if no tangents are specified */
|
||||
const std::vector<aiVector3D>& GetTangents() const;
|
||||
|
||||
/** Get a list of all vertex binormals or an empty array
|
||||
* if no binormals are specified */
|
||||
/** Get a list of all vertex bi-normals or an empty array
|
||||
* if no bi-normals are specified */
|
||||
const std::vector<aiVector3D>& GetBinormals() const;
|
||||
|
||||
/** Return list of faces - each entry denotes a face and specifies
|
||||
|
|
|
@ -42,13 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
* Implements a filter system to filter calls to Exists() and Open()
|
||||
* in order to improve the success rate of file opening ...
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef AI_FILESYSTEMFILTER_H_INC
|
||||
#define AI_FILESYSTEMFILTER_H_INC
|
||||
|
||||
#include "../include/assimp/IOSystem.hpp"
|
||||
#include "../include/assimp/DefaultLogger.hpp"
|
||||
#include "../include/assimp/fast_atof.h"
|
||||
#include "../include/assimp/ParsingUtils.h"
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
@ -64,90 +65,89 @@ class FileSystemFilter : public IOSystem
|
|||
public:
|
||||
/** Constructor. */
|
||||
FileSystemFilter(const std::string& file, IOSystem* old)
|
||||
: wrapped (old)
|
||||
, src_file (file)
|
||||
, sep(wrapped->getOsSeparator())
|
||||
{
|
||||
ai_assert(NULL != wrapped);
|
||||
: mWrapped (old)
|
||||
, mSrc_file(file)
|
||||
, sep(mWrapped->getOsSeparator()) {
|
||||
ai_assert(nullptr != mWrapped);
|
||||
|
||||
// Determine base directory
|
||||
base = src_file;
|
||||
mBase = mSrc_file;
|
||||
std::string::size_type ss2;
|
||||
if (std::string::npos != (ss2 = base.find_last_of("\\/"))) {
|
||||
base.erase(ss2,base.length()-ss2);
|
||||
}
|
||||
else {
|
||||
base = "";
|
||||
// return;
|
||||
if (std::string::npos != (ss2 = mBase.find_last_of("\\/"))) {
|
||||
mBase.erase(ss2,mBase.length()-ss2);
|
||||
} else {
|
||||
mBase = "";
|
||||
}
|
||||
|
||||
// make sure the directory is terminated properly
|
||||
char s;
|
||||
|
||||
if (base.length() == 0) {
|
||||
base = ".";
|
||||
base += getOsSeparator();
|
||||
}
|
||||
else if ((s = *(base.end()-1)) != '\\' && s != '/') {
|
||||
base += getOsSeparator();
|
||||
if ( mBase.empty() ) {
|
||||
mBase = ".";
|
||||
mBase += getOsSeparator();
|
||||
} else if ((s = *(mBase.end()-1)) != '\\' && s != '/') {
|
||||
mBase += getOsSeparator();
|
||||
}
|
||||
|
||||
DefaultLogger::get()->info("Import root directory is \'" + base + "\'");
|
||||
DefaultLogger::get()->info("Import root directory is \'" + mBase + "\'");
|
||||
}
|
||||
|
||||
/** Destructor. */
|
||||
~FileSystemFilter()
|
||||
{
|
||||
// haha
|
||||
~FileSystemFilter() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Tests for the existence of a file at the given path. */
|
||||
bool Exists( const char* pFile) const
|
||||
{
|
||||
bool Exists( const char* pFile) const {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
|
||||
std::string tmp = pFile;
|
||||
|
||||
// Currently this IOSystem is also used to open THE ONE FILE.
|
||||
if (tmp != src_file) {
|
||||
if (tmp != mSrc_file) {
|
||||
BuildPath(tmp);
|
||||
Cleanup(tmp);
|
||||
}
|
||||
|
||||
return wrapped->Exists(tmp);
|
||||
return mWrapped->Exists(tmp);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns the directory separator. */
|
||||
char getOsSeparator() const
|
||||
{
|
||||
char getOsSeparator() const {
|
||||
return sep;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Open a new file with a given path. */
|
||||
IOStream* Open( const char* pFile, const char* pMode = "rb")
|
||||
{
|
||||
ai_assert(pFile);
|
||||
ai_assert(pMode);
|
||||
IOStream* Open( const char* pFile, const char* pMode = "rb") {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
if ( nullptr == pFile || nullptr == pMode ) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ai_assert( nullptr != pFile );
|
||||
ai_assert( nullptr != pMode );
|
||||
|
||||
// First try the unchanged path
|
||||
IOStream* s = wrapped->Open(pFile,pMode);
|
||||
IOStream* s = mWrapped->Open(pFile,pMode);
|
||||
|
||||
if (!s) {
|
||||
if (nullptr == s) {
|
||||
std::string tmp = pFile;
|
||||
|
||||
// Try to convert between absolute and relative paths
|
||||
BuildPath(tmp);
|
||||
s = wrapped->Open(tmp,pMode);
|
||||
s = mWrapped->Open(tmp,pMode);
|
||||
|
||||
if (!s) {
|
||||
if (nullptr == s) {
|
||||
// Finally, look for typical issues with paths
|
||||
// and try to correct them. This is our last
|
||||
// resort.
|
||||
tmp = pFile;
|
||||
Cleanup(tmp);
|
||||
BuildPath(tmp);
|
||||
s = wrapped->Open(tmp,pMode);
|
||||
s = mWrapped->Open(tmp,pMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,27 +156,75 @@ public:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
/** Closes the given file and releases all resources associated with it. */
|
||||
void Close( IOStream* pFile)
|
||||
{
|
||||
return wrapped->Close(pFile);
|
||||
void Close( IOStream* pFile) {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
return mWrapped->Close(pFile);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Compare two paths */
|
||||
bool ComparePaths (const char* one, const char* second) const
|
||||
{
|
||||
return wrapped->ComparePaths (one,second);
|
||||
bool ComparePaths (const char* one, const char* second) const {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
return mWrapped->ComparePaths (one,second);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Pushes a new directory onto the directory stack. */
|
||||
bool PushDirectory(const std::string &path ) {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
return mWrapped->PushDirectory(path);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns the top directory from the stack. */
|
||||
const std::string &CurrentDirectory() const {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
return mWrapped->CurrentDirectory();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns the number of directories stored on the stack. */
|
||||
size_t StackSize() const {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
return mWrapped->StackSize();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Pops the top directory from the stack. */
|
||||
bool PopDirectory() {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
return mWrapped->PopDirectory();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Creates an new directory at the given path. */
|
||||
bool CreateDirectory(const std::string &path) {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
return mWrapped->CreateDirectory(path);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Will change the current directory to the given path. */
|
||||
bool ChangeDirectory(const std::string &path) {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
return mWrapped->ChangeDirectory(path);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Delete file. */
|
||||
bool DeleteFile(const std::string &file) {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
return mWrapped->DeleteFile(file);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Build a valid path from a given relative or absolute path.
|
||||
*/
|
||||
void BuildPath (std::string& in) const
|
||||
{
|
||||
void BuildPath (std::string& in) const {
|
||||
ai_assert( nullptr != mWrapped );
|
||||
// if we can already access the file, great.
|
||||
if (in.length() < 3 || wrapped->Exists(in)) {
|
||||
if (in.length() < 3 || mWrapped->Exists(in)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -184,8 +232,8 @@ private:
|
|||
if (in[1] != ':') {
|
||||
|
||||
// append base path and try
|
||||
const std::string tmp = base + in;
|
||||
if (wrapped->Exists(tmp)) {
|
||||
const std::string tmp = mBase + in;
|
||||
if (mWrapped->Exists(tmp)) {
|
||||
in = tmp;
|
||||
return;
|
||||
}
|
||||
|
@ -207,7 +255,7 @@ private:
|
|||
std::string::size_type last_dirsep = std::string::npos;
|
||||
|
||||
while(true) {
|
||||
tmp = base;
|
||||
tmp = mBase;
|
||||
tmp += sep;
|
||||
|
||||
std::string::size_type dirsep = in.rfind('/', last_dirsep);
|
||||
|
@ -223,7 +271,7 @@ private:
|
|||
last_dirsep = dirsep-1;
|
||||
|
||||
tmp += in.substr(dirsep+1, in.length()-pos);
|
||||
if (wrapped->Exists(tmp)) {
|
||||
if (mWrapped->Exists(tmp)) {
|
||||
in = tmp;
|
||||
return;
|
||||
}
|
||||
|
@ -236,15 +284,14 @@ private:
|
|||
// -------------------------------------------------------------------
|
||||
/** Cleanup the given path
|
||||
*/
|
||||
void Cleanup (std::string& in) const
|
||||
{
|
||||
char last = 0;
|
||||
void Cleanup (std::string& in) const {
|
||||
if(in.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove a very common issue when we're parsing file names: spaces at the
|
||||
// beginning of the path.
|
||||
char last = 0;
|
||||
std::string::iterator it = in.begin();
|
||||
while (IsSpaceOrNewLine( *it ))++it;
|
||||
if (it != in.begin()) {
|
||||
|
@ -274,9 +321,7 @@ private:
|
|||
it = in.erase(it);
|
||||
--it;
|
||||
}
|
||||
}
|
||||
else if (*it == '%' && in.end() - it > 2) {
|
||||
|
||||
} else if (*it == '%' && in.end() - it > 2) {
|
||||
// Hex sequence in URIs
|
||||
if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) {
|
||||
*it = HexOctetToDecimal(&*it);
|
||||
|
@ -290,8 +335,8 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
IOSystem* wrapped;
|
||||
std::string src_file, base;
|
||||
IOSystem *mWrapped;
|
||||
std::string mSrc_file, mBase;
|
||||
char sep;
|
||||
};
|
||||
|
||||
|
|
|
@ -54,6 +54,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
using namespace Assimp;
|
||||
|
||||
//remove mesh at position 'index' from the scene
|
||||
static void removeMesh(aiScene* pScene, unsigned const index);
|
||||
//correct node indices to meshes and remove references to deleted mesh
|
||||
static void updateSceneGraph(aiNode* pNode, unsigned const index);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
FindDegeneratesProcess::FindDegeneratesProcess()
|
||||
|
@ -85,11 +90,50 @@ void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void FindDegeneratesProcess::Execute( aiScene* pScene) {
|
||||
DefaultLogger::get()->debug("FindDegeneratesProcess begin");
|
||||
ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin");
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
|
||||
ExecuteOnMesh( pScene->mMeshes[ i ] );
|
||||
if (ExecuteOnMesh(pScene->mMeshes[i])) {
|
||||
removeMesh(pScene, i);
|
||||
--i; //the current i is removed, do not skip the next one
|
||||
}
|
||||
}
|
||||
ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished");
|
||||
}
|
||||
|
||||
static void removeMesh(aiScene* pScene, unsigned const index) {
|
||||
//we start at index and copy the pointers one position forward
|
||||
//save the mesh pointer to delete it later
|
||||
auto delete_me = pScene->mMeshes[index];
|
||||
for (unsigned i = index; i < pScene->mNumMeshes - 1; ++i) {
|
||||
pScene->mMeshes[i] = pScene->mMeshes[i+1];
|
||||
}
|
||||
pScene->mMeshes[pScene->mNumMeshes - 1] = nullptr;
|
||||
--(pScene->mNumMeshes);
|
||||
delete delete_me;
|
||||
|
||||
//removing a mesh also requires updating all references to it in the scene graph
|
||||
updateSceneGraph(pScene->mRootNode, index);
|
||||
}
|
||||
|
||||
static void updateSceneGraph(aiNode* pNode, unsigned const index) {
|
||||
for (unsigned i = 0; i < pNode->mNumMeshes; ++i) {
|
||||
if (pNode->mMeshes[i] > index) {
|
||||
--(pNode->mMeshes[i]);
|
||||
continue;
|
||||
}
|
||||
if (pNode->mMeshes[i] == index) {
|
||||
for (unsigned j = i; j < pNode->mNumMeshes -1; ++j) {
|
||||
pNode->mMeshes[j] = pNode->mMeshes[j+1];
|
||||
}
|
||||
--(pNode->mNumMeshes);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//recurse to all children
|
||||
for (unsigned i = 0; i < pNode->mNumChildren; ++i) {
|
||||
updateSceneGraph(pNode->mChildren[i], index);
|
||||
}
|
||||
DefaultLogger::get()->debug("FindDegeneratesProcess finished");
|
||||
}
|
||||
|
||||
static ai_real heron( ai_real a, ai_real b, ai_real c ) {
|
||||
|
@ -125,7 +169,7 @@ static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported mesh
|
||||
void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
|
||||
bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
|
||||
mesh->mPrimitiveTypes = 0;
|
||||
|
||||
std::vector<bool> remove_me;
|
||||
|
@ -161,7 +205,7 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
|
|||
|
||||
// NOTE: we set the removed vertex index to an unique value
|
||||
// to make sure the developer gets notified when his
|
||||
// application attemps to access this data.
|
||||
// application attempts to access this data.
|
||||
face.mIndices[ face.mNumIndices ] = 0xdeadbeef;
|
||||
|
||||
if(first) {
|
||||
|
@ -227,33 +271,28 @@ evil_jump_outside:
|
|||
if (&face_src != &face_dest) {
|
||||
// clear source
|
||||
face_src.mNumIndices = 0;
|
||||
face_src.mIndices = NULL;
|
||||
face_src.mIndices = nullptr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Otherwise delete it if we don't need this face
|
||||
delete[] face_src.mIndices;
|
||||
face_src.mIndices = NULL;
|
||||
face_src.mIndices = nullptr;
|
||||
face_src.mNumIndices = 0;
|
||||
}
|
||||
}
|
||||
// Just leave the rest of the array unreferenced, we don't care for now
|
||||
mesh->mNumFaces = n;
|
||||
if (!mesh->mNumFaces) {
|
||||
// WTF!?
|
||||
// OK ... for completeness and because I'm not yet tired,
|
||||
// let's write code that willl hopefully never be called
|
||||
// (famous last words)
|
||||
|
||||
// OK ... bad idea.
|
||||
throw DeadlyImportError("Mesh is empty after removal of degenerated primitives ... WTF!?");
|
||||
//The whole mesh consists of degenerated faces
|
||||
//signal upward, that this mesh should be deleted.
|
||||
ASSIMP_LOG_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (deg && !DefaultLogger::isNullLogger())
|
||||
{
|
||||
char s[64];
|
||||
ASSIMP_itoa10(s,deg);
|
||||
DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives");
|
||||
if (deg && !DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,8 @@ public:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
// Execute step on a given mesh
|
||||
void ExecuteOnMesh( aiMesh* mesh);
|
||||
///@returns true if the current mesh should be deleted, false otherwise
|
||||
bool ExecuteOnMesh( aiMesh* mesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/// @brief Enable the instant removal of degenerated primitives
|
||||
|
|
|
@ -119,7 +119,7 @@ void UpdateMeshIndices(aiNode* node, unsigned int* lookup)
|
|||
// Executes the post processing step on the given imported data.
|
||||
void FindInstancesProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("FindInstancesProcess begin");
|
||||
ASSIMP_LOG_DEBUG("FindInstancesProcess begin");
|
||||
if (pScene->mNumMeshes) {
|
||||
|
||||
// use a pseudo hash for all meshes in the scene to quickly find
|
||||
|
@ -267,13 +267,11 @@ void FindInstancesProcess::Execute( aiScene* pScene)
|
|||
|
||||
// write to log
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
|
||||
char buffer[512];
|
||||
::ai_snprintf(buffer,512,"FindInstancesProcess finished. Found %i instances",pScene->mNumMeshes-numMeshesOut);
|
||||
DefaultLogger::get()->info(buffer);
|
||||
ASSIMP_LOG_INFO_F( "FindInstancesProcess finished. Found ", (pScene->mNumMeshes - numMeshesOut), " instances" );
|
||||
}
|
||||
pScene->mNumMeshes = numMeshesOut;
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("FindInstancesProcess finished. No instanced meshes found");
|
||||
}
|
||||
else DefaultLogger::get()->debug("FindInstancesProcess finished. No instanced meshes found");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,9 +60,9 @@ namespace Assimp {
|
|||
* @param in Input mesh
|
||||
* @return Hash.
|
||||
*/
|
||||
inline uint64_t GetMeshHash(aiMesh* in)
|
||||
{
|
||||
ai_assert(NULL != in);
|
||||
inline
|
||||
uint64_t GetMeshHash(aiMesh* in) {
|
||||
ai_assert(nullptr != in);
|
||||
|
||||
// ... get an unique value representing the vertex format of the mesh
|
||||
const unsigned int fhash = GetMeshVFormatUnique(in);
|
||||
|
@ -78,14 +78,14 @@ inline uint64_t GetMeshHash(aiMesh* in)
|
|||
/** @brief Perform a component-wise comparison of two arrays
|
||||
*
|
||||
* @param first First array
|
||||
* @param second Second aray
|
||||
* @param second Second array
|
||||
* @param size Size of both arrays
|
||||
* @param e Epsilon
|
||||
* @return true if the arrays are identical
|
||||
*/
|
||||
inline bool CompareArrays(const aiVector3D* first, const aiVector3D* second,
|
||||
unsigned int size, float e)
|
||||
{
|
||||
inline
|
||||
bool CompareArrays(const aiVector3D* first, const aiVector3D* second,
|
||||
unsigned int size, float e) {
|
||||
for (const aiVector3D* end = first+size; first != end; ++first,++second) {
|
||||
if ( (*first - *second).SquareLength() >= e)
|
||||
return false;
|
||||
|
|
|
@ -118,7 +118,7 @@ void UpdateMeshReferences(aiNode* node, const std::vector<unsigned int>& meshMap
|
|||
// Executes the post processing step on the given imported data.
|
||||
void FindInvalidDataProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("FindInvalidDataProcess begin");
|
||||
ASSIMP_LOG_DEBUG("FindInvalidDataProcess begin");
|
||||
|
||||
bool out = false;
|
||||
std::vector<unsigned int> meshMapping(pScene->mNumMeshes);
|
||||
|
@ -163,9 +163,10 @@ void FindInvalidDataProcess::Execute( aiScene* pScene)
|
|||
pScene->mNumMeshes = real;
|
||||
}
|
||||
|
||||
DefaultLogger::get()->info("FindInvalidDataProcess finished. Found issues ...");
|
||||
ASSIMP_LOG_INFO("FindInvalidDataProcess finished. Found issues ...");
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("FindInvalidDataProcess finished. Everything seems to be OK.");
|
||||
}
|
||||
else DefaultLogger::get()->debug("FindInvalidDataProcess finished. Everything seems to be OK.");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -212,8 +213,7 @@ inline bool ProcessArray(T*& in, unsigned int num,const char* name,
|
|||
{
|
||||
const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero);
|
||||
if (err) {
|
||||
DefaultLogger::get()->error(std::string("FindInvalidDataProcess fails on mesh ") + name + ": " + err);
|
||||
|
||||
ASSIMP_LOG_ERROR_F( "FindInvalidDataProcess fails on mesh ", name, ": ", err);
|
||||
delete[] in;
|
||||
in = NULL;
|
||||
return true;
|
||||
|
@ -332,7 +332,7 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
|
|||
i = 1;
|
||||
}
|
||||
if (1 == i)
|
||||
DefaultLogger::get()->warn("Simplified dummy tracks with just one key");
|
||||
ASSIMP_LOG_WARN("Simplified dummy tracks with just one key");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -354,7 +354,7 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
|
|||
|
||||
// Process vertex positions
|
||||
if (pMesh->mVertices && ProcessArray(pMesh->mVertices, pMesh->mNumVertices, "positions", dirtyMask)) {
|
||||
DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions");
|
||||
ASSIMP_LOG_ERROR("Deleting mesh: Unable to continue without vertex positions");
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
|
|
@ -82,28 +82,35 @@ bool FixInfacingNormalsProcess::IsActive( unsigned int pFlags) const
|
|||
// Executes the post processing step on the given imported data.
|
||||
void FixInfacingNormalsProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("FixInfacingNormalsProcess begin");
|
||||
ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess begin");
|
||||
|
||||
bool bHas = false;
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
|
||||
if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
|
||||
bool bHas( false );
|
||||
for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
|
||||
if (ProcessMesh(pScene->mMeshes[a], a)) {
|
||||
bHas = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bHas)
|
||||
DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. Found issues.");
|
||||
else DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. No changes to the scene.");
|
||||
if (bHas) {
|
||||
ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess finished. Found issues.");
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess finished. No changes to the scene.");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Apply the step to the mesh
|
||||
bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
|
||||
{
|
||||
ai_assert(NULL != pcMesh);
|
||||
ai_assert(nullptr != pcMesh);
|
||||
|
||||
// Nothing to do if there are no model normals
|
||||
if (!pcMesh->HasNormals())return false;
|
||||
if (!pcMesh->HasNormals()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute the bounding box of both the model vertices + normals and
|
||||
// the umodified model vertices. Then check whether the first BB
|
||||
// the unmodified model vertices. Then check whether the first BB
|
||||
// is smaller than the second. In this case we can assume that the
|
||||
// normals need to be flipped, although there are a few special cases ..
|
||||
// convex, concave, planar models ...
|
||||
|
@ -155,14 +162,9 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
|
|||
if (fDelta1_z < 0.05f * std::sqrt( fDelta1_y * fDelta1_x ))return false;
|
||||
|
||||
// now compare the volumes of the bounding boxes
|
||||
if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) <
|
||||
std::fabs(fDelta1_x * fDelta1_yz))
|
||||
{
|
||||
if (!DefaultLogger::isNullLogger())
|
||||
{
|
||||
char buffer[128]; // should be sufficiently large
|
||||
ai_snprintf(buffer,128,"Mesh %u: Normals are facing inwards (or the mesh is planar)",index);
|
||||
DefaultLogger::get()->info(buffer);
|
||||
if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) < std::fabs(fDelta1_x * fDelta1_yz)) {
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_INFO_F("Mesh ", index, ": Normals are facing inwards (or the mesh is planar)", index);
|
||||
}
|
||||
|
||||
// Invert normals
|
||||
|
|
|
@ -72,16 +72,15 @@ GenFaceNormalsProcess::~GenFaceNormalsProcess()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const {
|
||||
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
|
||||
return (pFlags & aiProcess_GenNormals) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void GenFaceNormalsProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("GenFaceNormalsProcess begin");
|
||||
void GenFaceNormalsProcess::Execute( aiScene* pScene) {
|
||||
ASSIMP_LOG_DEBUG("GenFaceNormalsProcess begin");
|
||||
|
||||
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
|
||||
throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
|
||||
|
@ -94,11 +93,12 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene)
|
|||
}
|
||||
}
|
||||
if (bHas) {
|
||||
DefaultLogger::get()->info("GenFaceNormalsProcess finished. "
|
||||
ASSIMP_LOG_INFO("GenFaceNormalsProcess finished. "
|
||||
"Face normals have been calculated");
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("GenFaceNormalsProcess finished. "
|
||||
"Normals are already there");
|
||||
}
|
||||
else DefaultLogger::get()->debug("GenFaceNormalsProcess finished. "
|
||||
"Normals are already there");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -106,14 +106,15 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene)
|
|||
bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
|
||||
{
|
||||
if (NULL != pMesh->mNormals) {
|
||||
return false;
|
||||
if (force_) delete[] pMesh->mNormals;
|
||||
else return false;
|
||||
}
|
||||
|
||||
// If the mesh consists of lines and/or points but not of
|
||||
// triangles or higher-order polygons the normal vectors
|
||||
// are undefined.
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
|
||||
DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes");
|
||||
ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -135,7 +136,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
|
|||
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
|
||||
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i) {
|
||||
pMesh->mNormals[face.mIndices[i]] = vNor;
|
||||
|
|
|
@ -78,7 +78,8 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
bool GenMeshFaceNormals (aiMesh* pcMesh);
|
||||
bool GenMeshFaceNormals(aiMesh* pcMesh);
|
||||
mutable bool force_ = false;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -72,6 +72,7 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() {
|
|||
// Returns whether the processing step is present in the given flag field.
|
||||
bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
|
||||
return (pFlags & aiProcess_GenSmoothNormals) != 0;
|
||||
}
|
||||
|
||||
|
@ -88,39 +89,42 @@ void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
|
|||
// Executes the post processing step on the given imported data.
|
||||
void GenVertexNormalsProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("GenVertexNormalsProcess begin");
|
||||
ASSIMP_LOG_DEBUG("GenVertexNormalsProcess begin");
|
||||
|
||||
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
|
||||
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
|
||||
throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
|
||||
}
|
||||
|
||||
bool bHas = false;
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
|
||||
{
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
|
||||
if(GenMeshVertexNormals( pScene->mMeshes[a],a))
|
||||
bHas = true;
|
||||
}
|
||||
|
||||
if (bHas) {
|
||||
DefaultLogger::get()->info("GenVertexNormalsProcess finished. "
|
||||
ASSIMP_LOG_INFO("GenVertexNormalsProcess finished. "
|
||||
"Vertex normals have been calculated");
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("GenVertexNormalsProcess finished. "
|
||||
"Normals are already there");
|
||||
}
|
||||
else DefaultLogger::get()->debug("GenVertexNormalsProcess finished. "
|
||||
"Normals are already there");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
|
||||
{
|
||||
if (NULL != pMesh->mNormals)
|
||||
return false;
|
||||
if (NULL != pMesh->mNormals) {
|
||||
if (force_) delete[] pMesh->mNormals;
|
||||
else return false;
|
||||
}
|
||||
|
||||
// If the mesh consists of lines and/or points but not of
|
||||
// triangles or higher-order polygons the normal vectors
|
||||
// are undefined.
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
|
||||
{
|
||||
DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes");
|
||||
ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -145,7 +149,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
|||
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1));
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
|
||||
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i) {
|
||||
pMesh->mNormals[face.mIndices[i]] = vNor;
|
||||
|
@ -213,17 +217,15 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
|||
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
|
||||
|
||||
aiVector3D vr = pMesh->mNormals[i];
|
||||
ai_real vrlen = vr.Length();
|
||||
|
||||
aiVector3D pcNor;
|
||||
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
|
||||
aiVector3D v = pMesh->mNormals[verticesFound[a]];
|
||||
|
||||
// check whether the angle between the two normals is not too large
|
||||
// HACK: if v.x is qnan the dot product will become qnan, too
|
||||
// therefore the comparison against fLimit should be false
|
||||
// in every case.
|
||||
if (v * vr >= fLimit * vrlen * v.Length())
|
||||
// Check whether the angle between the two normals is not too large.
|
||||
// Skip the angle check on our own normal to avoid false negatives
|
||||
// (v*v is not guaranteed to be 1.0 for all unit vectors v)
|
||||
if (is_not_qnan(v.x) && (verticesFound[a] == i || (v * vr >= fLimit)))
|
||||
pcNor += v;
|
||||
}
|
||||
pcNew[i] = pcNor.NormalizeSafe();
|
||||
|
|
|
@ -107,6 +107,7 @@ private:
|
|||
|
||||
/** Configuration option: maximum smoothing angle, in radians*/
|
||||
ai_real configMaxAngle;
|
||||
mutable bool force_ = false;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -141,21 +141,21 @@ void HMPImporter::InternReadFile( const std::string& pFile,
|
|||
if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
|
||||
AI_HMP_MAGIC_NUMBER_BE_4 == iMagic)
|
||||
{
|
||||
DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A4, magic word is HMP4");
|
||||
ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A4, magic word is HMP4");
|
||||
InternReadFile_HMP4();
|
||||
}
|
||||
// HMP5 format
|
||||
else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
|
||||
AI_HMP_MAGIC_NUMBER_BE_5 == iMagic)
|
||||
{
|
||||
DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A5, magic word is HMP5");
|
||||
ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A5, magic word is HMP5");
|
||||
InternReadFile_HMP5();
|
||||
}
|
||||
// HMP7 format
|
||||
else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
|
||||
AI_HMP_MAGIC_NUMBER_BE_7 == iMagic)
|
||||
{
|
||||
DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A7, magic word is HMP7");
|
||||
ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A7, magic word is HMP7");
|
||||
InternReadFile_HMP7();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -100,26 +100,22 @@ IRRImporter::~IRRImporter()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
||||
{
|
||||
/* NOTE: A simple check for the file extension is not enough
|
||||
* here. Irrmesh and irr are easy, but xml is too generic
|
||||
* and could be collada, too. So we need to open the file and
|
||||
* search for typical tokens.
|
||||
*/
|
||||
bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
|
||||
const std::string extension = GetExtension(pFile);
|
||||
|
||||
if (extension == "irr")return true;
|
||||
else if (extension == "xml" || checkSig)
|
||||
{
|
||||
if ( extension == "irr" ) {
|
||||
return true;
|
||||
} else if (extension == "xml" || checkSig) {
|
||||
/* If CanRead() is called in order to check whether we
|
||||
* support a specific file extension in general pIOHandler
|
||||
* might be NULL and it's our duty to return true here.
|
||||
*/
|
||||
if (!pIOHandler)return true;
|
||||
if ( nullptr == pIOHandler ) {
|
||||
return true;
|
||||
}
|
||||
const char* tokens[] = {"irr_scene"};
|
||||
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -135,7 +131,7 @@ void IRRImporter::SetupProperties(const Importer* pImp)
|
|||
// read the output frame rate of all node animation channels
|
||||
fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS,100);
|
||||
if (fps < 10.) {
|
||||
DefaultLogger::get()->error("IRR: Invalid FPS configuration");
|
||||
ASSIMP_LOG_ERROR("IRR: Invalid FPS configuration");
|
||||
fps = 100;
|
||||
}
|
||||
|
||||
|
@ -285,7 +281,7 @@ void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
|
|||
return;
|
||||
}
|
||||
else if (inmaterials.size() > 1) {
|
||||
DefaultLogger::get()->info("IRR: Skipping additional materials");
|
||||
ASSIMP_LOG_INFO("IRR: Skipping additional materials");
|
||||
}
|
||||
|
||||
mesh->mMaterialIndex = (unsigned int)materials.size();
|
||||
|
@ -323,17 +319,18 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
|
|||
if (root->animators.empty()) {
|
||||
return;
|
||||
}
|
||||
unsigned int total = 0;
|
||||
unsigned int total( 0 );
|
||||
for (std::list<Animator>::iterator it = root->animators.begin();it != root->animators.end(); ++it) {
|
||||
if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) {
|
||||
DefaultLogger::get()->warn("IRR: Skipping unknown or unsupported animator");
|
||||
ASSIMP_LOG_WARN("IRR: Skipping unknown or unsupported animator");
|
||||
continue;
|
||||
}
|
||||
++total;
|
||||
}
|
||||
if (!total)return;
|
||||
else if (1 == total) {
|
||||
DefaultLogger::get()->warn("IRR: Adding dummy nodes to simulate multiple animators");
|
||||
if (!total) {
|
||||
return;
|
||||
} else if (1 == total) {
|
||||
ASSIMP_LOG_WARN("IRR: Adding dummy nodes to simulate multiple animators");
|
||||
}
|
||||
|
||||
// NOTE: 1 tick == i millisecond
|
||||
|
@ -522,9 +519,9 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
|
|||
const int size = (int)in.splineKeys.size();
|
||||
if (!size) {
|
||||
// We have no point in the spline. That's bad. Really bad.
|
||||
DefaultLogger::get()->warn("IRR: Spline animators with no points defined");
|
||||
ASSIMP_LOG_WARN("IRR: Spline animators with no points defined");
|
||||
|
||||
delete anim;anim = NULL;
|
||||
delete anim;anim = nullptr;
|
||||
break;
|
||||
}
|
||||
else if (size == 1) {
|
||||
|
@ -676,7 +673,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
|
|||
// graph we're currently building
|
||||
aiScene* scene = batch.GetImport(root->id);
|
||||
if (!scene) {
|
||||
DefaultLogger::get()->error("IRR: Unable to load external file: " + root->meshPath);
|
||||
ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath);
|
||||
break;
|
||||
}
|
||||
attach.push_back(AttachmentInfo(scene,rootOut));
|
||||
|
@ -687,7 +684,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
|
|||
// should be equal. If they are not, we can impossibly
|
||||
// do this ...
|
||||
if (root->materials.size() != (unsigned int)scene->mNumMaterials) {
|
||||
DefaultLogger::get()->warn("IRR: Failed to match imported materials "
|
||||
ASSIMP_LOG_WARN("IRR: Failed to match imported materials "
|
||||
"with the materials found in the IRR scene file");
|
||||
|
||||
break;
|
||||
|
@ -726,7 +723,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
|
|||
}
|
||||
}
|
||||
if (bdo) {
|
||||
DefaultLogger::get()->info("IRR: Replacing mesh vertex alpha with common opacity");
|
||||
ASSIMP_LOG_INFO("IRR: Replacing mesh vertex alpha with common opacity");
|
||||
|
||||
for (unsigned int a = 0; a < mesh->mNumVertices;++a)
|
||||
mesh->mColors[0][a].a = 1.f;
|
||||
|
@ -810,7 +807,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
|
|||
{
|
||||
// A skybox is defined by six materials
|
||||
if (root->materials.size() < 6) {
|
||||
DefaultLogger::get()->error("IRR: There should be six materials for a skybox");
|
||||
ASSIMP_LOG_ERROR("IRR: There should be six materials for a skybox");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -827,7 +824,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
|
|||
// for IRR skyboxes. We add a 'IRR.SkyBox_' prefix to the node.
|
||||
// *************************************************************
|
||||
root->name = "IRR.SkyBox_" + root->name;
|
||||
DefaultLogger::get()->info("IRR: Loading skybox, this will "
|
||||
ASSIMP_LOG_INFO("IRR: Loading skybox, this will "
|
||||
"require special handling to be displayed correctly");
|
||||
}
|
||||
break;
|
||||
|
@ -835,7 +832,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
|
|||
case Node::TERRAIN:
|
||||
{
|
||||
// to support terrains, we'd need to have a texture decoder
|
||||
DefaultLogger::get()->error("IRR: Unsupported node - TERRAIN");
|
||||
ASSIMP_LOG_ERROR("IRR: Unsupported node - TERRAIN");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1014,11 +1011,11 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
else if (!ASSIMP_stricmp(sz,"billBoard")) {
|
||||
// We don't support billboards, so ignore them
|
||||
DefaultLogger::get()->error("IRR: Billboards are not supported by Assimp");
|
||||
ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp");
|
||||
nd = new Node(Node::DUMMY);
|
||||
}
|
||||
else {
|
||||
DefaultLogger::get()->warn("IRR: Found unknown node: " + std::string(sz));
|
||||
ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(sz));
|
||||
|
||||
/* We skip the contents of nodes we don't know.
|
||||
* We parse the transformation and all animators
|
||||
|
@ -1045,7 +1042,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
*/
|
||||
if (!curNode) {
|
||||
#if 0
|
||||
DefaultLogger::get()->error("IRR: Encountered <attributes> element, but "
|
||||
ASSIMP_LOG_ERROR("IRR: Encountered <attributes> element, but "
|
||||
"there is no node active");
|
||||
#endif
|
||||
continue;
|
||||
|
@ -1273,7 +1270,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
lights.pop_back();
|
||||
curNode->type = Node::DUMMY;
|
||||
|
||||
DefaultLogger::get()->error("Ignoring light of unknown type: " + prop.value);
|
||||
ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value);
|
||||
}
|
||||
}
|
||||
else if ((prop.name == "Mesh" && Node::MESH == curNode->type) ||
|
||||
|
@ -1281,7 +1278,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
{
|
||||
/* This is the file name of the mesh - either
|
||||
* animated or not. We need to make sure we setup
|
||||
* the correct postprocessing settings here.
|
||||
* the correct post-processing settings here.
|
||||
*/
|
||||
unsigned int pp = 0;
|
||||
BatchLoader::PropertyMap map;
|
||||
|
@ -1303,7 +1300,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
const std::string extension = GetExtension(prop.value);
|
||||
if ("irr" == extension) {
|
||||
DefaultLogger::get()->error("IRR: Can't load another IRR file recursively");
|
||||
ASSIMP_LOG_ERROR("IRR: Can't load another IRR file recursively");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1327,7 +1324,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
curAnim->type = Animator::FOLLOW_SPLINE;
|
||||
}
|
||||
else {
|
||||
DefaultLogger::get()->warn("IRR: Ignoring unknown animator: "
|
||||
ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: "
|
||||
+ prop.value);
|
||||
|
||||
curAnim->type = Animator::UNKNOWN;
|
||||
|
@ -1352,7 +1349,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
// back in the node hierarchy
|
||||
if (!curParent) {
|
||||
curParent = root;
|
||||
DefaultLogger::get()->error("IRR: Too many closing <node> elements");
|
||||
ASSIMP_LOG_ERROR("IRR: Too many closing <node> elements");
|
||||
}
|
||||
else curParent = curParent->parent;
|
||||
}
|
||||
|
@ -1373,15 +1370,14 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
}
|
||||
|
||||
/* Now iterate through all cameras and compute their final (horizontal) FOV
|
||||
*/
|
||||
// Now iterate through all cameras and compute their final (horizontal) FOV
|
||||
for (aiCamera *cam : cameras) {
|
||||
|
||||
// screen aspect could be missing
|
||||
if (cam->mAspect) {
|
||||
cam->mHorizontalFOV *= cam->mAspect;
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("IRR: Camera aspect is not given, can't compute horizontal FOV");
|
||||
}
|
||||
else DefaultLogger::get()->warn("IRR: Camera aspect is not given, can't compute horizontal FOV");
|
||||
}
|
||||
|
||||
batch.LoadAll();
|
||||
|
@ -1476,7 +1472,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
* models from external files
|
||||
*/
|
||||
if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
|
||||
DefaultLogger::get()->warn("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE");
|
||||
ASSIMP_LOG_WARN("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE");
|
||||
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) {
|
||||
// end of previous buffer. A material and a mesh should be there
|
||||
if ( !curMat || !curMesh) {
|
||||
DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
|
||||
ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material");
|
||||
releaseMaterial( &curMat );
|
||||
releaseMesh( &curMesh );
|
||||
} else {
|
||||
|
@ -197,7 +197,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
if (!ASSIMP_stricmp(reader->getNodeName(),"material")) {
|
||||
if (curMat) {
|
||||
DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
|
||||
ASSIMP_LOG_WARN("IRRMESH: Only one material description per buffer, please");
|
||||
releaseMaterial( &curMat );
|
||||
}
|
||||
curMat = ParseMaterial(curMatFlags);
|
||||
|
@ -208,7 +208,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
if (!num) {
|
||||
// This is possible ... remove the mesh from the list and skip further reading
|
||||
DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices");
|
||||
ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero vertices");
|
||||
|
||||
releaseMaterial( &curMat );
|
||||
releaseMesh( &curMesh );
|
||||
|
@ -255,7 +255,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
else if (ASSIMP_stricmp("standard", t)) {
|
||||
releaseMaterial( &curMat );
|
||||
DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
|
||||
ASSIMP_LOG_WARN("IRRMESH: Unknown vertex format");
|
||||
}
|
||||
else vertexFormat = 0;
|
||||
textMeaning = 1;
|
||||
|
@ -275,7 +275,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount");
|
||||
if (!curMesh->mNumVertices) {
|
||||
// This is possible ... remove the mesh from the list and skip further reading
|
||||
DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
|
||||
ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero indices");
|
||||
|
||||
// mesh - away
|
||||
releaseMesh( &curMesh );
|
||||
|
@ -288,7 +288,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
|
||||
if (curMesh->mNumVertices % 3) {
|
||||
DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3");
|
||||
ASSIMP_LOG_WARN("IRRMESH: Number if indices isn't divisible by 3");
|
||||
}
|
||||
|
||||
curMesh->mNumFaces = curMesh->mNumVertices / 3;
|
||||
|
@ -439,7 +439,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
unsigned int total = 0;
|
||||
while(SkipSpacesAndLineEnd(&sz)) {
|
||||
if (curFace >= faceEnd) {
|
||||
DefaultLogger::get()->error("IRRMESH: Too many indices");
|
||||
ASSIMP_LOG_ERROR("IRRMESH: Too many indices");
|
||||
break;
|
||||
}
|
||||
if (!curIdx) {
|
||||
|
@ -449,7 +449,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
unsigned int idx = strtoul10(sz,&sz);
|
||||
if (idx >= curVertices.size()) {
|
||||
DefaultLogger::get()->error("IRRMESH: Index out of range");
|
||||
ASSIMP_LOG_ERROR("IRRMESH: Index out of range");
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
|
@ -470,7 +470,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
|
||||
if (curFace != faceEnd)
|
||||
DefaultLogger::get()->error("IRRMESH: Not enough indices");
|
||||
ASSIMP_LOG_ERROR("IRRMESH: Not enough indices");
|
||||
|
||||
// Finish processing the mesh - do some small material workarounds
|
||||
if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors) {
|
||||
|
@ -492,7 +492,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
// End of the last buffer. A material and a mesh should be there
|
||||
if (curMat || curMesh) {
|
||||
if ( !curMat || !curMesh) {
|
||||
DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
|
||||
ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material");
|
||||
releaseMaterial( &curMat );
|
||||
releaseMesh( &curMesh );
|
||||
}
|
||||
|
|
|
@ -179,14 +179,14 @@ void IrrlichtBase::ReadVectorProperty (VectorProperty& out)
|
|||
SkipSpaces(&ptr);
|
||||
if (',' != *ptr)
|
||||
{
|
||||
DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
|
||||
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
|
||||
}
|
||||
else SkipSpaces(ptr+1,&ptr);
|
||||
ptr = fast_atoreal_move<float>( ptr,(float&)out.value.y );
|
||||
SkipSpaces(&ptr);
|
||||
if (',' != *ptr)
|
||||
{
|
||||
DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
|
||||
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
|
||||
}
|
||||
else SkipSpaces(ptr+1,&ptr);
|
||||
ptr = fast_atoreal_move<float>( ptr,(float&)out.value.z );
|
||||
|
@ -360,7 +360,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
|
|||
matFlags = AI_IRRMESH_MAT_normalmap_ta;
|
||||
}
|
||||
else {
|
||||
DefaultLogger::get()->warn("IRRMat: Unrecognized material type: " + prop.value);
|
||||
ASSIMP_LOG_WARN("IRRMat: Unrecognized material type: " + prop.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,9 +391,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
|
|||
|
||||
// set the corresponding material flag
|
||||
matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
|
||||
}
|
||||
// or just as second diffuse texture
|
||||
else if (matFlags & AI_IRRMESH_MAT_solid_2layer) {
|
||||
} else if (matFlags & AI_IRRMESH_MAT_solid_2layer) {// or just as second diffuse texture
|
||||
++cnt;
|
||||
s.Set(prop.value);
|
||||
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(1));
|
||||
|
@ -401,19 +399,15 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
|
|||
|
||||
// set the corresponding material flag
|
||||
matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("IRRmat: Skipping second texture");
|
||||
}
|
||||
else DefaultLogger::get()->warn("IRRmat: Skipping second texture");
|
||||
}
|
||||
|
||||
else if (prop.name == "Texture3" && cnt == 2)
|
||||
{
|
||||
} else if (prop.name == "Texture3" && cnt == 2) {
|
||||
// Irrlicht does not seem to use these channels.
|
||||
++cnt;
|
||||
s.Set(prop.value);
|
||||
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+1));
|
||||
}
|
||||
else if (prop.name == "Texture4" && cnt == 3)
|
||||
{
|
||||
} else if (prop.name == "Texture4" && cnt == 3) {
|
||||
// Irrlicht does not seem to use these channels.
|
||||
++cnt;
|
||||
s.Set(prop.value);
|
||||
|
@ -499,7 +493,8 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
|
|||
break;
|
||||
}
|
||||
}
|
||||
DefaultLogger::get()->error("IRRMESH: Unexpected end of file. Material is not complete");
|
||||
ASSIMP_LOG_ERROR("IRRMESH: Unexpected end of file. Material is not complete");
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ protected:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
/** Read a property of the specified type from the current XML element.
|
||||
* @param out Recives output data
|
||||
* @param out Receives output data
|
||||
*/
|
||||
void ReadHexProperty (HexProperty& out);
|
||||
void ReadStringProperty (StringProperty& out);
|
||||
|
|
|
@ -147,10 +147,7 @@ void AllocateFromAssimpHeap::operator delete[] ( void* data) {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Importer constructor.
|
||||
Importer::Importer()
|
||||
: pimpl( NULL ) {
|
||||
// allocate the pimpl first
|
||||
pimpl = new ImporterPimpl();
|
||||
|
||||
: pimpl( new ImporterPimpl ) {
|
||||
pimpl->mScene = NULL;
|
||||
pimpl->mErrorString = "";
|
||||
|
||||
|
@ -190,7 +187,7 @@ Importer::~Importer()
|
|||
delete pimpl->mIOHandler;
|
||||
delete pimpl->mProgressHandler;
|
||||
|
||||
// Kill imported scene. Destructors should do that recursivly
|
||||
// Kill imported scene. Destructor's should do that recursively
|
||||
delete pimpl->mScene;
|
||||
|
||||
// Delete shared post-processing data
|
||||
|
@ -200,18 +197,6 @@ Importer::~Importer()
|
|||
delete pimpl;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Copy constructor - copies the config of another Importer, not the scene
|
||||
Importer::Importer(const Importer &other)
|
||||
: pimpl(NULL) {
|
||||
new(this) Importer();
|
||||
|
||||
pimpl->mIntProperties = other.pimpl->mIntProperties;
|
||||
pimpl->mFloatProperties = other.pimpl->mFloatProperties;
|
||||
pimpl->mStringProperties = other.pimpl->mStringProperties;
|
||||
pimpl->mMatrixProperties = other.pimpl->mMatrixProperties;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Register a custom post-processing step
|
||||
aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
|
||||
|
@ -220,7 +205,7 @@ aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
|
|||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
pimpl->mPostProcessingSteps.push_back(pImp);
|
||||
DefaultLogger::get()->info("Registering custom post-processing step");
|
||||
ASSIMP_LOG_INFO("Registering custom post-processing step");
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
||||
return AI_SUCCESS;
|
||||
|
@ -247,7 +232,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp)
|
|||
|
||||
#ifdef ASSIMP_BUILD_DEBUG
|
||||
if (IsExtensionSupported(*it)) {
|
||||
DefaultLogger::get()->warn("The file extension " + *it + " is already in use");
|
||||
ASSIMP_LOG_WARN_F("The file extension ", *it, " is already in use");
|
||||
}
|
||||
#endif
|
||||
baked += *it;
|
||||
|
@ -255,7 +240,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp)
|
|||
|
||||
// add the loader
|
||||
pimpl->mImporter.push_back(pImp);
|
||||
DefaultLogger::get()->info("Registering custom importer for these file extensions: " + baked);
|
||||
ASSIMP_LOG_INFO_F("Registering custom importer for these file extensions: ", baked);
|
||||
ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
||||
return AI_SUCCESS;
|
||||
}
|
||||
|
@ -275,10 +260,10 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
|
|||
|
||||
if (it != pimpl->mImporter.end()) {
|
||||
pimpl->mImporter.erase(it);
|
||||
DefaultLogger::get()->info("Unregistering custom importer: ");
|
||||
ASSIMP_LOG_INFO("Unregistering custom importer: ");
|
||||
return AI_SUCCESS;
|
||||
}
|
||||
DefaultLogger::get()->warn("Unable to remove custom importer: I can't find you ...");
|
||||
ASSIMP_LOG_WARN("Unable to remove custom importer: I can't find you ...");
|
||||
ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
||||
return AI_FAILURE;
|
||||
}
|
||||
|
@ -298,10 +283,10 @@ aiReturn Importer::UnregisterPPStep(BaseProcess* pImp)
|
|||
|
||||
if (it != pimpl->mPostProcessingSteps.end()) {
|
||||
pimpl->mPostProcessingSteps.erase(it);
|
||||
DefaultLogger::get()->info("Unregistering custom post-processing step");
|
||||
ASSIMP_LOG_INFO("Unregistering custom post-processing step");
|
||||
return AI_SUCCESS;
|
||||
}
|
||||
DefaultLogger::get()->warn("Unable to remove custom post-processing step: I can't find you ..");
|
||||
ASSIMP_LOG_WARN("Unable to remove custom post-processing step: I can't find you ..");
|
||||
ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
||||
return AI_FAILURE;
|
||||
}
|
||||
|
@ -383,11 +368,11 @@ bool Importer::IsDefaultProgressHandler() const
|
|||
bool _ValidateFlags(unsigned int pFlags)
|
||||
{
|
||||
if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) {
|
||||
DefaultLogger::get()->error("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
|
||||
ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
|
||||
return false;
|
||||
}
|
||||
if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices) {
|
||||
DefaultLogger::get()->error("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
|
||||
ASSIMP_LOG_ERROR("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -519,26 +504,15 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void WriteLogOpening(const std::string& file)
|
||||
{
|
||||
Logger* l = DefaultLogger::get();
|
||||
if (!l) {
|
||||
return;
|
||||
}
|
||||
l->info("Load " + file);
|
||||
ASSIMP_LOG_INFO_F("Load ", file);
|
||||
|
||||
// print a full version dump. This is nice because we don't
|
||||
// need to ask the authors of incoming bug reports for
|
||||
// the library version they're using - a log dump is
|
||||
// sufficient.
|
||||
const unsigned int flags = aiGetCompileFlags();
|
||||
l->debug(format()
|
||||
<< "Assimp "
|
||||
<< aiGetVersionMajor()
|
||||
<< "."
|
||||
<< aiGetVersionMinor()
|
||||
<< "."
|
||||
<< aiGetVersionRevision()
|
||||
|
||||
<< " "
|
||||
const unsigned int flags( aiGetCompileFlags() );
|
||||
std::stringstream stream;
|
||||
stream << "Assimp " << aiGetVersionMajor() << "." << aiGetVersionMinor() << "." << aiGetVersionRevision() << " "
|
||||
#if defined(ASSIMP_BUILD_ARCHITECTURE)
|
||||
<< ASSIMP_BUILD_ARCHITECTURE
|
||||
#elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
|
||||
|
@ -554,12 +528,11 @@ void WriteLogOpening(const std::string& file)
|
|||
#elif defined(__arm__)
|
||||
<< "arm"
|
||||
#else
|
||||
<< "<unknown architecture>"
|
||||
<< "<unknown architecture>"
|
||||
#endif
|
||||
|
||||
<< " "
|
||||
#if defined(ASSIMP_BUILD_COMPILER)
|
||||
<< ASSIMP_BUILD_COMPILER
|
||||
<< ( ASSIMP_BUILD_COMPILER )
|
||||
#elif defined(_MSC_VER)
|
||||
<< "msvc"
|
||||
#elif defined(__GNUC__)
|
||||
|
@ -574,8 +547,9 @@ void WriteLogOpening(const std::string& file)
|
|||
|
||||
<< (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
|
||||
<< (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "")
|
||||
<< (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "")
|
||||
);
|
||||
<< (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "");
|
||||
|
||||
ASSIMP_LOG_DEBUG(stream.str());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -601,7 +575,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
|||
// a scene. In this case we need to delete the old one
|
||||
if (pimpl->mScene) {
|
||||
|
||||
DefaultLogger::get()->debug("(Deleting previous scene)");
|
||||
ASSIMP_LOG_DEBUG("(Deleting previous scene)");
|
||||
FreeScene();
|
||||
}
|
||||
|
||||
|
@ -609,7 +583,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
|||
if( !pimpl->mIOHandler->Exists( pFile)) {
|
||||
|
||||
pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
|
||||
DefaultLogger::get()->error(pimpl->mErrorString);
|
||||
ASSIMP_LOG_ERROR(pimpl->mErrorString);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -632,9 +606,8 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
|||
// not so bad yet ... try format auto detection.
|
||||
const std::string::size_type s = pFile.find_last_of('.');
|
||||
if (s != std::string::npos) {
|
||||
DefaultLogger::get()->info("File extension not known, trying signature-based detection");
|
||||
ASSIMP_LOG_INFO("File extension not known, trying signature-based detection");
|
||||
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
|
||||
|
||||
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
|
||||
imp = pimpl->mImporter[a];
|
||||
break;
|
||||
|
@ -644,7 +617,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
|||
// Put a proper error message if no suitable importer was found
|
||||
if( !imp) {
|
||||
pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
|
||||
DefaultLogger::get()->error(pimpl->mErrorString);
|
||||
ASSIMP_LOG_ERROR(pimpl->mErrorString);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -664,7 +637,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
|||
if ( NULL != desc ) {
|
||||
ext = desc->mName;
|
||||
}
|
||||
DefaultLogger::get()->info("Found a matching importer for this file format: " + ext + "." );
|
||||
ASSIMP_LOG_INFO("Found a matching importer for this file format: " + ext + "." );
|
||||
pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
|
||||
|
||||
if (profiler) {
|
||||
|
@ -732,7 +705,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
|||
pimpl->mErrorString = std::string("std::exception: ") + e.what();
|
||||
#endif
|
||||
|
||||
DefaultLogger::get()->error(pimpl->mErrorString);
|
||||
ASSIMP_LOG_ERROR(pimpl->mErrorString);
|
||||
delete pimpl->mScene; pimpl->mScene = NULL;
|
||||
}
|
||||
#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
|
||||
|
@ -760,7 +733,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
|
|||
|
||||
// In debug builds: run basic flag validation
|
||||
ai_assert(_ValidateFlags(pFlags));
|
||||
DefaultLogger::get()->info("Entering post processing pipeline");
|
||||
ASSIMP_LOG_INFO("Entering post processing pipeline");
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
// The ValidateDS process plays an exceptional role. It isn't contained in the global
|
||||
|
@ -778,13 +751,13 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
|
|||
if (pimpl->bExtraVerbose)
|
||||
{
|
||||
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
DefaultLogger::get()->error("Verbose Import is not available due to build settings");
|
||||
ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
|
||||
#endif // no validation
|
||||
pFlags |= aiProcess_ValidateDataStructure;
|
||||
}
|
||||
#else
|
||||
if (pimpl->bExtraVerbose) {
|
||||
DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
|
||||
ASSIMP_LOG_WARN("Not a debug build, ignoring extra verbose setting");
|
||||
}
|
||||
#endif // ! DEBUG
|
||||
|
||||
|
@ -816,18 +789,19 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
|
|||
|
||||
// If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
|
||||
if (pimpl->bExtraVerbose) {
|
||||
DefaultLogger::get()->debug("Verbose Import: revalidating data structures");
|
||||
ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures");
|
||||
|
||||
ValidateDSProcess ds;
|
||||
ds.ExecuteOnScene (this);
|
||||
if( !pimpl->mScene) {
|
||||
DefaultLogger::get()->error("Verbose Import: failed to revalidate data structures");
|
||||
ASSIMP_LOG_ERROR("Verbose Import: failed to re-validate data structures");
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // ! DEBUG
|
||||
}
|
||||
pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
|
||||
pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()),
|
||||
static_cast<int>(pimpl->mPostProcessingSteps.size()) );
|
||||
|
||||
// update private scene flags
|
||||
if( pimpl->mScene )
|
||||
|
@ -835,7 +809,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
|
|||
|
||||
// clear any data allocated by post-process steps
|
||||
pimpl->mPPShared->Clean();
|
||||
DefaultLogger::get()->info("Leaving post processing pipeline");
|
||||
ASSIMP_LOG_INFO("Leaving post processing pipeline");
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
|
||||
return pimpl->mScene;
|
||||
|
@ -856,7 +830,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
|
|||
}
|
||||
|
||||
// In debug builds: run basic flag validation
|
||||
DefaultLogger::get()->info( "Entering customized post processing pipeline" );
|
||||
ASSIMP_LOG_INFO( "Entering customized post processing pipeline" );
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
// The ValidateDS process plays an exceptional role. It isn't contained in the global
|
||||
|
@ -874,12 +848,12 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
|
|||
if ( pimpl->bExtraVerbose )
|
||||
{
|
||||
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
DefaultLogger::get()->error( "Verbose Import is not available due to build settings" );
|
||||
ASSIMP_LOG_ERROR( "Verbose Import is not available due to build settings" );
|
||||
#endif // no validation
|
||||
}
|
||||
#else
|
||||
if ( pimpl->bExtraVerbose ) {
|
||||
DefaultLogger::get()->warn( "Not a debug build, ignoring extra verbose setting" );
|
||||
ASSIMP_LOG_WARN( "Not a debug build, ignoring extra verbose setting" );
|
||||
}
|
||||
#endif // ! DEBUG
|
||||
|
||||
|
@ -897,18 +871,18 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
|
|||
|
||||
// If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
|
||||
if ( pimpl->bExtraVerbose || requestValidation ) {
|
||||
DefaultLogger::get()->debug( "Verbose Import: revalidating data structures" );
|
||||
ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" );
|
||||
|
||||
ValidateDSProcess ds;
|
||||
ds.ExecuteOnScene( this );
|
||||
if ( !pimpl->mScene ) {
|
||||
DefaultLogger::get()->error( "Verbose Import: failed to revalidate data structures" );
|
||||
ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" );
|
||||
}
|
||||
}
|
||||
|
||||
// clear any data allocated by post-process steps
|
||||
pimpl->mPPShared->Clean();
|
||||
DefaultLogger::get()->info( "Leaving customized post processing pipeline" );
|
||||
ASSIMP_LOG_INFO( "Leaving customized post processing pipeline" );
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION( const aiScene* );
|
||||
|
||||
|
@ -919,7 +893,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
|
|||
// Helper function to check whether an extension is supported by ASSIMP
|
||||
bool Importer::IsExtensionSupported(const char* szExtension) const
|
||||
{
|
||||
return NULL != GetImporter(szExtension);
|
||||
return nullptr != GetImporter(szExtension);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -959,6 +933,7 @@ BaseImporter* Importer::GetImporter (const char* szExtension) const
|
|||
size_t Importer::GetImporterIndex (const char* szExtension) const
|
||||
{
|
||||
ai_assert(szExtension);
|
||||
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// skip over wildcard and dot characters at string head --
|
||||
|
@ -995,15 +970,18 @@ void Importer::GetExtensionList(aiString& szOut) const
|
|||
(*i)->GetExtensionList(str);
|
||||
}
|
||||
|
||||
for (std::set<std::string>::const_iterator it = str.begin();; ) {
|
||||
szOut.Append("*.");
|
||||
szOut.Append((*it).c_str());
|
||||
// List can be empty
|
||||
if( !str.empty() ) {
|
||||
for (std::set<std::string>::const_iterator it = str.begin();; ) {
|
||||
szOut.Append("*.");
|
||||
szOut.Append((*it).c_str());
|
||||
|
||||
if (++it == str.end()) {
|
||||
break;
|
||||
}
|
||||
szOut.Append(";");
|
||||
}
|
||||
if (++it == str.end()) {
|
||||
break;
|
||||
}
|
||||
szOut.Append(";");
|
||||
}
|
||||
}
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
|
@ -1022,33 +1000,33 @@ bool Importer::SetPropertyInteger(const char* szName, int iValue)
|
|||
// Set a configuration property
|
||||
bool Importer::SetPropertyFloat(const char* szName, ai_real iValue)
|
||||
{
|
||||
bool exising;
|
||||
bool existing;
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
exising = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
|
||||
existing = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
|
||||
ASSIMP_END_EXCEPTION_REGION(bool);
|
||||
return exising;
|
||||
return existing;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Set a configuration property
|
||||
bool Importer::SetPropertyString(const char* szName, const std::string& value)
|
||||
{
|
||||
bool exising;
|
||||
bool existing;
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
exising = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
|
||||
existing = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
|
||||
ASSIMP_END_EXCEPTION_REGION(bool);
|
||||
return exising;
|
||||
return existing;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Set a configuration property
|
||||
bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
|
||||
{
|
||||
bool exising;
|
||||
bool existing;
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
exising = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
|
||||
existing = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
|
||||
ASSIMP_END_EXCEPTION_REGION(bool);
|
||||
return exising;
|
||||
return existing;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -68,10 +68,8 @@ namespace Assimp {
|
|||
* std::vector and std::map in the public headers. Furthermore we are dropping
|
||||
* any STL interface problems caused by mismatching STL settings. All
|
||||
* size calculation are now done by us, not the app heap. */
|
||||
class ImporterPimpl
|
||||
{
|
||||
class ImporterPimpl {
|
||||
public:
|
||||
|
||||
// Data type to store the key hash
|
||||
typedef unsigned int KeyType;
|
||||
|
||||
|
@ -82,8 +80,6 @@ public:
|
|||
typedef std::map<KeyType, std::string> StringPropertyMap;
|
||||
typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
|
||||
|
||||
public:
|
||||
|
||||
/** IO handler to use for all file accesses. */
|
||||
IOSystem* mIOHandler;
|
||||
bool mIsDefaultHandler;
|
||||
|
@ -117,12 +113,34 @@ public:
|
|||
MatrixPropertyMap mMatrixProperties;
|
||||
|
||||
/** Used for testing - extra verbose mode causes the ValidateDataStructure-Step
|
||||
* to be executed before and after every single postprocess step */
|
||||
* to be executed before and after every single post-process step */
|
||||
bool bExtraVerbose;
|
||||
|
||||
/** Used by post-process steps to share data */
|
||||
SharedPostProcessInfo* mPPShared;
|
||||
|
||||
/// The default class constructor.
|
||||
ImporterPimpl();
|
||||
};
|
||||
|
||||
inline
|
||||
ImporterPimpl::ImporterPimpl()
|
||||
: mIOHandler( nullptr )
|
||||
, mIsDefaultHandler( false )
|
||||
, mProgressHandler( nullptr )
|
||||
, mIsDefaultProgressHandler( false )
|
||||
, mImporter()
|
||||
, mPostProcessingSteps()
|
||||
, mScene( nullptr )
|
||||
, mErrorString()
|
||||
, mIntProperties()
|
||||
, mFloatProperties()
|
||||
, mStringProperties()
|
||||
, mMatrixProperties()
|
||||
, bExtraVerbose( false )
|
||||
, mPPShared( nullptr ) {
|
||||
// empty
|
||||
}
|
||||
//! @endcond
|
||||
|
||||
|
||||
|
|
|
@ -728,7 +728,7 @@ void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept, TempMesh&
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned int matid, std::vector<unsigned int>& mesh_indices,
|
||||
bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned int matid, std::set<unsigned int>& mesh_indices,
|
||||
ConversionData& conv)
|
||||
{
|
||||
bool fix_orientation = false;
|
||||
|
@ -810,7 +810,7 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
|
|||
aiMesh* const mesh = meshtmp->ToMesh();
|
||||
if(mesh) {
|
||||
mesh->mMaterialIndex = matid;
|
||||
mesh_indices.push_back(static_cast<unsigned int>(conv.meshes.size()));
|
||||
mesh_indices.insert(static_cast<unsigned int>(conv.meshes.size()));
|
||||
conv.meshes.push_back(mesh);
|
||||
return true;
|
||||
}
|
||||
|
@ -818,33 +818,31 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void AssignAddedMeshes(std::vector<unsigned int>& mesh_indices,aiNode* nd,
|
||||
void AssignAddedMeshes(std::set<unsigned int>& mesh_indices,aiNode* nd,
|
||||
ConversionData& /*conv*/)
|
||||
{
|
||||
if (!mesh_indices.empty()) {
|
||||
std::set<unsigned int>::const_iterator it = mesh_indices.cbegin();
|
||||
std::set<unsigned int>::const_iterator end = mesh_indices.cend();
|
||||
|
||||
// make unique
|
||||
std::sort(mesh_indices.begin(),mesh_indices.end());
|
||||
std::vector<unsigned int>::iterator it_end = std::unique(mesh_indices.begin(),mesh_indices.end());
|
||||
|
||||
nd->mNumMeshes = static_cast<unsigned int>(std::distance(mesh_indices.begin(),it_end));
|
||||
nd->mNumMeshes = static_cast<unsigned int>(mesh_indices.size());
|
||||
|
||||
nd->mMeshes = new unsigned int[nd->mNumMeshes];
|
||||
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
|
||||
nd->mMeshes[i] = mesh_indices[i];
|
||||
for(unsigned int i = 0; it != end && i < nd->mNumMeshes; ++i, ++it) {
|
||||
nd->mMeshes[i] = *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool TryQueryMeshCache(const Schema_2x3::IfcRepresentationItem& item,
|
||||
std::vector<unsigned int>& mesh_indices, unsigned int mat_index,
|
||||
std::set<unsigned int>& mesh_indices, unsigned int mat_index,
|
||||
ConversionData& conv)
|
||||
{
|
||||
ConversionData::MeshCacheIndex idx(&item, mat_index);
|
||||
ConversionData::MeshCache::const_iterator it = conv.cached_meshes.find(idx);
|
||||
if (it != conv.cached_meshes.end()) {
|
||||
std::copy((*it).second.begin(),(*it).second.end(),std::back_inserter(mesh_indices));
|
||||
std::copy((*it).second.begin(),(*it).second.end(),std::inserter(mesh_indices, mesh_indices.end()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -852,7 +850,7 @@ bool TryQueryMeshCache(const Schema_2x3::IfcRepresentationItem& item,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void PopulateMeshCache(const Schema_2x3::IfcRepresentationItem& item,
|
||||
const std::vector<unsigned int>& mesh_indices, unsigned int mat_index,
|
||||
const std::set<unsigned int>& mesh_indices, unsigned int mat_index,
|
||||
ConversionData& conv)
|
||||
{
|
||||
ConversionData::MeshCacheIndex idx(&item, mat_index);
|
||||
|
@ -861,7 +859,7 @@ void PopulateMeshCache(const Schema_2x3::IfcRepresentationItem& item,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item, unsigned int matid,
|
||||
std::vector<unsigned int>& mesh_indices,
|
||||
std::set<unsigned int>& mesh_indices,
|
||||
ConversionData& conv)
|
||||
{
|
||||
// determine material
|
||||
|
|
|
@ -141,7 +141,8 @@ bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
|
|||
// it is only unambiguous as long as we don't support any further
|
||||
// file formats with STEP as their encoding.
|
||||
const char* tokens[] = {"ISO-10303-21"};
|
||||
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
|
||||
const bool found( SearchFileHeaderForToken( pIOHandler, pFile, tokens, 1 ) );
|
||||
return found;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -434,7 +435,7 @@ bool ProcessMappedItem(const Schema_2x3::IfcMappedItem& mapped, aiNode* nd_src,
|
|||
|
||||
msrc = m*msrc;
|
||||
|
||||
std::vector<unsigned int> meshes;
|
||||
std::set<unsigned int> meshes;
|
||||
const size_t old_openings = conv.collect_openings ? conv.collect_openings->size() : 0;
|
||||
if (conv.apply_openings) {
|
||||
IfcMatrix4 minv = msrc;
|
||||
|
@ -549,7 +550,7 @@ void ProcessProductRepresentation(const Schema_2x3::IfcProduct& el, aiNode* nd,
|
|||
|
||||
// extract Color from metadata, if present
|
||||
unsigned int matid = ProcessMaterials( el.GetID(), std::numeric_limits<uint32_t>::max(), conv, false);
|
||||
std::vector<unsigned int> meshes;
|
||||
std::set<unsigned int> meshes;
|
||||
|
||||
// we want only one representation type, so bring them in a suitable order (i.e try those
|
||||
// that look as if we could read them quickly at first). This way of reading
|
||||
|
@ -582,9 +583,8 @@ typedef std::map<std::string, std::string> Metadata;
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties,
|
||||
const std::string& prefix = "",
|
||||
unsigned int nest = 0)
|
||||
{
|
||||
const std::string& prefix = "",
|
||||
unsigned int nest = 0) {
|
||||
for(const Schema_2x3::IfcProperty& property : set) {
|
||||
const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
|
||||
if (const Schema_2x3::IfcPropertySingleValue* const singleValue = property.ToPtr<Schema_2x3::IfcPropertySingleValue>()) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue