@@ -70,8 +70,8 @@ IncludeCategories:
- Regex: '^<.*'
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
-IndentCaseLabels: true
-IndentPPDirectives: AfterHash
+IndentCaseLabels: false
+#IndentPPDirectives: AfterHash
IndentWidth: 4
# IndentWrappedFunctionNames: false
# JavaScriptQuotes: Leave
@@ -1,2 +1,2 @@
patreon: assimp
-Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4
+custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4
@@ -0,0 +1,46 @@
+name: C/C++ CI
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+jobs:
+ linux:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: configure
+ run: cmake CMakeLists.txt
+ - name: build
+ run: cmake --build .
+ - name: test
+ run: cd bin && ./unit
+ mac:
+ runs-on: macos-latest
+ windows:
+ runs-on: windows-latest
+ run: cmake --build . --config Release
+ run: |
+ cd bin\Release
+ .\unit
@@ -39,9 +39,9 @@ SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW)
CMAKE_MINIMUM_REQUIRED( VERSION 3.0 )
# Toggles the use of the hunter package manager
-option(HUNTER_ENABLED "Enable Hunter package manager support" OFF)
+option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
-IF(HUNTER_ENABLED)
+IF(ASSIMP_HUNTER_ENABLED)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.23.176.tar.gz"
@@ -60,7 +60,7 @@ OPTION( BUILD_SHARED_LIBS
ON
)
-OPTION( BUILD_FRAMEWORK
+OPTION( ASSIMP_BUILD_FRAMEWORK
"Build package as Mac OS X Framework bundle."
OFF
@@ -101,7 +101,7 @@ OPTION ( ASSIMP_COVERALLS
OPTION( ASSIMP_INSTALL
- "DIsable this if you want to use assimp as a submodule."
+ "Disable this if you want to use assimp as a submodule."
OPTION ( ASSIMP_ERROR_MAX
@@ -120,25 +120,25 @@ OPTION ( ASSIMP_UBSAN
"Enable Undefined Behavior sanitizer."
-OPTION ( SYSTEM_IRRXML
+OPTION ( ASSIMP_SYSTEM_IRRXML
"Use system installed Irrlicht/IrrXML library."
-OPTION ( BUILD_DOCS
+OPTION ( ASSIMP_BUILD_DOCS
"Build documentation using Doxygen."
-OPTION( INJECT_DEBUG_POSTFIX
+OPTION( ASSIMP_INJECT_DEBUG_POSTFIX
"Inject debug postfix in .a/.so/.dll lib names"
-OPTION ( IGNORE_GIT_HASH
+OPTION ( ASSIMP_IGNORE_GIT_HASH
"Don't call git to get the hash."
-IF (IOS AND NOT HUNTER_ENABLED)
+IF (IOS AND NOT ASSIMP_HUNTER_ENABLED)
IF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release")
ENDIF ()
@@ -161,7 +161,7 @@ IF(MSVC)
ENDIF()
-IF (BUILD_FRAMEWORK)
+IF (ASSIMP_BUILD_FRAMEWORK)
SET (BUILD_SHARED_LIBS ON)
MESSAGE(STATUS "Framework bundle building enabled")
@@ -181,12 +181,12 @@ SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VER
SET (ASSIMP_SOVERSION 5)
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
-if(NOT HUNTER_ENABLED)
+if(NOT ASSIMP_HUNTER_ENABLED)
# Enable C++11 support globally
set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
endif()
-IF(NOT IGNORE_GIT_HASH)
+IF(NOT ASSIMP_IGNORE_GIT_HASH)
# Get the current working branch
EXECUTE_PROCESS(
COMMAND git rev-parse --abbrev-ref HEAD
@@ -238,14 +238,9 @@ SET(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_M
SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
-IF( UNIX )
- # Use GNUInstallDirs for Unix predefined directories
- INCLUDE(GNUInstallDirs)
-ENDIF()
-
# Grouped compiler settings
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
- IF(NOT HUNTER_ENABLED)
+ IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++0x ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
@@ -255,15 +250,14 @@ 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)
- ADD_COMPILE_OPTIONS( /bigobj )
+ ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX )
# disable "elements of array '' will be default initialized" warning on MSVC2013
IF(MSVC12)
ADD_COMPILE_OPTIONS(/wd4351)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
@@ -275,7 +269,7 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW )
ELSEIF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3)
message(WARNING "MinGW is old, if you experience errors, update MinGW.")
SET(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
@@ -284,7 +278,7 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW )
ADD_DEFINITIONS( -U__STRICT_ANSI__ )
-IF ( IOS AND NOT HUNTER_ENABLED)
+IF ( IOS AND NOT ASSIMP_HUNTER_ENABLED)
IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -Og")
@@ -351,17 +345,9 @@ ELSE()
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
-# Cache these to allow the user to override them manually.
-SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE STRING
- "Path the built library files are installed to." )
-SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE STRING
- "Path the header files are installed to." )
-SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE STRING
- "Path the tool executables are installed to." )
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
-IF (INJECT_DEBUG_POSTFIX AND (is_multi_config OR CMAKE_BUILD_TYPE STREQUAL "Debug"))
+IF (ASSIMP_INJECT_DEBUG_POSTFIX AND (is_multi_config OR CMAKE_BUILD_TYPE STREQUAL "Debug"))
SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfix for lib, samples and tools")
ELSE()
SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools")
@@ -374,7 +360,7 @@ IF (NOT TARGET uninstall)
ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
set(INCLUDE_INSTALL_DIR "include")
@@ -418,6 +404,28 @@ ELSE()
else()
set(BUILD_LIB_TYPE STATIC)
+ IF( UNIX )
+ # Use GNUInstallDirs for Unix predefined directories
+ INCLUDE(GNUInstallDirs)
+ SET( ASSIMP_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR})
+ SET( ASSIMP_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
+ SET( ASSIMP_BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR})
+ ELSE()
+ # Cache these to allow the user to override them on non-Unix platforms
+ SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE STRING
+ "Path the built library files are installed to." )
+ SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE STRING
+ "Path the header files are installed to." )
+ SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE STRING
+ "Path the tool executables are installed to." )
+ SET(CMAKE_INSTALL_FULL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX}/${ASSIMP_INCLUDE_INSTALL_DIR})
+ SET(CMAKE_INSTALL_FULL_LIBDIR ${CMAKE_INSTALL_PREFIX}/${ASSIMP_LIB_INSTALL_DIR})
+ SET(CMAKE_INSTALL_FULL_BINDIR ${CMAKE_INSTALL_PREFIX}/${ASSIMP_BIN_INSTALL_DIR})
+ ENDIF()
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}/assimpTargets.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" @ONLY IMMEDIATE)
IF (is_multi_config)
@@ -441,18 +449,18 @@ ELSE()
DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
-IF( BUILD_DOCS )
+IF( ASSIMP_BUILD_DOCS )
ADD_SUBDIRECTORY(doc)
# Look for system installed irrXML
-IF ( SYSTEM_IRRXML )
+IF ( ASSIMP_SYSTEM_IRRXML )
FIND_PACKAGE( IrrXML REQUIRED )
# Search for external dependencies, and build them from source if not found
# Search for zlib
hunter_add_package(ZLIB)
find_package(ZLIB CONFIG REQUIRED)
@@ -576,24 +584,26 @@ ELSE ()
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
-IF(NOT HUNTER_ENABLED)
+IF(NOT ASSIMP_HUNTER_ENABLED)
ADD_SUBDIRECTORY(contrib)
ADD_SUBDIRECTORY( code/ )
IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
# The viewer for windows only
- IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
- OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
+ IF ( WIN32 )
+ OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" OFF )
IF ( ASSIMP_BUILD_ASSIMP_VIEW )
ADD_SUBDIRECTORY( tools/assimp_view/ )
- # Te command line tool
+ # The command line tool
ADD_SUBDIRECTORY( tools/assimp_cmd/ )
IF ( ASSIMP_BUILD_SAMPLES)
+ SET( SAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/samples )
+ SET( SAMPLES_SHARED_CODE_DIR ${SAMPLES_DIR}/SharedCode )
IF ( WIN32 )
ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 )
@@ -2,6 +2,7 @@ Open Asset Import Library (assimp)
==================================
A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
### Current project status ###
+
[](https://travis-ci.org/assimp/assimp)
[](https://ci.appveyor.com/project/kimkulling/assimp)
<a href="https://scan.coverity.com/projects/5607">
@@ -1,7 +1,5 @@
-prefix=@CMAKE_INSTALL_PREFIX@
-exec_prefix=@CMAKE_INSTALL_PREFIX@/
-libdir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_LIB_INSTALL_DIR@
-includedir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_INCLUDE_INSTALL_DIR@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: @CMAKE_PROJECT_NAME@
Description: Import various well-known 3D model formats in an uniform manner.
@@ -7,6 +7,14 @@ set(CMAKE_IMPORT_FILE_VERSION 1)
set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@)
+get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
+if ("${LIB64}" STREQUAL "TRUE")
+ set(LIBSUFFIX 64)
+else()
+ set(LIBSUFFIX "")
+endif()
if(MSVC)
if(MSVC_TOOLSET_VERSION)
set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
@@ -35,7 +43,7 @@ if(MSVC)
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
- file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX)
+ file(TO_NATIVE_PATH "${_IMPORT_PREFIX}" _IMPORT_PREFIX)
if(ASSIMP_BUILD_SHARED_LIBS)
set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@")
@@ -44,22 +52,22 @@ if(MSVC)
# Import target "assimp::assimp" for configuration "Debug"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(assimp::assimp PROPERTIES
- IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/lib/${importLibraryName}"
- IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/${sharedLibraryName}"
+ IMPORTED_IMPLIB_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${importLibraryName}"
+ IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_BINDIR@/${sharedLibraryName}"
list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
- list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${importLibraryName}")
- list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" )
+ list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${importLibraryName}")
+ list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_BINDIR@/${sharedLibraryName}" )
set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@")
- IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
+ IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
- list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}")
+ list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}")
@@ -75,23 +83,20 @@ else()
IMPORTED_SONAME_DEBUG "${sharedLibraryName}"
- IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${sharedLibraryName}"
+ IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${sharedLibraryName}"
- list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" )
+ list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${sharedLibraryName}" )
set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@")
+ IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${staticLibraryName}"
- list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}" )
+ list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${staticLibraryName}" )
# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)
set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@")
@@ -44,12 +52,12 @@ if(MSVC)
# Import target "assimp::assimp" for configuration "Release"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
- IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/lib/${importLibraryName}"
- IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/${sharedLibraryName}"
+ IMPORTED_IMPLIB_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${importLibraryName}"
+ IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_BINDIR@/${sharedLibraryName}"
set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@")
@@ -59,7 +67,7 @@ if(MSVC)
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
@@ -75,18 +83,17 @@ else()
IMPORTED_SONAME_RELEASE "${sharedLibraryName}"
- IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${sharedLibraryName}"
+ IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${sharedLibraryName}"
set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@")
- IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
+ IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${staticLibraryName}"
@@ -43,23 +43,13 @@ unset(_targetsDefined)
unset(_targetsNotDefined)
unset(_expectedTargets)
-# Compute the installation prefix relative to this file.
-get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
-get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
-if(_IMPORT_PREFIX STREQUAL "/")
- set(_IMPORT_PREFIX "")
-endif()
# Create imported target assimp::assimp
add_library(assimp::assimp @BUILD_LIB_TYPE@ IMPORTED)
COMPATIBLE_INTERFACE_STRING "assimp_MAJOR_VERSION"
INTERFACE_assimp_MAJOR_VERSION "1"
- INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include"
+ INTERFACE_INCLUDE_DIRECTORIES "@CMAKE_INSTALL_FULL_INCLUDEDIR@"
#INTERFACE_LINK_LIBRARIES "TxtUtils::TxtUtils;MealyMachine::MealyMachine"
@@ -74,9 +64,6 @@ foreach(f ${CONFIG_FILES})
include(${f})
endforeach()
-# Cleanup temporary variables.
-set(_IMPORT_PREFIX)
# Loop over all imported files and verify that they actually exist
foreach(target ${_IMPORT_CHECK_TARGETS} )
foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the 3ds importer class */
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// internal headers
@@ -80,7 +80,7 @@ namespace {
{
chunk_start_pos = writer.GetCurrentPos();
writer.PutU2(chunk_type);
- writer.PutU4(CHUNK_SIZE_NOT_SET);
+ writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET);
}
~ChunkWriter() {
@@ -193,21 +193,21 @@ Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, co
CollectTrafos(scene->mRootNode, trafos);
CollectMeshes(scene->mRootNode, meshes);
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN);
+ ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_MAIN);
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_OBJMESH);
WriteMaterials();
WriteMeshes();
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
+ ChunkWriter curChunk1(writer, Discreet3DS::CHUNK_MASTER_SCALE);
writer.PutF4(1.0f);
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
WriteHierarchy(*scene->mRootNode, -1, -1);
@@ -223,9 +223,9 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling
// 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
+ ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_TRACKINFO);
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
// Assimp node names are unique and distinct from all mesh-node
// names we generate; thus we can use them as-is
@@ -237,7 +237,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling
int16_t hierarchy_pos = static_cast<int16_t>(seq);
if (sibling_level != -1) {
- hierarchy_pos = sibling_level;
+ hierarchy_pos =(uint16_t) sibling_level;
// Write the hierarchy position
@@ -262,7 +262,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling
const unsigned int mesh_idx = node.mMeshes[i];
const aiMesh& mesh = *scene->mMeshes[mesh_idx];
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRACKINFO);
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
WriteString(GetMeshName(mesh, mesh_idx, node));
@@ -279,7 +279,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling
void Discreet3DSExporter::WriteMaterials()
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
+ ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
const aiMaterial& mat = *scene->mMaterials[i];
@@ -290,22 +290,22 @@ void Discreet3DSExporter::WriteMaterials()
aiColor3D color;
if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
WriteColor(color);
if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) {
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) {
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
@@ -389,14 +389,14 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type
ChunkWriter chunk(writer, chunk_flags);
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAPFILE);
WriteString(path);
WritePercentChunk(blend);
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
uint16_t val = 0; // WRAP
if (map_mode[0] == aiTextureMapMode_Mirror) {
val = 0x2;
@@ -447,7 +447,7 @@ void Discreet3DSExporter::WriteMeshes()
// Vertices in world space
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_VERTLIST);
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count);
@@ -461,7 +461,7 @@ void Discreet3DSExporter::WriteMeshes()
// UV coordinates
if (mesh.HasTextureCoords(0)) {
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAPLIST);
@@ -474,7 +474,7 @@ void Discreet3DSExporter::WriteMeshes()
// Faces (indices)
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_FACELIST);
ai_assert(mesh.mNumFaces <= 0xffff);
@@ -513,7 +513,7 @@ void Discreet3DSExporter::WriteMeshes()
// Transformation matrix by which the mesh vertices have been pre-transformed with.
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRMATRIX);
for (unsigned int r = 0; r < 4; ++r) {
for (unsigned int c = 0; c < 3; ++c) {
writer.PutF4(trafo[r][c]);
@@ -526,7 +526,7 @@ void Discreet3DSExporter::WriteMeshes()
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh)
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_FACEMAT);
const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex);
WriteString(name);
@@ -559,7 +559,7 @@ void Discreet3DSExporter::WriteString(const aiString& s) {
void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_RGBF);
writer.PutF4(color.r);
writer.PutF4(color.g);
writer.PutF4(color.b);
@@ -567,13 +567,13 @@ void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
void Discreet3DSExporter::WritePercentChunk(float f) {
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF);
+ ChunkWriter curChunk(writer, Discreet3DS::CHUNK_PERCENTF);
writer.PutF4(f);
void Discreet3DSExporter::WritePercentChunk(double f) {
- ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTD);
+ ChunkWriter ccurChunkhunk(writer, Discreet3DS::CHUNK_PERCENTD);
writer.PutF8(f);
@@ -45,18 +45,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_3DSFILEHELPER_H_INC
#define AI_3DSFILEHELPER_H_INC
-#include <assimp/SpatialSort.h>
#include <assimp/SmoothingGroups.h>
+#include <assimp/SpatialSort.h>
#include <assimp/StringUtils.h>
-#include <assimp/qnan.h>
-#include <assimp/material.h>
+#include <assimp/anim.h>
#include <assimp/camera.h>
#include <assimp/light.h>
-#include <assimp/anim.h>
+#include <assimp/material.h>
+#include <assimp/qnan.h>
#include <stdio.h> //sprintf
-namespace Assimp {
-namespace D3DS {
+namespace Assimp {
+namespace D3DS {
#include <assimp/Compiler/pushpack1.h>
@@ -77,15 +77,13 @@ private:
public:
//! data structure for a single chunk in a .3ds file
struct Chunk {
- uint16_t Flag;
- uint32_t Size;
+ uint16_t Flag;
+ uint32_t Size;
} PACK_STRUCT;
//! Used for shading field in material3ds structure
//! From AutoDesk 3ds SDK
- typedef enum
- {
+ typedef enum {
// translated to gouraud shading with wireframe active
Wire = 0x0,
@@ -109,59 +107,57 @@ public:
} shadetype3ds;
// Flags for animated keys
- enum
- KEY_USE_TENS = 0x1,
- KEY_USE_CONT = 0x2,
- KEY_USE_BIAS = 0x4,
- KEY_USE_EASE_TO = 0x8,
- KEY_USE_EASE_FROM = 0x10
- } ;
+ enum {
+ KEY_USE_TENS = 0x1,
+ KEY_USE_CONT = 0x2,
+ KEY_USE_BIAS = 0x4,
+ KEY_USE_EASE_TO = 0x8,
+ KEY_USE_EASE_FROM = 0x10
+ };
// ********************************************************************
// Basic chunks which can be found everywhere in the file
- CHUNK_VERSION = 0x0002,
- CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B
- CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B
+ CHUNK_VERSION = 0x0002,
+ CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B
+ CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B
// Linear color values (gamma = 2.2?)
- CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B
- CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B
+ CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B
+ CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B
- CHUNK_PERCENTW = 0x0030, // int2 percentage
- CHUNK_PERCENTF = 0x0031, // float4 percentage
- CHUNK_PERCENTD = 0x0032, // float8 percentage
+ CHUNK_PERCENTW = 0x0030, // int2 percentage
+ CHUNK_PERCENTF = 0x0031, // float4 percentage
+ CHUNK_PERCENTD = 0x0032, // float8 percentage
// Prj master chunk
- CHUNK_PRJ = 0xC23D,
+ CHUNK_PRJ = 0xC23D,
// MDLI master chunk
- CHUNK_MLI = 0x3DAA,
+ CHUNK_MLI = 0x3DAA,
// Primary main chunk of the .3ds file
- CHUNK_MAIN = 0x4D4D,
+ CHUNK_MAIN = 0x4D4D,
// Mesh main chunk
- CHUNK_OBJMESH = 0x3D3D,
+ CHUNK_OBJMESH = 0x3D3D,
// Specifies the background color of the .3ds file
// This is passed through the material system for
// viewing purposes.
- CHUNK_BKGCOLOR = 0x1200,
+ CHUNK_BKGCOLOR = 0x1200,
// Specifies the ambient base color of the scene.
// This is added to all materials in the file
- CHUNK_AMBCOLOR = 0x2100,
+ CHUNK_AMBCOLOR = 0x2100,
// Specifies the background image for the whole scene
// This value is passed through the material system
// to the viewer
- CHUNK_BIT_MAP = 0x1100,
- CHUNK_BIT_MAP_EXISTS = 0x1101,
+ CHUNK_BIT_MAP = 0x1100,
+ CHUNK_BIT_MAP_EXISTS = 0x1101,
// Viewport related stuff. Ignored
@@ -177,171 +173,222 @@ public:
// Mesh chunks
- CHUNK_OBJBLOCK = 0x4000,
- CHUNK_TRIMESH = 0x4100,
- CHUNK_VERTLIST = 0x4110,
+ CHUNK_OBJBLOCK = 0x4000,
+ CHUNK_TRIMESH = 0x4100,
+ CHUNK_VERTLIST = 0x4110,
CHUNK_VERTFLAGS = 0x4111,
- CHUNK_FACELIST = 0x4120,
- CHUNK_FACEMAT = 0x4130,
- CHUNK_MAPLIST = 0x4140,
- CHUNK_SMOOLIST = 0x4150,
- CHUNK_TRMATRIX = 0x4160,
+ CHUNK_FACELIST = 0x4120,
+ CHUNK_FACEMAT = 0x4130,
+ CHUNK_MAPLIST = 0x4140,
+ CHUNK_SMOOLIST = 0x4150,
+ CHUNK_TRMATRIX = 0x4160,
CHUNK_MESHCOLOR = 0x4165,
- CHUNK_TXTINFO = 0x4170,
- CHUNK_LIGHT = 0x4600,
- CHUNK_CAMERA = 0x4700,
+ CHUNK_TXTINFO = 0x4170,
+ CHUNK_LIGHT = 0x4600,
+ CHUNK_CAMERA = 0x4700,
CHUNK_HIERARCHY = 0x4F00,
// Specifies the global scaling factor. This is applied
// to the root node's transformation matrix
- CHUNK_MASTER_SCALE = 0x0100,
+ CHUNK_MASTER_SCALE = 0x0100,
// Material chunks
- CHUNK_MAT_MATERIAL = 0xAFFF,
+ CHUNK_MAT_MATERIAL = 0xAFFF,
- // asciiz containing the name of the material
- CHUNK_MAT_MATNAME = 0xA000,
- CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk
- CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk
- CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk
+ // asciiz containing the name of the material
+ CHUNK_MAT_MATNAME = 0xA000,
+ CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk
+ CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk
+ CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk
- // Specifies the shininess of the material
- // followed by percentage chunk
- CHUNK_MAT_SHININESS = 0xA040,
- CHUNK_MAT_SHININESS_PERCENT = 0xA041 ,
+ // Specifies the shininess of the material
+ // followed by percentage chunk
+ CHUNK_MAT_SHININESS = 0xA040,
+ CHUNK_MAT_SHININESS_PERCENT = 0xA041,
- // Specifies the shading mode to be used
- // followed by a short
- CHUNK_MAT_SHADING = 0xA100,
+ // Specifies the shading mode to be used
+ // followed by a short
+ CHUNK_MAT_SHADING = 0xA100,
- // NOTE: Emissive color (self illumination) seems not
- // to be a color but a single value, type is unknown.
- // Make the parser accept both of them.
- // followed by percentage chunk (?)
- CHUNK_MAT_SELF_ILLUM = 0xA080,
+ // NOTE: Emissive color (self illumination) seems not
+ // to be a color but a single value, type is unknown.
+ // Make the parser accept both of them.
+ // followed by percentage chunk (?)
+ CHUNK_MAT_SELF_ILLUM = 0xA080,
- // Always followed by percentage chunk (?)
- CHUNK_MAT_SELF_ILPCT = 0xA084,
+ // Always followed by percentage chunk (?)
+ CHUNK_MAT_SELF_ILPCT = 0xA084,
- // Always followed by percentage chunk
- CHUNK_MAT_TRANSPARENCY = 0xA050,
+ // Always followed by percentage chunk
+ CHUNK_MAT_TRANSPARENCY = 0xA050,
- // Diffuse texture channel 0
- CHUNK_MAT_TEXTURE = 0xA200,
+ // Diffuse texture channel 0
+ CHUNK_MAT_TEXTURE = 0xA200,
- // Contains opacity information for each texel
- CHUNK_MAT_OPACMAP = 0xA210,
+ // Contains opacity information for each texel
+ CHUNK_MAT_OPACMAP = 0xA210,
- // Contains a reflection map to be used to reflect
- // the environment. This is partially supported.
- CHUNK_MAT_REFLMAP = 0xA220,
+ // Contains a reflection map to be used to reflect
+ // the environment. This is partially supported.
+ CHUNK_MAT_REFLMAP = 0xA220,
- // Self Illumination map (emissive colors)
- CHUNK_MAT_SELFIMAP = 0xA33d,
+ // Self Illumination map (emissive colors)
+ CHUNK_MAT_SELFIMAP = 0xA33d,
- // Bumpmap. Not specified whether it is a heightmap
- // or a normal map. Assme it is a heightmap since
- // artist normally prefer this format.
- CHUNK_MAT_BUMPMAP = 0xA230,
+ // Bumpmap. Not specified whether it is a heightmap
+ // or a normal map. Assme it is a heightmap since
+ // artist normally prefer this format.
+ CHUNK_MAT_BUMPMAP = 0xA230,
- // Specular map. Seems to influence the specular color
- CHUNK_MAT_SPECMAP = 0xA204,
+ // Specular map. Seems to influence the specular color
+ CHUNK_MAT_SPECMAP = 0xA204,
- // Holds shininess data.
- CHUNK_MAT_MAT_SHINMAP = 0xA33C,
+ // Holds shininess data.
+ CHUNK_MAT_MAT_SHINMAP = 0xA33C,
- // Scaling in U/V direction.
- // (need to gen separate UV coordinate set
- // and do this by hand)
- CHUNK_MAT_MAP_USCALE = 0xA354,
- CHUNK_MAT_MAP_VSCALE = 0xA356,
+ // Scaling in U/V direction.
+ // (need to gen separate UV coordinate set
+ // and do this by hand)
+ CHUNK_MAT_MAP_USCALE = 0xA354,
+ CHUNK_MAT_MAP_VSCALE = 0xA356,
- // Translation in U/V direction.
- CHUNK_MAT_MAP_UOFFSET = 0xA358,
- CHUNK_MAT_MAP_VOFFSET = 0xA35a,
+ // Translation in U/V direction.
+ CHUNK_MAT_MAP_UOFFSET = 0xA358,
+ CHUNK_MAT_MAP_VOFFSET = 0xA35a,
- // UV-coordinates rotation around the z-axis
- // Assumed to be in radians.
- CHUNK_MAT_MAP_ANG = 0xA35C,
+ // UV-coordinates rotation around the z-axis
+ // Assumed to be in radians.
+ CHUNK_MAT_MAP_ANG = 0xA35C,
- // Tiling flags for 3DS files
- CHUNK_MAT_MAP_TILING = 0xa351,
+ // Tiling flags for 3DS files
+ CHUNK_MAT_MAP_TILING = 0xa351,
- // Specifies the file name of a texture
- CHUNK_MAPFILE = 0xA300,
+ // Specifies the file name of a texture
+ CHUNK_MAPFILE = 0xA300,
- // Specifies whether a materail requires two-sided rendering
- CHUNK_MAT_TWO_SIDE = 0xA081,
+ // Specifies whether a materail requires two-sided rendering
+ CHUNK_MAT_TWO_SIDE = 0xA081,
// Main keyframer chunk. Contains translation/rotation/scaling data
- CHUNK_KEYFRAMER = 0xB000,
+ CHUNK_KEYFRAMER = 0xB000,
// Supported sub chunks
- CHUNK_TRACKINFO = 0xB002,
- CHUNK_TRACKOBJNAME = 0xB010,
- CHUNK_TRACKDUMMYOBJNAME = 0xB011,
- CHUNK_TRACKPIVOT = 0xB013,
- CHUNK_TRACKPOS = 0xB020,
- CHUNK_TRACKROTATE = 0xB021,
- CHUNK_TRACKSCALE = 0xB022,
+ CHUNK_TRACKINFO = 0xB002,
+ CHUNK_TRACKOBJNAME = 0xB010,
+ CHUNK_TRACKDUMMYOBJNAME = 0xB011,
+ CHUNK_TRACKPIVOT = 0xB013,
+ CHUNK_TRACKPOS = 0xB020,
+ CHUNK_TRACKROTATE = 0xB021,
+ CHUNK_TRACKSCALE = 0xB022,
// Keyframes for various other stuff in the file
// Partially ignored
- CHUNK_AMBIENTKEY = 0xB001,
- CHUNK_TRACKMORPH = 0xB026,
- CHUNK_TRACKHIDE = 0xB029,
- CHUNK_OBJNUMBER = 0xB030,
- CHUNK_TRACKCAMERA = 0xB003,
- CHUNK_TRACKFOV = 0xB023,
- CHUNK_TRACKROLL = 0xB024,
- CHUNK_TRACKCAMTGT = 0xB004,
- CHUNK_TRACKLIGHT = 0xB005,
- CHUNK_TRACKLIGTGT = 0xB006,
- CHUNK_TRACKSPOTL = 0xB007,
- CHUNK_FRAMES = 0xB008,
+ CHUNK_AMBIENTKEY = 0xB001,
+ CHUNK_TRACKMORPH = 0xB026,
+ CHUNK_TRACKHIDE = 0xB029,
+ CHUNK_OBJNUMBER = 0xB030,
+ CHUNK_TRACKCAMERA = 0xB003,
+ CHUNK_TRACKFOV = 0xB023,
+ CHUNK_TRACKROLL = 0xB024,
+ CHUNK_TRACKCAMTGT = 0xB004,
+ CHUNK_TRACKLIGHT = 0xB005,
+ CHUNK_TRACKLIGTGT = 0xB006,
+ CHUNK_TRACKSPOTL = 0xB007,
+ CHUNK_FRAMES = 0xB008,
// light sub-chunks
- CHUNK_DL_OFF = 0x4620,
- CHUNK_DL_OUTER_RANGE = 0x465A,
- CHUNK_DL_INNER_RANGE = 0x4659,
- CHUNK_DL_MULTIPLIER = 0x465B,
- CHUNK_DL_EXCLUDE = 0x4654,
- CHUNK_DL_ATTENUATE = 0x4625,
- CHUNK_DL_SPOTLIGHT = 0x4610,
+ CHUNK_DL_OFF = 0x4620,
+ CHUNK_DL_OUTER_RANGE = 0x465A,
+ CHUNK_DL_INNER_RANGE = 0x4659,
+ CHUNK_DL_MULTIPLIER = 0x465B,
+ CHUNK_DL_EXCLUDE = 0x4654,
+ CHUNK_DL_ATTENUATE = 0x4625,
+ CHUNK_DL_SPOTLIGHT = 0x4610,
// camera sub-chunks
- CHUNK_CAM_RANGES = 0x4720
+ CHUNK_CAM_RANGES = 0x4720
};
// ---------------------------------------------------------------------------
/** Helper structure representing a 3ds mesh face */
-struct Face : public FaceWithSmoothingGroup
-{
+struct Face : public FaceWithSmoothingGroup {
+#ifdef _WIN32
+#pragma warning(disable : 4315)
+#endif
/** Helper structure representing a texture */
struct Texture {
//! Default constructor
Texture() AI_NO_EXCEPT
- : mOffsetU (0.0)
- , mOffsetV (0.0)
- , mScaleU (1.0)
- , mScaleV (1.0)
- , mRotation (0.0)
- , mMapMode (aiTextureMapMode_Wrap)
- , bPrivate()
- , iUVSrc (0) {
+ : mTextureBlend(0.0f),
+ mMapName(),
+ mOffsetU(0.0),
+ mOffsetV(0.0),
+ mScaleU(1.0),
+ mScaleV(1.0),
+ mRotation(0.0),
+ mMapMode(aiTextureMapMode_Wrap),
+ bPrivate(),
+ iUVSrc(0) {
mTextureBlend = get_qnan();
+ Texture(const Texture &other) :
+ mTextureBlend(other.mTextureBlend),
+ mMapName(other.mMapName),
+ mOffsetU(other.mOffsetU),
+ mOffsetV(other.mOffsetV),
+ mScaleU(other.mScaleU),
+ mScaleV(other.mScaleV),
+ mRotation(other.mRotation),
+ mMapMode(other.mMapMode),
+ bPrivate(other.bPrivate),
+ iUVSrc(other.iUVSrc) {
+ // empty
+ }
+ Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)),
+ mMapName(std::move(other.mMapName)),
+ mOffsetU(std::move(other.mOffsetU)),
+ mOffsetV(std::move(other.mOffsetV)),
+ mScaleU(std::move(other.mScaleU)),
+ mScaleV(std::move(other.mScaleV)),
+ mRotation(std::move(other.mRotation)),
+ mMapMode(std::move(other.mMapMode)),
+ bPrivate(std::move(other.bPrivate)),
+ iUVSrc(std::move(other.iUVSrc)) {
+ Texture &operator=(Texture &&other) AI_NO_EXCEPT {
+ if (this == &other) {
+ return *this;
+ mTextureBlend = std::move(other.mTextureBlend);
+ mMapName = std::move(other.mMapName);
+ mOffsetU = std::move(other.mOffsetU);
+ mOffsetV = std::move(other.mOffsetV);
+ mScaleU = std::move(other.mScaleU);
+ mScaleV = std::move(other.mScaleV);
+ mRotation = std::move(other.mRotation);
+ mMapMode = std::move(other.mMapMode);
+ bPrivate = std::move(other.bPrivate);
+ iUVSrc = std::move(other.iUVSrc);
//! Specifies the blend factor for the texture
ai_real mTextureBlend;
@@ -367,55 +414,81 @@ struct Texture {
/** Helper structure representing a 3ds material */
-struct Material
+struct Material {
//! Default constructor has been deleted
- Material() = delete;
+ Material() :
+ mName(),
+ mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
+ mSpecularExponent(ai_real(0.0)),
+ mShininessStrength(ai_real(1.0)),
+ mShading(Discreet3DS::Gouraud),
+ mTransparency(ai_real(1.0)),
+ mBumpHeight(ai_real(1.0)),
+ mTwoSided(false) {
//! Constructor with explicit name
- explicit Material(const std::string &name)
- : mName(name)
- , mDiffuse ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black
- , mSpecularExponent ( ai_real( 0.0 ) )
- , mShininessStrength ( ai_real( 1.0 ) )
- , mShading(Discreet3DS::Gouraud)
- , mTransparency ( ai_real( 1.0 ) )
- , mBumpHeight ( ai_real( 1.0 ) )
- , mTwoSided (false)
+ explicit Material(const std::string &name) :
+ mName(name),
+ Material(const Material &other) :
+ mName(other.mName),
+ mDiffuse(other.mDiffuse),
+ mSpecularExponent(other.mSpecularExponent),
+ mShininessStrength(other.mShininessStrength),
+ mSpecular(other.mSpecular),
+ mAmbient(other.mAmbient),
+ mShading(other.mShading),
+ mTransparency(other.mTransparency),
+ sTexDiffuse(other.sTexDiffuse),
+ sTexOpacity(other.sTexOpacity),
+ sTexSpecular(other.sTexSpecular),
+ sTexReflective(other.sTexReflective),
+ sTexBump(other.sTexBump),
+ sTexEmissive(other.sTexEmissive),
+ sTexShininess(other.sTexShininess),
+ mBumpHeight(other.mBumpHeight),
+ mEmissive(other.mEmissive),
+ sTexAmbient(other.sTexAmbient),
+ mTwoSided(other.mTwoSided) {
- Material(const Material &other) = default;
- Material &operator=(const Material &other) = default;
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
- Material(Material &&other) AI_NO_EXCEPT
- : mName(std::move(other.mName))
- , mDiffuse(std::move(other.mDiffuse))
- , mSpecularExponent(std::move(other.mSpecularExponent))
- , mShininessStrength(std::move(other.mShininessStrength))
- , mSpecular(std::move(other.mSpecular))
- , mAmbient(std::move(other.mAmbient))
- , mShading(std::move(other.mShading))
- , mTransparency(std::move(other.mTransparency))
- , sTexDiffuse(std::move(other.sTexDiffuse))
- , sTexOpacity(std::move(other.sTexOpacity))
- , sTexSpecular(std::move(other.sTexSpecular))
- , sTexReflective(std::move(other.sTexReflective))
- , sTexBump(std::move(other.sTexBump))
- , sTexEmissive(std::move(other.sTexEmissive))
- , sTexShininess(std::move(other.sTexShininess))
- , mBumpHeight(std::move(other.mBumpHeight))
- , mEmissive(std::move(other.mEmissive))
- , sTexAmbient(std::move(other.sTexAmbient))
- , mTwoSided(std::move(other.mTwoSided))
+ Material(Material &&other) AI_NO_EXCEPT :
+ mName(std::move(other.mName)),
+ mDiffuse(std::move(other.mDiffuse)),
+ mSpecularExponent(std::move(other.mSpecularExponent)),
+ mShininessStrength(std::move(other.mShininessStrength)),
+ mSpecular(std::move(other.mSpecular)),
+ mAmbient(std::move(other.mAmbient)),
+ mShading(std::move(other.mShading)),
+ mTransparency(std::move(other.mTransparency)),
+ sTexDiffuse(std::move(other.sTexDiffuse)),
+ sTexOpacity(std::move(other.sTexOpacity)),
+ sTexSpecular(std::move(other.sTexSpecular)),
+ sTexReflective(std::move(other.sTexReflective)),
+ sTexBump(std::move(other.sTexBump)),
+ sTexEmissive(std::move(other.sTexEmissive)),
+ sTexShininess(std::move(other.sTexShininess)),
+ mBumpHeight(std::move(other.mBumpHeight)),
+ mEmissive(std::move(other.mEmissive)),
+ sTexAmbient(std::move(other.sTexAmbient)),
+ mTwoSided(std::move(other.mTwoSided)) {
Material &operator=(Material &&other) AI_NO_EXCEPT {
if (this == &other) {
return *this;
@@ -444,9 +517,9 @@ struct Material
- virtual ~Material() {}
+ virtual ~Material() {
//! Name of the material
std::string mName;
@@ -491,18 +564,15 @@ struct Material
/** Helper structure to represent a 3ds file mesh */
-struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
+struct Mesh : public MeshWithSmoothingGroups<D3DS::Face> {
Mesh() = delete;
- explicit Mesh(const std::string &name)
+ explicit Mesh(const std::string &name) :
+ mName(name) {
//! Name of the mesh
@@ -519,62 +589,48 @@ struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
/** Float key - quite similar to aiVectorKey and aiQuatKey. Both are in the
C-API, so it would be difficult to make them a template. */
-struct aiFloatKey
- double mTime; ///< The time of this key
- ai_real mValue; ///< The value of this key
+struct aiFloatKey {
+ double mTime; ///< The time of this key
+ ai_real mValue; ///< The value of this key
#ifdef __cplusplus
// time is not compared
- bool operator == (const aiFloatKey& o) const
- {return o.mValue == this->mValue;}
+ bool operator==(const aiFloatKey &o) const { return o.mValue == this->mValue; }
- bool operator != (const aiFloatKey& o) const
- {return o.mValue != this->mValue;}
+ bool operator!=(const aiFloatKey &o) const { return o.mValue != this->mValue; }
// Only time is compared. This operator is defined
// for use with std::sort
- bool operator < (const aiFloatKey& o) const
- {return mTime < o.mTime;}
+ bool operator<(const aiFloatKey &o) const { return mTime < o.mTime; }
- bool operator > (const aiFloatKey& o) const
- {return mTime > o.mTime;}
+ bool operator>(const aiFloatKey &o) const { return mTime > o.mTime; }
#endif
/** Helper structure to represent a 3ds file node */
-struct Node
+struct Node {
Node() = delete;
- explicit Node(const std::string &name)
- : mParent(NULL)
- , mName(name)
- , mInstanceNumber(0)
- , mHierarchyPos (0)
- , mHierarchyIndex (0)
- , mInstanceCount (1)
- aRotationKeys.reserve (20);
- aPositionKeys.reserve (20);
- aScalingKeys.reserve (20);
+ explicit Node(const std::string &name) :
+ mParent(NULL), mName(name), mInstanceNumber(0), mHierarchyPos(0), mHierarchyIndex(0), mInstanceCount(1) {
+ aRotationKeys.reserve(20);
+ aPositionKeys.reserve(20);
+ aScalingKeys.reserve(20);
- ~Node()
- for (unsigned int i = 0; i < mChildren.size();++i)
+ ~Node() {
+ for (unsigned int i = 0; i < mChildren.size(); ++i)
delete mChildren[i];
//! Pointer to the parent node
- Node* mParent;
+ Node *mParent;
//! Holds all child nodes
- std::vector<Node*> mChildren;
+ std::vector<Node *> mChildren;
//! Name of the node
@@ -600,13 +656,12 @@ struct Node
//! Scaling keys loaded from the file
std::vector<aiVectorKey> aScalingKeys;
// For target lights (spot lights and directional lights):
// The position of the target
- std::vector< aiVectorKey > aTargetPositionKeys;
+ std::vector<aiVectorKey> aTargetPositionKeys;
// For cameras: the camera roll angle
- std::vector< aiFloatKey > aCameraRollKeys;
+ std::vector<aiFloatKey> aCameraRollKeys;
//! Pivot position loaded from the file
aiVector3D vPivot;
@@ -616,8 +671,7 @@ struct Node
//! Add a child node, setup the right parent node for it
//! \param pc Node to be 'adopted'
- inline Node& push_back(Node* pc)
+ inline Node &push_back(Node *pc) {
mChildren.push_back(pc);
pc->mParent = this;
@@ -625,8 +679,7 @@ struct Node
/** Helper structure analogue to aiScene */
-struct Scene
+struct Scene {
//! List of all materials loaded
//! NOTE: 3ds references materials globally
std::vector<Material> mMaterials;
@@ -635,17 +688,16 @@ struct Scene
std::vector<Mesh> mMeshes;
//! List of all cameras loaded
- std::vector<aiCamera*> mCameras;
+ std::vector<aiCamera *> mCameras;
//! List of all lights loaded
- std::vector<aiLight*> mLights;
+ std::vector<aiLight *> mLights;
//! Pointer to the root node of the scene
// --- moved to main class
// Node* pcRootNode;
} // end of namespace D3DS
} // end of namespace Assimp
@@ -72,7 +70,6 @@ static const aiImporterDesc desc = {
"3ds prj"
// Begins a new parsing block
// - Reads the current chunk and validates it
@@ -141,15 +138,13 @@ bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandle
// Loader registry entry
-const aiImporterDesc* Discreet3DSImporter::GetInfo () const
+const aiImporterDesc* Discreet3DSImporter::GetInfo () const {
return &desc;
// Setup configuration properties
-void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/)
+void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/) {
// nothing to be done for the moment
@@ -158,13 +153,13 @@ void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/)
void Discreet3DSImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
- StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
+ StreamReaderLE theStream(pIOHandler->Open(pFile,"rb"));
// We should have at least one chunk
- if (stream.GetRemainingSize() < 16) {
+ if (theStream.GetRemainingSize() < 16) {
throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile);
- this->stream = &stream;
+ this->stream = &theStream;
// Allocate our temporary 3DS representation
D3DS::Scene _scene;
@@ -200,7 +195,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh);
- // Replace all occurences of the default material with a
+ // Replace all occurrences of the default material with a
// valid material. Generate it if no material containing
// DEFAULT in its name has been found in the file
ReplaceDefaultMaterial();
@@ -227,8 +222,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
// Applies a master-scaling factor to the imported scene
-void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene)
+void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene) {
// There are some 3DS files with a zero scaling factor
if (!mMasterScale)mMasterScale = 1.0f;
else mMasterScale = 1.0f / mMasterScale;
@@ -599,16 +593,19 @@ void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCur
// Find a node with a specific name in the import hierarchy
-D3DS::Node* FindNode(D3DS::Node* root, const std::string& name)
- if (root->mName == name)
+D3DS::Node* FindNode(D3DS::Node* root, const std::string& name) {
+ if (root->mName == name) {
return root;
for (std::vector<D3DS::Node*>::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) {
- D3DS::Node* nd;
- if (( nd = FindNode(*it,name)))
+ D3DS::Node *nd = FindNode(*it, name);
+ if (nullptr != nd) {
return nd;
- return NULL;
+ return nullptr;
@@ -1081,7 +1078,7 @@ void Discreet3DSImporter::ParseMeshChunk()
mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd);
// Larger 3DS files could have multiple FACE chunks here
- chunkSize = stream->GetRemainingSizeToLimit();
+ chunkSize = (int)stream->GetRemainingSizeToLimit();
if ( chunkSize > (int) sizeof(Discreet3DS::Chunk ) )
ParseFaceChunk();
@@ -65,15 +65,11 @@ using namespace D3DS;
// ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files
*/
-class Discreet3DSImporter : public BaseImporter
+class Discreet3DSImporter : public BaseImporter {
Discreet3DSImporter();
~Discreet3DSImporter();
-public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details.
@@ -256,13 +256,13 @@ void D3MFExporter::writeBaseMaterials() {
tmp.clear();
hexDiffuseColor = "#";
- tmp = DecimalToHexa( color.r );
+ tmp = DecimalToHexa( (ai_real) color.r );
hexDiffuseColor += tmp;
- tmp = DecimalToHexa( color.g );
+ tmp = DecimalToHexa((ai_real)color.g);
- tmp = DecimalToHexa( color.b );
+ tmp = DecimalToHexa((ai_real)color.b);
- tmp = DecimalToHexa( color.a );
+ tmp = DecimalToHexa((ai_real)color.a);
} else {
hexDiffuseColor = "#FFFFFFFF";
@@ -68,8 +68,6 @@ public:
AC3DImporter();
~AC3DImporter();
// Represents an AC3D material
struct Material
@@ -245,8 +243,6 @@ private:
aiMaterial& matDest);
private:
// points to the next data line
const char* buffer;
@@ -268,7 +264,7 @@ private:
std::vector<aiLight*>* mLights;
// name counters
- unsigned int lights, groups, polys, worlds;
+ unsigned int mLightsCounter, mGroupsCounter, mPolysCounter, mWorldsCounter;
@@ -465,7 +465,7 @@ std::list<unsigned int> mesh_idx;
auto VertexIndex_GetMinimal = [](const std::list<SComplexFace>& pFaceList, const size_t* pBiggerThan) -> size_t
- size_t rv;
+ size_t rv=0;
if(pBiggerThan != nullptr)
@@ -80,7 +80,18 @@ struct Material : public D3DS::Material
Material(const Material &other) = default;
+ Material &operator=(const Material &other) {
+ avSubMaterials = other.avSubMaterials;
+ pcInstance = other.pcInstance;
+ bNeed = other.bNeed;
@@ -94,12 +105,12 @@ struct Material : public D3DS::Material
- Material &operator=(Material &&other) AI_NO_EXCEPT {
+ Material &operator=( Material &&other) AI_NO_EXCEPT {
- D3DS::Material::operator=(std::move(other));
+ //D3DS::Material::operator=(std::move(other));
avSubMaterials = std::move(other.avSubMaterials);
pcInstance = std::move(other.pcInstance);
@@ -49,19 +49,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssbinFileWriter.h"
#include <assimp/scene.h>
-#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
+#include <assimp/IOSystem.hpp>
namespace Assimp {
-void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) {
+void ExportSceneAssbin(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties * /*pProperties*/) {
DumpSceneToAssbin(
- pFile,
- "\0", // no command(s).
- pIOSystem,
- pScene,
- false, // shortened?
- false); // compressed?
+ pFile,
+ "\0", // no command(s).
+ pIOSystem,
+ pScene,
+ false, // shortened?
+ false); // compressed?
@@ -53,16 +51,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Assbin/AssbinLoader.h"
#include "Common/assbin_chunks.h"
#include <assimp/MemoryIOWrapper.h>
-#include <assimp/mesh.h>
#include <assimp/anim.h>
-#include <assimp/scene.h>
#include <assimp/importerdesc.h>
+#include <assimp/mesh.h>
+#include <assimp/scene.h>
#include <memory>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-# include <zlib.h>
+#include <zlib.h>
#else
-# include <contrib/zlib/zlib.h>
+#include <contrib/zlib/zlib.h>
using namespace Assimp;
@@ -81,94 +79,97 @@ static const aiImporterDesc desc = {
// -----------------------------------------------------------------------------------
-const aiImporterDesc* AssbinImporter::GetInfo() const {
+const aiImporterDesc *AssbinImporter::GetInfo() const {
-bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const {
- IOStream * in = pIOHandler->Open(pFile);
+bool AssbinImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
+ IOStream *in = pIOHandler->Open(pFile);
if (nullptr == in) {
return false;
char s[32];
- in->Read( s, sizeof(char), 32 );
+ in->Read(s, sizeof(char), 32);
pIOHandler->Close(in);
- return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0;
+ return strncmp(s, "ASSIMP.binary-dump.", 19) == 0;
template <typename T>
-T Read(IOStream * stream) {
+T Read(IOStream *stream) {
T t;
- size_t res = stream->Read( &t, sizeof(T), 1 );
- if(res != 1)
+ size_t res = stream->Read(&t, sizeof(T), 1);
+ if (res != 1) {
throw DeadlyImportError("Unexpected EOF");
return t;
template <>
-aiVector3D Read<aiVector3D>(IOStream * stream) {
+aiVector3D Read<aiVector3D>(IOStream *stream) {
aiVector3D v;
- v.x = Read<float>(stream);
- v.y = Read<float>(stream);
- v.z = Read<float>(stream);
+ v.x = Read<ai_real>(stream);
+ v.y = Read<ai_real>(stream);
+ v.z = Read<ai_real>(stream);
return v;
-aiColor4D Read<aiColor4D>(IOStream * stream) {
+aiColor4D Read<aiColor4D>(IOStream *stream) {
aiColor4D c;
- c.r = Read<float>(stream);
- c.g = Read<float>(stream);
- c.b = Read<float>(stream);
- c.a = Read<float>(stream);
+ c.r = Read<ai_real>(stream);
+ c.g = Read<ai_real>(stream);
+ c.b = Read<ai_real>(stream);
+ c.a = Read<ai_real>(stream);
return c;
-aiQuaternion Read<aiQuaternion>(IOStream * stream) {
+aiQuaternion Read<aiQuaternion>(IOStream *stream) {
aiQuaternion v;
- v.w = Read<float>(stream);
+ v.w = Read<ai_real>(stream);
-aiString Read<aiString>(IOStream * stream) {
+aiString Read<aiString>(IOStream *stream) {
aiString s;
- stream->Read(&s.length,4,1);
- if(s.length)
- stream->Read(s.data,s.length,1);
+ stream->Read(&s.length, 4, 1);
+ if (s.length) {
+ stream->Read(s.data, s.length, 1);
s.data[s.length] = 0;
return s;
-aiVertexWeight Read<aiVertexWeight>(IOStream * stream) {
+aiVertexWeight Read<aiVertexWeight>(IOStream *stream) {
aiVertexWeight w;
w.mVertexId = Read<unsigned int>(stream);
- w.mWeight = Read<float>(stream);
+ w.mWeight = Read<ai_real>(stream);
return w;
-aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream) {
+aiMatrix4x4 Read<aiMatrix4x4>(IOStream *stream) {
aiMatrix4x4 m;
- for (unsigned int i = 0; i < 4;++i) {
- for (unsigned int i2 = 0; i2 < 4;++i2) {
- m[i][i2] = Read<float>(stream);
+ for (unsigned int i = 0; i < 4; ++i) {
+ for (unsigned int i2 = 0; i2 < 4; ++i2) {
+ m[i][i2] = Read<ai_real>(stream);
return m;
@@ -176,7 +177,7 @@ aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream) {
-aiVectorKey Read<aiVectorKey>(IOStream * stream) {
+aiVectorKey Read<aiVectorKey>(IOStream *stream) {
aiVectorKey v;
v.mTime = Read<double>(stream);
v.mValue = Read<aiVector3D>(stream);
@@ -185,7 +186,7 @@ aiVectorKey Read<aiVectorKey>(IOStream * stream) {
-aiQuatKey Read<aiQuatKey>(IOStream * stream) {
+aiQuatKey Read<aiQuatKey>(IOStream *stream) {
aiQuatKey v;
v.mValue = Read<aiQuaternion>(stream);
@@ -194,27 +195,27 @@ aiQuatKey Read<aiQuatKey>(IOStream * stream) {
-void ReadArray( IOStream *stream, T * out, unsigned int size) {
- ai_assert( nullptr != stream );
- ai_assert( nullptr != out );
+void ReadArray(IOStream *stream, T *out, unsigned int size) {
+ ai_assert(nullptr != stream);
+ ai_assert(nullptr != out);
- for (unsigned int i=0; i<size; i++) {
+ for (unsigned int i = 0; i < size; i++) {
out[i] = Read<T>(stream);
-void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n ) {
+void ReadBounds(IOStream *stream, T * /*p*/, unsigned int n) {
// not sure what to do here, the data isn't really useful.
- stream->Seek( sizeof(T) * n, aiOrigin_CUR );
+ stream->Seek(sizeof(T) * n, aiOrigin_CUR);
-void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode* parent ) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODE)
+void AssbinImporter::ReadBinaryNode(IOStream *stream, aiNode **onode, aiNode *parent) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODE)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
- /*uint32_t size =*/ Read<uint32_t>(stream);
+ /*uint32_t size =*/Read<uint32_t>(stream);
std::unique_ptr<aiNode> node(new aiNode());
@@ -222,14 +223,13 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode*
node->mTransformation = Read<aiMatrix4x4>(stream);
unsigned numChildren = Read<unsigned int>(stream);
unsigned numMeshes = Read<unsigned int>(stream);
- unsigned int nb_metadata = Read<unsigned int>(stream);
+ unsigned int nb_metadata = Read<unsigned int>(stream);
- if(parent) {
+ if (parent) {
node->mParent = parent;
- if (numMeshes)
+ if (numMeshes) {
node->mMeshes = new unsigned int[numMeshes];
for (unsigned int i = 0; i < numMeshes; ++i) {
node->mMeshes[i] = Read<unsigned int>(stream);
@@ -238,19 +238,19 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode*
if (numChildren) {
- node->mChildren = new aiNode*[numChildren];
+ node->mChildren = new aiNode *[numChildren];
for (unsigned int i = 0; i < numChildren; ++i) {
- ReadBinaryNode( stream, &node->mChildren[i], node.get() );
+ ReadBinaryNode(stream, &node->mChildren[i], node.get());
node->mNumChildren++;
- if ( nb_metadata > 0 ) {
+ if (nb_metadata > 0) {
node->mMetaData = aiMetadata::Alloc(nb_metadata);
for (unsigned int i = 0; i < nb_metadata; ++i) {
node->mMetaData->mKeys[i] = Read<aiString>(stream);
- node->mMetaData->mValues[i].mType = (aiMetadataType) Read<uint16_t>(stream);
- void* data = nullptr;
+ node->mMetaData->mValues[i].mType = (aiMetadataType)Read<uint16_t>(stream);
+ void *data = nullptr;
switch (node->mMetaData->mValues[i].mType) {
case AI_BOOL:
@@ -263,7 +263,7 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode*
data = new uint64_t(Read<uint64_t>(stream));
break;
case AI_FLOAT:
- data = new float(Read<float>(stream));
+ data = new ai_real(Read<ai_real>(stream));
case AI_DOUBLE:
data = new double(Read<double>(stream));
@@ -281,17 +281,17 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode*
- node->mMetaData->mValues[i].mData = data;
- }
+ node->mMetaData->mValues[i].mData = data;
*onode = node.release();
-void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIBONE)
+void AssbinImporter::ReadBinaryBone(IOStream *stream, aiBone *b) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIBONE)
b->mName = Read<aiString>(stream);
b->mNumWeights = Read<unsigned int>(stream);
@@ -300,23 +300,24 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) {
// for the moment we write dumb min/max values for the bones, too.
// maybe I'll add a better, hash-like solution later
if (shortened) {
- ReadBounds(stream,b->mWeights,b->mNumWeights);
+ ReadBounds(stream, b->mWeights, b->mNumWeights);
// else write as usual
b->mWeights = new aiVertexWeight[b->mNumWeights];
- ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights);
+ ReadArray<aiVertexWeight>(stream, b->mWeights, b->mNumWeights);
static bool fitsIntoUI16(unsigned int mNumVertices) {
- return ( mNumVertices < (1u<<16) );
+ return (mNumVertices < (1u << 16));
-void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMESH)
+void AssbinImporter::ReadBinaryMesh(IOStream *stream, aiMesh *mesh) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMESH)
mesh->mPrimitiveTypes = Read<unsigned int>(stream);
mesh->mNumVertices = Read<unsigned int>(stream);
@@ -329,48 +330,48 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
if (c & ASSBIN_MESH_HAS_POSITIONS) {
- ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
- } else {
+ ReadBounds(stream, mesh->mVertices, mesh->mNumVertices);
+ } else {
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
- ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices);
+ ReadArray<aiVector3D>(stream, mesh->mVertices, mesh->mNumVertices);
if (c & ASSBIN_MESH_HAS_NORMALS) {
- ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
+ ReadBounds(stream, mesh->mNormals, mesh->mNumVertices);
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
- ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices);
+ ReadArray<aiVector3D>(stream, mesh->mNormals, mesh->mNumVertices);
if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) {
- ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
- ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
+ ReadBounds(stream, mesh->mTangents, mesh->mNumVertices);
+ ReadBounds(stream, mesh->mBitangents, mesh->mNumVertices);
mesh->mTangents = new aiVector3D[mesh->mNumVertices];
- ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices);
+ ReadArray<aiVector3D>(stream, mesh->mTangents, mesh->mNumVertices);
mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
- ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices);
+ ReadArray<aiVector3D>(stream, mesh->mBitangents, mesh->mNumVertices);
- for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS; ++n) {
if (!(c & ASSBIN_MESH_HAS_COLOR(n))) {
- ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
+ ReadBounds(stream, mesh->mColors[n], mesh->mNumVertices);
mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
- ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices);
+ ReadArray<aiColor4D>(stream, mesh->mColors[n], mesh->mNumVertices);
- for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++n) {
if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n))) {
@@ -379,11 +380,11 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
- ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
+ ReadBounds(stream, mesh->mTextureCoords[n], mesh->mNumVertices);
mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
- ReadArray<aiVector3D>(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
+ ReadArray<aiVector3D>(stream, mesh->mTextureCoords[n], mesh->mNumVertices);
@@ -393,20 +394,20 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
// using Assimp's standard hashing function.
Read<unsigned int>(stream);
// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
mesh->mFaces = new aiFace[mesh->mNumFaces];
- for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
- aiFace& f = mesh->mFaces[i];
+ for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
+ aiFace &f = mesh->mFaces[i];
static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff");
f.mNumIndices = Read<uint16_t>(stream);
f.mIndices = new unsigned int[f.mNumIndices];
- for (unsigned int a = 0; a < f.mNumIndices;++a) {
+ for (unsigned int a = 0; a < f.mNumIndices; ++a) {
// Check if unsigned short ( 16 bit ) are big enought for the indices
- if ( fitsIntoUI16( mesh->mNumVertices ) ) {
+ if (fitsIntoUI16(mesh->mNumVertices)) {
f.mIndices[a] = Read<uint16_t>(stream);
f.mIndices[a] = Read<unsigned int>(stream);
@@ -417,19 +418,19 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
// write bones
if (mesh->mNumBones) {
- mesh->mBones = new C_STRUCT aiBone*[mesh->mNumBones];
- for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+ mesh->mBones = new C_STRUCT aiBone *[mesh->mNumBones];
+ for (unsigned int a = 0; a < mesh->mNumBones; ++a) {
mesh->mBones[a] = new aiBone();
- ReadBinaryBone(stream,mesh->mBones[a]);
+ ReadBinaryBone(stream, mesh->mBones[a]);
-void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY)
+void AssbinImporter::ReadBinaryMaterialProperty(IOStream *stream, aiMaterialProperty *prop) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY)
prop->mKey = Read<aiString>(stream);
prop->mSemantic = Read<unsigned int>(stream);
@@ -437,36 +438,34 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro
prop->mDataLength = Read<unsigned int>(stream);
prop->mType = (aiPropertyTypeInfo)Read<unsigned int>(stream);
- prop->mData = new char [ prop->mDataLength ];
- stream->Read(prop->mData,1,prop->mDataLength);
+ prop->mData = new char[prop->mDataLength];
+ stream->Read(prop->mData, 1, prop->mDataLength);
-void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIAL)
+void AssbinImporter::ReadBinaryMaterial(IOStream *stream, aiMaterial *mat) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIAL)
mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
- if (mat->mNumProperties)
- if (mat->mProperties)
+ if (mat->mNumProperties) {
+ if (mat->mProperties) {
delete[] mat->mProperties;
- mat->mProperties = new aiMaterialProperty*[mat->mNumProperties];
- for (unsigned int i = 0; i < mat->mNumProperties;++i) {
+ mat->mProperties = new aiMaterialProperty *[mat->mNumProperties];
+ for (unsigned int i = 0; i < mat->mNumProperties; ++i) {
mat->mProperties[i] = new aiMaterialProperty();
- ReadBinaryMaterialProperty( stream, mat->mProperties[i]);
+ ReadBinaryMaterialProperty(stream, mat->mProperties[i]);
-void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODEANIM)
+void AssbinImporter::ReadBinaryNodeAnim(IOStream *stream, aiNodeAnim *nd) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODEANIM)
nd->mNodeName = Read<aiString>(stream);
nd->mNumPositionKeys = Read<unsigned int>(stream);
@@ -477,82 +476,82 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) {
if (nd->mNumPositionKeys) {
- ReadBounds(stream,nd->mPositionKeys,nd->mNumPositionKeys);
+ ReadBounds(stream, nd->mPositionKeys, nd->mNumPositionKeys);
} // else write as usual
else {
nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
- ReadArray<aiVectorKey>(stream,nd->mPositionKeys,nd->mNumPositionKeys);
+ ReadArray<aiVectorKey>(stream, nd->mPositionKeys, nd->mNumPositionKeys);
if (nd->mNumRotationKeys) {
- ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
+ ReadBounds(stream, nd->mRotationKeys, nd->mNumRotationKeys);
nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
- ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys);
+ ReadArray<aiQuatKey>(stream, nd->mRotationKeys, nd->mNumRotationKeys);
if (nd->mNumScalingKeys) {
- ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
+ ReadBounds(stream, nd->mScalingKeys, nd->mNumScalingKeys);
nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
- ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys);
+ ReadArray<aiVectorKey>(stream, nd->mScalingKeys, nd->mNumScalingKeys);
-void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIANIMATION)
+void AssbinImporter::ReadBinaryAnim(IOStream *stream, aiAnimation *anim) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIANIMATION)
- anim->mName = Read<aiString> (stream);
- anim->mDuration = Read<double> (stream);
- anim->mTicksPerSecond = Read<double> (stream);
+ anim->mName = Read<aiString>(stream);
+ anim->mDuration = Read<double>(stream);
+ anim->mTicksPerSecond = Read<double>(stream);
anim->mNumChannels = Read<unsigned int>(stream);
if (anim->mNumChannels) {
- anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ];
- for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+ anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
+ for (unsigned int a = 0; a < anim->mNumChannels; ++a) {
anim->mChannels[a] = new aiNodeAnim();
- ReadBinaryNodeAnim(stream,anim->mChannels[a]);
+ ReadBinaryNodeAnim(stream, anim->mChannels[a]);
-void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AITEXTURE)
+void AssbinImporter::ReadBinaryTexture(IOStream *stream, aiTexture *tex) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AITEXTURE)
tex->mWidth = Read<unsigned int>(stream);
tex->mHeight = Read<unsigned int>(stream);
- stream->Read( tex->achFormatHint, sizeof(char), HINTMAXTEXTURELEN - 1 );
+ stream->Read(tex->achFormatHint, sizeof(char), HINTMAXTEXTURELEN - 1);
- if(!shortened) {
+ if (!shortened) {
if (!tex->mHeight) {
- tex->pcData = new aiTexel[ tex->mWidth ];
- stream->Read(tex->pcData,1,tex->mWidth);
+ tex->pcData = new aiTexel[tex->mWidth];
+ stream->Read(tex->pcData, 1, tex->mWidth);
- tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ];
- stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4);
+ tex->pcData = new aiTexel[tex->mWidth * tex->mHeight];
+ stream->Read(tex->pcData, 1, tex->mWidth * tex->mHeight * 4);
-void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AILIGHT)
+void AssbinImporter::ReadBinaryLight(IOStream *stream, aiLight *l) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AILIGHT)
l->mName = Read<aiString>(stream);
l->mType = (aiLightSourceType)Read<unsigned int>(stream);
@@ -574,10 +573,10 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) {
-void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AICAMERA)
+void AssbinImporter::ReadBinaryCamera(IOStream *stream, aiCamera *cam) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AICAMERA)
cam->mName = Read<aiString>(stream);
cam->mPosition = Read<aiVector3D>(stream);
@@ -590,141 +589,139 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) {
-void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
- if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AISCENE)
+void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) {
+ if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AISCENE)
- scene->mFlags = Read<unsigned int>(stream);
- scene->mNumMeshes = Read<unsigned int>(stream);
- scene->mNumMaterials = Read<unsigned int>(stream);
+ scene->mFlags = Read<unsigned int>(stream);
+ scene->mNumMeshes = Read<unsigned int>(stream);
+ scene->mNumMaterials = Read<unsigned int>(stream);
scene->mNumAnimations = Read<unsigned int>(stream);
- scene->mNumTextures = Read<unsigned int>(stream);
- scene->mNumLights = Read<unsigned int>(stream);
- scene->mNumCameras = Read<unsigned int>(stream);
+ scene->mNumTextures = Read<unsigned int>(stream);
+ scene->mNumLights = Read<unsigned int>(stream);
+ scene->mNumCameras = Read<unsigned int>(stream);
// Read node graph
//scene->mRootNode = new aiNode[1];
- ReadBinaryNode( stream, &scene->mRootNode, (aiNode*)NULL );
+ ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)NULL);
// Read all meshes
if (scene->mNumMeshes) {
- scene->mMeshes = new aiMesh*[scene->mNumMeshes];
- memset(scene->mMeshes, 0, scene->mNumMeshes*sizeof(aiMesh*));
- for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+ scene->mMeshes = new aiMesh *[scene->mNumMeshes];
+ memset(scene->mMeshes, 0, scene->mNumMeshes * sizeof(aiMesh *));
+ for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
scene->mMeshes[i] = new aiMesh();
- ReadBinaryMesh( stream,scene->mMeshes[i]);
+ ReadBinaryMesh(stream, scene->mMeshes[i]);
// Read materials
if (scene->mNumMaterials) {
- scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
- memset(scene->mMaterials, 0, scene->mNumMaterials*sizeof(aiMaterial*));
- for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+ scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
+ memset(scene->mMaterials, 0, scene->mNumMaterials * sizeof(aiMaterial *));
+ for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
scene->mMaterials[i] = new aiMaterial();
- ReadBinaryMaterial(stream,scene->mMaterials[i]);
+ ReadBinaryMaterial(stream, scene->mMaterials[i]);
// Read all animations
if (scene->mNumAnimations) {
- scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
- memset(scene->mAnimations, 0, scene->mNumAnimations*sizeof(aiAnimation*));
- for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+ scene->mAnimations = new aiAnimation *[scene->mNumAnimations];
+ memset(scene->mAnimations, 0, scene->mNumAnimations * sizeof(aiAnimation *));
+ for (unsigned int i = 0; i < scene->mNumAnimations; ++i) {
scene->mAnimations[i] = new aiAnimation();
- ReadBinaryAnim(stream,scene->mAnimations[i]);
+ ReadBinaryAnim(stream, scene->mAnimations[i]);
// Read all textures
if (scene->mNumTextures) {
- scene->mTextures = new aiTexture*[scene->mNumTextures];
- memset(scene->mTextures, 0, scene->mNumTextures*sizeof(aiTexture*));
- for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+ scene->mTextures = new aiTexture *[scene->mNumTextures];
+ memset(scene->mTextures, 0, scene->mNumTextures * sizeof(aiTexture *));
+ for (unsigned int i = 0; i < scene->mNumTextures; ++i) {
scene->mTextures[i] = new aiTexture();
- ReadBinaryTexture(stream,scene->mTextures[i]);
+ ReadBinaryTexture(stream, scene->mTextures[i]);
// Read lights
if (scene->mNumLights) {
- scene->mLights = new aiLight*[scene->mNumLights];
- memset(scene->mLights, 0, scene->mNumLights*sizeof(aiLight*));
- for (unsigned int i = 0; i < scene->mNumLights;++i) {
+ scene->mLights = new aiLight *[scene->mNumLights];
+ memset(scene->mLights, 0, scene->mNumLights * sizeof(aiLight *));
+ for (unsigned int i = 0; i < scene->mNumLights; ++i) {
scene->mLights[i] = new aiLight();
- ReadBinaryLight(stream,scene->mLights[i]);
+ ReadBinaryLight(stream, scene->mLights[i]);
// Read cameras
if (scene->mNumCameras) {
- scene->mCameras = new aiCamera*[scene->mNumCameras];
- memset(scene->mCameras, 0, scene->mNumCameras*sizeof(aiCamera*));
- for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+ scene->mCameras = new aiCamera *[scene->mNumCameras];
+ memset(scene->mCameras, 0, scene->mNumCameras * sizeof(aiCamera *));
+ for (unsigned int i = 0; i < scene->mNumCameras; ++i) {
scene->mCameras[i] = new aiCamera();
- ReadBinaryCamera(stream,scene->mCameras[i]);
+ ReadBinaryCamera(stream, scene->mCameras[i]);
-void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) {
- IOStream * stream = pIOHandler->Open(pFile,"rb");
+void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
+ IOStream *stream = pIOHandler->Open(pFile, "rb");
if (nullptr == stream) {
return;
// signature
- stream->Seek( 44, aiOrigin_CUR );
+ stream->Seek(44, aiOrigin_CUR);
unsigned int versionMajor = Read<unsigned int>(stream);
unsigned int versionMinor = Read<unsigned int>(stream);
if (versionMinor != ASSBIN_VERSION_MINOR || versionMajor != ASSBIN_VERSION_MAJOR) {
- throw DeadlyImportError( "Invalid version, data format not compatible!" );
+ throw DeadlyImportError("Invalid version, data format not compatible!");
- /*unsigned int versionRevision =*/ Read<unsigned int>(stream);
- /*unsigned int compileFlags =*/ Read<unsigned int>(stream);
+ /*unsigned int versionRevision =*/Read<unsigned int>(stream);
+ /*unsigned int compileFlags =*/Read<unsigned int>(stream);
shortened = Read<uint16_t>(stream) > 0;
compressed = Read<uint16_t>(stream) > 0;
if (shortened)
- throw DeadlyImportError( "Shortened binaries are not supported!" );
+ throw DeadlyImportError("Shortened binaries are not supported!");
- stream->Seek( 256, aiOrigin_CUR ); // original filename
- stream->Seek( 128, aiOrigin_CUR ); // options
- stream->Seek( 64, aiOrigin_CUR ); // padding
+ stream->Seek(256, aiOrigin_CUR); // original filename
+ stream->Seek(128, aiOrigin_CUR); // options
+ stream->Seek(64, aiOrigin_CUR); // padding
if (compressed) {
uLongf uncompressedSize = Read<uint32_t>(stream);
uLongf compressedSize = static_cast<uLongf>(stream->FileSize() - stream->Tell());
- unsigned char * compressedData = new unsigned char[ compressedSize ];
- size_t len = stream->Read( compressedData, 1, compressedSize );
+ unsigned char *compressedData = new unsigned char[compressedSize];
+ size_t len = stream->Read(compressedData, 1, compressedSize);
ai_assert(len == compressedSize);
- unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
+ unsigned char *uncompressedData = new unsigned char[uncompressedSize];
- int res = uncompress( uncompressedData, &uncompressedSize, compressedData, (uLong) len );
- if(res != Z_OK)
- delete [] uncompressedData;
- delete [] compressedData;
+ int res = uncompress(uncompressedData, &uncompressedSize, compressedData, (uLong)len);
+ if (res != Z_OK) {
+ delete[] uncompressedData;
+ delete[] compressedData;
pIOHandler->Close(stream);
throw DeadlyImportError("Zlib decompression failed.");
- MemoryIOStream io( uncompressedData, uncompressedSize );
+ MemoryIOStream io(uncompressedData, uncompressedSize);
- ReadBinaryScene(&io,pScene);
+ ReadBinaryScene(&io, pScene);
delete[] uncompressedData;
delete[] compressedData;
- ReadBinaryScene(stream,pScene);
+ ReadBinaryScene(stream, pScene);
@@ -9,6 +9,9 @@ For details, see http://sourceforge.net/projects/libb64
const int CHARS_PER_LINE = 72;
+#pragma warning(push)
+#pragma warning(disable : 4244)
void base64_init_encodestate(base64_encodestate* state_in)
state_in->step = step_A;
@@ -107,3 +110,4 @@ int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
return (int)(codechar - code_out);
+#pragma warning(pop)
@@ -8,6 +8,10 @@ For details, see http://sourceforge.net/projects/libb64
#ifndef BASE64_CENCODE_H
#define BASE64_CENCODE_H
+#pragma warning(disable : 4127 )
+#endif // _WIN32
typedef enum
step_A, step_B, step_C
@@ -91,20 +91,20 @@ public:
base64_encodestate s;
base64_init_encodestate(&s);
- char* const out = new char[std::max(len * 2, static_cast<size_t>(16u))];
- const int n = base64_encode_block(reinterpret_cast<const char*>(buffer), static_cast<int>(len), out, &s);
- out[n + base64_encode_blockend(out + n, &s)] = '\0';
+ char* const cur_out = new char[std::max(len * 2, static_cast<size_t>(16u))];
+ const int n = base64_encode_block(reinterpret_cast<const char *>(buffer), static_cast<int>(len), cur_out, &s);
+ cur_out[n + base64_encode_blockend(cur_out + n, &s)] = '\0';
// base64 encoding may add newlines, but JSON strings may not contain 'real' newlines
// (only escaped ones). Remove any newlines in out.
- for (char* cur = out; *cur; ++cur) {
+ for (char *cur = cur_out; *cur; ++cur) {
if (*cur == '\n') {
*cur = ' ';
- buff << '\"' << out << "\"\n";
- delete[] out;
+ buff << '\"' << cur_out << "\"\n";
+ delete[] cur_out;
void StartObj(bool is_element = false) {
@@ -464,8 +464,8 @@ void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) {
case aiPTI_Float:
if (prop->mDataLength / sizeof(float) > 1) {
out.StartArray();
- for (unsigned int i = 0; i < prop->mDataLength / sizeof(float); ++i) {
- out.Element(reinterpret_cast<float*>(prop->mData)[i]);
+ for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(float); ++ii) {
+ out.Element(reinterpret_cast<float*>(prop->mData)[ii]);
out.EndArray();
@@ -477,8 +477,8 @@ void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) {
case aiPTI_Integer:
if (prop->mDataLength / sizeof(int) > 1) {
- for (unsigned int i = 0; i < prop->mDataLength / sizeof(int); ++i) {
- out.Element(reinterpret_cast<int*>(prop->mData)[i]);
+ for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(int); ++ii) {
+ out.Element(reinterpret_cast<int*>(prop->mData)[ii]);
@@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
@@ -373,25 +373,25 @@ void WriteDump(const char* pFile, const char* cmd, const aiScene* scene, IOStrea
ioprintf(io," size=\"%i\">\n\t\t\t\t",
static_cast<int>(prop->mDataLength/sizeof(float)));
- for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) {
- ioprintf(io,"%f ",*((float*)(prop->mData+p*sizeof(float))));
+ for (unsigned int pp = 0; pp < prop->mDataLength/sizeof(float);++pp) {
+ ioprintf(io,"%f ",*((float*)(prop->mData+pp*sizeof(float))));
else if (prop->mType == aiPTI_Integer) {
static_cast<int>(prop->mDataLength/sizeof(int)));
- for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) {
- ioprintf(io,"%i ",*((int*)(prop->mData+p*sizeof(int))));
+ for (unsigned int pp = 0; pp < prop->mDataLength/sizeof(int);++pp) {
+ ioprintf(io,"%i ",*((int*)(prop->mData+pp*sizeof(int))));
else if (prop->mType == aiPTI_Buffer) {
static_cast<int>(prop->mDataLength));
- for (unsigned int p = 0; p < prop->mDataLength;++p) {
- ioprintf(io,"%2x ",prop->mData[p]);
- if (p && 0 == p%30) {
+ for (unsigned int pp = 0; pp< prop->mDataLength;++pp) {
+ ioprintf(io,"%2x ",prop->mData[pp]);
+ if (pp && 0 == pp%30) {
ioprintf(io,"\n\t\t\t\t");
@@ -155,36 +155,37 @@ AI_WONT_RETURN void B3DImporter::Fail( string str ){
int B3DImporter::ReadByte(){
- if( _pos<_buf.size() ) {
- return _buf[_pos++];
- Fail( "EOF" );
- return 0;
+ if (_pos > _buf.size()) {
+ Fail("EOF");
+ return _buf[_pos++];
int B3DImporter::ReadInt(){
- if( _pos+4<=_buf.size() ){
- int n;
- memcpy(&n, &_buf[_pos], 4);
- _pos+=4;
- return n;
+ if (_pos + 4 > _buf.size()) {
+ int n;
+ memcpy(&n, &_buf[_pos], 4);
+ _pos+=4;
+ return n;
-float B3DImporter::ReadFloat(){
- float n;
- return 0.0f;
+float B3DImporter::ReadFloat() {
+ float n;
@@ -214,6 +215,9 @@ aiQuaternion B3DImporter::ReadQuat(){
string B3DImporter::ReadString(){
string str;
while( _pos<_buf.size() ){
char c=(char)ReadByte();
@@ -222,7 +226,6 @@ string B3DImporter::ReadString(){
str+=c;
return string();
@@ -247,7 +250,7 @@ void B3DImporter::ExitChunk(){
-unsigned B3DImporter::ChunkSize(){
+size_t B3DImporter::ChunkSize(){
return _stack.back()-_pos;
@@ -355,13 +358,13 @@ void B3DImporter::ReadVRTS(){
Fail( "Bad texcoord data" );
- int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
- int n_verts=ChunkSize()/sz;
+ int sz = 12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
+ size_t n_verts = ChunkSize()/sz;
int v0=static_cast<int>(_vertices.size());
_vertices.resize( v0+n_verts );
- for( int i=0;i<n_verts;++i ){
+ for( unsigned int i=0;i<n_verts;++i ){
Vertex &v=_vertices[v0+i];
memset( v.bones,0,sizeof(v.bones) );
@@ -377,14 +380,14 @@ void B3DImporter::ReadVRTS(){
ReadQuat(); //skip v 4bytes...
- for( int i=0;i<_tcsets;++i ){
+ for( int j=0;j<_tcsets;++j ){
float t[4]={0,0,0,0};
- for( int j=0;j<_tcsize;++j ){
- t[j]=ReadFloat();
+ for( int k=0;k<_tcsize;++k ){
+ t[k]=ReadFloat();
- t[1]=1-t[1];
- if( !i ) {
- v.texcoords=aiVector3D( t[0],t[1],t[2] );
+ t[1] = 1 - t[1];
+ if( !j ) {
+ v.texcoords = aiVector3D( t[0],t[1],t[2] );
@@ -408,10 +411,10 @@ void B3DImporter::ReadTRIS(int v0) {
mesh->mNumFaces = 0;
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
- int n_tris = ChunkSize() / 12;
+ size_t n_tris = ChunkSize() / 12;
aiFace *face = mesh->mFaces = new aiFace[n_tris];
- for (int i = 0; i < n_tris; ++i) {
+ for (unsigned int i = 0; i < n_tris; ++i) {
int i0 = ReadInt() + v0;
int i1 = ReadInt() + v0;
int i2 = ReadInt() + v0;
@@ -463,7 +466,7 @@ void B3DImporter::ReadBONE(int id) {
Vertex &v = _vertices[vertex];
for (int i = 0; i < 4; ++i) {
if (!v.weights[i]) {
- v.bones[i] = id;
+ v.bones[i] = static_cast<unsigned char>(id);
v.weights[i] = weight;
@@ -547,24 +550,24 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
vector<aiNode*> children;
while( ChunkSize() ){
- string t=ReadChunk();
- if( t=="MESH" ){
+ const string chunk = ReadChunk();
+ if (chunk == "MESH") {
unsigned int n= static_cast<unsigned int>(_meshes.size());
ReadMESH();
for( unsigned int i=n;i<static_cast<unsigned int>(_meshes.size());++i ){
meshes.push_back( i );
- }else if( t=="BONE" ){
+ } else if (chunk == "BONE") {
ReadBONE( nodeid );
- }else if( t=="ANIM" ){
+ } else if (chunk == "ANIM") {
ReadANIM();
- }else if( t=="KEYS" ){
+ } else if (chunk == "KEYS") {
if( !nodeAnim ){
nodeAnim.reset(new aiNodeAnim);
nodeAnim->mNodeName=node->mName;
ReadKEYS( nodeAnim.get() );
- }else if( t=="NODE" ){
+ } else if (chunk == "NODE") {
aiNode *child=ReadNODE( node );
children.push_back( child );
@@ -613,12 +616,12 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
- if( t=="TEXS" ){
+ if (chunk == "TEXS") {
ReadTEXS();
- }else if( t=="BRUS" ){
+ } else if (chunk == "BRUS") {
ReadBRUS();
ReadNODE( 0 );
ExitChunk();
@@ -656,48 +659,51 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
vector< vector<aiVertexWeight> > vweights( _nodes.size() );
- for( int i=0;i<n_verts;i+=3 ){
- for( int j=0;j<3;++j ){
- Vertex &v=_vertices[face->mIndices[j]];
+ for (int vertIdx = 0; vertIdx < n_verts; vertIdx += 3) {
+ for (int faceIndex = 0; faceIndex < 3; ++faceIndex) {
+ Vertex &v = _vertices[face->mIndices[faceIndex]];
*mv++=v.vertex;
if( mn ) *mn++=v.normal;
if( mc ) *mc++=v.texcoords;
- face->mIndices[j]=i+j;
+ face->mIndices[faceIndex] = vertIdx + faceIndex;
for( int k=0;k<4;++k ){
- if( !v.weights[k] ) break;
+ if( !v.weights[k] )
+ break;
- int bone=v.bones[k];
- float weight=v.weights[k];
+ int bone = v.bones[k];
+ float weight = v.weights[k];
- vweights[bone].push_back( aiVertexWeight(i+j,weight) );
+ vweights[bone].push_back(aiVertexWeight(vertIdx + faceIndex, weight));
++face;
vector<aiBone*> bones;
- for(size_t i=0;i<vweights.size();++i ){
- vector<aiVertexWeight> &weights=vweights[i];
- if( !weights.size() ) continue;
+ for (size_t weightIndx = 0; weightIndx < vweights.size(); ++weightIndx) {
+ vector<aiVertexWeight> &weights = vweights[weightIndx];
+ if (!weights.size()) {
+ continue;
- aiBone *bone=new aiBone;
+ aiBone *bone = new aiBone;
bones.push_back( bone );
- aiNode *bnode=_nodes[i];
+ aiNode *bnode = _nodes[weightIndx];
- bone->mName=bnode->mName;
- bone->mNumWeights= static_cast<unsigned int>(weights.size());
- bone->mWeights=to_array( weights );
+ bone->mName = bnode->mName;
+ bone->mNumWeights = static_cast<unsigned int>(weights.size());
+ bone->mWeights = to_array( weights );
- aiMatrix4x4 mat=bnode->mTransformation;
+ aiMatrix4x4 mat = bnode->mTransformation;
while( bnode->mParent ){
bnode=bnode->mParent;
mat=bnode->mTransformation * mat;
- bone->mOffsetMatrix=mat.Inverse();
+ bone->mOffsetMatrix = mat.Inverse();
mesh->mNumBones= static_cast<unsigned int>(bones.size());
mesh->mBones=to_array( bones );
@@ -82,7 +82,7 @@ private:
std::string ReadString();
std::string ReadChunk();
void ExitChunk();
- unsigned ChunkSize();
+ size_t ChunkSize();
template<class T>
T *to_array( const std::vector<T> &v );
@@ -112,10 +112,10 @@ private:
void ReadBB3D( aiScene *scene );
- unsigned _pos;
+ size_t _pos;
// unsigned _size;
std::vector<unsigned char> _buf;
- std::vector<unsigned> _stack;
+ std::vector<size_t> _stack;
std::vector<std::string> _textures;
std::vector<std::unique_ptr<aiMaterial> > _materials;
@@ -206,7 +206,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
inflateInit2(&zstream, 16+MAX_WBITS);
zstream.next_in = reinterpret_cast<Bytef*>( reader->GetPtr() );
- zstream.avail_in = reader->GetRemainingSize();
+ zstream.avail_in = (uInt) reader->GetRemainingSize();
size_t total = 0l;
@@ -429,7 +429,7 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
name.length = 1+ ASSIMP_itoa10(name.data+1,static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(conv_data.textures->size()));
conv_data.textures->push_back(new aiTexture());
- aiTexture* tex = conv_data.textures->back();
+ aiTexture* curTex = conv_data.textures->back();
// usually 'img->name' will be the original file name of the embedded textures,
// so we can extract the file extension from it.
@@ -439,19 +439,19 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
--s;
- tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
- tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
- tex->achFormatHint[2] = s+3>e ? '\0' : ::tolower( s[3] );
- tex->achFormatHint[3] = '\0';
+ curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower(s[1]);
+ curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower(s[2]);
+ curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower(s[3]);
+ curTex->achFormatHint[3] = '\0';
// tex->mHeight = 0;
- tex->mWidth = img->packedfile->size;
- uint8_t* ch = new uint8_t[tex->mWidth];
+ curTex->mWidth = img->packedfile->size;
+ uint8_t *ch = new uint8_t[curTex->mWidth];
conv_data.db.reader->SetCurrentPos(static_cast<size_t>( img->packedfile->data->val));
- conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth);
+ conv_data.db.reader->CopyAndAdvance(ch, curTex->mWidth);
- tex->pcData = reinterpret_cast<aiTexel*>(ch);
+ curTex->pcData = reinterpret_cast<aiTexel *>(ch);
LogInfo("Reading embedded texture, original file was "+std::string(img->name));
@@ -1078,9 +1078,9 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
const aiFace& f = out->mFaces[out->mNumFaces++];
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
- for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
- vo->x = v->uv[i][0];
- vo->y = v->uv[i][1];
+ for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
+ vo->x = v->uv[j][0];
+ vo->y = v->uv[j][1];
@@ -1098,8 +1098,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
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];
@@ -1139,9 +1138,9 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
@@ -57,52 +57,51 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp::Blender;
-template <typename T> BlenderModifier* god() {
+template <typename T>
+BlenderModifier *god() {
return new T();
// add all available modifiers here
-typedef BlenderModifier* (*fpCreateModifier)();
+typedef BlenderModifier *(*fpCreateModifier)();
static const fpCreateModifier creators[] = {
- &god<BlenderModifier_Mirror>,
- &god<BlenderModifier_Subdivision>,
+ &god<BlenderModifier_Mirror>,
+ &god<BlenderModifier_Subdivision>,
- NULL // sentinel
+ NULL // sentinel
-struct SharedModifierData : ElemBase
+struct SharedModifierData : ElemBase {
ModifierData modifier;
-void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
+void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_data, const Scene &in, const Object &orig_object) {
size_t cnt = 0u, ful = 0u;
// NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
// we're allowed to dereference the pointers without risking to crash. We might still be
// invoking UB btw - we're assuming that the ModifierData member of the respective modifier
// structures is at offset sizeof(vftable) with no padding.
- const SharedModifierData* cur = static_cast<const SharedModifierData *> ( orig_object.modifiers.first.get() );
- for (; cur; cur = static_cast<const SharedModifierData *> ( cur->modifier.next.get() ), ++ful) {
+ const SharedModifierData *cur = static_cast<const SharedModifierData *>(orig_object.modifiers.first.get());
+ for (; cur; cur = static_cast<const SharedModifierData *>(cur->modifier.next.get()), ++ful) {
ai_assert(cur->dna_type);
- const Structure* s = conv_data.db.dna.Get( cur->dna_type );
+ const Structure *s = conv_data.db.dna.Get(cur->dna_type);
if (!s) {
- ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type);
+ ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ", cur->dna_type);
continue;
// this is a common trait of all XXXMirrorData structures in BlenderDNA
- const Field* f = s->Get("modifier");
+ const Field *f = s->Get("modifier");
if (!f || f->offset != 0) {
ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0");
- s = conv_data.db.dna.Get( f->type );
+ s = conv_data.db.dna.Get(f->type);
if (!s || s->name != "ModifierData") {
ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member");
@@ -110,22 +109,22 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
// now, we can be sure that we should be fine to dereference *cur* as
// ModifierData (with the above note).
- const ModifierData& dat = cur->modifier;
+ const ModifierData &dat = cur->modifier;
- const fpCreateModifier* curgod = creators;
- std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
+ const fpCreateModifier *curgod = creators;
+ std::vector<BlenderModifier *>::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
- for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly
+ for (; *curgod; ++curgod, ++curmod) { // allocate modifiers on the fly
if (curmod == endmod) {
cached_modifiers->push_back((*curgod)());
endmod = cached_modifiers->end();
- curmod = endmod-1;
+ curmod = endmod - 1;
- BlenderModifier* const modifier = *curmod;
- if(modifier->IsActive(dat)) {
- modifier->DoIt(out,conv_data,*static_cast<const ElemBase *>(cur),in,orig_object);
+ BlenderModifier *const modifier = *curmod;
+ if (modifier->IsActive(dat)) {
+ modifier->DoIt(out, conv_data, *static_cast<const ElemBase *>(cur), in, orig_object);
cnt++;
curgod = NULL;
@@ -133,7 +132,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
if (curgod) {
- ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name);
+ ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ", dat.name);
@@ -141,26 +140,22 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
// object, we still can't say whether our modifier implementations were
// able to fully do their job.
if (ful) {
- ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name,
- "`, check log messages above for errors");
+ ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ", cnt, " of ", ful, " modifiers on `", orig_object.id.name,
+ "`, check log messages above for errors");
-bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin)
+bool BlenderModifier_Mirror ::IsActive(const ModifierData &modin) {
return modin.type == ModifierData::eModifierType_Mirror;
-void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
- const Scene& /*in*/,
- const Object& orig_object )
+void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const ElemBase &orig_modifier,
+ const Scene & /*in*/,
+ const Object &orig_object) {
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
- const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier);
+ const MirrorModifierData &mir = static_cast<const MirrorModifierData &>(orig_modifier);
ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
@@ -169,48 +164,55 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
// take all input meshes and clone them
for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
- aiMesh* mesh;
- SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]);
+ aiMesh *mesh;
+ SceneCombiner::Copy(&mesh, conv_data.meshes[out.mMeshes[i]]);
const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f;
const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
if (mir.mirror_ob) {
- const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- aiVector3D& v = mesh->mVertices[i];
+ const aiVector3D center(mir.mirror_ob->obmat[3][0], mir.mirror_ob->obmat[3][1], mir.mirror_ob->obmat[3][2]);
+ for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
+ aiVector3D &v = mesh->mVertices[j];
- v.x = center.x + xs*(center.x - v.x);
- v.y = center.y + ys*(center.y - v.y);
- v.z = center.z + zs*(center.z - v.z);
+ v.x = center.x + xs * (center.x - v.x);
+ v.y = center.y + ys * (center.y - v.y);
+ v.z = center.z + zs * (center.z - v.z);
- v.x *= xs;v.y *= ys;v.z *= zs;
+ v.x *= xs;
+ v.y *= ys;
+ v.z *= zs;
if (mesh->mNormals) {
- aiVector3D& v = mesh->mNormals[i];
+ aiVector3D &v = mesh->mNormals[j];
if (mesh->mTangents) {
- aiVector3D& v = mesh->mTangents[i];
+ aiVector3D &v = mesh->mTangents[j];
if (mesh->mBitangents) {
- aiVector3D& v = mesh->mBitangents[i];
+ aiVector3D &v = mesh->mBitangents[j];
@@ -218,82 +220,80 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
- aiVector3D& v = mesh->mTextureCoords[n][i];
- v.x *= us;v.y *= vs;
+ aiVector3D &v = mesh->mTextureCoords[n][j];
+ v.x *= us;
+ v.y *= vs;
// Only reverse the winding order if an odd number of axes were mirrored.
if (xs * ys * zs < 0) {
- for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
- aiFace& face = mesh->mFaces[i];
- for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
- std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
+ for (unsigned int j = 0; j < mesh->mNumFaces; ++j ) {
+ aiFace &face = mesh->mFaces[j];
+ for (unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
+ std::swap(face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
conv_data.meshes->push_back(mesh);
- unsigned int* nind = new unsigned int[out.mNumMeshes*2];
+ unsigned int *nind = new unsigned int[out.mNumMeshes * 2];
- std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
- std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
- [&out](unsigned int n) { return out.mNumMeshes + n; });
+ std::copy(out.mMeshes, out.mMeshes + out.mNumMeshes, nind);
+ std::transform(out.mMeshes, out.mMeshes + out.mNumMeshes, nind + out.mNumMeshes,
+ [&out](unsigned int n) { return out.mNumMeshes + n; });
delete[] out.mMeshes;
out.mMeshes = nind;
out.mNumMeshes *= 2;
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `",
- orig_object.id.name,"`");
+ orig_object.id.name, "`");
-bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
+bool BlenderModifier_Subdivision ::IsActive(const ModifierData &modin) {
return modin.type == ModifierData::eModifierType_Subsurf;
-void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
+void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data, const ElemBase &orig_modifier,
- const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier);
+ const SubsurfModifierData &mir = static_cast<const SubsurfModifierData &>(orig_modifier);
ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
Subdivider::Algorithm algo;
- switch (mir.subdivType)
- case SubsurfModifierData::TYPE_CatmullClarke:
- algo = Subdivider::CATMULL_CLARKE;
- break;
- case SubsurfModifierData::TYPE_Simple:
- ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
- default:
- ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType);
- return;
+ switch (mir.subdivType) {
+ case SubsurfModifierData::TYPE_CatmullClarke:
+ algo = Subdivider::CATMULL_CLARKE;
+ case SubsurfModifierData::TYPE_Simple:
+ ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
+ default:
+ ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ", mir.subdivType);
+ return;
std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
ai_assert(subd);
- if ( conv_data.meshes->empty() ) {
+ if (conv_data.meshes->empty()) {
- aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
- std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
+ aiMesh **const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
+ std::unique_ptr<aiMesh *[]> tempmeshes(new aiMesh *[out.mNumMeshes]());
- subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
- std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
+ subd->Subdivide(meshes, out.mNumMeshes, tempmeshes.get(), std::max(mir.renderLevels, mir.levels), true);
+ std::copy(tempmeshes.get(), tempmeshes.get() + out.mNumMeshes, meshes);
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `",
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
@@ -185,8 +185,6 @@ SET( Common_SRCS
Common/ScenePreprocessor.cpp
Common/ScenePreprocessor.h
Common/SkeletonMeshBuilder.cpp
- Common/SplitByBoneCountProcess.cpp
- Common/SplitByBoneCountProcess.h
Common/StandardShapes.cpp
Common/TargetAnimation.cpp
Common/TargetAnimation.h
@@ -737,6 +735,8 @@ SET( PostProcessing_SRCS
PostProcessing/ArmaturePopulate.h
PostProcessing/GenBoundingBoxesProcess.cpp
PostProcessing/GenBoundingBoxesProcess.h
+ PostProcessing/SplitByBoneCountProcess.cpp
+ PostProcessing/SplitByBoneCountProcess.h
SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
@@ -861,15 +861,15 @@ if ((CMAKE_COMPILER_IS_MINGW) AND (CMAKE_BUILD_TYPE MATCHES Debug))
SET_SOURCE_FILES_PROPERTIES(Importer/StepFile/StepFileGen1.cpp PROPERTIES STATIC_LIBRARY_FLAGS -Os )
-ADD_ASSIMP_IMPORTER( STEP
- Step/STEPFile.h
- Importer/StepFile/StepFileImporter.h
- Importer/StepFile/StepFileImporter.cpp
- Importer/StepFile/StepFileGen1.cpp
- Importer/StepFile/StepFileGen2.cpp
- Importer/StepFile/StepFileGen3.cpp
- Importer/StepFile/StepReaderGen.h
-)
+#ADD_ASSIMP_IMPORTER( STEP
+# Step/STEPFile.h
+# Importer/StepFile/StepFileImporter.h
+# Importer/StepFile/StepFileImporter.cpp
+# Importer/StepFile/StepFileGen1.cpp
+# Importer/StepFile/StepFileGen2.cpp
+# Importer/StepFile/StepFileGen3.cpp
+# Importer/StepFile/StepReaderGen.h
+#)
if ((NOT ASSIMP_NO_EXPORT) OR (NOT ASSIMP_EXPORTERS_ENABLED STREQUAL ""))
SET( Exporter_SRCS
@@ -886,7 +886,7 @@ SET( Extra_SRCS
SOURCE_GROUP( Extra FILES ${Extra_SRCS})
# irrXML
hunter_add_package(irrXML)
find_package(irrXML CONFIG REQUIRED)
@@ -894,7 +894,7 @@ ELSE()
# utf8
hunter_add_package(utf8)
find_package(utf8 CONFIG REQUIRED)
@@ -902,7 +902,7 @@ ELSE()
# polyclipping
hunter_add_package(polyclipping)
find_package(polyclipping CONFIG REQUIRED)
@@ -914,7 +914,7 @@ ELSE()
# poly2tri
hunter_add_package(poly2tri)
find_package(poly2tri CONFIG REQUIRED)
@@ -935,7 +935,7 @@ ELSE()
# minizip/unzip
hunter_add_package(minizip)
find_package(minizip CONFIG REQUIRED)
@@ -950,7 +950,7 @@ ELSE()
# zip (https://github.com/kuba--/zip)
hunter_add_package(zip)
find_package(zip CONFIG REQUIRED)
@@ -971,7 +971,7 @@ ELSE()
# openddlparser
hunter_add_package(openddlparser)
find_package(openddlparser CONFIG REQUIRED)
@@ -994,7 +994,7 @@ ELSE()
# Open3DGC
# Nothing to do, not available in Hunter yet.
SET ( open3dgc_SRCS
@@ -1035,7 +1035,7 @@ ENDIF()
# RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file
# has implementation for different platforms: WIN32, __MACH__ and other ("else" block).
FIND_PACKAGE(RT QUIET)
-IF (NOT HUNTER_ENABLED AND (RT_FOUND OR MSVC))
+IF (NOT ASSIMP_HUNTER_ENABLED AND (RT_FOUND OR MSVC))
SET( ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC 1 )
ADD_DEFINITIONS( -DASSIMP_IMPORTER_GLTF_USE_OPEN3DGC=1 )
ELSE ()
@@ -1045,7 +1045,7 @@ ELSE ()
# RapidJSON
hunter_add_package(RapidJSON)
find_package(RapidJSON CONFIG REQUIRED)
@@ -1068,7 +1068,7 @@ if ( MSVC )
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
endif ()
if (UNZIP_FOUND)
SET (unzip_compile_SRCS "")
else ()
@@ -1118,7 +1118,7 @@ SET( assimp_src
ADD_DEFINITIONS( -DOPENDDLPARSER_BUILD )
INCLUDE_DIRECTORIES(
${IRRXML_INCLUDE_DIR}
../contrib/openddlparser/include
@@ -1139,7 +1139,7 @@ TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
$<INSTALL_INTERFACE:include>
TARGET_LINK_LIBRARIES(assimp
PUBLIC
polyclipping::polyclipping
@@ -1212,7 +1212,7 @@ SET_TARGET_PROPERTIES( assimp PROPERTIES
if (APPLE)
- if (BUILD_FRAMEWORK)
+ if (ASSIMP_BUILD_FRAMEWORK)
SET_TARGET_PROPERTIES( assimp PROPERTIES
FRAMEWORK TRUE
FRAMEWORK_VERSION C
@@ -1232,7 +1232,7 @@ ENDIF()
# Build against external unzip, or add ../contrib/unzip so
# assimp can #include "unzip.h"
INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
@@ -1246,7 +1246,7 @@ IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
TARGET_LINK_LIBRARIES(assimp ${RT_LIBRARY})
INSTALL( TARGETS assimp
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
@@ -1015,8 +1015,8 @@ void COBImporter::ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const
// XXX backface culling flag is 0x10 in flags
// hole?
- bool hole;
- if ((hole = (reader.GetI1() & 0x08) != 0)) {
+ bool hole = (reader.GetI1() & 0x08) != 0;
+ if ( hole ) {
// XXX Basically this should just work fine - then triangulator
// should output properly triangulated data even for polygons
// with holes. Test data specific to COB is needed to confirm it.
@@ -75,10 +75,10 @@ struct Face
// ------------------
/** COB chunk header information */
+const unsigned int NO_SIZE = UINT_MAX;
struct ChunkInfo
- enum {NO_SIZE=UINT_MAX};
ChunkInfo ()
: id (0)
, parent_id (0)
@@ -178,7 +178,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
*ot++ = *buffer++;
*ot = '\0';
- nda->mNodeName.length = (ai_uint32)(ot-nda->mNodeName.data);
+ nda->mNodeName.length = static_cast<ai_uint32>(ot-nda->mNodeName.data);
anim->mNumChannels = static_cast<unsigned int>(anims_temp.size());
@@ -1335,32 +1335,34 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
PushTag();
- std::string node_idstr;
+ std::string cur_node_idstr;
for (size_t a = 0; a < anim->mNumChannels; ++a) {
const aiNodeAnim * nodeAnim = anim->mChannels[a];
// sanity check
- if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
+ if (nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys) {
- node_idstr.clear();
- node_idstr += nodeAnim->mNodeName.data;
- node_idstr += std::string( "_matrix-input" );
+ cur_node_idstr.clear();
+ cur_node_idstr += nodeAnim->mNodeName.data;
+ cur_node_idstr += std::string("_matrix-input");
std::vector<ai_real> frames;
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
frames.push_back(static_cast<ai_real>(nodeAnim->mPositionKeys[i].mTime));
- WriteFloatArray( node_idstr , FloatType_Time, (const ai_real*) frames.data(), frames.size());
+ WriteFloatArray(cur_node_idstr, FloatType_Time, (const ai_real *)frames.data(), frames.size());
frames.clear();
- node_idstr += std::string("_matrix-output");
+ cur_node_idstr += std::string("_matrix-output");
std::vector<ai_real> keyframes;
keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
@@ -1385,7 +1387,7 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
- WriteFloatArray( node_idstr, FloatType_Mat4x4, (const ai_real*) keyframes.data(), keyframes.size() / 16);
+ WriteFloatArray(cur_node_idstr, FloatType_Mat4x4, (const ai_real *)keyframes.data(), keyframes.size() / 16);
@@ -1401,16 +1403,16 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
- const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-interpolation");
- std::string arrayId = XMLIDEncode(node_idstr) + "-array";
+ const std::string cur_node_idstr2 = nodeAnim->mNodeName.data + std::string("_matrix-interpolation");
+ std::string arrayId = XMLIDEncode(cur_node_idstr2) + "-array";
- mOutput << startstr << "<source id=\"" << XMLIDEncode(node_idstr) << "\">" << endstr;
+ mOutput << startstr << "<source id=\"" << XMLIDEncode(cur_node_idstr2) << "\">" << endstr;
// source array
mOutput << startstr << "<Name_array id=\"" << arrayId << "\" count=\"" << names.size() << "\"> ";
- for( size_t a = 0; a < names.size(); ++a ) {
- mOutput << names[a] << " ";
+ for( size_t aa = 0; aa < names.size(); ++aa ) {
+ mOutput << names[aa] << " ";
mOutput << "</Name_array>" << endstr;
@@ -1672,13 +1674,13 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLIDEncode(materials[mesh->mMaterialIndex].name) << "\">" << endstr;
- for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
+ for( size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa )
- if( mesh->HasTextureCoords( static_cast<unsigned int>(a) ) )
+ if( mesh->HasTextureCoords( static_cast<unsigned int>(aa) ) )
// semantic as in <texture texcoord=...>
// input_semantic as in <input semantic=...>
// input_set as in <input set=...>
- mOutput << startstr << "<bind_vertex_input semantic=\"CHANNEL" << a << "\" input_semantic=\"TEXCOORD\" input_set=\"" << a << "\"/>" << endstr;
+ mOutput << startstr << "<bind_vertex_input semantic=\"CHANNEL" << aa << "\" input_semantic=\"TEXCOORD\" input_set=\"" << aa << "\"/>" << endstr;
PopTag();
mOutput << startstr << "</instance_material>" << endstr;
@@ -714,8 +714,8 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent)
else if (IsElement("sampler"))
// read the ID to assign the corresponding collada channel afterwards.
- int indexID = GetAttribute("id");
- std::string id = mReader->getAttributeValue(indexID);
+ int indexId = GetAttribute("id");
+ std::string id = mReader->getAttributeValue(indexId);
ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
// have it read into a channel
@@ -3339,13 +3339,12 @@ void ColladaParser::TestClosing(const char* pName) {
// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
int ColladaParser::GetAttribute(const char* pAttr) const {
int index = TestAttribute(pAttr);
- if (index != -1) {
- return index;
+ if (index == -1) {
+ ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
// attribute not found -> throw an exception
- ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
- return -1;
+ return index;
@@ -44,15 +44,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Plain-C API
+#include <assimp/BaseImporter.h>
+#include <assimp/Exceptional.h>
+#include <assimp/GenericProperty.h>
#include <assimp/cimport.h>
-#include <assimp/LogStream.hpp>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/Importer.hpp>
-#include <assimp/GenericProperty.h>
-#include <assimp/Exceptional.h>
-#include <assimp/BaseImporter.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Importer.hpp>
+#include <assimp/LogStream.hpp>
#include "CApi/CInterfaceIOWrapper.h"
#include "Importer.h"
@@ -62,46 +62,45 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_SINGLETHREADED
-# include <thread>
-# include <mutex>
+#include <mutex>
+#include <thread>
- // underlying structure for aiPropertyStore
- typedef BatchLoader::PropertyMap PropertyMap;
- /** Stores the LogStream objects for all active C log streams */
- struct mpred {
- bool operator () (const aiLogStream& s0, const aiLogStream& s1) const {
- return s0.callback<s1.callback&&s0.user<s1.user;
- };
- typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap;
+// underlying structure for aiPropertyStore
+typedef BatchLoader::PropertyMap PropertyMap;
- /** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
- typedef std::list<Assimp::LogStream*> PredefLogStreamMap;
+/** Stores the LogStream objects for all active C log streams */
+struct mpred {
+ bool operator()(const aiLogStream &s0, const aiLogStream &s1) const {
+ return s0.callback < s1.callback && s0.user < s1.user;
+};
+typedef std::map<aiLogStream, Assimp::LogStream *, mpred> LogStreamMap;
- /** Local storage of all active log streams */
- static LogStreamMap gActiveLogStreams;
+/** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
+typedef std::list<Assimp::LogStream *> PredefLogStreamMap;
- /** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
- static PredefLogStreamMap gPredefinedStreams;
+/** Local storage of all active log streams */
+static LogStreamMap gActiveLogStreams;
- /** Error message of the last failed import process */
- static std::string gLastErrorString;
+/** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
+static PredefLogStreamMap gPredefinedStreams;
- /** Verbose logging active or not? */
- static aiBool gVerboseLogging = false;
+/** Error message of the last failed import process */
+static std::string gLastErrorString;
- /** will return all registered importers. */
- void GetImporterInstanceList(std::vector< BaseImporter* >& out);
+/** Verbose logging active or not? */
+static aiBool gVerboseLogging = false;
- /** will delete all registered importers. */
- void DeleteImporterInstanceList(std::vector< BaseImporter* >& out);
-} // namespace assimp
+/** will return all registered importers. */
+void GetImporterInstanceList(std::vector<BaseImporter *> &out);
+/** will delete all registered importers. */
+void DeleteImporterInstanceList(std::vector<BaseImporter *> &out);
+} // namespace Assimp
/** Global mutex to manage the access to the log-stream map */
@@ -112,12 +111,12 @@ static std::mutex gLogStreamMutex;
// Custom LogStream implementation for the C-API
class LogToCallbackRedirector : public LogStream {
- explicit LogToCallbackRedirector(const aiLogStream& s)
- : stream (s) {
+ explicit LogToCallbackRedirector(const aiLogStream &s) :
+ stream(s) {
ai_assert(NULL != s.callback);
- ~LogToCallbackRedirector() {
+ ~LogToCallbackRedirector() {
std::lock_guard<std::mutex> lock(gLogStreamMutex);
@@ -127,7 +126,7 @@ public:
// might cause strange problems, but the chance is quite low.
PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
- gPredefinedStreams.end(), (Assimp::LogStream*)stream.user);
+ gPredefinedStreams.end(), (Assimp::LogStream *)stream.user);
if (it != gPredefinedStreams.end()) {
delete *it;
@@ -136,8 +135,8 @@ public:
/** @copydoc LogStream::write */
- void write(const char* message) {
- stream.callback(message,stream.user);
+ void write(const char *message) {
+ stream.callback(message, stream.user);
@@ -147,37 +146,37 @@ private:
void ReportSceneNotFoundError() {
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");
+ "The C-API does not accept scenes produced by the C++ API and vice versa");
ai_assert(false);
// Reads the given file and returns its content.
-const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
- return aiImportFileEx(pFile,pFlags,NULL);
+const aiScene *aiImportFile(const char *pFile, unsigned int pFlags) {
+ return aiImportFileEx(pFile, pFlags, NULL);
-const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) {
+const aiScene *aiImportFileEx(const char *pFile, unsigned int pFlags, aiFileIO *pFS) {
return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
-const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
- aiFileIO* pFS, const aiPropertyStore* props) {
+const aiScene *aiImportFileExWithProperties(const char *pFile, unsigned int pFlags,
+ aiFileIO *pFS, const aiPropertyStore *props) {
ai_assert(NULL != pFile);
- const aiScene* scene = NULL;
+ const aiScene *scene = NULL;
ASSIMP_BEGIN_EXCEPTION_REGION();
// create an Importer for this file
- Assimp::Importer* imp = new Assimp::Importer();
+ Assimp::Importer *imp = new Assimp::Importer();
// copy properties
- if(props) {
- const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
- ImporterPimpl* pimpl = imp->Pimpl();
+ if (props) {
+ const PropertyMap *pp = reinterpret_cast<const PropertyMap *>(props);
+ ImporterPimpl *pimpl = imp->Pimpl();
pimpl->mIntProperties = pp->ints;
pimpl->mFloatProperties = pp->floats;
pimpl->mStringProperties = pp->strings;
@@ -185,15 +184,15 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
// setup a custom IO system if necessary
if (pFS) {
- imp->SetIOHandler( new CIOSystemWrapper (pFS) );
+ imp->SetIOHandler(new CIOSystemWrapper(pFS));
// and have it read the file
- scene = imp->ReadFile( pFile, pFlags);
+ scene = imp->ReadFile(pFile, pFlags);
// if succeeded, store the importer in the scene and keep it alive
- if( scene) {
- ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
+ if (scene) {
+ ScenePrivateData *priv = const_cast<ScenePrivateData *>(ScenePriv(scene));
priv->mOrigImporter = imp;
// if failed, extract error code and destroy the import
@@ -202,42 +201,40 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
// return imported data. If the import failed the pointer is NULL anyways
- ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+ ASSIMP_END_EXCEPTION_REGION(const aiScene *);
return scene;
-const aiScene* aiImportFileFromMemory(
- const char* pBuffer,
- unsigned int pLength,
- unsigned int pFlags,
- const char* pHint)
+const aiScene *aiImportFileFromMemory(
+ const char *pBuffer,
+ unsigned int pLength,
+ unsigned int pFlags,
+ const char *pHint) {
return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
-const aiScene* aiImportFileFromMemoryWithProperties(
- const char* pHint,
- const aiPropertyStore* props)
- ai_assert( NULL != pBuffer );
- ai_assert( 0 != pLength );
+const aiScene *aiImportFileFromMemoryWithProperties(
+ const char *pHint,
+ const aiPropertyStore *props) {
+ ai_assert(NULL != pBuffer);
+ ai_assert(0 != pLength);
@@ -245,27 +242,25 @@ const aiScene* aiImportFileFromMemoryWithProperties(
// and have it read the file from the memory buffer
- scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);
+ scene = imp->ReadFileFromMemory(pBuffer, pLength, pFlags, pHint);
- priv->mOrigImporter = imp;
+ priv->mOrigImporter = imp;
gLastErrorString = imp->GetErrorString();
delete imp;
// Releases all resources associated with the given import process.
-void aiReleaseImport( const aiScene* pScene)
+void aiReleaseImport(const aiScene *pScene) {
if (!pScene) {
@@ -273,15 +268,14 @@ void aiReleaseImport( const aiScene* pScene)
// find the importer associated with this data
- const ScenePrivateData* priv = ScenePriv(pScene);
- if( !priv || !priv->mOrigImporter) {
+ const ScenePrivateData *priv = ScenePriv(pScene);
+ if (!priv || !priv->mOrigImporter) {
delete pScene;
// deleting the Importer also deletes the scene
// Note: the reason that this is not written as 'delete priv->mOrigImporter'
// is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339)
- Importer* importer = priv->mOrigImporter;
+ Importer *importer = priv->mOrigImporter;
delete importer;
@@ -289,17 +283,15 @@ void aiReleaseImport( const aiScene* pScene)
-ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene,
- unsigned int pFlags)
- const aiScene* sc = NULL;
+ASSIMP_API const aiScene *aiApplyPostProcessing(const aiScene *pScene,
+ unsigned int pFlags) {
+ const aiScene *sc = NULL;
ReportSceneNotFoundError();
return NULL;
@@ -311,61 +303,58 @@ ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene,
return sc;
-ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing( const aiScene *scene,
- BaseProcess* process,
- bool requestValidation ) {
- const aiScene* sc( NULL );
+ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing(const aiScene *scene,
+ BaseProcess *process,
+ bool requestValidation) {
+ const aiScene *sc(NULL);
- const ScenePrivateData* priv = ScenePriv( scene );
- if ( NULL == priv || NULL == priv->mOrigImporter ) {
+ const ScenePrivateData *priv = ScenePriv(scene);
+ if (NULL == priv || NULL == priv->mOrigImporter) {
- sc = priv->mOrigImporter->ApplyCustomizedPostProcessing( process, requestValidation );
+ sc = priv->mOrigImporter->ApplyCustomizedPostProcessing(process, requestValidation);
- if ( !sc ) {
- aiReleaseImport( scene );
+ if (!sc) {
+ aiReleaseImport(scene);
- ASSIMP_END_EXCEPTION_REGION( const aiScene* );
-void CallbackToLogRedirector (const char* msg, char* dt)
- ai_assert( NULL != msg );
- ai_assert( NULL != dt );
- LogStream* s = (LogStream*)dt;
+void CallbackToLogRedirector(const char *msg, char *dt) {
+ ai_assert(NULL != msg);
+ ai_assert(NULL != dt);
+ LogStream *s = (LogStream *)dt;
s->write(msg);
-ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file)
+ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, const char *file) {
aiLogStream sout;
- LogStream* stream = LogStream::createDefaultStream(pStream,file);
+ LogStream *stream = LogStream::createDefaultStream(pStream, file);
if (!stream) {
sout.callback = NULL;
sout.user = NULL;
sout.callback = &CallbackToLogRedirector;
- sout.user = (char*)stream;
+ sout.user = (char *)stream;
gPredefinedStreams.push_back(stream);
ASSIMP_END_EXCEPTION_REGION(aiLogStream);
@@ -373,42 +362,40 @@ ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const
-ASSIMP_API void aiAttachLogStream( const aiLogStream* stream )
+ASSIMP_API void aiAttachLogStream(const aiLogStream *stream) {
- LogStream* lg = new LogToCallbackRedirector(*stream);
+ LogStream *lg = new LogToCallbackRedirector(*stream);
gActiveLogStreams[*stream] = lg;
if (DefaultLogger::isNullLogger()) {
- DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
+ DefaultLogger::create(NULL, (gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
DefaultLogger::get()->attachStream(lg);
ASSIMP_END_EXCEPTION_REGION(void);
-ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream)
+ASSIMP_API aiReturn aiDetachLogStream(const aiLogStream *stream) {
// find the log-stream associated with this data
- LogStreamMap::iterator it = gActiveLogStreams.find( *stream);
+ LogStreamMap::iterator it = gActiveLogStreams.find(*stream);
// it should be there... else the user is playing fools with us
- if( it == gActiveLogStreams.end()) {
+ if (it == gActiveLogStreams.end()) {
return AI_FAILURE;
- DefaultLogger::get()->detatchStream( it->second );
+ DefaultLogger::get()->detatchStream(it->second);
delete it->second;
- gActiveLogStreams.erase( it);
+ gActiveLogStreams.erase(it);
if (gActiveLogStreams.empty()) {
DefaultLogger::kill();
@@ -418,19 +405,18 @@ ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream)
-ASSIMP_API void aiDetachAllLogStreams(void)
+ASSIMP_API void aiDetachAllLogStreams(void) {
- Logger *logger( DefaultLogger::get() );
- if ( NULL == logger ) {
+ Logger *logger(DefaultLogger::get());
+ if (NULL == logger) {
for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
- logger->detatchStream( it->second );
+ logger->detatchStream(it->second);
gActiveLogStreams.clear();
@@ -440,8 +426,7 @@ ASSIMP_API void aiDetachAllLogStreams(void)
-ASSIMP_API void aiEnableVerboseLogging(aiBool d)
+ASSIMP_API void aiEnableVerboseLogging(aiBool d) {
if (!DefaultLogger::isNullLogger()) {
DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
@@ -450,31 +435,27 @@ ASSIMP_API void aiEnableVerboseLogging(aiBool d)
// Returns the error text of the last failed import process.
-const char* aiGetErrorString()
+const char *aiGetErrorString() {
return gLastErrorString.c_str();
// -----------------------------------------------------------------------------------------------
// Return the description of a importer given its index
-const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex)
+const aiImporterDesc *aiGetImportFormatDescription(size_t pIndex) {
return Importer().GetImporterInfo(pIndex);
// Return the number of importers
-size_t aiGetImportFormatCount(void)
+size_t aiGetImportFormatCount(void) {
return Importer().GetImporterCount();
-aiBool aiIsExtensionSupported(const char* szExtension)
+aiBool aiIsExtensionSupported(const char *szExtension) {
ai_assert(NULL != szExtension);
- aiBool candoit=AI_FALSE;
+ aiBool candoit = AI_FALSE;
// FIXME: no need to create a temporary Importer instance just for that ..
@@ -487,8 +468,7 @@ aiBool aiIsExtensionSupported(const char* szExtension)
// Get a list of all file extensions supported by ASSIMP
-void aiGetExtensionList(aiString* szOut)
+void aiGetExtensionList(aiString *szOut) {
ai_assert(NULL != szOut);
@@ -501,14 +481,13 @@ void aiGetExtensionList(aiString* szOut)
// Get the memory requirements for a particular import.
-void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn,
- C_STRUCT aiMemoryInfo* in)
+void aiGetMemoryRequirements(const C_STRUCT aiScene *pIn,
+ C_STRUCT aiMemoryInfo *in) {
- const ScenePrivateData* priv = ScenePriv(pIn);
+ const ScenePrivateData *priv = ScenePriv(pIn);
@@ -518,118 +497,106 @@ void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn,
-ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void)
- return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
+ASSIMP_API aiPropertyStore *aiCreatePropertyStore(void) {
+ return reinterpret_cast<aiPropertyStore *>(new PropertyMap());
-ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p)
- delete reinterpret_cast<PropertyMap*>(p);
+ASSIMP_API void aiReleasePropertyStore(aiPropertyStore *p) {
+ delete reinterpret_cast<PropertyMap *>(p);
// Importer::SetPropertyInteger
-ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szName, int value)
+ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore *p, const char *szName, int value) {
- PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
- SetGenericProperty<int>(pp->ints,szName,value);
+ PropertyMap *pp = reinterpret_cast<PropertyMap *>(p);
+ SetGenericProperty<int>(pp->ints, szName, value);
// Importer::SetPropertyFloat
-ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, ai_real value)
+ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore *p, const char *szName, ai_real value) {
- SetGenericProperty<ai_real>(pp->floats,szName,value);
+ SetGenericProperty<ai_real>(pp->floats, szName, value);
// Importer::SetPropertyString
-ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName,
- const C_STRUCT aiString* st)
+ASSIMP_API void aiSetImportPropertyString(aiPropertyStore *p, const char *szName,
+ const C_STRUCT aiString *st) {
if (!st) {
- SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()));
+ SetGenericProperty<std::string>(pp->strings, szName, std::string(st->C_Str()));
// Importer::SetPropertyMatrix
-ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName,
- const C_STRUCT aiMatrix4x4* mat)
+ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore *p, const char *szName,
+ const C_STRUCT aiMatrix4x4 *mat) {
if (!mat) {
- SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat);
+ SetGenericProperty<aiMatrix4x4>(pp->matrices, szName, *mat);
// Rotation matrix to quaternion
-ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat)
- ai_assert( NULL != quat );
- ai_assert( NULL != mat );
+ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion *quat, const aiMatrix3x3 *mat) {
+ ai_assert(NULL != quat);
+ ai_assert(NULL != mat);
*quat = aiQuaternion(*mat);
// Matrix decomposition
-ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling,
- aiQuaternion* rotation,
- aiVector3D* position)
- ai_assert( NULL != rotation );
- ai_assert( NULL != position );
- ai_assert( NULL != scaling );
- mat->Decompose(*scaling,*rotation,*position);
+ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4 *mat, aiVector3D *scaling,
+ aiQuaternion *rotation,
+ aiVector3D *position) {
+ ai_assert(NULL != rotation);
+ ai_assert(NULL != position);
+ ai_assert(NULL != scaling);
+ mat->Decompose(*scaling, *rotation, *position);
// Matrix transpose
-ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat)
+ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3 *mat) {
ai_assert(NULL != mat);
mat->Transpose();
-ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat)
+ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4 *mat) {
// Vector transformation
-ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
- const aiMatrix3x3* mat)
- ai_assert( NULL != vec);
+ASSIMP_API void aiTransformVecByMatrix3(aiVector3D *vec,
+ const aiMatrix3x3 *mat) {
+ ai_assert(NULL != vec);
*vec *= (*mat);
-ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
- const aiMatrix4x4* mat)
- ai_assert( NULL != vec );
+ASSIMP_API void aiTransformVecByMatrix4(aiVector3D *vec,
+ const aiMatrix4x4 *mat) {
@@ -637,52 +604,48 @@ ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
// Matrix multiplication
ASSIMP_API void aiMultiplyMatrix4(
- aiMatrix4x4* dst,
- const aiMatrix4x4* src)
- ai_assert( NULL != dst );
- ai_assert( NULL != src );
+ aiMatrix4x4 *dst,
+ const aiMatrix4x4 *src) {
+ ai_assert(NULL != dst);
+ ai_assert(NULL != src);
*dst = (*dst) * (*src);
ASSIMP_API void aiMultiplyMatrix3(
- aiMatrix3x3* dst,
- const aiMatrix3x3* src)
+ aiMatrix3x3 *dst,
+ const aiMatrix3x3 *src) {
// Matrix identity
ASSIMP_API void aiIdentityMatrix3(
- aiMatrix3x3* mat)
+ aiMatrix3x3 *mat) {
*mat = aiMatrix3x3();
ASSIMP_API void aiIdentityMatrix4(
- aiMatrix4x4* mat)
+ aiMatrix4x4 *mat) {
*mat = aiMatrix4x4();
-ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) {
- if( NULL == extension ) {
+ASSIMP_API C_STRUCT const aiImporterDesc *aiGetImporterDesc(const char *extension) {
+ if (NULL == extension) {
- const aiImporterDesc *desc( NULL );
- std::vector< BaseImporter* > out;
- GetImporterInstanceList( out );
- for( size_t i = 0; i < out.size(); ++i ) {
- if( 0 == strncmp( out[ i ]->GetInfo()->mFileExtensions, extension, strlen( extension ) ) ) {
- desc = out[ i ]->GetInfo();
+ const aiImporterDesc *desc(NULL);
+ std::vector<BaseImporter *> out;
+ GetImporterInstanceList(out);
+ for (size_t i = 0; i < out.size(); ++i) {
+ if (0 == strncmp(out[i]->GetInfo()->mFileExtensions, extension, strlen(extension))) {
+ desc = out[i]->GetInfo();
@@ -693,3 +656,598 @@ ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extensi
+ASSIMP_API int aiVector2AreEqual(
+ const C_STRUCT aiVector2D *a,
+ const C_STRUCT aiVector2D *b) {
+ ai_assert(NULL != a);
+ ai_assert(NULL != b);
+ return *a == *b;
+}
+// ------------------------------------------------------------------------------------------------
+ASSIMP_API int aiVector2AreEqualEpsilon(
+ const C_STRUCT aiVector2D *b,
+ const float epsilon) {
+ return a->Equal(*b, epsilon);
+ASSIMP_API void aiVector2Add(
+ C_STRUCT aiVector2D *dst,
+ const C_STRUCT aiVector2D *src) {
+ *dst = *dst + *src;
+ASSIMP_API void aiVector2Subtract(
+ *dst = *dst - *src;
+ASSIMP_API void aiVector2Scale(
+ const float s) {
+ *dst *= s;
+ASSIMP_API void aiVector2SymMul(
+ const C_STRUCT aiVector2D *other) {
+ ai_assert(NULL != other);
+ *dst = dst->SymMul(*other);
+ASSIMP_API void aiVector2DivideByScalar(
+ *dst /= s;
+ASSIMP_API void aiVector2DivideByVector(
+ C_STRUCT aiVector2D *v) {
+ ai_assert(NULL != v);
+ *dst = *dst / *v;
+ASSIMP_API float aiVector2Length(
+ const C_STRUCT aiVector2D *v) {
+ return v->Length();
+ASSIMP_API float aiVector2SquareLength(
+ return v->SquareLength();
+ASSIMP_API void aiVector2Negate(
+ C_STRUCT aiVector2D *dst) {
+ *dst = -(*dst);
+ASSIMP_API float aiVector2DotProduct(
+ return (*a) * (*b);
+ASSIMP_API void aiVector2Normalize(
+ v->Normalize();
+ASSIMP_API int aiVector3AreEqual(
+ const C_STRUCT aiVector3D *a,
+ const C_STRUCT aiVector3D *b) {
+ASSIMP_API int aiVector3AreEqualEpsilon(
+ const C_STRUCT aiVector3D *b,
+ASSIMP_API int aiVector3LessThan(
+ return *a < *b;
+ASSIMP_API void aiVector3Add(
+ C_STRUCT aiVector3D *dst,
+ const C_STRUCT aiVector3D *src) {
+ASSIMP_API void aiVector3Subtract(
+ASSIMP_API void aiVector3Scale(
+ASSIMP_API void aiVector3SymMul(
+ const C_STRUCT aiVector3D *other) {
+ASSIMP_API void aiVector3DivideByScalar(
+ C_STRUCT aiVector3D *dst, const float s) {
+ASSIMP_API void aiVector3DivideByVector(
+ C_STRUCT aiVector3D *v) {
+ASSIMP_API float aiVector3Length(
+ const C_STRUCT aiVector3D *v) {
+ASSIMP_API float aiVector3SquareLength(
+ASSIMP_API void aiVector3Negate(
+ C_STRUCT aiVector3D *dst) {
+ASSIMP_API float aiVector3DotProduct(
+ASSIMP_API void aiVector3CrossProduct(
+ *dst = *a ^ *b;
+ASSIMP_API void aiVector3Normalize(
+ASSIMP_API void aiVector3NormalizeSafe(
+ v->NormalizeSafe();
+ASSIMP_API void aiVector3RotateByQuaternion(
+ C_STRUCT aiVector3D *v,
+ const C_STRUCT aiQuaternion *q) {
+ ai_assert(NULL != q);
+ *v = q->Rotate(*v);
+ASSIMP_API void aiMatrix3FromMatrix4(
+ C_STRUCT aiMatrix3x3 *dst,
+ *dst = aiMatrix3x3(*mat);
+ASSIMP_API void aiMatrix3FromQuaternion(
+ C_STRUCT aiMatrix3x3 *mat,
+ *mat = q->GetMatrix();
+ASSIMP_API int aiMatrix3AreEqual(
+ const C_STRUCT aiMatrix3x3 *a,
+ const C_STRUCT aiMatrix3x3 *b) {
+ASSIMP_API int aiMatrix3AreEqualEpsilon(
+ const C_STRUCT aiMatrix3x3 *b,
+ASSIMP_API void aiMatrix3Inverse(C_STRUCT aiMatrix3x3 *mat) {
+ mat->Inverse();
+ASSIMP_API float aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) {
+ return mat->Determinant();
+ASSIMP_API void aiMatrix3RotationZ(
+ const float angle) {
+ aiMatrix3x3::RotationZ(angle, *mat);
+ASSIMP_API void aiMatrix3FromRotationAroundAxis(
+ const C_STRUCT aiVector3D *axis,
+ ai_assert(NULL != axis);
+ aiMatrix3x3::Rotation(angle, *axis, *mat);
+ASSIMP_API void aiMatrix3Translation(
+ const C_STRUCT aiVector2D *translation) {
+ ai_assert(NULL != translation);
+ aiMatrix3x3::Translation(*translation, *mat);
+ASSIMP_API void aiMatrix3FromTo(
+ const C_STRUCT aiVector3D *from,
+ const C_STRUCT aiVector3D *to) {
+ ai_assert(NULL != from);
+ ai_assert(NULL != to);
+ aiMatrix3x3::FromToMatrix(*from, *to, *mat);
+ASSIMP_API void aiMatrix4FromMatrix3(
+ C_STRUCT aiMatrix4x4 *dst,
+ const C_STRUCT aiMatrix3x3 *mat) {
+ *dst = aiMatrix4x4(*mat);
+ASSIMP_API void aiMatrix4FromScalingQuaternionPosition(
+ C_STRUCT aiMatrix4x4 *mat,
+ const C_STRUCT aiVector3D *scaling,
+ const C_STRUCT aiQuaternion *rotation,
+ const C_STRUCT aiVector3D *position) {
+ *mat = aiMatrix4x4(*scaling, *rotation, *position);
+ASSIMP_API void aiMatrix4Add(
+ const C_STRUCT aiMatrix4x4 *src) {
+ASSIMP_API int aiMatrix4AreEqual(
+ const C_STRUCT aiMatrix4x4 *a,
+ const C_STRUCT aiMatrix4x4 *b) {
+ASSIMP_API int aiMatrix4AreEqualEpsilon(
+ const C_STRUCT aiMatrix4x4 *b,
+ASSIMP_API void aiMatrix4Inverse(C_STRUCT aiMatrix4x4 *mat) {
+ASSIMP_API float aiMatrix4Determinant(const C_STRUCT aiMatrix4x4 *mat) {
+ASSIMP_API int aiMatrix4IsIdentity(const C_STRUCT aiMatrix4x4 *mat) {
+ return mat->IsIdentity();
+ASSIMP_API void aiMatrix4DecomposeIntoScalingEulerAnglesPosition(
+ const C_STRUCT aiMatrix4x4 *mat,
+ C_STRUCT aiVector3D *scaling,
+ C_STRUCT aiVector3D *rotation,
+ C_STRUCT aiVector3D *position) {
+ASSIMP_API void aiMatrix4DecomposeIntoScalingAxisAnglePosition(
+ C_STRUCT aiVector3D *axis,
+ float *angle,
+ ai_assert(NULL != angle);
+ mat->Decompose(*scaling, *axis, *angle, *position);
+ASSIMP_API void aiMatrix4DecomposeNoScaling(
+ C_STRUCT aiQuaternion *rotation,
+ mat->DecomposeNoScaling(*rotation, *position);
+ASSIMP_API void aiMatrix4FromEulerAngles(
+ float x, float y, float z) {
+ mat->FromEulerAnglesXYZ(x, y, z);
+ASSIMP_API void aiMatrix4RotationX(
+ aiMatrix4x4::RotationX(angle, *mat);
+ASSIMP_API void aiMatrix4RotationY(
+ aiMatrix4x4::RotationY(angle, *mat);
+ASSIMP_API void aiMatrix4RotationZ(
+ aiMatrix4x4::RotationZ(angle, *mat);
+ASSIMP_API void aiMatrix4FromRotationAroundAxis(
+ aiMatrix4x4::Rotation(angle, *axis, *mat);
+ASSIMP_API void aiMatrix4Translation(
+ const C_STRUCT aiVector3D *translation) {
+ aiMatrix4x4::Translation(*translation, *mat);
+ASSIMP_API void aiMatrix4Scaling(
+ const C_STRUCT aiVector3D *scaling) {
+ aiMatrix4x4::Scaling(*scaling, *mat);
+ASSIMP_API void aiMatrix4FromTo(
+ aiMatrix4x4::FromToMatrix(*from, *to, *mat);
+ASSIMP_API void aiQuaternionFromEulerAngles(
+ C_STRUCT aiQuaternion *q,
+ *q = aiQuaternion(x, y, z);
+ASSIMP_API void aiQuaternionFromAxisAngle(
+ *q = aiQuaternion(*axis, angle);
+ASSIMP_API void aiQuaternionFromNormalizedQuaternion(
+ const C_STRUCT aiVector3D *normalized) {
+ ai_assert(NULL != normalized);
+ *q = aiQuaternion(*normalized);
+ASSIMP_API int aiQuaternionAreEqual(
+ const C_STRUCT aiQuaternion *a,
+ const C_STRUCT aiQuaternion *b) {
+ASSIMP_API int aiQuaternionAreEqualEpsilon(
+ const C_STRUCT aiQuaternion *b,
+ASSIMP_API void aiQuaternionNormalize(
+ C_STRUCT aiQuaternion *q) {
+ q->Normalize();
+ASSIMP_API void aiQuaternionConjugate(
+ q->Conjugate();
+ASSIMP_API void aiQuaternionMultiply(
+ C_STRUCT aiQuaternion *dst,
+ *dst = (*dst) * (*q);
+ASSIMP_API void aiQuaternionInterpolate(
+ const C_STRUCT aiQuaternion *start,
+ const C_STRUCT aiQuaternion *end,
+ const float factor) {
+ ai_assert(NULL != start);
+ ai_assert(NULL != end);
+ aiQuaternion::Interpolate(*dst, *start, *end, factor);
@@ -146,7 +146,7 @@ aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSyst
-void BaseImporter::SetupProperties(const Importer* pImp)
+void BaseImporter::SetupProperties(const Importer* )
// the default implementation does nothing
@@ -43,45 +41,43 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of BaseProcess */
#include "BaseProcess.h"
// Constructor to be privately used by Importer
BaseProcess::BaseProcess() AI_NO_EXCEPT
-: shared()
-, progress()
+ : shared(),
+ progress() {
// Destructor, private as well
-BaseProcess::~BaseProcess()
+BaseProcess::~BaseProcess() {
// nothing to do here
-void BaseProcess::ExecuteOnScene( Importer* pImp)
- ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
+void BaseProcess::ExecuteOnScene(Importer *pImp) {
+ ai_assert( nullptr != pImp );
+ ai_assert( nullptr != pImp->Pimpl()->mScene);
progress = pImp->GetProgressHandler();
- ai_assert(progress);
+ ai_assert(nullptr != progress);
- SetupProperties( pImp );
+ SetupProperties(pImp);
// catch exceptions thrown inside the PostProcess-Step
- try
+ try {
Execute(pImp->Pimpl()->mScene);
- } catch( const std::exception& err ) {
+ } catch (const std::exception &err) {
// extract error description
pImp->Pimpl()->mErrorString = err.what();
@@ -94,14 +90,11 @@ void BaseProcess::ExecuteOnScene( Importer* pImp)
-void BaseProcess::SetupProperties(const Importer* /*pImp*/)
+void BaseProcess::SetupProperties(const Importer * /*pImp*/) {
-bool BaseProcess::RequireVerboseFormat() const
+bool BaseProcess::RequireVerboseFormat() const {
return true;
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
@@ -44,12 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_BASEPROCESS_H
#define INCLUDED_AI_BASEPROCESS_H
-#include <map>
#include <assimp/GenericProperty.h>
+#include <map>
struct aiScene;
class Importer;
@@ -60,64 +60,50 @@ class Importer;
* to provide additional information to other steps. This is primarily
* intended for cross-step optimizations.
-class SharedPostProcessInfo
+class SharedPostProcessInfo {
- struct Base
- virtual ~Base()
- {}
+ struct Base {
+ virtual ~Base() {}
//! Represents data that is allocated on the heap, thus needs to be deleted
- struct THeapData : public Base
- explicit THeapData(T* in)
- : data (in)
- ~THeapData()
+ struct THeapData : public Base {
+ explicit THeapData(T *in) :
+ data(in) {}
+ ~THeapData() {
delete data;
- T* data;
+ T *data;
//! Represents static, by-value data not allocated on the heap
- struct TStaticData : public Base
- explicit TStaticData(T in)
+ struct TStaticData : public Base {
+ explicit TStaticData(T in) :
- ~TStaticData()
+ ~TStaticData() {}
T data;
// some typedefs for cleaner code
typedef unsigned int KeyType;
- typedef std::map<KeyType, Base*> PropertyMap;
+ typedef std::map<KeyType, Base *> PropertyMap;
//! Destructor
- ~SharedPostProcessInfo()
+ ~SharedPostProcessInfo() {
Clean();
//! Remove all stored properties from the table
- void Clean()
+ void Clean() {
// invoke the virtual destructor for all stored properties
for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
- it != end; ++it)
+ it != end; ++it) {
delete (*it).second;
pmap.clear();
@@ -125,24 +111,21 @@ public:
//! Add a heap property to the list
- void AddProperty( const char* name, T* in ){
- AddProperty(name,(Base*)new THeapData<T>(in));
+ void AddProperty(const char *name, T *in) {
+ AddProperty(name, (Base *)new THeapData<T>(in));
//! Add a static by-value property to the list
- void AddProperty( const char* name, T in ){
- AddProperty(name,(Base*)new TStaticData<T>(in));
+ void AddProperty(const char *name, T in) {
+ AddProperty(name, (Base *)new TStaticData<T>(in));
//! Get a heap property
- bool GetProperty( const char* name, T*& out ) const
- THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name);
- if(!t)
+ bool GetProperty(const char *name, T *&out) const {
+ THeapData<T> *t = (THeapData<T> *)GetPropertyInternal(name);
+ if (!t) {
out = NULL;
@@ -152,53 +135,34 @@ public:
//! Get a static, by-value property
- bool GetProperty( const char* name, T& out ) const
- TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name);
- if(!t)return false;
+ bool GetProperty(const char *name, T &out) const {
+ TStaticData<T> *t = (TStaticData<T> *)GetPropertyInternal(name);
+ if ( nullptr == t) {
+ return false;
out = t->data;
//! Remove a property of a specific type
- void RemoveProperty( const char* name) {
- SetGenericPropertyPtr<Base>(pmap,name,NULL);
+ void RemoveProperty(const char *name) {
+ SetGenericPropertyPtr<Base>(pmap, name, nullptr );
- void AddProperty( const char* name, Base* data) {
- SetGenericPropertyPtr<Base>(pmap,name,data);
+ void AddProperty(const char *name, Base *data) {
+ SetGenericPropertyPtr<Base>(pmap, name, data);
- Base* GetPropertyInternal( const char* name) const {
- return GetGenericProperty<Base*>(pmap,name,NULL);
+ Base *GetPropertyInternal(const char *name) const {
+ return GetGenericProperty<Base *>(pmap, name, nullptr );
//! Map of all stored properties
PropertyMap pmap;
-#if 0
-// ---------------------------------------------------------------------------
-/** @brief Represents a dependency table for a postprocessing steps.
- *
- * For future use.
- */
- struct PPDependencyTable
- unsigned int execute_me_before_these;
- unsigned int execute_me_after_these;
- unsigned int only_if_these_are_not_specified;
- unsigned int mutually_exclusive_with;
-#endif
#define AI_SPP_SPATIAL_SORT "$Spat"
@@ -228,7 +192,7 @@ public:
* @return true if the process is present in this flag fields,
* false if not.
- virtual bool IsActive( unsigned int pFlags) const = 0;
+ virtual bool IsActive(unsigned int pFlags) const = 0;
/** Check whether this step expects its input vertex data to be
@@ -241,14 +205,14 @@ public:
* the object pointer will be set to NULL).
* @param pImp Importer instance (pImp->mScene must be valid)
- void ExecuteOnScene( Importer* pImp);
+ void ExecuteOnScene(Importer *pImp);
/** Called prior to ExecuteOnScene().
* The function is a request to the process to update its configuration
* basing on the Importer's configuration property list.
- virtual void SetupProperties(const Importer* pImp);
+ virtual void SetupProperties(const Importer *pImp);
/** Executes the post processing step on the given imported data.
@@ -256,35 +220,32 @@ public:
* This method must be implemented by deriving classes.
* @param pScene The imported data to work at.
- virtual void Execute( aiScene* pScene) = 0;
+ virtual void Execute(aiScene *pScene) = 0;
/** Assign a new SharedPostProcessInfo to the step. This object
* allows multiple postprocess steps to share data.
* @param sh May be NULL
- inline void SetSharedData(SharedPostProcessInfo* sh) {
+ inline void SetSharedData(SharedPostProcessInfo *sh) {
shared = sh;
/** Get the shared data that is assigned to the step.
- inline SharedPostProcessInfo* GetSharedData() {
+ inline SharedPostProcessInfo *GetSharedData() {
return shared;
protected:
/** See the doc of #SharedPostProcessInfo for more details */
- SharedPostProcessInfo* shared;
+ SharedPostProcessInfo *shared;
/** Currently active progress handler */
- ProgressHandler* progress;
+ ProgressHandler *progress;
#endif // AI_BASEPROCESS_H_INC
@@ -70,7 +70,7 @@ namespace
template<>
size_t select_ftell<8>(FILE* file)
- return ::_ftelli64(file);
+ return (size_t)::_ftelli64(file);
@@ -44,26 +44,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/StringComparison.h>
-#include <assimp/DefaultIOSystem.h>
#include <assimp/DefaultIOStream.h>
+#include <assimp/DefaultIOSystem.h>
#include <assimp/ai_assert.h>
#include <stdlib.h>
#ifdef __unix__
-#include <sys/param.h>
-#include <stdlib.h>
+# include <stdlib.h>
+# include <sys/param.h>
#ifdef _WIN32
-#include <windows.h>
+# include <windows.h>
-static std::wstring Utf8ToWide(const char* in)
+static std::wstring Utf8ToWide(const char *in) {
int size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0);
// size includes terminating null; std::wstring adds null automatically
std::wstring out(static_cast<size_t>(size) - 1, L'\0');
@@ -71,8 +70,7 @@ static std::wstring Utf8ToWide(const char* in)
return out;
-static std::string WideToUtf8(const wchar_t* in)
+static std::string WideToUtf8(const wchar_t *in) {
int size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr);
// size includes terminating null; std::string adds null automatically
std::string out(static_cast<size_t>(size) - 1, '\0');
@@ -83,52 +81,51 @@ static std::string WideToUtf8(const wchar_t* in)
// Tests for the existence of a file at the given path.
-bool DefaultIOSystem::Exists(const char* pFile) const
+bool DefaultIOSystem::Exists(const char *pFile) const {
struct __stat64 filestat;
if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) {
- FILE* file = ::fopen(pFile, "rb");
- if (!file)
+ FILE *file = ::fopen(pFile, "rb");
+ if (!file) {
::fclose(file);
// Open a new file with a given path.
-IOStream* DefaultIOSystem::Open(const char* strFile, const char* strMode)
+IOStream *DefaultIOSystem::Open(const char *strFile, const char *strMode) {
ai_assert(strFile != nullptr);
ai_assert(strMode != nullptr);
- FILE* file;
+ FILE *file;
file = ::_wfopen(Utf8ToWide(strFile).c_str(), Utf8ToWide(strMode).c_str());
file = ::fopen(strFile, strMode);
return nullptr;
return new DefaultIOStream(file, strFile);
// Closes the given file and releases all resources associated with it.
-void DefaultIOSystem::Close(IOStream* pFile)
+void DefaultIOSystem::Close(IOStream *pFile) {
delete pFile;
// Returns the operation specific directory separator
-char DefaultIOSystem::getOsSeparator() const
+char DefaultIOSystem::getOsSeparator() const {
#ifndef _WIN32
return '/';
@@ -138,25 +135,23 @@ char DefaultIOSystem::getOsSeparator() const
// IOSystem default implementation (ComparePaths isn't a pure virtual function)
-bool IOSystem::ComparePaths(const char* one, const char* second) const
+bool IOSystem::ComparePaths(const char *one, const char *second) const {
return !ASSIMP_stricmp(one, second);
// Convert a relative path into an absolute path
-inline static std::string MakeAbsolutePath(const char* in)
+inline static std::string MakeAbsolutePath(const char *in) {
ai_assert(in);
std::string out;
- wchar_t* ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0);
+ wchar_t *ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0);
if (ret) {
out = WideToUtf8(ret);
free(ret);
- char* ret = realpath(in, nullptr);
+ char *ret = realpath(in, nullptr);
out = ret;
@@ -173,8 +168,7 @@ inline static std::string MakeAbsolutePath(const char* in)
// DefaultIOSystem's more specialized implementation
-bool DefaultIOSystem::ComparePaths(const char* one, const char* second) const
+bool DefaultIOSystem::ComparePaths(const char *one, const char *second) const {
// chances are quite good both paths are formatted identically,
// so we can hopefully return here already
if (!ASSIMP_stricmp(one, second))
@@ -187,8 +181,7 @@ bool DefaultIOSystem::ComparePaths(const char* one, const char* second) const
-std::string DefaultIOSystem::fileName(const std::string& path)
+std::string DefaultIOSystem::fileName(const std::string &path) {
std::string ret = path;
std::size_t last = ret.find_last_of("\\/");
if (last != std::string::npos) ret = ret.substr(last + 1);
@@ -196,8 +189,7 @@ std::string DefaultIOSystem::fileName(const std::string& path)
-std::string DefaultIOSystem::completeBaseName(const std::string& path)
+std::string DefaultIOSystem::completeBaseName(const std::string &path) {
std::string ret = fileName(path);
std::size_t pos = ret.find_last_of('.');
if (pos != std::string::npos) ret = ret.substr(0, pos);
@@ -205,8 +197,7 @@ std::string DefaultIOSystem::completeBaseName(const std::string& path)
-std::string DefaultIOSystem::absolutePath(const std::string& path)
+std::string DefaultIOSystem::absolutePath(const std::string &path) {
if (last != std::string::npos) ret = ret.substr(0, last);
@@ -76,6 +74,11 @@ Here we implement only the C++ interface (Assimp::Exporter).
+# pragma warning( disable : 4800 )
// PostStepRegistry.cpp
void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
@@ -200,9 +198,9 @@ corresponding preprocessor flag to selectively disable formats.
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
# include "M3D/M3DImporter.h"
-#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
-# include "Importer/StepFile/StepFileImporter.h"
+//#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
+//# include "Importer/StepFile/StepFileImporter.h"
+//#endif
@@ -361,9 +359,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
out.push_back( new MMDImporter() );
- out.push_back(new StepFile::StepFileImporter());
+// out.push_back(new StepFile::StepFileImporter());
/** will delete all registered importers. */
@@ -123,7 +123,7 @@ corresponding preprocessor flag to selectively disable steps.
# include "PostProcessing/OptimizeGraph.h"
#ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
-# include "Common/SplitByBoneCountProcess.h"
+# include "PostProcessing/SplitByBoneCountProcess.h"
#ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
# include "PostProcessing/DeboneProcess.h"
@@ -53,6 +53,10 @@ using namespace Assimp;
# define CHAR_BIT 8
+# pragma warning(disable : 4127)
// Constructs a spatially sorted representation from the given position array.
SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
@@ -53,6 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
void mydummy() {}
+# pragma warning( disable : 4709 )
/** Subdivider stub class to implement the Catmull-Clarke subdivision algorithm. The
* implementation is basing on recursive refinement. Directly evaluating the result is also
@@ -42,51 +42,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Actually just a dummy, used by the compiler to build the precompiled header.
-#include <assimp/version.h>
#include "ScenePrivate.h"
+#include <assimp/version.h>
#include "revision.h"
// --------------------------------------------------------------------------------
// Legal information string - don't remove this.
-static const char* LEGAL_INFORMATION =
+static const char *LEGAL_INFORMATION =
-"Open Asset Import Library (Assimp).\n"
-"A free C/C++ library to import various 3D file formats into applications\n\n"
+ "Open Asset Import Library (Assimp).\n"
+ "A free C/C++ library to import various 3D file formats into applications\n\n"
-"(c) 2006-2020, assimp team\n"
-"License under the terms and conditions of the 3-clause BSD license\n"
-"http://assimp.org\n"
-;
+ "(c) 2006-2020, assimp team\n"
+ "License under the terms and conditions of the 3-clause BSD license\n"
+ "http://assimp.org\n";
// Get legal string
-ASSIMP_API const char* aiGetLegalString () {
+ASSIMP_API const char *aiGetLegalString() {
return LEGAL_INFORMATION;
// Get Assimp patch version
ASSIMP_API unsigned int aiGetVersionPatch() {
- return VER_PATCH;
+ return VER_PATCH;
// Get Assimp minor version
-ASSIMP_API unsigned int aiGetVersionMinor () {
+ASSIMP_API unsigned int aiGetVersionMinor() {
return VER_MINOR;
// Get Assimp major version
-ASSIMP_API unsigned int aiGetVersionMajor () {
+ASSIMP_API unsigned int aiGetVersionMajor() {
return VER_MAJOR;
// Get flags used for compilation
-ASSIMP_API unsigned int aiGetCompileFlags () {
+ASSIMP_API unsigned int aiGetCompileFlags() {
unsigned int flags = 0;
@@ -119,24 +118,9 @@ ASSIMP_API const char *aiGetBranchName() {
-ASSIMP_API aiScene::aiScene()
-: mFlags(0)
-, mRootNode(nullptr)
-, mNumMeshes(0)
-, mMeshes(nullptr)
-, mNumMaterials(0)
-, mMaterials(nullptr)
-, mNumAnimations(0)
-, mAnimations(nullptr)
-, mNumTextures(0)
-, mTextures(nullptr)
-, mNumLights(0)
-, mLights(nullptr)
-, mNumCameras(0)
-, mCameras(nullptr)
-, mMetaData(nullptr)
-, mPrivate(new Assimp::ScenePrivateData()) {
- // empty
+ASSIMP_API aiScene::aiScene() :
+ mFlags(0), mRootNode(nullptr), mNumMeshes(0), mMeshes(nullptr), mNumMaterials(0), mMaterials(nullptr), mNumAnimations(0), mAnimations(nullptr), mNumTextures(0), mTextures(nullptr), mNumLights(0), mLights(nullptr), mNumCameras(0), mCameras(nullptr), mMetaData(nullptr), mPrivate(new Assimp::ScenePrivateData()) {
@@ -148,40 +132,39 @@ ASSIMP_API aiScene::~aiScene() {
// much better to check whether both mNumXXX and mXXX are
// valid instead of relying on just one of them.
if (mNumMeshes && mMeshes)
- for( unsigned int a = 0; a < mNumMeshes; a++)
+ for (unsigned int a = 0; a < mNumMeshes; a++)
delete mMeshes[a];
- delete [] mMeshes;
+ delete[] mMeshes;
if (mNumMaterials && mMaterials) {
- for (unsigned int a = 0; a < mNumMaterials; ++a ) {
- delete mMaterials[ a ];
+ for (unsigned int a = 0; a < mNumMaterials; ++a) {
+ delete mMaterials[a];
- delete [] mMaterials;
+ delete[] mMaterials;
if (mNumAnimations && mAnimations)
- for( unsigned int a = 0; a < mNumAnimations; a++)
+ for (unsigned int a = 0; a < mNumAnimations; a++)
delete mAnimations[a];
- delete [] mAnimations;
+ delete[] mAnimations;
if (mNumTextures && mTextures)
- for( unsigned int a = 0; a < mNumTextures; a++)
+ for (unsigned int a = 0; a < mNumTextures; a++)
delete mTextures[a];
- delete [] mTextures;
+ delete[] mTextures;
if (mNumLights && mLights)
- for( unsigned int a = 0; a < mNumLights; a++)
+ for (unsigned int a = 0; a < mNumLights; a++)
delete mLights[a];
- delete [] mLights;
+ delete[] mLights;
if (mNumCameras && mCameras)
- for( unsigned int a = 0; a < mNumCameras; a++)
+ for (unsigned int a = 0; a < mNumCameras; a++)
delete mCameras[a];
- delete [] mCameras;
+ delete[] mCameras;
aiMetadata::Dealloc(mMetaData);
mMetaData = nullptr;
- delete static_cast<Assimp::ScenePrivateData*>( mPrivate );
+ delete static_cast<Assimp::ScenePrivateData *>(mPrivate);
@@ -44,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Zip File I/O implementation for #Importer
-#include <assimp/ZipArchiveIOSystem.h>
#include <assimp/BaseImporter.h>
+#include <assimp/ZipArchiveIOSystem.h>
@@ -53,70 +52,69 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ASSIMP_USE_HUNTER
-# include <minizip/unzip.h>
+# include <minizip/unzip.h>
-# include <unzip.h>
+# include <unzip.h>
- // ----------------------------------------------------------------
- // Wraps an existing Assimp::IOSystem for unzip
- class IOSystem2Unzip {
- public:
- static voidpf open(voidpf opaque, const char* filename, int mode);
- static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
- static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
- static long tell(voidpf opaque, voidpf stream);
- static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
- static int close(voidpf opaque, voidpf stream);
- static int testerror(voidpf opaque, voidpf stream);
- static zlib_filefunc_def get(IOSystem* pIOHandler);
- voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
- IOSystem* io_system = reinterpret_cast<IOSystem*>(opaque);
- const char* mode_fopen = nullptr;
- if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) {
- mode_fopen = "rb";
- if (mode & ZLIB_FILEFUNC_MODE_EXISTING) {
- mode_fopen = "r+b";
- if (mode & ZLIB_FILEFUNC_MODE_CREATE) {
- mode_fopen = "wb";
+// ----------------------------------------------------------------
+// Wraps an existing Assimp::IOSystem for unzip
+class IOSystem2Unzip {
+public:
+ static voidpf open(voidpf opaque, const char *filename, int mode);
+ static uLong read(voidpf opaque, voidpf stream, void *buf, uLong size);
+ static uLong write(voidpf opaque, voidpf stream, const void *buf, uLong size);
+ static long tell(voidpf opaque, voidpf stream);
+ static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
+ static int close(voidpf opaque, voidpf stream);
+ static int testerror(voidpf opaque, voidpf stream);
+ static zlib_filefunc_def get(IOSystem *pIOHandler);
+voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) {
+ IOSystem *io_system = reinterpret_cast<IOSystem *>(opaque);
+ const char *mode_fopen = nullptr;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) {
+ mode_fopen = "rb";
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING) {
+ mode_fopen = "r+b";
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE) {
+ mode_fopen = "wb";
- return (voidpf)io_system->Open(filename, mode_fopen);
- uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
- IOStream* io_stream = (IOStream*)stream;
+ return (voidpf)io_system->Open(filename, mode_fopen);
- return static_cast<uLong>(io_stream->Read(buf, 1, size));
+uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void *buf, uLong size) {
+ IOStream *io_stream = (IOStream *)stream;
- uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
+ return static_cast<uLong>(io_stream->Read(buf, 1, size));
- return static_cast<uLong>(io_stream->Write(buf, 1, size));
+uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void *buf, uLong size) {
- long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
+ return static_cast<uLong>(io_stream->Write(buf, 1, size));
- return static_cast<long>(io_stream->Tell());
+long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
- long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
+ return static_cast<long>(io_stream->Tell());
+long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
- aiOrigin assimp_origin;
- switch (origin) {
+ aiOrigin assimp_origin;
+ switch (origin) {
default:
case ZLIB_FILEFUNC_SEEK_CUR:
assimp_origin = aiOrigin_CUR;
@@ -127,157 +125,153 @@ namespace Assimp {
case ZLIB_FILEFUNC_SEEK_SET:
assimp_origin = aiOrigin_SET;
- return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
- int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
- IOSystem* io_system = (IOSystem*)opaque;
+ return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
- io_system->Close(io_stream);
+int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
+ IOSystem *io_system = (IOSystem *)opaque;
+ io_system->Close(io_stream);
- int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
+ return 0;
+int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
- zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
- zlib_filefunc_def mapping;
+zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) {
+ zlib_filefunc_def mapping;
- mapping.zopen_file = (open_file_func)open;
- mapping.zread_file = (read_file_func)read;
- mapping.zwrite_file = (write_file_func)write;
- mapping.ztell_file = (tell_file_func)tell;
- mapping.zseek_file = (seek_file_func)seek;
- mapping.zclose_file = (close_file_func)close;
- mapping.zerror_file = (error_file_func)testerror;
+ mapping.zopen_file = (open_file_func)open;
+ mapping.zread_file = (read_file_func)read;
+ mapping.zwrite_file = (write_file_func)write;
+ mapping.ztell_file = (tell_file_func)tell;
+ mapping.zseek_file = (seek_file_func)seek;
+ mapping.zclose_file = (close_file_func)close;
+ mapping.zerror_file = (error_file_func)testerror;
- mapping.zopen_file = open;
- mapping.zread_file = read;
- mapping.zwrite_file = write;
- mapping.ztell_file = tell;
- mapping.zseek_file = seek;
- mapping.zclose_file = close;
- mapping.zerror_file = testerror;
+ mapping.zopen_file = open;
+ mapping.zread_file = read;
+ mapping.zwrite_file = write;
+ mapping.ztell_file = tell;
+ mapping.zseek_file = seek;
+ mapping.zclose_file = close;
+ mapping.zerror_file = testerror;
- mapping.opaque = reinterpret_cast<voidpf>(pIOHandler);
+ mapping.opaque = reinterpret_cast<voidpf>(pIOHandler);
- return mapping;
- // A read-only file inside a ZIP
- class ZipFile : public IOStream {
- friend class ZipFileInfo;
- explicit ZipFile(size_t size);
- virtual ~ZipFile();
- // IOStream interface
- size_t Read(void* pvBuffer, size_t pSize, size_t pCount) override;
- size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override { return 0; }
- size_t FileSize() const override;
- aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override;
- size_t Tell() const override;
- void Flush() override {}
- private:
- size_t m_Size = 0;
- size_t m_SeekPtr = 0;
- std::unique_ptr<uint8_t[]> m_Buffer;
- // Info about a read-only file inside a ZIP
- class ZipFileInfo
- explicit ZipFileInfo(unzFile zip_handle, size_t size);
- // Allocate and Extract data from the ZIP
- ZipFile * Extract(unzFile zip_handle) const;
- unz_file_pos_s m_ZipFilePos;
- ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size)
- : m_Size(size) {
- ai_assert(m_Size != 0);
- // Workaround for MSVC 2013 - C2797
- m_ZipFilePos.num_of_file = 0;
- m_ZipFilePos.pos_in_zip_directory = 0;
- unzGetFilePos(zip_handle, &(m_ZipFilePos));
- ZipFile * ZipFileInfo::Extract(unzFile zip_handle) const {
- // Find in the ZIP. This cannot fail
- unz_file_pos_s *filepos = const_cast<unz_file_pos_s*>(&(m_ZipFilePos));
- if (unzGoToFilePos(zip_handle, filepos) != UNZ_OK)
- return nullptr;
+ return mapping;
- if (unzOpenCurrentFile(zip_handle) != UNZ_OK)
+// A read-only file inside a ZIP
+class ZipFile : public IOStream {
+ friend class ZipFileInfo;
+ explicit ZipFile(size_t size);
+ virtual ~ZipFile();
+ // IOStream interface
+ size_t Read(void *pvBuffer, size_t pSize, size_t pCount) override;
+ size_t Write(const void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override { return 0; }
+ size_t FileSize() const override;
+ aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override;
+ size_t Tell() const override;
+ void Flush() override {}
+private:
+ size_t m_Size = 0;
+ size_t m_SeekPtr = 0;
+ std::unique_ptr<uint8_t[]> m_Buffer;
+// Info about a read-only file inside a ZIP
+class ZipFileInfo {
+ explicit ZipFileInfo(unzFile zip_handle, size_t size);
+ // Allocate and Extract data from the ZIP
+ ZipFile *Extract(unzFile zip_handle) const;
+ unz_file_pos_s m_ZipFilePos;
+ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size) :
+ m_Size(size) {
+ ai_assert(m_Size != 0);
+ // Workaround for MSVC 2013 - C2797
+ m_ZipFilePos.num_of_file = 0;
+ m_ZipFilePos.pos_in_zip_directory = 0;
+ unzGetFilePos(zip_handle, &(m_ZipFilePos));
- ZipFile *zip_file = new ZipFile(m_Size);
+ZipFile *ZipFileInfo::Extract(unzFile zip_handle) const {
+ // Find in the ZIP. This cannot fail
+ unz_file_pos_s *filepos = const_cast<unz_file_pos_s *>(&(m_ZipFilePos));
+ if (unzGoToFilePos(zip_handle, filepos) != UNZ_OK)
- if (unzReadCurrentFile(zip_handle, zip_file->m_Buffer.get(), static_cast<unsigned int>(m_Size)) != static_cast<int>(m_Size))
- // Failed, release the memory
- delete zip_file;
- zip_file = nullptr;
+ if (unzOpenCurrentFile(zip_handle) != UNZ_OK)
- ai_assert(unzCloseCurrentFile(zip_handle) == UNZ_OK);
- return zip_file;
+ ZipFile *zip_file = new ZipFile(m_Size);
- ZipFile::ZipFile(size_t size)
- m_Buffer = std::unique_ptr<uint8_t[]>(new uint8_t[m_Size]);
+ if (unzReadCurrentFile(zip_handle, zip_file->m_Buffer.get(), static_cast<unsigned int>(m_Size)) != static_cast<int>(m_Size)) {
+ // Failed, release the memory
+ delete zip_file;
+ zip_file = nullptr;
- ZipFile::~ZipFile() {
+ ai_assert(unzCloseCurrentFile(zip_handle) == UNZ_OK);
+ return zip_file;
- size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) {
- // Should be impossible
- ai_assert(m_Buffer != nullptr);
- ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
- // Clip down to file size
- size_t byteSize = pSize * pCount;
- if ((byteSize + m_SeekPtr) > m_Size)
- pCount = (m_Size - m_SeekPtr) / pSize;
- byteSize = pSize * pCount;
- if (byteSize == 0)
+ZipFile::ZipFile(size_t size) :
+ m_Buffer = std::unique_ptr<uint8_t[]>(new uint8_t[m_Size]);
- std::memcpy(pvBuffer, m_Buffer.get() + m_SeekPtr, byteSize);
+ZipFile::~ZipFile() {
- m_SeekPtr += byteSize;
+size_t ZipFile::Read(void *pvBuffer, size_t pSize, size_t pCount) {
+ // Should be impossible
+ ai_assert(m_Buffer != nullptr);
+ ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
- return pCount;
+ // Clip down to file size
+ size_t byteSize = pSize * pCount;
+ if ((byteSize + m_SeekPtr) > m_Size) {
+ pCount = (m_Size - m_SeekPtr) / pSize;
+ byteSize = pSize * pCount;
+ if (byteSize == 0)
- size_t ZipFile::FileSize() const {
- return m_Size;
+ std::memcpy(pvBuffer, m_Buffer.get() + m_SeekPtr, byteSize);
- aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) {
- switch (pOrigin)
+ m_SeekPtr += byteSize;
+ return pCount;
+size_t ZipFile::FileSize() const {
+ return m_Size;
+aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) {
+ switch (pOrigin) {
case aiOrigin_SET: {
if (pOffset > m_Size) return aiReturn_FAILURE;
m_SeekPtr = pOffset;
@@ -296,242 +290,237 @@ namespace Assimp {
return aiReturn_SUCCESS;
default:;
- return aiReturn_FAILURE;
- size_t ZipFile::Tell() const {
- return m_SeekPtr;
+ return aiReturn_FAILURE;
- // pImpl of the Zip Archive IO
- class ZipArchiveIOSystem::Implement {
- static const unsigned int FileNameSize = 256;
+size_t ZipFile::Tell() const {
+ return m_SeekPtr;
- Implement(IOSystem* pIOHandler, const char* pFilename, const char* pMode);
- ~Implement();
+// pImpl of the Zip Archive IO
+class ZipArchiveIOSystem::Implement {
+ static const unsigned int FileNameSize = 256;
- bool isOpen() const;
- void getFileList(std::vector<std::string>& rFileList);
- void getFileListExtension(std::vector<std::string>& rFileList, const std::string& extension);
- bool Exists(std::string& filename);
- IOStream* OpenFile(std::string& filename);
+ Implement(IOSystem *pIOHandler, const char *pFilename, const char *pMode);
+ ~Implement();
- static void SimplifyFilename(std::string& filename);
+ bool isOpen() const;
+ void getFileList(std::vector<std::string> &rFileList);
+ void getFileListExtension(std::vector<std::string> &rFileList, const std::string &extension);
+ bool Exists(std::string &filename);
+ IOStream *OpenFile(std::string &filename);
- void MapArchive();
+ static void SimplifyFilename(std::string &filename);
- typedef std::map<std::string, ZipFileInfo> ZipFileInfoMap;
+ void MapArchive();
- unzFile m_ZipFileHandle = nullptr;
- ZipFileInfoMap m_ArchiveMap;
+ typedef std::map<std::string, ZipFileInfo> ZipFileInfoMap;
- ZipArchiveIOSystem::Implement::Implement(IOSystem* pIOHandler, const char* pFilename, const char* pMode) {
- ai_assert(strcmp(pMode, "r") == 0);
- ai_assert(pFilename != nullptr);
- if (pFilename[0] == 0)
+ unzFile m_ZipFileHandle = nullptr;
+ ZipFileInfoMap m_ArchiveMap;
- zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
- m_ZipFileHandle = unzOpen2(pFilename, &mapping);
+ZipArchiveIOSystem::Implement::Implement(IOSystem *pIOHandler, const char *pFilename, const char *pMode) {
+ ai_assert(strcmp(pMode, "r") == 0);
+ ai_assert(pFilename != nullptr);
+ if (pFilename[0] == 0 || nullptr == pMode) {
+ zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
+ m_ZipFileHandle = unzOpen2(pFilename, &mapping);
- ZipArchiveIOSystem::Implement::~Implement() {
- if (m_ZipFileHandle != nullptr) {
- unzClose(m_ZipFileHandle);
- m_ZipFileHandle = nullptr;
+ZipArchiveIOSystem::Implement::~Implement() {
+ if (m_ZipFileHandle != nullptr) {
+ unzClose(m_ZipFileHandle);
+ m_ZipFileHandle = nullptr;
- void ZipArchiveIOSystem::Implement::MapArchive() {
- if (m_ZipFileHandle == nullptr)
+void ZipArchiveIOSystem::Implement::MapArchive() {
+ if (m_ZipFileHandle == nullptr)
- if (!m_ArchiveMap.empty())
+ if (!m_ArchiveMap.empty())
- // At first ensure file is already open
- if (unzGoToFirstFile(m_ZipFileHandle) != UNZ_OK)
+ // At first ensure file is already open
+ if (unzGoToFirstFile(m_ZipFileHandle) != UNZ_OK)
- // Loop over all files
- do {
- char filename[FileNameSize];
- unz_file_info fileInfo;
+ // Loop over all files
+ do {
+ char filename[FileNameSize];
+ unz_file_info fileInfo;
- if (unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, nullptr, 0, nullptr, 0) == UNZ_OK) {
- if (fileInfo.uncompressed_size != 0) {
- std::string filename_string(filename, fileInfo.size_filename);
- SimplifyFilename(filename_string);
- m_ArchiveMap.emplace(filename_string, ZipFileInfo(m_ZipFileHandle, fileInfo.uncompressed_size));
+ if (unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, nullptr, 0, nullptr, 0) == UNZ_OK) {
+ if (fileInfo.uncompressed_size != 0) {
+ std::string filename_string(filename, fileInfo.size_filename);
+ SimplifyFilename(filename_string);
+ m_ArchiveMap.emplace(filename_string, ZipFileInfo(m_ZipFileHandle, fileInfo.uncompressed_size));
- } while (unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
+ } while (unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
- bool ZipArchiveIOSystem::Implement::isOpen() const {
- return (m_ZipFileHandle != nullptr);
+bool ZipArchiveIOSystem::Implement::isOpen() const {
+ return (m_ZipFileHandle != nullptr);
- void ZipArchiveIOSystem::Implement::getFileList(std::vector<std::string>& rFileList) {
- MapArchive();
- rFileList.clear();
+void ZipArchiveIOSystem::Implement::getFileList(std::vector<std::string> &rFileList) {
+ MapArchive();
+ rFileList.clear();
- for (const auto &file : m_ArchiveMap) {
- rFileList.push_back(file.first);
+ for (const auto &file : m_ArchiveMap) {
+ rFileList.push_back(file.first);
- void ZipArchiveIOSystem::Implement::getFileListExtension(std::vector<std::string>& rFileList, const std::string& extension) {
+void ZipArchiveIOSystem::Implement::getFileListExtension(std::vector<std::string> &rFileList, const std::string &extension) {
- if (extension == BaseImporter::GetExtension(file.first))
+ if (extension == BaseImporter::GetExtension(file.first))
- bool ZipArchiveIOSystem::Implement::Exists(std::string& filename) {
+bool ZipArchiveIOSystem::Implement::Exists(std::string &filename) {
- ZipFileInfoMap::const_iterator it = m_ArchiveMap.find(filename);
- return (it != m_ArchiveMap.end());
+ ZipFileInfoMap::const_iterator it = m_ArchiveMap.find(filename);
+ return (it != m_ArchiveMap.end());
- IOStream * ZipArchiveIOSystem::Implement::OpenFile(std::string& filename) {
+IOStream *ZipArchiveIOSystem::Implement::OpenFile(std::string &filename) {
- SimplifyFilename(filename);
+ SimplifyFilename(filename);
- // Find in the map
- ZipFileInfoMap::const_iterator zip_it = m_ArchiveMap.find(filename);
- if (zip_it == m_ArchiveMap.cend())
+ // Find in the map
+ ZipFileInfoMap::const_iterator zip_it = m_ArchiveMap.find(filename);
+ if (zip_it == m_ArchiveMap.cend())
- const ZipFileInfo &zip_file = (*zip_it).second;
- return zip_file.Extract(m_ZipFileHandle);
+ const ZipFileInfo &zip_file = (*zip_it).second;
+ return zip_file.Extract(m_ZipFileHandle);
- inline void ReplaceAll(std::string& data, const std::string& before, const std::string& after) {
- size_t pos = data.find(before);
- while (pos != std::string::npos)
- data.replace(pos, before.size(), after);
- pos = data.find(before, pos + after.size());
+inline void ReplaceAll(std::string &data, const std::string &before, const std::string &after) {
+ size_t pos = data.find(before);
+ while (pos != std::string::npos) {
+ data.replace(pos, before.size(), after);
+ pos = data.find(before, pos + after.size());
- inline void ReplaceAllChar(std::string& data, const char before, const char after) {
- data[pos] = after;
- pos = data.find(before, pos + 1);
+inline void ReplaceAllChar(std::string &data, const char before, const char after) {
+ data[pos] = after;
+ pos = data.find(before, pos + 1);
- void ZipArchiveIOSystem::Implement::SimplifyFilename(std::string& filename)
- ReplaceAllChar(filename, '\\', '/');
- // Remove all . and / from the beginning of the path
- size_t pos = filename.find_first_not_of("./");
- if (pos != 0)
- filename.erase(0, pos);
+void ZipArchiveIOSystem::Implement::SimplifyFilename(std::string &filename) {
+ ReplaceAllChar(filename, '\\', '/');
+ // Remove all . and / from the beginning of the path
+ size_t pos = filename.find_first_not_of("./");
+ if (pos != 0)
+ filename.erase(0, pos);
+ // Simplify "my/folder/../file.png" constructions, if any
+ static const std::string relative("/../");
+ const size_t relsize = relative.size() - 1;
+ pos = filename.find(relative);
+ // Previous slash
+ size_t prevpos = filename.rfind('/', pos - 1);
+ if (prevpos == pos)
+ filename.erase(0, pos + relative.size());
+ else
+ filename.erase(prevpos, pos + relsize - prevpos);
- // Simplify "my/folder/../file.png" constructions, if any
- static const std::string relative("/../");
- const size_t relsize = relative.size() - 1;
pos = filename.find(relative);
- // Previous slash
- size_t prevpos = filename.rfind('/', pos - 1);
- if (prevpos == pos)
- filename.erase(0, pos + relative.size());
- else
- filename.erase(prevpos, pos + relsize - prevpos);
- pos = filename.find(relative);
- ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem* pIOHandler, const char* pFilename, const char* pMode)
- : pImpl(new Implement(pIOHandler, pFilename, pMode)) {
- // The ZipArchiveIO
- ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem* pIOHandler, const std::string& rFilename, const char* pMode)
- : pImpl(new Implement(pIOHandler, rFilename.c_str(), pMode))
+ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem *pIOHandler, const char *pFilename, const char *pMode) :
+ pImpl(new Implement(pIOHandler, pFilename, pMode)) {
- ZipArchiveIOSystem::~ZipArchiveIOSystem() {
- delete pImpl;
+// The ZipArchiveIO
+ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem *pIOHandler, const std::string &rFilename, const char *pMode) :
+ pImpl(new Implement(pIOHandler, rFilename.c_str(), pMode)) {
- bool ZipArchiveIOSystem::Exists(const char* pFilename) const {
+ZipArchiveIOSystem::~ZipArchiveIOSystem() {
+ delete pImpl;
- if (pFilename == nullptr) {
- return false;
+bool ZipArchiveIOSystem::Exists(const char *pFilename) const {
- std::string filename(pFilename);
- return pImpl->Exists(filename);
+ if (pFilename == nullptr) {
- // This is always '/' in a ZIP
- char ZipArchiveIOSystem::getOsSeparator() const {
- return '/';
+ std::string filename(pFilename);
+ return pImpl->Exists(filename);
- // Only supports Reading
- IOStream * ZipArchiveIOSystem::Open(const char* pFilename, const char* pMode) {
+// This is always '/' in a ZIP
+char ZipArchiveIOSystem::getOsSeparator() const {
+ return '/';
- for (size_t i = 0; pMode[i] != 0; ++i)
- ai_assert(pMode[i] != 'w');
- if (pMode[i] == 'w')
+// Only supports Reading
+IOStream *ZipArchiveIOSystem::Open(const char *pFilename, const char *pMode) {
- return pImpl->OpenFile(filename);
+ for (size_t i = 0; pMode[i] != 0; ++i) {
+ ai_assert(pMode[i] != 'w');
+ if (pMode[i] == 'w')
- void ZipArchiveIOSystem::Close(IOStream* pFile) {
- delete pFile;
+ return pImpl->OpenFile(filename);
- bool ZipArchiveIOSystem::isOpen() const {
- return (pImpl->isOpen());
+void ZipArchiveIOSystem::Close(IOStream *pFile) {
+ delete pFile;
- void ZipArchiveIOSystem::getFileList(std::vector<std::string>& rFileList) const {
- return pImpl->getFileList(rFileList);
+bool ZipArchiveIOSystem::isOpen() const {
+ return (pImpl->isOpen());
- void ZipArchiveIOSystem::getFileListExtension(std::vector<std::string>& rFileList, const std::string& extension) const {
- return pImpl->getFileListExtension(rFileList, extension);
+void ZipArchiveIOSystem::getFileList(std::vector<std::string> &rFileList) const {
+ return pImpl->getFileList(rFileList);
- bool ZipArchiveIOSystem::isZipArchive(IOSystem* pIOHandler, const char* pFilename) {
- Implement tmp(pIOHandler, pFilename, "r");
- return tmp.isOpen();
+void ZipArchiveIOSystem::getFileListExtension(std::vector<std::string> &rFileList, const std::string &extension) const {
+ return pImpl->getFileListExtension(rFileList, extension);
- bool ZipArchiveIOSystem::isZipArchive(IOSystem* pIOHandler, const std::string& rFilename) {
- return isZipArchive(pIOHandler, rFilename.c_str());
+bool ZipArchiveIOSystem::isZipArchive(IOSystem *pIOHandler, const char *pFilename) {
+ Implement tmp(pIOHandler, pFilename, "r");
+ return tmp.isOpen();
+bool ZipArchiveIOSystem::isZipArchive(IOSystem *pIOHandler, const std::string &rFilename) {
+ return isZipArchive(pIOHandler, rFilename.c_str());
@@ -48,40 +48,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
-namespace FBX
- const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
- '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
- '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'
- }; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
- 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
-}
+namespace FBX {
+const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+}; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
+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
+} // namespace FBX
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // AI_FBXCOMMON_H_INC
@@ -189,8 +189,7 @@ private:
const aiMatrix4x4 &absolute_transform);
- std::vector<unsigned int> ConvertLine(const LineGeometry& line, const Model& model,
- aiNode *parent, aiNode *root_node);
+ std::vector<unsigned int> ConvertLine(const LineGeometry& line, aiNode *root_node);
aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
@@ -220,17 +219,15 @@ private:
* - outputVertStartIndices is only used when a material index is specified, it gives for
* each output vertex the DOM index it maps to.
- void ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
- aiNode *parent = NULL, aiNode *root_node = NULL,
- unsigned int materialIndex = NO_MATERIAL_SEPARATION,
+ void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
+ aiNode *parent = NULL, unsigned int materialIndex = NO_MATERIAL_SEPARATION,
std::vector<unsigned int> *outputVertStartIndices = NULL);
- // lookup
- static const aiNode* GetNodeByName( const aiString& name, aiNode *current_node );
void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
+ aiNode *parent );
void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
@@ -352,12 +349,10 @@ private:
aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name,
const Model& target,
NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
- NodeMap::const_iterator iter_end,
- const LayerMap& layer_map,
+ NodeMap::const_iterator iterEnd,
int64_t start, int64_t stop,
- double& max_time,
- double& min_time,
- bool reverse_order = false);
+ double& maxTime,
+ double& minTime);
// key (time), value, mapto (component index)
typedef std::tuple<std::shared_ptr<KeyTimeList>, std::shared_ptr<KeyValueList>, unsigned int > KeyFrameList;
@@ -382,20 +377,6 @@ private:
double& minTime,
Model::RotOrder order);
- // ------------------------------------------------------------------------------------------------
- void ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
- aiVectorKey* out_translation,
- const KeyFrameListList& scaling,
- const KeyFrameListList& translation,
- const KeyFrameListList& rotation,
- const KeyTimeList& times,
- double& maxTime,
- double& minTime,
- Model::RotOrder order,
- const aiVector3D& def_scale,
- const aiVector3D& def_translate,
- const aiVector3D& def_rotation);
// euler xyz -> quat
aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order);
@@ -437,7 +418,7 @@ private:
// 0: not assigned yet, others: index is value - 1
unsigned int defaultMaterialIndex;
- std::vector<aiMesh*> meshes;
+ std::vector<aiMesh*> mMeshes;
std::vector<aiMaterial*> materials;
std::vector<aiAnimation*> animations;
std::vector<aiLight*> lights;
@@ -467,9 +448,9 @@ private:
double anim_fps;
- aiScene* const out;
+ aiScene* const mSceneOut;
const FBX::Document& doc;
+ bool mRemoveEmptyBones;
static void BuildBoneList(aiNode *current_node, const aiNode *root_node, const aiScene *scene,
std::vector<aiBone*>& bones);
@@ -428,8 +428,8 @@ void Document::ReadPropertyTemplates()
const ElementCollection otypes = sdefs.GetCollection("ObjectType");
for(ElementMap::const_iterator it = otypes.first; it != otypes.second; ++it) {
const Element& el = *(*it).second;
- const Scope* sc = el.Compound();
- if(!sc) {
+ const Scope* curSc = el.Compound();
+ if (!curSc) {
DOMWarning("expected nested scope in ObjectType, ignoring",&el);
@@ -442,24 +442,24 @@ void Document::ReadPropertyTemplates()
const std::string& oname = ParseTokenAsString(*tok[0]);
- const ElementCollection templs = sc->GetCollection("PropertyTemplate");
- for(ElementMap::const_iterator it = templs.first; it != templs.second; ++it) {
- const Element& el = *(*it).second;
+ const ElementCollection templs = curSc->GetCollection("PropertyTemplate");
+ for (ElementMap::const_iterator elemIt = templs.first; elemIt != templs.second; ++elemIt) {
+ const Element &innerEl = *(*elemIt).second;
+ const Scope *innerSc = innerEl.Compound();
+ if (!innerSc) {
DOMWarning("expected nested scope in PropertyTemplate, ignoring",&el);
- const TokenList& tok = el.Tokens();
- if(tok.empty()) {
+ const TokenList &curTok = innerEl.Tokens();
+ if (curTok.empty()) {
DOMWarning("expected name for PropertyTemplate element, ignoring",&el);
- const std::string& pname = ParseTokenAsString(*tok[0]);
+ const std::string &pname = ParseTokenAsString(*curTok[0]);
- const Element* Properties70 = (*sc)["Properties70"];
+ const Element *Properties70 = (*innerSc)["Properties70"];
if(Properties70) {
std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>(
*Properties70,std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable*>(NULL))
@@ -529,8 +529,8 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
animationStacksResolved.reserve(animationStacks.size());
for(uint64_t id : animationStacks) {
LazyObject* const lazy = GetObject(id);
- const AnimationStack* stack;
- if(!lazy || !(stack = lazy->Get<AnimationStack>())) {
+ const AnimationStack *stack = lazy->Get<AnimationStack>();
+ if(!lazy || nullptr == stack ) {
DOMWarning("failed to read AnimationStack object");
@@ -62,90 +62,81 @@ namespace Assimp {
// so they are specified with an 'A' suffix.
void FBX::Node::AddP70int(
- const std::string& name, int32_t value
+ const std::string& cur_name, int32_t value
) {
FBX::Node n("P");
- n.AddProperties(name, "int", "Integer", "", value);
+ n.AddProperties(cur_name, "int", "Integer", "", value);
AddChild(n);
void FBX::Node::AddP70bool(
- const std::string& name, bool value
+ const std::string& cur_name, bool value
- n.AddProperties(name, "bool", "", "", int32_t(value));
+ n.AddProperties(cur_name, "bool", "", "", int32_t(value));
void FBX::Node::AddP70double(
- const std::string& name, double value
-) {
+ const std::string &cur_name, double value) {
- n.AddProperties(name, "double", "Number", "", value);
+ n.AddProperties(cur_name, "double", "Number", "", value);
void FBX::Node::AddP70numberA(
- n.AddProperties(name, "Number", "", "A", value);
+ n.AddProperties(cur_name, "Number", "", "A", value);
void FBX::Node::AddP70color(
- const std::string& name, double r, double g, double b
+ const std::string &cur_name, double r, double g, double b) {
- n.AddProperties(name, "ColorRGB", "Color", "", r, g, b);
+ n.AddProperties(cur_name, "ColorRGB", "Color", "", r, g, b);
void FBX::Node::AddP70colorA(
- n.AddProperties(name, "Color", "", "A", r, g, b);
+ n.AddProperties(cur_name, "Color", "", "A", r, g, b);
void FBX::Node::AddP70vector(
- const std::string& name, double x, double y, double z
+ const std::string &cur_name, double x, double y, double z) {
- n.AddProperties(name, "Vector3D", "Vector", "", x, y, z);
+ n.AddProperties(cur_name, "Vector3D", "Vector", "", x, y, z);
void FBX::Node::AddP70vectorA(
- n.AddProperties(name, "Vector", "", "A", x, y, z);
+ n.AddProperties(cur_name, "Vector", "", "A", x, y, z);
void FBX::Node::AddP70string(
- const std::string& name, const std::string& value
+ const std::string &cur_name, const std::string &value) {
- n.AddProperties(name, "KString", "", "", value);
+ n.AddProperties(cur_name, "KString", "", "", value);
void FBX::Node::AddP70enum(
+ const std::string &cur_name, int32_t value) {
- n.AddProperties(name, "enum", "", "", value);
+ n.AddProperties(cur_name, "enum", "", "", value);
void FBX::Node::AddP70time(
- const std::string& name, int64_t value
+ const std::string &cur_name, int64_t value) {
- n.AddProperties(name, "KTime", "Time", "", value);
+ n.AddProperties(cur_name, "KTime", "Time", "", value);
@@ -944,7 +944,9 @@ void FBXExporter::WriteDefinitions ()
FBX::Node defs("Definitions");
defs.AddChild("Version", int32_t(100));
defs.AddChild("Count", int32_t(total_count));
- for (auto &n : object_nodes) { defs.AddChild(n); }
+ for (auto &on : object_nodes) {
+ defs.AddChild(on);
defs.Dump(outfile, binary, 0);
@@ -1119,10 +1121,10 @@ void FBXExporter::WriteObjects ()
for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
const aiFace &f = m->mFaces[fi];
for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
- const aiVector3D &n = m->mNormals[f.mIndices[pvi]];
- normal_data.push_back(n.x);
- normal_data.push_back(n.y);
- normal_data.push_back(n.z);
+ const aiVector3D &curN = m->mNormals[f.mIndices[pvi]];
+ normal_data.push_back(curN.x);
+ normal_data.push_back(curN.y);
+ normal_data.push_back(curN.z);
FBX::Node::WritePropertyNode(
@@ -1226,14 +1228,14 @@ void FBXExporter::WriteObjects ()
- const aiVector3D &uv =
+ const aiVector3D &curUv =
m->mTextureCoords[uvi][f.mIndices[pvi]];
- auto elem = index_by_uv.find(uv);
+ auto elem = index_by_uv.find(curUv);
if (elem == index_by_uv.end()) {
- index_by_uv[uv] = index;
+ index_by_uv[curUv] = index;
uv_indices.push_back(index);
for (unsigned int x = 0; x < m->mNumUVComponents[uvi]; ++x) {
- uv_data.push_back(uv[x]);
+ uv_data.push_back(curUv[x]);
++index;
@@ -2246,7 +2248,7 @@ const std::map<std::string,std::pair<std::string,char>> transform_types = {
// write a single model node to the stream
void FBXExporter::WriteModelNode(
StreamWriterLE& outstream,
- bool binary,
+ bool,
const aiNode* node,
int64_t node_uid,
const std::string& type,
@@ -2299,16 +2301,13 @@ void FBXExporter::WriteModelNode(
err << item.first;
throw DeadlyExportError(err.str());
- const std::string &name = elem->second.first;
+ const std::string &cur_name = elem->second.first;
const aiVector3D &v = item.second;
- if (name.compare(0, 4, "Lcl ") == 0) {
+ if (cur_name.compare(0, 4, "Lcl ") == 0) {
// special handling for animatable properties
- p.AddP70(
- name, name, "", "A",
- double(v.x), double(v.y), double(v.z)
- );
+ p.AddP70( cur_name, cur_name, "", "A", double(v.x), double(v.y), double(v.z) );
- p.AddP70vector(name, v.x, v.y, v.z);
+ p.AddP70vector(cur_name, v.x, v.y, v.z);
@@ -50,27 +49,25 @@ namespace Assimp {
namespace FBX {
/** FBX import settings, parts of which are publicly accessible via their corresponding AI_CONFIG constants */
-struct ImportSettings
- ImportSettings()
- : strictMode(true)
- , readAllLayers(true)
- , readAllMaterials(false)
- , readMaterials(true)
- , readTextures(true)
- , readCameras(true)
- , readLights(true)
- , readAnimations(true)
- , readWeights(true)
- , preservePivots(true)
- , optimizeEmptyAnimationCurves(true)
- , useLegacyEmbeddedTextureNaming(false)
- , removeEmptyBones( true )
- , convertToMeters( false ) {
+struct ImportSettings {
+ ImportSettings() :
+ strictMode(true),
+ readAllLayers(true),
+ readAllMaterials(false),
+ readMaterials(true),
+ readTextures(true),
+ readCameras(true),
+ readLights(true),
+ readAnimations(true),
+ readWeights(true),
+ preservePivots(true),
+ optimizeEmptyAnimationCurves(true),
+ useLegacyEmbeddedTextureNaming(false),
+ removeEmptyBones(true),
+ convertToMeters(false) {
// empty
/** enable strict mode:
* - only accept fbx 2012, 2013 files
* - on the slightest error, give up.
@@ -94,7 +91,6 @@ struct ImportSettings
* This bit is ignored unless readMaterials=true*/
bool readAllMaterials;
/** import materials (true) or skip them and assign a default
* material. The default value is true.*/
bool readMaterials;
@@ -156,9 +152,7 @@ struct ImportSettings
bool convertToMeters;
-} // !FBX
-} // !Assimp
@@ -51,45 +50,44 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXImportSettings.h"
// TinyFormatter.h
namespace Formatter {
- template <typename T,typename TR, typename A> class basic_formatter;
- typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
-// -------------------------------------------------------------------------------------------
-/** Load the Autodesk FBX file format.
+template <typename T, typename TR, typename A>
+class basic_formatter;
- See http://en.wikipedia.org/wiki/FBX
-*/
+typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
+} // namespace Formatter
+// -------------------------------------------------------------------------------------------
+/// Loads the Autodesk FBX file format.
+///
+/// See http://en.wikipedia.org/wiki/FBX
// -------------------------------------------------------------------------------------------
-class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter>
+class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
FBXImporter();
virtual ~FBXImporter();
// --------------------
- bool CanRead( const std::string& pFile,
- IOSystem* pIOHandler,
- bool checkSig
- ) const;
+ bool CanRead(const std::string &pFile,
+ IOSystem *pIOHandler,
+ bool checkSig) const;
- const aiImporterDesc* GetInfo () const;
+ const aiImporterDesc *GetInfo() const;
- void SetupProperties(const Importer* pImp);
+ void SetupProperties(const Importer *pImp);
- void InternReadFile( const std::string& pFile,
- aiScene* pScene,
- IOSystem* pIOHandler
+ void InternReadFile(const std::string &pFile,
+ aiScene *pScene,
+ IOSystem *pIOHandler);
FBX::ImportSettings settings;
@@ -97,4 +95,3 @@ private:
#endif // !INCLUDED_AI_FBX_IMPORTER_H
@@ -53,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXDocumentUtil.h"
#include "FBXProperties.h"
#include <assimp/ByteSwapper.h>
+#include <assimp/ParsingUtils.h>
#include <algorithm> // std::transform
#include "FBXUtil.h"
@@ -86,7 +86,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
std::string templateName;
// lower-case shading because Blender (for example) writes "Phong"
- std::transform(shading.begin(), shading.end(), shading.begin(), ::tolower);
+ std::transform(shading.begin(), shading.end(), shading.begin(), Assimp::ToLower<char>);
if(shading == "phong") {
templateName = "Material.FbxSurfacePhong";
@@ -46,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-#include "FBXParser.h"
-#include "FBXMeshGeometry.h"
#include "FBXDocument.h"
-#include "FBXImporter.h"
+#include "FBXImporter.h"
+#include "FBXMeshGeometry.h"
+#include "FBXParser.h"
@@ -58,87 +58,81 @@ namespace FBX {
using namespace Util;
-Model::Model(uint64_t id, const Element& element, const Document& doc, const std::string& name)
- : Object(id,element,name)
- , shading("Y")
- const Scope& sc = GetRequiredScope(element);
- const Element* const Shading = sc["Shading"];
- const Element* const Culling = sc["Culling"];
- if(Shading) {
- shading = GetRequiredToken(*Shading,0).StringContents();
+Model::Model(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
+ Object(id, element, name), shading("Y") {
+ const Scope &sc = GetRequiredScope(element);
+ const Element *const Shading = sc["Shading"];
+ const Element *const Culling = sc["Culling"];
+ if (Shading) {
+ shading = GetRequiredToken(*Shading, 0).StringContents();
if (Culling) {
- culling = ParseTokenAsString(GetRequiredToken(*Culling,0));
+ culling = ParseTokenAsString(GetRequiredToken(*Culling, 0));
- props = GetPropertyTable(doc,"Model.FbxNode",element,sc);
- ResolveLinks(element,doc);
+ props = GetPropertyTable(doc, "Model.FbxNode", element, sc);
+ ResolveLinks(element, doc);
-Model::~Model()
+Model::~Model() {
-void Model::ResolveLinks(const Element& element, const Document& doc)
- const char* const arr[] = {"Geometry","Material","NodeAttribute"};
+void Model::ResolveLinks(const Element&, const Document &doc) {
+ const char *const arr[] = { "Geometry", "Material", "NodeAttribute" };
// resolve material
- const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),arr, 3);
+ const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), arr, 3);
materials.reserve(conns.size());
geometry.reserve(conns.size());
attributes.reserve(conns.size());
- for(const Connection* con : conns) {
+ for (const Connection *con : conns) {
// material and geometry links should be Object-Object connections
if (con->PropertyName().length()) {
- const Object* const ob = con->SourceObject();
- if(!ob) {
- DOMWarning("failed to read source object for incoming Model link, ignoring",&element);
+ const Object *const ob = con->SourceObject();
+ if (!ob) {
+ DOMWarning("failed to read source object for incoming Model link, ignoring", &element);
- const Material* const mat = dynamic_cast<const Material*>(ob);
- if(mat) {
+ const Material *const mat = dynamic_cast<const Material *>(ob);
+ if (mat) {
materials.push_back(mat);
- const Geometry* const geo = dynamic_cast<const Geometry*>(ob);
- if(geo) {
+ const Geometry *const geo = dynamic_cast<const Geometry *>(ob);
+ if (geo) {
geometry.push_back(geo);
- const NodeAttribute* const att = dynamic_cast<const NodeAttribute*>(ob);
- if(att) {
+ const NodeAttribute *const att = dynamic_cast<const NodeAttribute *>(ob);
+ if (att) {
attributes.push_back(att);
- DOMWarning("source object for model link is neither Material, NodeAttribute nor Geometry, ignoring",&element);
+ DOMWarning("source object for model link is neither Material, NodeAttribute nor Geometry, ignoring", &element);
-bool Model::IsNull() const
- const std::vector<const NodeAttribute*>& attrs = GetAttributes();
- for(const NodeAttribute* att : attrs) {
+bool Model::IsNull() const {
+ const std::vector<const NodeAttribute *> &attrs = GetAttributes();
+ for (const NodeAttribute *att : attrs) {
- const Null* null_tag = dynamic_cast<const Null*>(att);
- if(null_tag) {
+ const Null *null_tag = dynamic_cast<const Null *>(att);
+ if (null_tag) {
@@ -146,8 +140,7 @@ bool Model::IsNull() const
-} //!FBX
-} //!Assimp
@@ -49,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h>
#include <map>
+#include <vector>
#include <assimp/LogAux.h>
#include <assimp/fast_atof.h>
@@ -126,7 +126,7 @@ public:
const Element* operator[] (const std::string& index) const {
ElementMap::const_iterator it = elements.find(index);
- return it == elements.end() ? NULL : (*it).second;
+ return it == elements.end() ? nullptr : (*it).second;
const Element* FindElementCaseInsensitive(const std::string& elementName) const {
@@ -209,21 +209,25 @@ DirectPropertyMap PropertyTable::GetUnparsedProperties() const
DirectPropertyMap result;
// Loop through all the lazy properties (which is all the properties)
- for(const LazyPropertyMap::value_type& element : lazyProps) {
+ for(const LazyPropertyMap::value_type& currentElement : lazyProps) {
// Skip parsed properties
- if (props.end() != props.find(element.first)) continue;
+ if (props.end() != props.find(currentElement.first)) {
// Read the element's value.
// Wrap the naked pointer (since the call site is required to acquire ownership)
// std::unique_ptr from C++11 would be preferred both as a wrapper and a return value.
- std::shared_ptr<Property> prop = std::shared_ptr<Property>(ReadTypedProperty(*element.second));
+ std::shared_ptr<Property> prop = std::shared_ptr<Property>(ReadTypedProperty(*currentElement.second));
// Element could not be read. Skip it.
- if (!prop) continue;
+ if (!prop) {
// Add to result
- result[element.first] = prop;
+ result[currentElement.first] = prop;
return result;
@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXCompileConfig.h"
+#include <assimp/defs.h>
#include <vector>
#include <string>
@@ -118,11 +118,11 @@ void HMPImporter::InternReadFile( const std::string& pFile,
aiScene* _pScene, IOSystem* _pIOHandler)
pScene = _pScene;
- pIOHandler = _pIOHandler;
- std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+ mIOHandler = _pIOHandler;
+ std::unique_ptr<IOStream> file(mIOHandler->Open(pFile));
// Check whether we can read from the file
- if( file.get() == NULL)
+ if( file.get() == nullptr)
throw DeadlyImportError( "Failed to open HMP file " + pFile + ".");
// Check whether the HMP file is large enough to contain
@@ -285,11 +285,11 @@ public:
out.mVerts.reserve(out.mVerts.size() + cnt);
for(const CurveEntry& entry : curves) {
- const size_t cnt = out.mVerts.size();
+ const size_t curCnt = out.mVerts.size();
entry.first->SampleDiscrete(out);
- if (!entry.second && cnt != out.mVerts.size()) {
- std::reverse(out.mVerts.begin()+cnt,out.mVerts.end());
+ if (!entry.second && curCnt != out.mVerts.size()) {
+ std::reverse(out.mVerts.begin() + curCnt, out.mVerts.end());
@@ -329,8 +329,8 @@ public:
have_param = true;
- else if (const Schema_2x3::IfcCartesianPoint* const r = sel->ResolveSelectPtr<Schema_2x3::IfcCartesianPoint>(conv.db)) {
- ConvertCartesianPoint(point,*r);
+ else if (const Schema_2x3::IfcCartesianPoint* const curR = sel->ResolveSelectPtr<Schema_2x3::IfcCartesianPoint>(conv.db)) {
+ ConvertCartesianPoint(point, *curR);
have_point = true;
@@ -346,8 +346,8 @@ public:
@@ -101,7 +101,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
- ai_assert(std::count(inmesh.mVertcnt.begin(), inmesh.mVertcnt.end(), 0) == 0);
+ ai_assert(std::count(inmesh.mVertcnt.begin(), inmesh.mVertcnt.end(), 0u) == 0);
typedef std::vector<unsigned int>::const_iterator face_iter;
@@ -379,7 +379,7 @@ void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh&
IfcVector3 q;
bool take_any = false;
- for (unsigned int i = 0; i < 2; ++i, take_any = true) {
+ for (unsigned int j = 0; j < 2; ++j, take_any = true) {
if ((last_dir == 0 || take_any) && std::abs(d.x) > 1e-6) {
q.y = startvec.y;
q.z = startvec.z;
@@ -294,7 +294,7 @@ void InsertWindowContours(const ContourVector& contours,
const IfcFloat epsilon = diag/1000.f;
// walk through all contour points and find those that lie on the BB corner
- size_t last_hit = -1, very_first_hit = -1;
+ size_t last_hit = (size_t)-1, very_first_hit = (size_t)-1;
IfcVector2 edge;
for(size_t n = 0, e=0, size = contour.size();; n=(n+1)%size, ++e) {
@@ -330,7 +330,7 @@ void InsertWindowContours(const ContourVector& contours,
const size_t old = curmesh.mVerts.size();
size_t cnt = last_hit > n ? size-(last_hit-n) : n-last_hit;
- for(size_t a = last_hit, e = 0; e <= cnt; a=(a+1)%size, ++e) {
+ for(size_t a = last_hit, ee = 0; ee <= cnt; a=(a+1)%size, ++ee) {
// hack: this is to fix cases where opening contours are self-intersecting.
// Clipper doesn't produce such polygons, but as soon as we're back in
// our brave new floating-point world, very small distances are consumed
@@ -45,6 +45,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "code/Step/STEPFile.h"
+# pragma warning( disable : 4512 )
namespace IFC {
namespace Schema_2x3 {
@@ -362,8 +362,9 @@ void TempMesh::FixupFaceOrientation()
std::reverse(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc);
std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
- for( size_t a = 0; a < nbvc - 1; ++a )
- std::swap(neighbour[nbvsi + a], neighbour[nbvsi + a + 1]);
+ for (size_t aa = 0; aa < nbvc - 1; ++aa) {
+ std::swap(neighbour[nbvsi + aa], neighbour[nbvsi + aa + 1]);
// either way we're done with the neighbour. Mark it as done and continue checking from there recursively
@@ -50,12 +50,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/TinyFormatter.h>
+#include <functional>
-namespace EXPRESS = STEP::EXPRESS;
-#include <functional>
+namespace EXPRESS = STEP::EXPRESS;
std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = "")
@@ -127,8 +126,8 @@ STEP::DB* STEP::ReadFileHeader(std::shared_ptr<IOStream> stream) {
if (list->GetSize() > 1) {
ASSIMP_LOG_WARN(AddLineNumber("multiple schemas currently not supported",line));
- const EXPRESS::STRING* string( nullptr );
- if (!list->GetSize() || !(string=dynamic_cast<const EXPRESS::STRING*>( (*list)[0].get() ))) {
+ const EXPRESS::STRING *string = dynamic_cast<const EXPRESS::STRING *>((*list)[0].get());
+ if (!list->GetSize() || nullptr == string ) {
throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line);
head.fileSchema = *string;
@@ -539,7 +538,7 @@ void STEP::LazyObject::LazyInit() const {
const char* acopy = args;
- std::shared_ptr<const EXPRESS::LIST> conv_args = EXPRESS::LIST::Parse(acopy,STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema());
+ std::shared_ptr<const EXPRESS::LIST> conv_args = EXPRESS::LIST::Parse(acopy,(uint64_t)STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema());
delete[] args;
args = NULL;
@@ -225,7 +225,7 @@ namespace {
, SchemaEntry("presentation_representation_select",NULL )
, SchemaEntry("presentation_size_assignment_select",NULL )
, SchemaEntry("presentation_style_select",NULL )
-, SchemaEntry("presented_item_select",NULL )
+//, SchemaEntry("presented_item_select",NULL )
, SchemaEntry("pressure_measure",NULL )
, SchemaEntry("product_definition_or_assembly_relationship",NULL )
, SchemaEntry("product_definition_or_breakdown_element_usage",NULL )
@@ -397,7 +397,7 @@ namespace {
, SchemaEntry("applied_organizational_project_assignment",&STEP::ObjectHelper<applied_organizational_project_assignment,1>::Construct )
, SchemaEntry("person_and_organization_assignment",&STEP::ObjectHelper<person_and_organization_assignment,2>::Construct )
, SchemaEntry("applied_person_and_organization_assignment",&STEP::ObjectHelper<applied_person_and_organization_assignment,1>::Construct )
-, SchemaEntry("presented_item",&STEP::ObjectHelper<presented_item,0>::Construct )
+//, SchemaEntry("presented_item",&STEP::ObjectHelper<presented_item,0>::Construct )
, SchemaEntry("applied_presented_item",&STEP::ObjectHelper<applied_presented_item,1>::Construct )
, SchemaEntry("security_classification_assignment",&STEP::ObjectHelper<security_classification_assignment,1>::Construct )
, SchemaEntry("applied_security_classification_assignment",&STEP::ObjectHelper<applied_security_classification_assignment,1>::Construct )
@@ -1014,7 +1014,7 @@ namespace {
, SchemaEntry("presentation_size",&STEP::ObjectHelper<NotImplemented,0>::Construct )
, SchemaEntry("presentation_style_assignment",&STEP::ObjectHelper<presentation_style_assignment,1>::Construct )
, SchemaEntry("presentation_style_by_context",&STEP::ObjectHelper<presentation_style_by_context,1>::Construct )
-, SchemaEntry("presented_item_representation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+//, SchemaEntry("presented_item_representation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
, SchemaEntry("pressure_measure_with_unit",&STEP::ObjectHelper<pressure_measure_with_unit,0>::Construct )
, SchemaEntry("pressure_unit",&STEP::ObjectHelper<pressure_unit,0>::Construct )
, SchemaEntry("procedural_representation",&STEP::ObjectHelper<procedural_representation,0>::Construct )
@@ -1311,11 +1311,11 @@ void StepFile::GetSchema(EXPRESS::ConversionSchema& out)
namespace STEP {
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
+/*template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
return 0;
+*/
template <> size_t GenericFill<measure_with_unit>(const DB& db, const LIST& params, measure_with_unit* in)
@@ -1359,8 +1359,7 @@ template <> size_t GenericFill<absorbed_dose_unit>(const DB& db, const LIST& par
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to absorbed_dose_unit"); } return base;
-template <> size_t GenericFill<abstract_variable>(const DB& db, const LIST& params, abstract_variable* in)
+template <> size_t GenericFill<abstract_variable>(const DB&, const LIST&, abstract_variable*) {
size_t base = 0;
return base;
@@ -1680,7 +1679,7 @@ template <> size_t GenericFill<amount_of_substance_unit>(const DB& db, const LIS
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to amount_of_substance_unit"); } return base;
-template <> size_t GenericFill<angle_direction_reference>(const DB& db, const LIST& params, angle_direction_reference* in)
+template <> size_t GenericFill<angle_direction_reference>(const DB&, const LIST&, angle_direction_reference*)
@@ -452,11 +452,11 @@ template <> size_t GenericFill<applied_person_and_organization_assignment>(const
-template <> size_t GenericFill<presented_item>(const DB& db, const LIST& params, presented_item* in)
+/*template <> size_t GenericFill<presented_item>(const DB& db, const LIST& params, presented_item* in)
+}*/
template <> size_t GenericFill<applied_presented_item>(const DB& db, const LIST& params, applied_presented_item* in)
@@ -642,11 +642,11 @@ template <> size_t GenericFill<atomic_formula>(const DB& db, const LIST& params,
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to atomic_formula"); } return base;
-template <> size_t GenericFill<attribute_assertion>(const DB& db, const LIST& params, attribute_assertion* in)
+/*template <> size_t GenericFill<attribute_assertion>(const DB& db, const LIST& params, attribute_assertion* in)
template <> size_t GenericFill<attribute_language_assignment>(const DB& db, const LIST& params, attribute_language_assignment* in)
@@ -683,11 +683,11 @@ template <> size_t GenericFill<attribute_value_assignment>(const DB& db, const L
-template <> size_t GenericFill<auxiliary_geometric_representation_item>(const DB& db, const LIST& params, auxiliary_geometric_representation_item* in)
+/*template <> size_t GenericFill<auxiliary_geometric_representation_item>(const DB& db, const LIST& params, auxiliary_geometric_representation_item* in)
template <> size_t GenericFill<placement>(const DB& db, const LIST& params, placement* in)
@@ -946,7 +946,7 @@ template <> size_t GenericFill<back_chaining_rule>(const DB& db, const LIST& par
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to back_chaining_rule"); } return base;
-template <> size_t GenericFill<back_chaining_rule_body>(const DB& db, const LIST& params, back_chaining_rule_body* in)
+/*template <> size_t GenericFill<back_chaining_rule_body>(const DB& db, const LIST& params, back_chaining_rule_body* in)
@@ -956,7 +956,7 @@ template <> size_t GenericFill<colour>(const DB& db, const LIST& params, colour*
template <> size_t GenericFill<background_colour>(const DB& db, const LIST& params, background_colour* in)
@@ -987,11 +987,11 @@ template <> size_t GenericFill<bezier_surface>(const DB& db, const LIST& params,
if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to bezier_surface"); } return base;
-template <> size_t GenericFill<generic_expression>(const DB& db, const LIST& params, generic_expression* in)
+/*template <> size_t GenericFill<generic_expression>(const DB& db, const LIST& params, generic_expression* in)
template <> size_t GenericFill<binary_generic_expression>(const DB& db, const LIST& params, binary_generic_expression* in)
@@ -1004,11 +1004,11 @@ template <> size_t GenericFill<binary_generic_expression>(const DB& db, const LI
-template <> size_t GenericFill<binary_numeric_expression>(const DB& db, const LIST& params, binary_numeric_expression* in)
+/*template <> size_t GenericFill<binary_numeric_expression>(const DB& db, const LIST& params, binary_numeric_expression* in)
template <> size_t GenericFill<binary_representation_item>(const DB& db, const LIST& params, binary_representation_item* in)
@@ -1071,11 +1071,11 @@ template <> size_t GenericFill<boolean_literal>(const DB& db, const LIST& params
-template <> size_t GenericFill<boolean_representation_item>(const DB& db, const LIST& params, boolean_representation_item* in)
+/*template <> size_t GenericFill<boolean_representation_item>(const DB& db, const LIST& params, boolean_representation_item* in)
template <> size_t GenericFill<boolean_result>(const DB& db, const LIST& params, boolean_result* in)
@@ -1128,7 +1128,7 @@ template <> size_t GenericFill<boundary_curve>(const DB& db, const LIST& params,
if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to boundary_curve"); } return base;
-template <> size_t GenericFill<bounded_pcurve>(const DB& db, const LIST& params, bounded_pcurve* in)
+/*template <> size_t GenericFill<bounded_pcurve>(const DB& db, const LIST& params, bounded_pcurve* in)
@@ -1144,7 +1144,7 @@ template <> size_t GenericFill<founded_item>(const DB& db, const LIST& params, f
template <> size_t GenericFill<box_domain>(const DB& db, const LIST& params, box_domain* in)
@@ -1218,11 +1218,11 @@ template <> size_t GenericFill<breakdown_element_group_assignment>(const DB& db,
-template <> size_t GenericFill<breakdown_element_realization>(const DB& db, const LIST& params, breakdown_element_realization* in)
+/*template <> size_t GenericFill<breakdown_element_realization>(const DB& db, const LIST& params, breakdown_element_realization* in)
template <> size_t GenericFill<breakdown_element_usage>(const DB& db, const LIST& params, breakdown_element_usage* in)
@@ -1784,11 +1784,11 @@ template <> size_t GenericFill<characteristic_type>(const DB& db, const LIST& pa
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to characteristic_type"); } return base;
-template <> size_t GenericFill<characterized_class>(const DB& db, const LIST& params, characterized_class* in)
+/*template <> size_t GenericFill<characterized_class>(const DB& db, const LIST& params, characterized_class* in)
template <> size_t GenericFill<characterized_object>(const DB& db, const LIST& params, characterized_object* in)
@@ -1947,6 +1947,7 @@ template <> size_t GenericFill<colour_rgb>(const DB& db, const LIST& params, col
} while (0);
+/*
template <> size_t GenericFill<common_datum>(const DB& db, const LIST& params, common_datum* in)
@@ -1958,7 +1959,7 @@ template <> size_t GenericFill<comparison_expression>(const DB& db, const LIST&
template <> size_t GenericFill<complex_clause>(const DB& db, const LIST& params, complex_clause* in)
@@ -2792,7 +2793,7 @@ template <> size_t GenericFill<cylindricity_tolerance>(const DB& db, const LIST&
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to cylindricity_tolerance"); } return base;
-template <> size_t GenericFill<date_representation_item>(const DB& db, const LIST& params, date_representation_item* in)
+/*template <> size_t GenericFill<date_representation_item>(const DB& db, const LIST& params, date_representation_item* in)
@@ -2802,7 +2803,7 @@ template <> size_t GenericFill<date_time_representation_item>(const DB& db, cons
template <> size_t GenericFill<dated_effectivity>(const DB& db, const LIST& params, dated_effectivity* in)
@@ -98,11 +98,11 @@ template <> size_t GenericFill<dimension_pair>(const DB& db, const LIST& params,
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to dimension_pair"); } return base;
-template <> size_t GenericFill<dimension_text_associativity>(const DB& db, const LIST& params, dimension_text_associativity* in)
+/*template <> size_t GenericFill<dimension_text_associativity>(const DB& db, const LIST& params, dimension_text_associativity* in)
template <> size_t GenericFill<dimensional_location_with_path>(const DB& db, const LIST& params, dimensional_location_with_path* in)
@@ -160,11 +160,11 @@ template <> size_t GenericFill<direction>(const DB& db, const LIST& params, dire
-template <> size_t GenericFill<document_file>(const DB& db, const LIST& params, document_file* in)
+/*template <> size_t GenericFill<document_file>(const DB& db, const LIST& params, document_file* in)
template <> size_t GenericFill<document_identifier>(const DB& db, const LIST& params, document_identifier* in)
@@ -347,11 +347,11 @@ template <> size_t GenericFill<draughting_model_item_association>(const DB& db,
if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to draughting_model_item_association"); } return base;
-template <> size_t GenericFill<pre_defined_colour>(const DB& db, const LIST& params, pre_defined_colour* in)
+/*template <> size_t GenericFill<pre_defined_colour>(const DB& db, const LIST& params, pre_defined_colour* in)
template <> size_t GenericFill<draughting_pre_defined_colour>(const DB& db, const LIST& params, draughting_pre_defined_colour* in)
@@ -461,11 +461,11 @@ template <> size_t GenericFill<draughting_text_literal_with_delineation>(const D
if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to draughting_text_literal_with_delineation"); } return base;
-template <> size_t GenericFill<presentation_set>(const DB& db, const LIST& params, presentation_set* in)
+/*template <> size_t GenericFill<presentation_set>(const DB& db, const LIST& params, presentation_set* in)
template <> size_t GenericFill<drawing_revision>(const DB& db, const LIST& params, drawing_revision* in)
@@ -592,11 +592,11 @@ template <> size_t GenericFill<edge_curve>(const DB& db, const LIST& params, edg
-template <> size_t GenericFill<edge_loop>(const DB& db, const LIST& params, edge_loop* in)
+/*template <> size_t GenericFill<edge_loop>(const DB& db, const LIST& params, edge_loop* in)
template <> size_t GenericFill<electric_charge_measure_with_unit>(const DB& db, const LIST& params, electric_charge_measure_with_unit* in)
@@ -711,11 +711,11 @@ template <> size_t GenericFill<enum_reference_prefix>(const DB& db, const LIST&
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to enum_reference_prefix"); } return base;
-template <> size_t GenericFill<evaluated_characteristic>(const DB& db, const LIST& params, evaluated_characteristic* in)
+/*template <> size_t GenericFill<evaluated_characteristic>(const DB& db, const LIST& params, evaluated_characteristic* in)
template <> size_t GenericFill<evaluated_degenerate_pcurve>(const DB& db, const LIST& params, evaluated_degenerate_pcurve* in)
@@ -867,11 +867,11 @@ template <> size_t GenericFill<explicit_procedural_shape_representation_relation
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to explicit_procedural_shape_representation_relationship"); } return base;
-template <> size_t GenericFill<expression_conversion_based_unit>(const DB& db, const LIST& params, expression_conversion_based_unit* in)
+/*template <> size_t GenericFill<expression_conversion_based_unit>(const DB& db, const LIST& params, expression_conversion_based_unit* in)
template <> size_t GenericFill<extension>(const DB& db, const LIST& params, extension* in)
@@ -903,35 +903,35 @@ template <> size_t GenericFill<external_class_library>(const DB& db, const LIST&
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to external_class_library"); } return base;
-template <> size_t GenericFill<externally_defined_class>(const DB& db, const LIST& params, externally_defined_class* in)
+/*template <> size_t GenericFill<externally_defined_class>(const DB& db, const LIST& params, externally_defined_class* in)
-template <> size_t GenericFill<externally_defined_colour>(const DB& db, const LIST& params, externally_defined_colour* in)
+/*template <> size_t GenericFill<externally_defined_colour>(const DB& db, const LIST& params, externally_defined_colour* in)
-template <> size_t GenericFill<externally_defined_context_dependent_unit>(const DB& db, const LIST& params, externally_defined_context_dependent_unit* in)
+/*template <> size_t GenericFill<externally_defined_context_dependent_unit>(const DB& db, const LIST& params, externally_defined_context_dependent_unit* in)
-template <> size_t GenericFill<externally_defined_conversion_based_unit>(const DB& db, const LIST& params, externally_defined_conversion_based_unit* in)
+/*template <> size_t GenericFill<externally_defined_conversion_based_unit>(const DB& db, const LIST& params, externally_defined_conversion_based_unit* in)
-template <> size_t GenericFill<externally_defined_currency>(const DB& db, const LIST& params, externally_defined_currency* in)
+/*template <> size_t GenericFill<externally_defined_currency>(const DB& db, const LIST& params, externally_defined_currency* in)
template <> size_t GenericFill<externally_defined_item>(const DB& db, const LIST& params, externally_defined_item* in)
@@ -957,7 +957,7 @@ template <> size_t GenericFill<externally_defined_curve_font>(const DB& db, cons
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to externally_defined_curve_font"); } return base;
-template <> size_t GenericFill<externally_defined_dimension_definition>(const DB& db, const LIST& params, externally_defined_dimension_definition* in)
+/*template <> size_t GenericFill<externally_defined_dimension_definition>(const DB& db, const LIST& params, externally_defined_dimension_definition* in)
@@ -979,7 +979,7 @@ template <> size_t GenericFill<externally_defined_marker>(const DB& db, const LI
template <> size_t GenericFill<picture_representation_item>(const DB& db, const LIST& params, picture_representation_item* in)
@@ -993,7 +993,7 @@ template <> size_t GenericFill<externally_defined_picture_representation_item>(c
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to externally_defined_picture_representation_item"); } return base;
-template <> size_t GenericFill<externally_defined_representation_item>(const DB& db, const LIST& params, externally_defined_representation_item* in)
+/*template <> size_t GenericFill<externally_defined_representation_item>(const DB& db, const LIST& params, externally_defined_representation_item* in)
@@ -1003,7 +1003,7 @@ template <> size_t GenericFill<externally_defined_string>(const DB& db, const LI
size_t base = GenericFill(db, params, static_cast<externally_defined_representation_item*>(in));
template <> size_t GenericFill<externally_defined_symbol>(const DB& db, const LIST& params, externally_defined_symbol* in)
@@ -1029,11 +1029,11 @@ template <> size_t GenericFill<externally_defined_tile>(const DB& db, const LIST
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to externally_defined_tile"); } return base;
-template <> size_t GenericFill<externally_defined_tile_style>(const DB& db, const LIST& params, externally_defined_tile_style* in)
+/*template <> size_t GenericFill<externally_defined_tile_style>(const DB& db, const LIST& params, externally_defined_tile_style* in)
template <> size_t GenericFill<swept_area_solid>(const DB& db, const LIST& params, swept_area_solid* in)
@@ -1358,11 +1358,11 @@ template <> size_t GenericFill<forward_chaining_rule>(const DB& db, const LIST&
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to forward_chaining_rule"); } return base;
-template <> size_t GenericFill<forward_chaining_rule_premise>(const DB& db, const LIST& params, forward_chaining_rule_premise* in)
+/*template <> size_t GenericFill<forward_chaining_rule_premise>(const DB& db, const LIST& params, forward_chaining_rule_premise* in)
template <> size_t GenericFill<frequency_measure_with_unit>(const DB& db, const LIST& params, frequency_measure_with_unit* in)
@@ -1454,11 +1454,11 @@ template <> size_t GenericFill<geometric_item_specific_usage>(const DB& db, cons
if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to geometric_item_specific_usage"); } return base;
-template <> size_t GenericFill<geometric_model_element_relationship>(const DB& db, const LIST& params, geometric_model_element_relationship* in)
+/*template <> size_t GenericFill<geometric_model_element_relationship>(const DB& db, const LIST& params, geometric_model_element_relationship* in)
template <> size_t GenericFill<representation_context>(const DB& db, const LIST& params, representation_context* in)
@@ -1633,11 +1633,11 @@ template <> size_t GenericFill<indirectly_selected_elements>(const DB& db, const
-template <> size_t GenericFill<indirectly_selected_shape_elements>(const DB& db, const LIST& params, indirectly_selected_shape_elements* in)
+/*template <> size_t GenericFill<indirectly_selected_shape_elements>(const DB& db, const LIST& params, indirectly_selected_shape_elements* in)
template <> size_t GenericFill<inductance_measure_with_unit>(const DB& db, const LIST& params, inductance_measure_with_unit* in)
@@ -1674,11 +1674,11 @@ template <> size_t GenericFill<instance_usage_context_assignment>(const DB& db,
-template <> size_t GenericFill<instanced_feature>(const DB& db, const LIST& params, instanced_feature* in)
+/*template <> size_t GenericFill<instanced_feature>(const DB& db, const LIST& params, instanced_feature* in)
template <> size_t GenericFill<literal_number>(const DB& db, const LIST& params, literal_number* in)
@@ -1698,11 +1698,11 @@ template <> size_t GenericFill<int_literal>(const DB& db, const LIST& params, in
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to int_literal"); } return base;
-template <> size_t GenericFill<integer_representation_item>(const DB& db, const LIST& params, integer_representation_item* in)
+/*template <> size_t GenericFill<integer_representation_item>(const DB& db, const LIST& params, integer_representation_item* in)
template <> size_t GenericFill<surface_curve>(const DB& db, const LIST& params, surface_curve* in)
@@ -1734,11 +1734,11 @@ template <> size_t GenericFill<intersection_curve>(const DB& db, const LIST& par
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to intersection_curve"); } return base;
-template <> size_t GenericFill<interval_expression>(const DB& db, const LIST& params, interval_expression* in)
+/*template <> size_t GenericFill<interval_expression>(const DB& db, const LIST& params, interval_expression* in)
template <> size_t GenericFill<iso4217_currency>(const DB& db, const LIST& params, iso4217_currency* in)
@@ -1746,11 +1746,11 @@ template <> size_t GenericFill<iso4217_currency>(const DB& db, const LIST& param
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to iso4217_currency"); } return base;
-template <> size_t GenericFill<known_source>(const DB& db, const LIST& params, known_source* in)
+/*template <> size_t GenericFill<known_source>(const DB& db, const LIST& params, known_source* in)
template <> size_t GenericFill<laid_defined_transformation>(const DB& db, const LIST& params, laid_defined_transformation* in)
@@ -1943,11 +1943,11 @@ template <> size_t GenericFill<logical_literal>(const DB& db, const LIST& params
-template <> size_t GenericFill<logical_representation_item>(const DB& db, const LIST& params, logical_representation_item* in)
+/*template <> size_t GenericFill<logical_representation_item>(const DB&, const LIST& params, logical_representation_item* )
template <> size_t GenericFill<loop>(const DB& db, const LIST& params, loop* in)
@@ -2105,11 +2105,11 @@ template <> size_t GenericFill<material_property_representation>(const DB& db, c
-template <> size_t GenericFill<measure_representation_item>(const DB& db, const LIST& params, measure_representation_item* in)
+/*template <> size_t GenericFill<measure_representation_item>(const DB& db, const LIST& params, measure_representation_item* in)
template <> size_t GenericFill<product_context>(const DB& db, const LIST& params, product_context* in)
@@ -2165,11 +2165,11 @@ template <> size_t GenericFill<mechanical_design_shaded_presentation_representat
if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to mechanical_design_shaded_presentation_representation"); } return base;
-template <> size_t GenericFill<min_and_major_ply_orientation_basis>(const DB& db, const LIST& params, min_and_major_ply_orientation_basis* in)
+/*template <> size_t GenericFill<min_and_major_ply_orientation_basis>(const DB& db, const LIST& params, min_and_major_ply_orientation_basis* in)
template <> size_t GenericFill<modified_geometric_tolerance>(const DB& db, const LIST& params, modified_geometric_tolerance* in)
@@ -2211,11 +2211,11 @@ template <> size_t GenericFill<multi_language_attribute_assignment>(const DB& db
-template <> size_t GenericFill<multiple_arity_boolean_expression>(const DB& db, const LIST& params, multiple_arity_boolean_expression* in)
+/*template <> size_t GenericFill<multiple_arity_boolean_expression>(const DB& db, const LIST& params, multiple_arity_boolean_expression* in)
template <> size_t GenericFill<multiple_arity_generic_expression>(const DB& db, const LIST& params, multiple_arity_generic_expression* in)
@@ -2228,11 +2228,11 @@ template <> size_t GenericFill<multiple_arity_generic_expression>(const DB& db,
-template <> size_t GenericFill<multiple_arity_numeric_expression>(const DB& db, const LIST& params, multiple_arity_numeric_expression* in)
+/*template <> size_t GenericFill<multiple_arity_numeric_expression>(const DB& db, const LIST& params, multiple_arity_numeric_expression* in)
template <> size_t GenericFill<next_assembly_usage_occurrence>(const DB& db, const LIST& params, next_assembly_usage_occurrence* in)
@@ -2533,11 +2533,11 @@ template <> size_t GenericFill<parametric_representation_context>(const DB& db,
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to parametric_representation_context"); } return base;
-template <> size_t GenericFill<partial_document_with_structured_text_representation_assignment>(const DB& db, const LIST& params, partial_document_with_structured_text_representation_assignment* in)
+/*template <> size_t GenericFill<partial_document_with_structured_text_representation_assignment>(const DB& db, const LIST& params, partial_document_with_structured_text_representation_assignment* in)
template <> size_t GenericFill<pcurve>(const DB& db, const LIST& params, pcurve* in)
@@ -2591,11 +2591,11 @@ template <> size_t GenericFill<perpendicularity_tolerance>(const DB& db, const L
if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to perpendicularity_tolerance"); } return base;
-template <> size_t GenericFill<person_and_organization_address>(const DB& db, const LIST& params, person_and_organization_address* in)
+/*template <> size_t GenericFill<person_and_organization_address>(const DB& db, const LIST& params, person_and_organization_address* in)
template <> size_t GenericFill<personal_address>(const DB& db, const LIST& params, personal_address* in)
@@ -2715,11 +2715,11 @@ template <> size_t GenericFill<ply_laminate_table>(const DB& db, const LIST& par
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to ply_laminate_table"); } return base;
-template <> size_t GenericFill<point_and_vector>(const DB& db, const LIST& params, point_and_vector* in)
+/*template <> size_t GenericFill<point_and_vector>(const DB& db, const LIST& params, point_and_vector* in)
template <> size_t GenericFill<point_on_curve>(const DB& db, const LIST& params, point_on_curve* in)
@@ -2758,11 +2758,11 @@ template <> size_t GenericFill<point_on_surface>(const DB& db, const LIST& param
-template <> size_t GenericFill<point_path>(const DB& db, const LIST& params, point_path* in)
+/*template <> size_t GenericFill<point_path>(const DB& db, const LIST& params, point_path* in)
template <> size_t GenericFill<point_replica>(const DB& db, const LIST& params, point_replica* in)
@@ -2904,11 +2904,11 @@ template <> size_t GenericFill<pre_defined_marker>(const DB& db, const LIST& par
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to pre_defined_marker"); } return base;
-template <> size_t GenericFill<pre_defined_point_marker_symbol>(const DB& db, const LIST& params, pre_defined_point_marker_symbol* in)
+/*template <> size_t GenericFill<pre_defined_point_marker_symbol>(const DB& db, const LIST& params, pre_defined_point_marker_symbol* in)
template <> size_t GenericFill<pre_defined_surface_condition_symbol>(const DB& db, const LIST& params, pre_defined_surface_condition_symbol* in)
@@ -3002,7 +3002,7 @@ template <> size_t GenericFill<procedural_representation_sequence>(const DB& db,
-template <> size_t GenericFill<procedural_shape_representation>(const DB& db, const LIST& params, procedural_shape_representation* in)
+/*template <> size_t GenericFill<procedural_shape_representation>(const DB& db, const LIST& params, procedural_shape_representation* in)
@@ -3012,7 +3012,7 @@ template <> size_t GenericFill<procedural_shape_representation_sequence>(const D
template <> size_t GenericFill<product_category>(const DB& db, const LIST& params, product_category* in)
@@ -3033,11 +3033,11 @@ template <> size_t GenericFill<product_category>(const DB& db, const LIST& param
-template <> size_t GenericFill<product_class>(const DB& db, const LIST& params, product_class* in)
+/*template <> size_t GenericFill<product_class>(const DB& db, const LIST& params, product_class* in)
template <> size_t GenericFill<product_concept_context>(const DB& db, const LIST& params, product_concept_context* in)
@@ -3131,11 +3131,11 @@ template <> size_t GenericFill<product_definition_with_associated_documents>(con
-template <> size_t GenericFill<product_identification>(const DB& db, const LIST& params, product_identification* in)
+/*template <> size_t GenericFill<product_identification>(const DB& db, const LIST& params, product_identification* in)
template <> size_t GenericFill<product_material_composition_relationship>(const DB& db, const LIST& params, product_material_composition_relationship* in)
@@ -3174,11 +3174,11 @@ template <> size_t GenericFill<product_related_product_category>(const DB& db, c
-template <> size_t GenericFill<product_specification>(const DB& db, const LIST& params, product_specification* in)
+/*template <> size_t GenericFill<product_specification>(const DB& db, const LIST& params, product_specification* in)
template <> size_t GenericFill<tolerance_zone_definition>(const DB& db, const LIST& params, tolerance_zone_definition* in)
@@ -3289,11 +3289,11 @@ template <> size_t GenericFill<radius_dimension>(const DB& db, const LIST& param
if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to radius_dimension"); } return base;
-template <> size_t GenericFill<range_characteristic>(const DB& db, const LIST& params, range_characteristic* in)
+/*template <> size_t GenericFill<range_characteristic>(const DB& db, const LIST& params, range_characteristic* in)
template <> size_t GenericFill<ratio_unit>(const DB& db, const LIST& params, ratio_unit* in)
@@ -3318,11 +3318,11 @@ template <> size_t GenericFill<rational_b_spline_surface>(const DB& db, const LI
if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to rational_b_spline_surface"); } return base;
-template <> size_t GenericFill<rational_representation_item>(const DB& db, const LIST& params, rational_representation_item* in)
+/*template <> size_t GenericFill<rational_representation_item>(const DB& db, const LIST& params, rational_representation_item* in)
template <> size_t GenericFill<real_literal>(const DB& db, const LIST& params, real_literal* in)
@@ -3330,11 +3330,11 @@ template <> size_t GenericFill<real_literal>(const DB& db, const LIST& params, r
if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to real_literal"); } return base;
-template <> size_t GenericFill<real_representation_item>(const DB& db, const LIST& params, real_representation_item* in)
+/*template <> size_t GenericFill<real_representation_item>(const DB& db, const LIST& params, real_representation_item* in)
template <> size_t GenericFill<rectangular_composite_surface>(const DB& db, const LIST& params, rectangular_composite_surface* in)
@@ -3410,11 +3410,11 @@ template <> size_t GenericFill<relative_event_occurrence>(const DB& db, const LI
-template <> size_t GenericFill<rep_item_group>(const DB& db, const LIST& params, rep_item_group* in)
+/*template <> size_t GenericFill<rep_item_group>(const DB& db, const LIST& params, rep_item_group* in)
template <> size_t GenericFill<reparametrised_composite_curve_segment>(const DB& db, const LIST& params, reparametrised_composite_curve_segment* in)
@@ -3449,11 +3449,11 @@ template <> size_t GenericFill<requirement_assigned_object>(const DB& db, const
-template <> size_t GenericFill<requirement_assignment>(const DB& db, const LIST& params, requirement_assignment* in)
+/*template <> size_t GenericFill<requirement_assignment>(const DB& db, const LIST& params, requirement_assignment* in)
template <> size_t GenericFill<requirement_source>(const DB& db, const LIST& params, requirement_source* in)
@@ -3891,7 +3891,7 @@ template <> size_t GenericFill<shell_based_wireframe_shape_representation>(const
if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to shell_based_wireframe_shape_representation"); } return base;
-template <> size_t GenericFill<si_absorbed_dose_unit>(const DB& db, const LIST& params, si_absorbed_dose_unit* in)
+/*template <> size_t GenericFill<si_absorbed_dose_unit>(const DB& db, const LIST& params, si_absorbed_dose_unit* in)
@@ -3991,7 +3991,7 @@ template <> size_t GenericFill<si_resistance_unit>(const DB& db, const LIST& par
template <> size_t GenericFill<si_unit>(const DB& db, const LIST& params, si_unit* in)
@@ -4010,7 +4010,7 @@ template <> size_t GenericFill<si_unit>(const DB& db, const LIST& params, si_uni
-template <> size_t GenericFill<simple_boolean_expression>(const DB& db, const LIST& params, simple_boolean_expression* in)
+/*template <> size_t GenericFill<simple_boolean_expression>(const DB& db, const LIST& params, simple_boolean_expression* in)
@@ -4026,7 +4026,7 @@ template <> size_t GenericFill<slash_expression>(const DB& db, const LIST& param
size_t base = GenericFill(db, params, static_cast<binary_numeric_expression*>(in));
template <> size_t GenericFill<smeared_material_definition>(const DB& db, const LIST& params, smeared_material_definition* in)
@@ -5450,11 +5450,11 @@ template <> size_t GenericFill<unary_generic_expression>(const DB& db, const LIS
-template <> size_t GenericFill<unary_numeric_expression>(const DB& db, const LIST& params, unary_numeric_expression* in)
+/*template <> size_t GenericFill<unary_numeric_expression>(const DB& db, const LIST& params, unary_numeric_expression* in)
template <> size_t GenericFill<uncertainty_assigned_representation>(const DB& db, const LIST& params, uncertainty_assigned_representation* in)
@@ -5508,7 +5508,7 @@ template <> size_t GenericFill<usage_association>(const DB& db, const LIST& para
if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to usage_association"); } return base;
-template <> size_t GenericFill<user_defined_curve_font>(const DB& db, const LIST& params, user_defined_curve_font* in)
+/*template <> size_t GenericFill<user_defined_curve_font>(const DB& db, const LIST& params, user_defined_curve_font* in)
@@ -5524,7 +5524,7 @@ template <> size_t GenericFill<user_defined_terminator_symbol>(const DB& db, con
template <> size_t GenericFill<user_selected_shape_elements>(const DB& db, const LIST& params, user_selected_shape_elements* in)
@@ -5549,11 +5549,11 @@ template <> size_t GenericFill<value_representation_item>(const DB& db, const LI
-template <> size_t GenericFill<variable_semantics>(const DB& db, const LIST& params, variable_semantics* in)
+/*template <> size_t GenericFill<variable_semantics>(const DB& db, const LIST& params, variable_semantics* in)
template <> size_t GenericFill<variational_representation_item>(const DB& db, const LIST& params, variational_representation_item* in)
@@ -5577,11 +5577,11 @@ template <> size_t GenericFill<vector>(const DB& db, const LIST& params, vector*
-template <> size_t GenericFill<vector_style>(const DB& db, const LIST& params, vector_style* in)
+/*template <> size_t GenericFill<vector_style>(const DB& db, const LIST& params, vector_style* in)
template <> size_t GenericFill<velocity_measure_with_unit>(const DB& db, const LIST& params, velocity_measure_with_unit* in)
@@ -93,7 +93,7 @@ const aiImporterDesc *StepFileImporter::GetInfo() const {
static const std::string mode = "rb";
static const std::string StepFileSchema = "CONFIG_CONTROL_DESIGN";
-void StepFileImporter::InternReadFile(const std::string &file, aiScene* pScene, IOSystem* pIOHandler) {
+void StepFileImporter::InternReadFile(const std::string &file, aiScene*, IOSystem* pIOHandler) {
// Read file into memory
std::shared_ptr<IOStream> fileStream(pIOHandler->Open(file, mode));
if (!fileStream.get()) {
@@ -45,6 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace StepFile {
using namespace STEP;
@@ -404,7 +407,7 @@ namespace StepFile {
// C++ wrapper type for presentation_style_select
typedef SELECT presentation_style_select;
// C++ wrapper type for presented_item_select
- typedef SELECT presented_item_select;
+ //typedef SELECT presented_item_select;
// C++ wrapper type for pressure_measure
typedef REAL pressure_measure;
// C++ wrapper type for product_definition_or_assembly_relationship
@@ -545,7 +548,7 @@ namespace StepFile {
struct absorbed_dose_measure_with_unit;
struct derived_unit;
struct absorbed_dose_unit;
- struct abstract_variable;
+ //struct abstract_variable;
struct acceleration_measure_with_unit;
struct acceleration_unit;
struct action;
@@ -646,7 +649,7 @@ namespace StepFile {
struct applied_organizational_project_assignment;
struct person_and_organization_assignment;
struct applied_person_and_organization_assignment;
- struct presented_item;
+ //struct presented_item;
struct applied_presented_item;
struct security_classification_assignment;
struct applied_security_classification_assignment;
@@ -1483,6 +1483,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
delete root;
+ delete reader;
#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
@@ -185,9 +185,11 @@ void AnimResolver::UpdateAnimRangeSetup()
for (unsigned int i = 0; i < num; ++i) {
m = n+old_size*(i+1);
std::copy(n,n+old_size,m);
- if ((*it).pre == LWO::PrePostBehaviour_Oscillate && (reverse = !reverse))
+ const bool res = ((*it).pre == LWO::PrePostBehaviour_Oscillate);
+ reverse = !reverse;
+ if (res && reverse ) {
std::reverse(m,m+old_size-1);
// update time values
@@ -533,7 +535,7 @@ void AnimResolver::GetKeys(std::vector<aiVectorKey>& out,
// Extract animation channel
-void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int flags /*= 0*/)
+void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int /*= 0*/)
*out = NULL;
@@ -76,9 +76,6 @@ public:
LWOImporter();
~LWOImporter();
@@ -86,7 +83,6 @@ public:
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
@@ -389,7 +385,7 @@ protected:
unsigned int fileSize;
/** Output scene */
- aiScene* pScene;
+ aiScene* mScene;
/** Configuration option: speed flag set? */
bool configSpeedFlag;
@@ -406,8 +402,8 @@ protected:
-inline float LWOImporter::GetF4()
+inline
+float LWOImporter::GetF4() {
float f;
::memcpy(&f, mFileBuffer, 4);
mFileBuffer += 4;
@@ -43,30 +43,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the material oart of the LWO importer class */
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
#include "LWOLoader.h"
template <class T>
-T lerp(const T& one, const T& two, float val)
- return one + (two-one)*val;
+T lerp(const T &one, const T &two, float val) {
+ return one + (two - one) * val;
// Convert a lightwave mapping mode to our's
-inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
- switch (in)
+inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) {
+ switch (in) {
case LWO::Texture::REPEAT:
return aiTextureMapMode_Wrap;
@@ -84,15 +78,14 @@ inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
-bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTextureType type)
+bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTextureType type) {
ai_assert(NULL != pcMat);
unsigned int cur = 0, temp = 0;
bool ret = false;
- for (const auto &texture : in) {
+ for (const auto &texture : in) {
if (!texture.enabled || !texture.bCanUse)
ret = true;
@@ -101,9 +94,8 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
// as they are, the GenUVcoords step will compute UV
// channels if they're not there.
- aiTextureMapping mapping;
- switch (texture.mapMode)
+ aiTextureMapping mapping = aiTextureMapping_OTHER;
+ switch (texture.mapMode) {
case LWO::Texture::Planar:
mapping = aiTextureMapping_PLANE;
@@ -120,20 +112,18 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
ASSIMP_LOG_ERROR("LWO2: Unsupported texture mapping: FrontProjection");
mapping = aiTextureMapping_OTHER;
- case LWO::Texture::UV:
- if( UINT_MAX == texture.mRealUVIndex ) {
- // We have no UV index for this texture, so we can't display it
- continue;
+ case LWO::Texture::UV: {
+ if (UINT_MAX == texture.mRealUVIndex) {
+ // We have no UV index for this texture, so we can't display it
- // add the UV source index
- temp = texture.mRealUVIndex;
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur));
+ // add the UV source index
+ temp = texture.mRealUVIndex;
+ pcMat->AddProperty<int>((int *)&temp, 1, AI_MATKEY_UVWSRC(type, cur));
- mapping = aiTextureMapping_UV;
+ mapping = aiTextureMapping_UV;
+ } break;
@@ -143,17 +133,17 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
switch (texture.majorAxis) {
case Texture::AXIS_X:
- v = aiVector3D(1.0,0.0,0.0);
+ v = aiVector3D(1.0, 0.0, 0.0);
case Texture::AXIS_Y:
- v = aiVector3D(0.0,1.0,0.0);
+ v = aiVector3D(0.0, 1.0, 0.0);
default: // case Texture::AXIS_Z:
- v = aiVector3D(0.0,0.0,1.0);
+ v = aiVector3D(0.0, 0.0, 1.0);
- pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur));
+ pcMat->AddProperty(&v, 1, AI_MATKEY_TEXMAP_AXIS(type, cur));
// Setup UV scalings for cylindric and spherical projections
if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) {
@@ -161,15 +151,15 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
trafo.mScaling.x = texture.wrapAmountW;
trafo.mScaling.y = texture.wrapAmountH;
- static_assert(sizeof(aiUVTransform)/sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5");
- pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur));
+ static_assert(sizeof(aiUVTransform) / sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5");
+ pcMat->AddProperty(&trafo, 1, AI_MATKEY_UVTRANSFORM(type, cur));
ASSIMP_LOG_DEBUG("LWO2: Setting up non-UV mapping");
// The older LWOB format does not use indirect references to clips.
// The file name of a texture is directly specified in the tex chunk.
- if (mIsLWO2) {
+ if (mIsLWO2) {
// find the corresponding clip (take the last one if multiple
// share the same index)
ClipList::iterator end = mClips.end(), candidate = end;
@@ -178,9 +168,8 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
if ((*clip).idx == temp) {
candidate = clip;
- if (candidate == end) {
+ if (candidate == end) {
ASSIMP_LOG_ERROR("LWO2: Clip index is out of bounds");
temp = 0;
@@ -191,8 +180,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
s.Set("$texture.png");
//continue;
if (Clip::UNSUPPORTED == (*candidate).type) {
ASSIMP_LOG_ERROR("LWO2: Clip type is not supported");
@@ -205,11 +193,9 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
if ((*candidate).negate) {
flags |= aiTextureFlags_Invert;
- pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));
+ pcMat->AddProperty(&flags, 1, AI_MATKEY_TEXFLAGS(type, cur));
std::string ss = texture.mFileName;
if (!ss.length()) {
ASSIMP_LOG_WARN("LWOB: Empty file name");
@@ -218,14 +204,13 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
AdjustTexturePath(ss);
s.Set(ss);
- pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur));
+ pcMat->AddProperty(&s, AI_MATKEY_TEXTURE(type, cur));
// add the blend factor
- pcMat->AddProperty<float>(&texture.mStrength,1,AI_MATKEY_TEXBLEND(type,cur));
+ pcMat->AddProperty<float>(&texture.mStrength, 1, AI_MATKEY_TEXBLEND(type, cur));
// add the blend operation
- switch (texture.blendType)
+ switch (texture.blendType) {
case LWO::Texture::Normal:
case LWO::Texture::Multiply:
temp = (unsigned int)aiTextureOp_Multiply;
@@ -247,10 +232,9 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
ASSIMP_LOG_WARN("LWO2: Unsupported texture blend mode: alpha or displacement");
// Setup texture operation
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
+ pcMat->AddProperty<int>((int *)&temp, 1, AI_MATKEY_TEXOP(type, cur));
// setup the mapping mode
int mapping_ = static_cast<int>(mapping);
@@ -258,11 +242,11 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
// add the u-wrapping
temp = (unsigned int)GetMapMode(texture.wrapModeWidth);
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur));
+ pcMat->AddProperty<int>((int *)&temp, 1, AI_MATKEY_MAPPINGMODE_U(type, cur));
// add the v-wrapping
temp = (unsigned int)GetMapMode(texture.wrapModeHeight);
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur));
+ pcMat->AddProperty<int>((int *)&temp, 1, AI_MATKEY_MAPPINGMODE_V(type, cur));
++cur;
@@ -270,94 +254,87 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
-void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
+void LWOImporter::ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat) {
// copy the name of the surface
aiString st;
st.Set(surf.mName);
- pcMat->AddProperty(&st,AI_MATKEY_NAME);
+ pcMat->AddProperty(&st, AI_MATKEY_NAME);
const int i = surf.bDoubleSided ? 1 : 0;
- pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED);
+ pcMat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED);
// add the refraction index and the bump intensity
- pcMat->AddProperty(&surf.mIOR,1,AI_MATKEY_REFRACTI);
- pcMat->AddProperty(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING);
+ pcMat->AddProperty(&surf.mIOR, 1, AI_MATKEY_REFRACTI);
+ pcMat->AddProperty(&surf.mBumpIntensity, 1, AI_MATKEY_BUMPSCALING);
aiShadingMode m;
- if (surf.mSpecularValue && surf.mGlossiness)
+ if (surf.mSpecularValue && surf.mGlossiness) {
float fGloss;
- fGloss = std::pow( surf.mGlossiness*ai_real( 10.0 )+ ai_real( 2.0 ), ai_real( 2.0 ) );
+ fGloss = std::pow(surf.mGlossiness * ai_real(10.0) + ai_real(2.0), ai_real(2.0));
if (16.0 >= surf.mGlossiness)
fGloss = 6.0;
else if (64.0 >= surf.mGlossiness)
fGloss = 20.0;
else if (256.0 >= surf.mGlossiness)
fGloss = 50.0;
- else fGloss = 80.0;
+ fGloss = 80.0;
- pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
- pcMat->AddProperty(&fGloss,1,AI_MATKEY_SHININESS);
+ pcMat->AddProperty(&surf.mSpecularValue, 1, AI_MATKEY_SHININESS_STRENGTH);
+ pcMat->AddProperty(&fGloss, 1, AI_MATKEY_SHININESS);
m = aiShadingMode_Phong;
- else m = aiShadingMode_Gouraud;
+ } else
+ m = aiShadingMode_Gouraud;
// specular color
- aiColor3D clr = lerp( aiColor3D(1.0,1.0,1.0), surf.mColor, surf.mColorHighlights );
- pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR);
+ aiColor3D clr = lerp(aiColor3D(1.0, 1.0, 1.0), surf.mColor, surf.mColorHighlights);
+ pcMat->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
// emissive color
// luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good.
- clr.g = clr.b = clr.r = surf.mLuminosity*ai_real( 0.8 );
- pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
+ clr.g = clr.b = clr.r = surf.mLuminosity * ai_real(0.8);
+ pcMat->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_EMISSIVE);
// opacity ... either additive or default-blended, please
- if (0.0 != surf.mAdditiveTransparency) {
+ if (0.0 != surf.mAdditiveTransparency) {
const int add = aiBlendMode_Additive;
- pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY);
- pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC);
- } else if (10e10f != surf.mTransparency) {
+ pcMat->AddProperty(&surf.mAdditiveTransparency, 1, AI_MATKEY_OPACITY);
+ pcMat->AddProperty(&add, 1, AI_MATKEY_BLEND_FUNC);
+ } else if (10e10f != surf.mTransparency) {
const int def = aiBlendMode_Default;
- const float f = 1.0f-surf.mTransparency;
- pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY);
- pcMat->AddProperty(&def,1,AI_MATKEY_BLEND_FUNC);
+ const float f = 1.0f - surf.mTransparency;
+ pcMat->AddProperty(&f, 1, AI_MATKEY_OPACITY);
+ pcMat->AddProperty(&def, 1, AI_MATKEY_BLEND_FUNC);
// ADD TEXTURES to the material
// TODO: find out how we can handle COLOR textures correctly...
- bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE);
- b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE));
- HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR);
- HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS);
- HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT);
- HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY);
- HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION);
+ bool b = HandleTextures(pcMat, surf.mColorTextures, aiTextureType_DIFFUSE);
+ b = (b || HandleTextures(pcMat, surf.mDiffuseTextures, aiTextureType_DIFFUSE));
+ HandleTextures(pcMat, surf.mSpecularTextures, aiTextureType_SPECULAR);
+ HandleTextures(pcMat, surf.mGlossinessTextures, aiTextureType_SHININESS);
+ HandleTextures(pcMat, surf.mBumpTextures, aiTextureType_HEIGHT);
+ HandleTextures(pcMat, surf.mOpacityTextures, aiTextureType_OPACITY);
+ HandleTextures(pcMat, surf.mReflectionTextures, aiTextureType_REFLECTION);
// Now we need to know which shader to use .. iterate through the shader list of
// the surface and search for a name which we know ...
- for (const auto &shader : surf.mShaders) {
- if (shader.functionName == "LW_SuperCelShader" || shader.functionName == "AH_CelShader") {
+ for (const auto &shader : surf.mShaders) {
+ if (shader.functionName == "LW_SuperCelShader" || shader.functionName == "AH_CelShader") {
ASSIMP_LOG_INFO("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon");
m = aiShadingMode_Toon;
- else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel") {
+ } else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel") {
ASSIMP_LOG_INFO("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
m = aiShadingMode_Fresnel;
ASSIMP_LOG_WARN_F("LWO2: Unknown surface shader: ", shader.functionName);
@@ -368,22 +345,21 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
// (the diffuse value is just a scaling factor)
// If a diffuse texture is set, we set this value to 1.0
- clr = (b && false ? aiColor3D(1.0,1.0,1.0) : surf.mColor);
+ clr = (b && false ? aiColor3D(1.0, 1.0, 1.0) : surf.mColor);
clr.r *= surf.mDiffuseValue;
clr.g *= surf.mDiffuseValue;
clr.b *= surf.mDiffuseValue;
- pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+ pcMat->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
-char LWOImporter::FindUVChannels(LWO::TextureList& list,
- LWO::Layer& /*layer*/,LWO::UVChannel& uv, unsigned int next)
+char LWOImporter::FindUVChannels(LWO::TextureList &list,
+ LWO::Layer & /*layer*/, LWO::UVChannel &uv, unsigned int next) {
char ret = 0;
- for (auto &texture : list) {
+ for (auto &texture : list) {
// Ignore textures with non-UV mappings for the moment.
- if (!texture.enabled || !texture.bCanUse || texture.mapMode != LWO::Texture::UV) {
+ if (!texture.enabled || !texture.bCanUse || texture.mapMode != LWO::Texture::UV) {
@@ -391,11 +367,9 @@ char LWOImporter::FindUVChannels(LWO::TextureList& list,
ret = 1;
// got it.
- if (texture.mRealUVIndex == UINT_MAX || texture.mRealUVIndex == next)
+ if (texture.mRealUVIndex == UINT_MAX || texture.mRealUVIndex == next) {
texture.mRealUVIndex = next;
// channel mismatch. need to duplicate the material.
ASSIMP_LOG_WARN("LWO: Channel mismatch, would need to duplicate surface [design bug]");
@@ -407,49 +381,48 @@ char LWOImporter::FindUVChannels(LWO::TextureList& list,
-void LWOImporter::FindUVChannels(LWO::Surface& surf,
- LWO::SortedRep& sorted,LWO::Layer& layer,
- unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
+void LWOImporter::FindUVChannels(LWO::Surface &surf,
+ LWO::SortedRep &sorted, LWO::Layer &layer,
+ unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]) {
unsigned int next = 0, extra = 0, num_extra = 0;
// Check whether we have an UV entry != 0 for one of the faces in 'sorted'
- for (unsigned int i = 0; i < layer.mUVChannels.size();++i) {
- LWO::UVChannel& uv = layer.mUVChannels[i];
+ for (unsigned int i = 0; i < layer.mUVChannels.size(); ++i) {
+ LWO::UVChannel &uv = layer.mUVChannels[i];
- for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
+ for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
- LWO::Face& face = layer.mFaces[*it];
+ LWO::Face &face = layer.mFaces[*it];
for (unsigned int n = 0; n < face.mNumIndices; ++n) {
unsigned int idx = face.mIndices[n];
- if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) {
+ if (uv.abAssigned[idx] && ((aiVector2D *)&uv.rawData[0])[idx] != aiVector2D()) {
if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
ASSIMP_LOG_ERROR("LWO: Maximum number of UV channels for "
- "this mesh reached. Skipping channel \'" + uv.name + "\'");
+ "this mesh reached. Skipping channel \'" +
+ uv.name + "\'");
// Search through all textures assigned to 'surf' and look for this UV channel
char had = 0;
- had |= FindUVChannels(surf.mColorTextures,layer,uv,next);
- had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next);
- had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next);
- had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next);
- had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next);
- had |= FindUVChannels(surf.mBumpTextures,layer,uv,next);
- had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mColorTextures, layer, uv, next);
+ had |= FindUVChannels(surf.mDiffuseTextures, layer, uv, next);
+ had |= FindUVChannels(surf.mSpecularTextures, layer, uv, next);
+ had |= FindUVChannels(surf.mGlossinessTextures, layer, uv, next);
+ had |= FindUVChannels(surf.mOpacityTextures, layer, uv, next);
+ had |= FindUVChannels(surf.mBumpTextures, layer, uv, next);
+ had |= FindUVChannels(surf.mReflectionTextures, layer, uv, next);
// We have a texture referencing this UV channel so we have to take special care
// and are willing to drop unreferenced channels in favour of it.
if (had != 0) {
if (num_extra) {
- for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) {
- out[a+1] = out[a];
+ for (unsigned int a = next; a < std::min(extra, AI_MAX_NUMBER_OF_TEXTURECOORDS - 1u); ++a) {
+ out[a + 1] = out[a];
++extra;
@@ -461,7 +434,7 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf,
++num_extra;
- it = sorted.end()-1;
+ it = sorted.end() - 1;
@@ -473,42 +446,40 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf,
-void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorted, const LWO::Layer& layer,
- unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
+void LWOImporter::FindVCChannels(const LWO::Surface &surf, LWO::SortedRep &sorted, const LWO::Layer &layer,
+ unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]) {
unsigned int next = 0;
// Check whether we have an vc entry != 0 for one of the faces in 'sorted'
- for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) {
- const LWO::VColorChannel& vc = layer.mVColorChannels[i];
+ for (unsigned int i = 0; i < layer.mVColorChannels.size(); ++i) {
+ const LWO::VColorChannel &vc = layer.mVColorChannels[i];
if (surf.mVCMap == vc.name) {
// The vertex color map is explicitly requested by the surface so we need to take special care of it
- for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) {
+ for (unsigned int a = 0; a < std::min(next, AI_MAX_NUMBER_OF_COLOR_SETS - 1u); ++a) {
out[0] = i;
++next;
- for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) {
- const LWO::Face& face = layer.mFaces[*it];
+ for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) {
+ const LWO::Face &face = layer.mFaces[*it];
- if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.0,0.0,0.0,1.0)) {
+ if (vc.abAssigned[idx] && ((aiColor4D *)&vc.rawData[0])[idx] != aiColor4D(0.0, 0.0, 0.0, 1.0)) {
if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
ASSIMP_LOG_ERROR("LWO: Maximum number of vertex color channels for "
- "this mesh reached. Skipping channel \'" + vc.name + "\'");
+ vc.name + "\'");
out[next++] = i;
@@ -521,154 +492,149 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte
-void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
- LE_NCONST uint8_t* const end = mFileBuffer + size;
- while (true)
- if (mFileBuffer + 6 >= end)break;
+void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture &tex) {
+ LE_NCONST uint8_t *const end = mFileBuffer + size;
+ while (true) {
+ if (mFileBuffer + 6 >= end) break;
LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
- uint8_t* const next = mFileBuffer+head.length;
- switch (head.type)
- case AI_LWO_PROJ:
- tex.mapMode = (Texture::MappingMode)GetU2();
- case AI_LWO_WRAP:
- tex.wrapModeWidth = (Texture::Wrap)GetU2();
- tex.wrapModeHeight = (Texture::Wrap)GetU2();
- case AI_LWO_AXIS:
- tex.majorAxis = (Texture::Axes)GetU2();
- case AI_LWO_IMAG:
- tex.mClipIdx = GetU2();
- case AI_LWO_VMAP:
- GetS0(tex.mUVChannelIndex,head.length);
- case AI_LWO_WRPH:
- tex.wrapAmountH = GetF4();
- case AI_LWO_WRPW:
- tex.wrapAmountW = GetF4();
+ uint8_t *const next = mFileBuffer + head.length;
+ switch (head.type) {
+ case AI_LWO_PROJ:
+ tex.mapMode = (Texture::MappingMode)GetU2();
+ case AI_LWO_WRAP:
+ tex.wrapModeWidth = (Texture::Wrap)GetU2();
+ tex.wrapModeHeight = (Texture::Wrap)GetU2();
+ case AI_LWO_AXIS:
+ tex.majorAxis = (Texture::Axes)GetU2();
+ case AI_LWO_IMAG:
+ tex.mClipIdx = GetU2();
+ case AI_LWO_VMAP:
+ GetS0(tex.mUVChannelIndex, head.length);
+ case AI_LWO_WRPH:
+ tex.wrapAmountH = GetF4();
+ case AI_LWO_WRPW:
+ tex.wrapAmountW = GetF4();
mFileBuffer = next;
-void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex )
+void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture &tex) {
// --- not supported at the moment
ASSIMP_LOG_ERROR("LWO2: Found procedural texture, this is not supported");
tex.bCanUse = false;
-void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture& tex )
+void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture &tex) {
ASSIMP_LOG_ERROR("LWO2: Found gradient texture, this is not supported");
-void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
+void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture &tex) {
// get the ordinal string
- GetS0( tex.ordinal, size);
+ GetS0(tex.ordinal, size);
// we could crash later if this is an empty string ...
- if (!tex.ordinal.length())
+ if (!tex.ordinal.length()) {
ASSIMP_LOG_ERROR("LWO2: Ill-formed SURF.BLOK ordinal string");
tex.ordinal = "\x00";
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
throw DeadlyImportError("LWO2: Invalid texture header chunk length");
- case AI_LWO_CHAN:
- tex.type = GetU4();
- case AI_LWO_ENAB:
- tex.enabled = GetU2() ? true : false;
- case AI_LWO_OPAC:
- tex.blendType = (Texture::BlendType)GetU2();
- tex.mStrength = GetF4();
+ case AI_LWO_CHAN:
+ tex.type = GetU4();
+ case AI_LWO_ENAB:
+ tex.enabled = GetU2() ? true : false;
+ case AI_LWO_OPAC:
+ tex.blendType = (Texture::BlendType)GetU2();
+ tex.mStrength = GetF4();
-void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size )
+void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader *head, unsigned int size) {
ai_assert(!mSurfaces->empty());
- LWO::Surface& surf = mSurfaces->back();
+ LWO::Surface &surf = mSurfaces->back();
LWO::Texture tex;
// load the texture header
- LoadLWO2TextureHeader(head->length,tex);
+ LoadLWO2TextureHeader(head->length, tex);
size -= head->length + 6;
// now get the exact type of the texture
- switch (head->type)
- case AI_LWO_PROC:
- LoadLWO2Procedural(size,tex);
- case AI_LWO_GRAD:
- LoadLWO2Gradient(size,tex);
- case AI_LWO_IMAP:
- LoadLWO2ImageMap(size,tex);
+ switch (head->type) {
+ case AI_LWO_PROC:
+ LoadLWO2Procedural(size, tex);
+ case AI_LWO_GRAD:
+ LoadLWO2Gradient(size, tex);
+ case AI_LWO_IMAP:
+ LoadLWO2ImageMap(size, tex);
// get the destination channel
- TextureList* listRef = NULL;
- switch (tex.type)
- case AI_LWO_COLR:
- listRef = &surf.mColorTextures;break;
- case AI_LWO_DIFF:
- listRef = &surf.mDiffuseTextures;break;
- case AI_LWO_SPEC:
- listRef = &surf.mSpecularTextures;break;
- case AI_LWO_GLOS:
- listRef = &surf.mGlossinessTextures;break;
- case AI_LWO_BUMP:
- listRef = &surf.mBumpTextures;break;
- case AI_LWO_TRAN:
- listRef = &surf.mOpacityTextures;break;
- case AI_LWO_REFL:
- listRef = &surf.mReflectionTextures;break;
- ASSIMP_LOG_WARN("LWO2: Encountered unknown texture type");
+ TextureList *listRef = NULL;
+ switch (tex.type) {
+ case AI_LWO_COLR:
+ listRef = &surf.mColorTextures;
+ case AI_LWO_DIFF:
+ listRef = &surf.mDiffuseTextures;
+ case AI_LWO_SPEC:
+ listRef = &surf.mSpecularTextures;
+ case AI_LWO_GLOS:
+ listRef = &surf.mGlossinessTextures;
+ case AI_LWO_BUMP:
+ listRef = &surf.mBumpTextures;
+ case AI_LWO_TRAN:
+ listRef = &surf.mOpacityTextures;
+ case AI_LWO_REFL:
+ listRef = &surf.mReflectionTextures;
+ ASSIMP_LOG_WARN("LWO2: Encountered unknown texture type");
// now attach the texture to the parent surface - sort by ordinal string
- for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) {
- if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
- listRef->insert(it,tex);
+ for (TextureList::iterator it = listRef->begin(); it != listRef->end(); ++it) {
+ if (::strcmp(tex.ordinal.c_str(), (*it).ordinal.c_str()) < 0) {
+ listRef->insert(it, tex);
@@ -676,50 +642,46 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsi
-void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, unsigned int size )
+void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader * /*head*/, unsigned int size) {
LWO::Shader shader;
- GetS0( shader.ordinal, size);
+ GetS0(shader.ordinal, size);
- if (!shader.ordinal.length())
+ if (!shader.ordinal.length()) {
shader.ordinal = "\x00";
// read the header
throw DeadlyImportError("LWO2: Invalid shader header chunk length");
- shader.enabled = GetU2() ? true : false;
+ shader.enabled = GetU2() ? true : false;
- case AI_LWO_FUNC:
- GetS0( shader.functionName, head.length );
+ case AI_LWO_FUNC:
+ GetS0(shader.functionName, head.length);
// now attach the shader to the parent surface - sort by ordinal string
- for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) {
- if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
- surf.mShaders.insert(it,shader);
+ for (ShaderList::iterator it = surf.mShaders.begin(); it != surf.mShaders.end(); ++it) {
+ if (::strcmp(shader.ordinal.c_str(), (*it).ordinal.c_str()) < 0) {
+ surf.mShaders.insert(it, shader);
@@ -727,33 +689,33 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u
-void LWOImporter::LoadLWO2Surface(unsigned int size)
+void LWOImporter::LoadLWO2Surface(unsigned int size) {
- mSurfaces->push_back( LWO::Surface () );
+ mSurfaces->push_back(LWO::Surface());
- GetS0(surf.mName,size);
+ GetS0(surf.mName, size);
// check whether this surface was derived from any other surface
std::string derived;
- GetS0(derived,(unsigned int)(end - mFileBuffer));
- if (derived.length()) {
+ GetS0(derived, (unsigned int)(end - mFileBuffer));
+ if (derived.length()) {
// yes, find this surface
- for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) {
+ for (SurfaceList::iterator it = mSurfaces->begin(), itEnd = mSurfaces->end() - 1; it != itEnd; ++it) {
if ((*it).mName == derived) {
// we have it ...
surf = *it;
- derived.clear();break;
+ derived.clear();
- if (derived.size())
+ if (derived.size()) {
ASSIMP_LOG_WARN("LWO2: Unable to find source surface: " + derived);
if (mFileBuffer + 6 >= end)
@@ -761,131 +723,115 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
throw DeadlyImportError("LWO2: Invalid surface chunk length");
- // diffuse color
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,12);
+ // diffuse color
+ case AI_LWO_COLR: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, COLR, 12);
surf.mColor.r = GetF4();
surf.mColor.g = GetF4();
surf.mColor.b = GetF4();
- // diffuse strength ... hopefully
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,4);
+ // diffuse strength ... hopefully
+ case AI_LWO_DIFF: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, DIFF, 4);
surf.mDiffuseValue = GetF4();
- // specular strength ... hopefully
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,4);
+ // specular strength ... hopefully
+ case AI_LWO_SPEC: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SPEC, 4);
surf.mSpecularValue = GetF4();
- // transparency
+ // transparency
+ case AI_LWO_TRAN: {
// transparency explicitly disabled?
if (surf.mTransparency == 10e10f)
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,4);
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, TRAN, 4);
surf.mTransparency = GetF4();
- // additive transparency
- case AI_LWO_ADTR:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ADTR,4);
+ // additive transparency
+ case AI_LWO_ADTR: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, ADTR, 4);
surf.mAdditiveTransparency = GetF4();
- // wireframe mode
- case AI_LWO_LINE:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LINE,2);
+ // wireframe mode
+ case AI_LWO_LINE: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, LINE, 2);
if (GetU2() & 0x1)
surf.mWireframe = true;
- // glossiness
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,4);
+ // glossiness
+ case AI_LWO_GLOS: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, GLOS, 4);
surf.mGlossiness = GetF4();
- // bump intensity
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BUMP,4);
+ // bump intensity
+ case AI_LWO_BUMP: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, BUMP, 4);
surf.mBumpIntensity = GetF4();
- // color highlights
- case AI_LWO_CLRH:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,CLRH,4);
+ // color highlights
+ case AI_LWO_CLRH: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, CLRH, 4);
surf.mColorHighlights = GetF4();
- // index of refraction
- case AI_LWO_RIND:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,RIND,4);
+ // index of refraction
+ case AI_LWO_RIND: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, RIND, 4);
surf.mIOR = GetF4();
- // polygon sidedness
- case AI_LWO_SIDE:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SIDE,2);
+ // polygon sidedness
+ case AI_LWO_SIDE: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SIDE, 2);
surf.bDoubleSided = (3 == GetU2());
- // maximum smoothing angle
- case AI_LWO_SMAN:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
- surf.mMaximumSmoothAngle = std::fabs( GetF4() );
+ // maximum smoothing angle
+ case AI_LWO_SMAN: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SMAN, 4);
+ surf.mMaximumSmoothAngle = std::fabs(GetF4());
- // vertex color channel to be applied to the surface
- case AI_LWO_VCOL:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,VCOL,12);
- surf.mDiffuseValue *= GetF4(); // strength
- ReadVSizedIntLWO2(mFileBuffer); // skip envelope
- surf.mVCMapType = GetU4(); // type of the channel
+ // vertex color channel to be applied to the surface
+ case AI_LWO_VCOL: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, VCOL, 12);
+ surf.mDiffuseValue *= GetF4(); // strength
+ ReadVSizedIntLWO2(mFileBuffer); // skip envelope
+ surf.mVCMapType = GetU4(); // type of the channel
// name of the channel
- GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer ));
+ GetS0(surf.mVCMap, (unsigned int)(next - mFileBuffer));
- // surface bock entry
- case AI_LWO_BLOK:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BLOK,4);
+ // surface bock entry
+ case AI_LWO_BLOK: {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, BLOK, 4);
IFF::SubChunkHeader head2 = IFF::LoadSubChunk(mFileBuffer);
- switch (head2.type)
- LoadLWO2TextureBlock(&head2, head.length);
- case AI_LWO_SHDR:
- LoadLWO2ShaderBlock(&head2, head.length);
+ switch (head2.type) {
+ LoadLWO2TextureBlock(&head2, head.length);
+ case AI_LWO_SHDR:
+ LoadLWO2ShaderBlock(&head2, head.length);
- ASSIMP_LOG_WARN("LWO2: Found an unsupported surface BLOK");
+ ASSIMP_LOG_WARN("LWO2: Found an unsupported surface BLOK");
@@ -45,22 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the LWS importer class
#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
#include "LWS/LWSLoader.h"
-#include "PostProcessing/ConvertToLHProcess.h"
#include "Common/Importer.h"
+#include "PostProcessing/ConvertToLHProcess.h"
#include <assimp/ParsingUtils.h>
-#include <assimp/fast_atof.h>
#include <assimp/SceneCombiner.h>
#include <assimp/SkeletonMeshBuilder.h>
+#include <assimp/fast_atof.h>
+#include <assimp/importerdesc.h>
-#include <assimp/importerdesc.h>
@@ -81,9 +80,8 @@ static const aiImporterDesc desc = {
// Recursive parsing of LWS files
-void LWS::Element::Parse (const char*& buffer)
- for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) {
+void LWS::Element::Parse(const char *&buffer) {
+ for (; SkipSpacesAndLineEnd(&buffer); SkipLine(&buffer)) {
// begin of a new element with children
bool sub = false;
@@ -91,27 +89,26 @@ void LWS::Element::Parse (const char*& buffer)
++buffer;
SkipSpaces(&buffer);
sub = true;
- else if (*buffer == '}')
+ } else if (*buffer == '}')
children.push_back(Element());
// copy data line - read token per token
- const char* cur = buffer;
- while (!IsSpaceOrNewLine(*buffer)) ++buffer;
- children.back().tokens[0] = std::string(cur,(size_t) (buffer-cur));
+ const char *cur = buffer;
+ while (!IsSpaceOrNewLine(*buffer))
+ ++buffer;
+ children.back().tokens[0] = std::string(cur, (size_t)(buffer - cur));
- if (children.back().tokens[0] == "Plugin")
+ if (children.back().tokens[0] == "Plugin") {
ASSIMP_LOG_DEBUG("LWS: Skipping over plugin-specific data");
// strange stuff inside Plugin/Endplugin blocks. Needn't
// follow LWS syntax, so we skip over it
- if (!::strncmp(buffer,"EndPlugin",9)) {
+ if (!::strncmp(buffer, "EndPlugin", 9)) {
//SkipLine(&buffer);
@@ -120,8 +117,9 @@ void LWS::Element::Parse (const char*& buffer)
cur = buffer;
- while (!IsLineEnd(*buffer)) ++buffer;
- children.back().tokens[1] = std::string(cur,(size_t) (buffer-cur));
+ while (!IsLineEnd(*buffer))
+ children.back().tokens[1] = std::string(cur, (size_t)(buffer - cur));
// parse more elements recursively
if (sub)
@@ -131,28 +129,25 @@ void LWS::Element::Parse (const char*& buffer)
-LWSImporter::LWSImporter()
- : configSpeedFlag(),
- io(),
- first(),
- last(),
- fps(),
- noSkeletonMesh()
+LWSImporter::LWSImporter() :
+ configSpeedFlag(),
+ io(),
+ first(),
+ last(),
+ fps(),
+ noSkeletonMesh() {
-LWSImporter::~LWSImporter()
+LWSImporter::~LWSImporter() {
// Returns whether the class can handle the format of the given file.
-bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool checkSig) const
+bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "lws" || extension == "mot")
@@ -162,69 +157,67 @@ bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool c
uint32_t tokens[2];
tokens[0] = AI_MAKE_MAGIC("LWSC");
tokens[1] = AI_MAKE_MAGIC("LWMO");
- return CheckMagicToken(pIOHandler,pFile,tokens,2);
+ return CheckMagicToken(pIOHandler, pFile, tokens, 2);
// Get list of file extensions
-const aiImporterDesc* LWSImporter::GetInfo () const
+const aiImporterDesc *LWSImporter::GetInfo() const {
-void LWSImporter::SetupProperties(const Importer* pImp)
+void LWSImporter::SetupProperties(const Importer *pImp) {
// AI_CONFIG_FAVOUR_SPEED
- configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
+ configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0));
// AI_CONFIG_IMPORT_LWS_ANIM_START
first = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_START,
- 150392 /* magic hack */);
+ 150392 /* magic hack */);
// AI_CONFIG_IMPORT_LWS_ANIM_END
last = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_END,
if (last < first) {
- std::swap(last,first);
+ std::swap(last, first);
- noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+ noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0;
// Read an envelope description
-void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
+void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
if (dad.children.empty()) {
ASSIMP_LOG_ERROR("LWS: Envelope descriptions must not be empty");
// reserve enough storage
- std::list< LWS::Element >::const_iterator it = dad.children.begin();;
+ std::list<LWS::Element>::const_iterator it = dad.children.begin();
+ ;
fill.keys.reserve(strtoul10(it->tokens[1].c_str()));
for (++it; it != dad.children.end(); ++it) {
- const char* c = (*it).tokens[1].c_str();
+ const char *c = (*it).tokens[1].c_str();
if ((*it).tokens[0] == "Key") {
fill.keys.push_back(LWO::Key());
- LWO::Key& key = fill.keys.back();
+ LWO::Key &key = fill.keys.back();
SkipSpaces(&c);
- c = fast_atoreal_move<float>(c,key.value);
+ c = fast_atoreal_move<float>(c, key.value);
- c = fast_atoreal_move<float>(c,f);
+ c = fast_atoreal_move<float>(c, f);
key.time = f;
- unsigned int span = strtoul10(c,&c), num = 0;
+ unsigned int span = strtoul10(c, &c), num = 0;
switch (span) {
case 0:
@@ -251,16 +244,15 @@ void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
ASSIMP_LOG_ERROR("LWS: Unknown span type");
- for (unsigned int i = 0; i < num;++i) {
+ for (unsigned int i = 0; i < num; ++i) {
- c = fast_atoreal_move<float>(c,key.params[i]);
+ c = fast_atoreal_move<float>(c, key.params[i]);
- else if ((*it).tokens[0] == "Behaviors") {
+ } else if ((*it).tokens[0] == "Behaviors") {
- fill.pre = (LWO::PrePostBehaviour) strtoul10(c,&c);
+ fill.pre = (LWO::PrePostBehaviour)strtoul10(c, &c);
- fill.post = (LWO::PrePostBehaviour) strtoul10(c,&c);
+ fill.post = (LWO::PrePostBehaviour)strtoul10(c, &c);
@@ -268,36 +260,35 @@ void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
// Read animation channels in the old LightWave animation format
void LWSImporter::ReadEnvelope_Old(
- std::list< LWS::Element >::const_iterator& it,
- const std::list< LWS::Element >::const_iterator& end,
- LWS::NodeDesc& nodes,
- unsigned int /*version*/)
- unsigned int num,sub_num;
- if (++it == end)goto unexpected_end;
+ std::list<LWS::Element>::const_iterator &it,
+ const std::list<LWS::Element>::const_iterator &end,
+ LWS::NodeDesc &nodes,
+ unsigned int /*version*/) {
+ unsigned int num, sub_num;
+ if (++it == end) goto unexpected_end;
num = strtoul10((*it).tokens[0].c_str());
nodes.channels.push_back(LWO::Envelope());
- LWO::Envelope& envl = nodes.channels.back();
+ LWO::Envelope &envl = nodes.channels.back();
envl.index = i;
- envl.type = (LWO::EnvelopeType)(i+1);
+ envl.type = (LWO::EnvelopeType)(i + 1);
sub_num = strtoul10((*it).tokens[0].c_str());
- for (unsigned int n = 0; n < sub_num;++n) {
+ for (unsigned int n = 0; n < sub_num; ++n) {
// parse value and time, skip the rest for the moment.
LWO::Key key;
- const char* c = fast_atoreal_move<float>((*it).tokens[0].c_str(),key.value);
+ const char *c = fast_atoreal_move<float>((*it).tokens[0].c_str(), key.value);
- fast_atoreal_move<float>((*it).tokens[0].c_str(),f);
+ fast_atoreal_move<float>((*it).tokens[0].c_str(), f);
envl.keys.push_back(key);
@@ -311,51 +302,49 @@ unexpected_end:
// Setup a nice name for a node
-void LWSImporter::SetupNodeName(aiNode* nd, LWS::NodeDesc& src)
+void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
const unsigned int combined = src.number | ((unsigned int)src.type) << 28u;
// the name depends on the type. We break LWS's strange naming convention
// and return human-readable, but still machine-parsable and unique, strings.
- if (src.type == LWS::NodeDesc::OBJECT) {
+ if (src.type == LWS::NodeDesc::OBJECT) {
if (src.path.length()) {
std::string::size_type s = src.path.find_last_of("\\/");
if (s == std::string::npos)
s = 0;
- else ++s;
+ ++s;
std::string::size_type t = src.path.substr(s).find_last_of(".");
- nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.path.substr(s).substr(0,t).c_str(),combined);
+ nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
- nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.name,combined);
+ nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.name, combined);
// Recursively build the scenegraph
-void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<AttachmentInfo>& attach,
- BatchLoader& batch,
- aiCamera**& camOut,
- aiLight**& lightOut,
- std::vector<aiNodeAnim*>& animOut)
+void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vector<AttachmentInfo> &attach,
+ BatchLoader &batch,
+ aiCamera **&camOut,
+ aiLight **&lightOut,
+ std::vector<aiNodeAnim *> &animOut) {
// Setup a very cryptic name for the node, we want the user to be happy
- SetupNodeName(nd,src);
- aiNode* ndAnim = nd;
+ SetupNodeName(nd, src);
+ aiNode *ndAnim = nd;
// If the node is an object
if (src.type == LWS::NodeDesc::OBJECT) {
// If the object is from an external file, get it
- aiScene* obj = NULL;
- if (src.path.length() ) {
+ aiScene *obj = NULL;
+ if (src.path.length()) {
obj = batch.GetImport(src.id);
if (!obj) {
ASSIMP_LOG_ERROR("LWS: Failed to read external file " + src.path);
if (obj->mRootNode->mNumChildren == 1) {
//If the pivot is not set for this layer, get it from the external object
@@ -366,7 +355,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
//Remove first node from obj (the old pivot), reset transform of second node (the mesh node)
- aiNode* newRootNode = obj->mRootNode->mChildren[0];
+ aiNode *newRootNode = obj->mRootNode->mChildren[0];
obj->mRootNode->mChildren[0] = NULL;
delete obj->mRootNode;
@@ -384,7 +373,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
//Add the attachment node to it
nd->mNumChildren = 1;
- nd->mChildren = new aiNode*[1];
+ nd->mChildren = new aiNode *[1];
nd->mChildren[0] = new aiNode();
nd->mChildren[0]->mParent = nd;
nd->mChildren[0]->mTransformation.a4 = -src.pivotPos.x;
@@ -397,16 +386,16 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
//Push attachment, if the object came from an external file
if (obj) {
- attach.push_back(AttachmentInfo(obj,nd));
+ attach.push_back(AttachmentInfo(obj, nd));
// If object is a light source - setup a corresponding ai structure
else if (src.type == LWS::NodeDesc::LIGHT) {
- aiLight* lit = *lightOut++ = new aiLight();
+ aiLight *lit = *lightOut++ = new aiLight();
// compute final light color
- lit->mColorDiffuse = lit->mColorSpecular = src.lightColor*src.lightIntensity;
+ lit->mColorDiffuse = lit->mColorSpecular = src.lightColor * src.lightIntensity;
// name to attach light to node -> unique due to LWs indexing system
lit->mName = nd->mName;
@@ -415,14 +404,13 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
if (src.lightType == 2) { /* spot light */
lit->mType = aiLightSource_SPOT;
- lit->mAngleInnerCone = (float)AI_DEG_TO_RAD( src.lightConeAngle );
- lit->mAngleOuterCone = lit->mAngleInnerCone+(float)AI_DEG_TO_RAD( src.lightEdgeAngle );
+ lit->mAngleInnerCone = (float)AI_DEG_TO_RAD(src.lightConeAngle);
+ lit->mAngleOuterCone = lit->mAngleInnerCone + (float)AI_DEG_TO_RAD(src.lightEdgeAngle);
- else if (src.lightType == 1) { /* directional light source */
+ } else if (src.lightType == 1) { /* directional light source */
lit->mType = aiLightSource_DIRECTIONAL;
- else lit->mType = aiLightSource_POINT;
+ lit->mType = aiLightSource_POINT;
// fixme: no proper handling of light falloffs yet
if (src.lightFalloffType == 1)
@@ -435,22 +423,22 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
// If object is a camera - setup a corresponding ai structure
else if (src.type == LWS::NodeDesc::CAMERA) {
- aiCamera* cam = *camOut++ = new aiCamera();
+ aiCamera *cam = *camOut++ = new aiCamera();
// name to attach cam to node -> unique due to LWs indexing system
cam->mName = nd->mName;
// Get the node transformation from the LWO key
- LWO::AnimResolver resolver(src.channels,fps);
+ LWO::AnimResolver resolver(src.channels, fps);
resolver.ExtractBindPose(ndAnim->mTransformation);
// .. and construct animation channels
- aiNodeAnim* anim = NULL;
+ aiNodeAnim *anim = NULL;
if (first != last) {
- resolver.SetAnimationRange(first,last);
- resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO);
+ resolver.SetAnimationRange(first, last);
+ resolver.ExtractAnimChannel(&anim, AI_LWO_ANIM_FLAG_SAMPLE_ANIMS | AI_LWO_ANIM_FLAG_START_AT_ZERO);
if (anim) {
anim->mNodeName = ndAnim->mName;
animOut.push_back(anim);
@@ -459,27 +447,25 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
// Add children
if (!src.children.empty()) {
- nd->mChildren = new aiNode*[src.children.size()];
- for (std::list<LWS::NodeDesc*>::iterator it = src.children.begin(); it != src.children.end(); ++it) {
- aiNode* ndd = nd->mChildren[nd->mNumChildren++] = new aiNode();
+ nd->mChildren = new aiNode *[src.children.size()];
+ for (std::list<LWS::NodeDesc *>::iterator it = src.children.begin(); it != src.children.end(); ++it) {
+ aiNode *ndd = nd->mChildren[nd->mNumChildren++] = new aiNode();
ndd->mParent = nd;
- BuildGraph(ndd,**it,attach,batch,camOut,lightOut,animOut);
+ BuildGraph(ndd, **it, attach, batch, camOut, lightOut, animOut);
// Determine the exact location of a LWO file
-std::string LWSImporter::FindLWOFile(const std::string& in)
+std::string LWSImporter::FindLWOFile(const std::string &in) {
// insert missing directory separator if necessary
std::string tmp;
- if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
+ if (in.length() > 3 && in[1] == ':' && in[2] != '\\' && in[2] != '/') {
tmp = in[0] + (std::string(":\\") + in.substr(2));
- else tmp = in;
+ tmp = in;
if (io->Exists(tmp)) {
return in;
@@ -503,35 +489,34 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
return test;
// return original path, maybe the IOsystem knows better
return tmp;
// Read file into given scene data structure
-void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler)
+void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene,
+ IOSystem *pIOHandler) {
io = pIOHandler;
- std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+ std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open LWS file " + pFile + ".");
+ if (file.get() == NULL) {
+ throw DeadlyImportError("Failed to open LWS file " + pFile + ".");
// Allocate storage and copy the contents of the file to a memory buffer
- std::vector< char > mBuffer;
- TextFileToBuffer(file.get(),mBuffer);
+ std::vector<char> mBuffer;
+ TextFileToBuffer(file.get(), mBuffer);
// Parse the file structure
- LWS::Element root; const char* dummy = &mBuffer[0];
+ LWS::Element root;
+ const char *dummy = &mBuffer[0];
root.Parse(dummy);
// Construct a Batchimporter to read more files recursively
BatchLoader batch(pIOHandler);
-// batch.SetBasePath(pFile);
+ // batch.SetBasePath(pFile);
// Construct an array to receive the flat output graph
std::list<LWS::NodeDesc> nodes;
@@ -541,7 +526,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
// check magic identifier, 'LWSC'
bool motion_file = false;
- std::list< LWS::Element >::const_iterator it = root.children.begin();
+ std::list<LWS::Element>::const_iterator it = root.children.begin();
if ((*it).tokens[0] == "LWMO")
motion_file = true;
@@ -554,54 +539,54 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
unsigned int version = strtoul10((*it).tokens[0].c_str());
ASSIMP_LOG_INFO("LWS file format version is " + (*it).tokens[0]);
first = 0.;
- last = 60.;
- fps = 25.; /* seems to be a good default frame rate */
+ last = 60.;
+ fps = 25.; /* seems to be a good default frame rate */
// Now read all elements in a very straghtforward manner
for (; it != root.children.end(); ++it) {
// 'FirstFrame': begin of animation slice
if ((*it).tokens[0] == "FirstFrame") {
- if (150392. != first /* see SetupProperties() */)
- first = strtoul10(c,&c)-1.; /* we're zero-based */
+ if (150392. != first /* see SetupProperties() */)
+ first = strtoul10(c, &c) - 1.; /* we're zero-based */
// 'LastFrame': end of animation slice
else if ((*it).tokens[0] == "LastFrame") {
- if (150392. != last /* see SetupProperties() */)
- last = strtoul10(c,&c)-1.; /* we're zero-based */
+ if (150392. != last /* see SetupProperties() */)
+ last = strtoul10(c, &c) - 1.; /* we're zero-based */
// 'FramesPerSecond': frames per second
else if ((*it).tokens[0] == "FramesPerSecond") {
- fps = strtoul10(c,&c);
+ fps = strtoul10(c, &c);
// 'LoadObjectLayer': load a layer of a specific LWO file
else if ((*it).tokens[0] == "LoadObjectLayer") {
// get layer index
- const int layer = strtoul10(c,&c);
+ const int layer = strtoul10(c, &c);
// setup the layer to be loaded
BatchLoader::PropertyMap props;
- SetGenericProperty(props.ints,AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,layer);
+ SetGenericProperty(props.ints, AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY, layer);
// add node to list
LWS::NodeDesc d;
d.type = LWS::NodeDesc::OBJECT;
if (version >= 4) { // handle LWSC 4 explicit ID
- d.number = strtoul16(c,&c) & AI_LWS_MASK;
- else d.number = cur_object++;
+ d.number = strtoul16(c, &c) & AI_LWS_MASK;
+ d.number = cur_object++;
// and add the file to the import list
- std::string path = FindLWOFile( c );
+ std::string path = FindLWOFile(c);
d.path = path;
- d.id = batch.AddLoadRequest(path,0,&props);
+ d.id = batch.AddLoadRequest(path, 0, &props);
nodes.push_back(d);
num_object++;
@@ -614,12 +599,12 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
- d.id = batch.AddLoadRequest(path,0,NULL);
+ d.id = batch.AddLoadRequest(path, 0, NULL);
@@ -632,10 +617,10 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
d.name = c;
@@ -662,13 +647,13 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
// important: index of channel
nodes.back().channels.push_back(LWO::Envelope());
- LWO::Envelope& env = nodes.back().channels.back();
+ LWO::Envelope &env = nodes.back().channels.back();
env.index = strtoul10(c);
// currently we can just interpret the standard channels 0...9
// (hack) assume that index-i yields the binary channel type from LWO
- env.type = (LWO::EnvelopeType)(env.index+1);
+ env.type = (LWO::EnvelopeType)(env.index + 1);
// 'Envelope': a single animation channel
@@ -676,18 +661,18 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().channels.empty())
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Envelope\'");
- ReadEnvelope((*it),nodes.back().channels.back());
+ ReadEnvelope((*it), nodes.back().channels.back());
// 'ObjectMotion': animation information for older lightwave formats
- else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" ||
- (*it).tokens[0] == "CameraMotion" ||
- (*it).tokens[0] == "LightMotion")) {
+ else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" ||
+ (*it).tokens[0] == "CameraMotion" ||
+ (*it).tokens[0] == "LightMotion")) {
if (nodes.empty())
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'<Light|Object|Camera>Motion\'");
- ReadEnvelope_Old(it,root.children.end(),nodes.back(),version);
+ ReadEnvelope_Old(it, root.children.end(), nodes.back(), version);
// 'Pre/PostBehavior': pre/post animation behaviour for LWSC 2
@@ -695,11 +680,13 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Pre/PostBehavior'");
- for (std::list<LWO::Envelope>::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) {
+ for (std::list<LWO::Envelope>::iterator envelopeIt = nodes.back().channels.begin(); envelopeIt != nodes.back().channels.end(); ++envelopeIt) {
// two ints per envelope
- LWO::Envelope& env = *it;
- env.pre = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
- env.post = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
+ LWO::Envelope &env = *envelopeIt;
+ env.pre = (LWO::PrePostBehaviour)strtoul10(c, &c);
+ SkipSpaces(&c);
+ env.post = (LWO::PrePostBehaviour)strtoul10(c, &c);
@@ -708,7 +695,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentItem\'");
- else nodes.back().parent = strtoul16(c,&c);
+ nodes.back().parent = strtoul16(c, &c);
// 'ParentObject': deprecated one for older formats
else if (version < 3 && (*it).tokens[0] == "ParentObject") {
@@ -716,7 +704,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentObject\'");
- nodes.back().parent = strtoul10(c,&c) | (1u << 28u);
+ nodes.back().parent = strtoul10(c, &c) | (1u << 28u);
// 'AddCamera': add a camera to the scenegraph
@@ -727,9 +715,9 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
d.type = LWS::NodeDesc::CAMERA;
- else d.number = cur_camera++;
+ d.number = cur_camera++;
num_camera++;
@@ -739,7 +727,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA)
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'CameraName\'");
- else nodes.back().name = c;
+ nodes.back().name = c;
// 'AddLight': add a light to the scenegraph
else if ((*it).tokens[0] == "AddLight") {
@@ -749,9 +738,9 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
d.type = LWS::NodeDesc::LIGHT;
- else d.number = cur_light++;
+ d.number = cur_light++;
num_light++;
@@ -761,14 +750,16 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightName\'");
// 'LightIntensity': set intensity of currently active light
- else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity" ) {
+ else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity") {
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightIntensity\'");
- else fast_atoreal_move<float>(c, nodes.back().lightIntensity );
+ fast_atoreal_move<float>(c, nodes.back().lightIntensity);
// 'LightType': set type of currently active light
@@ -776,7 +767,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightType\'");
- else nodes.back().lightType = strtoul10(c);
+ nodes.back().lightType = strtoul10(c);
// 'LightFalloffType': set falloff type of currently active light
@@ -784,7 +776,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightFalloffType\'");
- else nodes.back().lightFalloffType = strtoul10(c);
+ nodes.back().lightFalloffType = strtoul10(c);
// 'LightConeAngle': set cone angle of currently active light
@@ -792,7 +785,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightConeAngle\'");
- else nodes.back().lightConeAngle = fast_atof(c);
+ nodes.back().lightConeAngle = fast_atof(c);
// 'LightEdgeAngle': set area where we're smoothing from min to max intensity
@@ -800,7 +794,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightEdgeAngle\'");
- else nodes.back().lightEdgeAngle = fast_atof(c);
+ nodes.back().lightEdgeAngle = fast_atof(c);
// 'LightColor': set color of currently active light
@@ -809,11 +804,11 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'");
- c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.r );
+ c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.r);
- c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.g );
+ c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.g);
- c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.b );
+ c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.b);
@@ -822,11 +817,11 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'");
- c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.x );
+ c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.x);
- c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.y );
+ c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.y);
- c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.z );
+ c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.z);
// Mark pivotPos as set
nodes.back().isPivotSet = true;
@@ -834,79 +829,80 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
// resolve parenting
- for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
+ for (std::list<LWS::NodeDesc>::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) {
// check whether there is another node which calls us a parent
for (std::list<LWS::NodeDesc>::iterator dit = nodes.begin(); dit != nodes.end(); ++dit) {
- if (dit != it && *it == (*dit).parent) {
+ if (dit != ndIt && *ndIt == (*dit).parent) {
if ((*dit).parent_resolved) {
// fixme: it's still possible to produce an overflow due to cross references ..
ASSIMP_LOG_ERROR("LWS: Found cross reference in scene-graph");
- (*it).children.push_back(&*dit);
- (*dit).parent_resolved = &*it;
+ ndIt->children.push_back(&*dit);
+ (*dit).parent_resolved = &*ndIt;
// find out how many nodes have no parent yet
unsigned int no_parent = 0;
- if (!(*it).parent_resolved)
- ++ no_parent;
+ if (!ndIt->parent_resolved) {
+ ++no_parent;
- if (!no_parent)
+ if (!no_parent) {
throw DeadlyImportError("LWS: Unable to find scene root node");
// Load all subsequent files
batch.LoadAll();
// and build the final output graph by attaching the loaded external
// files to ourselves. first build a master graph
- aiScene* master = new aiScene();
- aiNode* nd = master->mRootNode = new aiNode();
+ aiScene *master = new aiScene();
+ aiNode *nd = master->mRootNode = new aiNode();
// allocate storage for cameras&lights
if (num_camera) {
- master->mCameras = new aiCamera*[master->mNumCameras = num_camera];
+ master->mCameras = new aiCamera *[master->mNumCameras = num_camera];
- aiCamera** cams = master->mCameras;
+ aiCamera **cams = master->mCameras;
if (num_light) {
- master->mLights = new aiLight*[master->mNumLights = num_light];
+ master->mLights = new aiLight *[master->mNumLights = num_light];
- aiLight** lights = master->mLights;
+ aiLight **lights = master->mLights;
std::vector<AttachmentInfo> attach;
- std::vector<aiNodeAnim*> anims;
+ std::vector<aiNodeAnim *> anims;
nd->mName.Set("<LWSRoot>");
- nd->mChildren = new aiNode*[no_parent];
- if (!(*it).parent_resolved) {
- aiNode* ro = nd->mChildren[ nd->mNumChildren++ ] = new aiNode();
+ nd->mChildren = new aiNode *[no_parent];
+ aiNode *ro = nd->mChildren[nd->mNumChildren++] = new aiNode();
ro->mParent = nd;
// ... and build the scene graph. If we encounter object nodes,
// add then to our attachment table.
- BuildGraph(ro,*it, attach, batch, cams, lights, anims);
+ BuildGraph(ro, *ndIt, attach, batch, cams, lights, anims);
// create a master animation channel for us
if (anims.size()) {
- master->mAnimations = new aiAnimation*[master->mNumAnimations = 1];
- aiAnimation* anim = master->mAnimations[0] = new aiAnimation();
+ master->mAnimations = new aiAnimation *[master->mNumAnimations = 1];
+ aiAnimation *anim = master->mAnimations[0] = new aiAnimation();
anim->mName.Set("LWSMasterAnim");
// LWS uses seconds as time units, but we convert to frames
anim->mTicksPerSecond = fps;
- anim->mDuration = last-(first-1); /* fixme ... zero or one-based?*/
+ anim->mDuration = last - (first - 1); /* fixme ... zero or one-based?*/
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels = static_cast<unsigned int>(anims.size())];
- std::copy(anims.begin(),anims.end(),anim->mChannels);
+ anim->mChannels = new aiNodeAnim *[anim->mNumChannels = static_cast<unsigned int>(anims.size())];
+ std::copy(anims.begin(), anims.end(), anim->mChannels);
// convert the master scene to RH
@@ -918,9 +914,10 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
flipper.Execute(master);
// OK ... finally build the output graph
- SceneCombiner::MergeScenes(&pScene,master,attach,
- AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
- AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0));
+ SceneCombiner::MergeScenes(&pScene, master, attach,
+ AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
+ AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) :
+ 0));
// Check flags
if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
@@ -931,7 +928,6 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
SkeletonMeshBuilder builder(pScene);
#endif // !! ASSIMP_BUILD_NO_LWS_IMPORTER
@@ -64,9 +64,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include "M3DWrapper.h"
#include "M3DExporter.h"
#include "M3DMaterials.h"
+#include "M3DWrapper.h"
// RESOURCES:
// https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md
@@ -87,186 +87,187 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// helper to add a vertex (private to NodeWalk)
m3dv_t *AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) {
- if (v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0;
- if (v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0;
- if (v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0;
- if (v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0;
- vrtx = (m3dv_t *)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t));
- memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t));
- *idx = *numvrtx;
- (*numvrtx)++;
- return vrtx;
+ if (v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0;
+ if (v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0;
+ if (v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0;
+ if (v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0;
+ vrtx = (m3dv_t *)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t));
+ memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t));
+ *idx = *numvrtx;
+ (*numvrtx)++;
+ return vrtx;
// helper to add a tmap (private to NodeWalk)
m3dti_t *AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx) {
- tmap = (m3dti_t *)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t));
- memcpy(&tmap[*numtmap], ti, sizeof(m3dti_t));
- *idx = *numtmap;
- (*numtmap)++;
- return tmap;
+ tmap = (m3dti_t *)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t));
+ memcpy(&tmap[*numtmap], ti, sizeof(m3dti_t));
+ *idx = *numtmap;
+ (*numtmap)++;
+ return tmap;
// convert aiColor4D into uint32_t
uint32_t mkColor(aiColor4D *c) {
- return ((uint8_t)(c->a * 255) << 24L) |
- ((uint8_t)(c->b * 255) << 16L) |
- ((uint8_t)(c->g * 255) << 8L) |
- ((uint8_t)(c->r * 255) << 0L);
+ return ((uint8_t)(c->a * 255) << 24L) |
+ ((uint8_t)(c->b * 255) << 16L) |
+ ((uint8_t)(c->g * 255) << 8L) |
+ ((uint8_t)(c->r * 255) << 0L);
// add a material property to the output
void addProp(m3dm_t *m, uint8_t type, uint32_t value) {
- unsigned int i;
- i = m->numprop++;
- m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t));
- if (!m->prop) {
- throw DeadlyExportError("memory allocation error");
- m->prop[i].type = type;
- m->prop[i].value.num = value;
+ unsigned int i;
+ i = m->numprop++;
+ m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t));
+ if (!m->prop) {
+ throw DeadlyExportError("memory allocation error");
+ m->prop[i].type = type;
+ m->prop[i].value.num = value;
// convert aiString to identifier safe C string. This is a duplication of _m3d_safestr
-char *SafeStr(aiString str, bool isStrict)
- char *s = (char *)&str.data;
- char *d, *ret;
- int i, len;
- for(len = str.length + 1; *s && (*s == ' ' || *s == '\t'); s++, len--);
- if(len > 255) len = 255;
- ret = (char *)M3D_MALLOC(len + 1);
- if (!ret) {
- for(i = 0, d = ret; i < len && *s && *s != '\r' && *s != '\n'; s++, d++, i++) {
- *d = isStrict && (*s == ' ' || *s == '\t' || *s == '/' || *s == '\\') ? '_' : (*s == '\t' ? ' ' : *s);
- for(; d > ret && (*(d-1) == ' ' || *(d-1) == '\t'); d--);
- *d = 0;
- return ret;
+char *SafeStr(aiString str, bool isStrict) {
+ char *s = (char *)&str.data;
+ char *d, *ret;
+ int i, len;
+ for (len = str.length + 1; *s && (*s == ' ' || *s == '\t'); s++, len--)
+ if (len > 255) len = 255;
+ ret = (char *)M3D_MALLOC(len + 1);
+ if (!ret) {
+ for (i = 0, d = ret; i < len && *s && *s != '\r' && *s != '\n'; s++, d++, i++) {
+ *d = isStrict && (*s == ' ' || *s == '\t' || *s == '/' || *s == '\\') ? '_' : (*s == '\t' ? ' ' : *s);
+ for (; d > ret && (*(d - 1) == ' ' || *(d - 1) == '\t'); d--)
+ *d = 0;
+ return ret;
// add a material to the output
M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
- unsigned int mi = M3D_NOTDEFINED;
- aiColor4D c;
- aiString name;
- ai_real f;
- char *fn;
- if (mat && mat->Get(AI_MATKEY_NAME, name) == AI_SUCCESS && name.length &&
- strcmp((char *)&name.data, AI_DEFAULT_MATERIAL_NAME)) {
- // check if we have saved a material by this name. This has to be done
- // because only the referenced materials should be added to the output
- for (unsigned int i = 0; i < m3d->nummaterial; i++)
- if (!strcmp((char *)&name.data, m3d->material[i].name)) {
- mi = i;
- // if not found, add the material to the output
- if (mi == M3D_NOTDEFINED) {
- unsigned int k;
- mi = m3d->nummaterial++;
- m3d->material = (m3dm_t *)M3D_REALLOC(m3d->material, m3d->nummaterial * sizeof(m3dm_t));
- if (!m3d->material) {
- m3d->material[mi].name = SafeStr(name, true);
- m3d->material[mi].numprop = 0;
- m3d->material[mi].prop = NULL;
- // iterate through the material property table and see what we got
- for (k = 0; k < 15; k++) {
- unsigned int j;
- if (m3d_propertytypes[k].format == m3dpf_map)
- if (aiProps[k].pKey) {
- switch (m3d_propertytypes[k].format) {
- case m3dpf_color:
- if (mat->Get(aiProps[k].pKey, aiProps[k].type,
- aiProps[k].index, c) == AI_SUCCESS)
- addProp(&m3d->material[mi],
- m3d_propertytypes[k].id, mkColor(&c));
- case m3dpf_float:
- aiProps[k].index, f) == AI_SUCCESS)
- m3d_propertytypes[k].id,
- /* not (uint32_t)f, because we don't want to convert
+ unsigned int mi = M3D_NOTDEFINED;
+ aiColor4D c;
+ aiString name;
+ ai_real f;
+ char *fn;
+ if (mat && mat->Get(AI_MATKEY_NAME, name) == AI_SUCCESS && name.length &&
+ strcmp((char *)&name.data, AI_DEFAULT_MATERIAL_NAME)) {
+ // check if we have saved a material by this name. This has to be done
+ // because only the referenced materials should be added to the output
+ for (unsigned int i = 0; i < m3d->nummaterial; i++)
+ if (!strcmp((char *)&name.data, m3d->material[i].name)) {
+ mi = i;
+ // if not found, add the material to the output
+ if (mi == M3D_NOTDEFINED) {
+ unsigned int k;
+ mi = m3d->nummaterial++;
+ m3d->material = (m3dm_t *)M3D_REALLOC(m3d->material, m3d->nummaterial * sizeof(m3dm_t));
+ if (!m3d->material) {
+ m3d->material[mi].name = SafeStr(name, true);
+ m3d->material[mi].numprop = 0;
+ m3d->material[mi].prop = NULL;
+ // iterate through the material property table and see what we got
+ for (k = 0; k < 15; k++) {
+ unsigned int j;
+ if (m3d_propertytypes[k].format == m3dpf_map)
+ if (aiProps[k].pKey) {
+ switch (m3d_propertytypes[k].format) {
+ case m3dpf_color:
+ if (mat->Get(aiProps[k].pKey, aiProps[k].type,
+ aiProps[k].index, c) == AI_SUCCESS)
+ addProp(&m3d->material[mi],
+ m3d_propertytypes[k].id, mkColor(&c));
+ case m3dpf_float:
+ aiProps[k].index, f) == AI_SUCCESS)
+ m3d_propertytypes[k].id,
+ /* not (uint32_t)f, because we don't want to convert
* it, we want to see it as 32 bits of memory */
- *((uint32_t *)&f));
- case m3dpf_uint8:
- aiProps[k].index, j) == AI_SUCCESS) {
- // special conversion for illumination model property
- if (m3d_propertytypes[k].id == m3dp_il) {
- switch (j) {
- case aiShadingMode_NoShading: j = 0; break;
- case aiShadingMode_Phong: j = 2; break;
- default: j = 1; break;
- m3d_propertytypes[k].id, j);
- aiProps[k].index, j) == AI_SUCCESS)
- if (aiTxProps[k].pKey &&
- mat->GetTexture((aiTextureType)aiTxProps[k].type,
- aiTxProps[k].index, &name, NULL, NULL, NULL,
- NULL, NULL) == AI_SUCCESS) {
- for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++)
- ;
- if (j && name.data[j] == '.' &&
- (name.data[j + 1] == 'p' || name.data[j + 1] == 'P') &&
- (name.data[j + 1] == 'n' || name.data[j + 1] == 'N') &&
- (name.data[j + 1] == 'g' || name.data[j + 1] == 'G'))
- name.data[j] = 0;
- // do we have this texture saved already?
- fn = SafeStr(name, true);
- for (j = 0, i = M3D_NOTDEFINED; j < m3d->numtexture; j++)
- if (!strcmp(fn, m3d->texture[j].name)) {
- i = j;
- free(fn);
- if (i == M3D_NOTDEFINED) {
- i = m3d->numtexture++;
- m3d->texture = (m3dtx_t *)M3D_REALLOC(
- m3d->texture,
- m3d->numtexture * sizeof(m3dtx_t));
- if (!m3d->texture) {
- // we don't need the texture itself, only its name
- m3d->texture[i].name = fn;
- m3d->texture[i].w = 0;
- m3d->texture[i].h = 0;
- m3d->texture[i].d = NULL;
- m3d_propertytypes[k].id + 128, i);
- return mi;
+ *((uint32_t *)&f));
+ case m3dpf_uint8:
+ aiProps[k].index, j) == AI_SUCCESS) {
+ // special conversion for illumination model property
+ if (m3d_propertytypes[k].id == m3dp_il) {
+ switch (j) {
+ case aiShadingMode_NoShading: j = 0; break;
+ case aiShadingMode_Phong: j = 2; break;
+ default: j = 1; break;
+ m3d_propertytypes[k].id, j);
+ aiProps[k].index, j) == AI_SUCCESS)
+ if (aiTxProps[k].pKey &&
+ mat->GetTexture((aiTextureType)aiTxProps[k].type,
+ aiTxProps[k].index, &name, NULL, NULL, NULL,
+ NULL, NULL) == AI_SUCCESS) {
+ for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++)
+ if (j && name.data[j] == '.' &&
+ (name.data[j + 1] == 'p' || name.data[j + 1] == 'P') &&
+ (name.data[j + 1] == 'n' || name.data[j + 1] == 'N') &&
+ (name.data[j + 1] == 'g' || name.data[j + 1] == 'G'))
+ name.data[j] = 0;
+ // do we have this texture saved already?
+ fn = SafeStr(name, true);
+ for (j = 0, i = M3D_NOTDEFINED; j < m3d->numtexture; j++)
+ if (!strcmp(fn, m3d->texture[j].name)) {
+ i = j;
+ free(fn);
+ if (i == M3D_NOTDEFINED) {
+ i = m3d->numtexture++;
+ m3d->texture = (m3dtx_t *)M3D_REALLOC(
+ m3d->texture,
+ m3d->numtexture * sizeof(m3dtx_t));
+ if (!m3d->texture) {
+ // we don't need the texture itself, only its name
+ m3d->texture[i].name = fn;
+ m3d->texture[i].w = 0;
+ m3d->texture[i].h = 0;
+ m3d->texture[i].d = NULL;
+ m3d_propertytypes[k].id + 128, i);
+ return mi;
@@ -275,161 +276,166 @@ namespace Assimp {
// Worker function for exporting a scene to binary M3D.
// Prototyped and registered in Exporter.cpp
void ExportSceneM3D(
- const char *pFile,
- IOSystem *pIOSystem,
- const aiScene *pScene,
- const ExportProperties *pProperties) {
- // initialize the exporter
- M3DExporter exporter(pScene, pProperties);
- // perform binary export
- exporter.doExport(pFile, pIOSystem, false);
+ const char *pFile,
+ IOSystem *pIOSystem,
+ const aiScene *pScene,
+ const ExportProperties *pProperties) {
+ // initialize the exporter
+ M3DExporter exporter(pScene, pProperties);
+ // perform binary export
+ exporter.doExport(pFile, pIOSystem, false);
// ---------------------------------------------------------------------
// Worker function for exporting a scene to ASCII A3D.
void ExportSceneM3DA(
- const ExportProperties *pProperties
+ const char *,
+ IOSystem *,
+ const aiScene *,
+ const ExportProperties *
#ifdef M3D_ASCII
- // perform ascii export
- exporter.doExport(pFile, pIOSystem, true);
+ // perform ascii export
+ exporter.doExport(pFile, pIOSystem, true);
- throw DeadlyExportError("Assimp configured without M3D_ASCII support");
+ throw DeadlyExportError("Assimp configured without M3D_ASCII support");
M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) :
- mScene(pScene),
- mProperties(pProperties),
- outfile() {}
+ mScene(pScene),
+ mProperties(pProperties),
+ outfile() {
void M3DExporter::doExport(
- bool toAscii) {
- // TODO: convert mProperties into M3D_EXP_* flags
- (void)mProperties;
- // open the indicated file for writing (in binary / ASCII mode)
- outfile.reset(pIOSystem->Open(pFile, toAscii ? "wt" : "wb"));
- if (!outfile) {
- throw DeadlyExportError("could not open output .m3d file: " + std::string(pFile));
- M3DWrapper m3d;
- if (!m3d) {
- m3d->name = SafeStr(mScene->mRootNode->mName, false);
- // Create a model from assimp structures
- aiMatrix4x4 m;
- NodeWalk(m3d, mScene->mRootNode, m);
- // serialize the structures
- unsigned int size;
- unsigned char *output = m3d.Save(M3D_EXP_FLOAT, M3D_EXP_EXTRA | (toAscii ? M3D_EXP_ASCII : 0), size);
- if (!output || size < 8) {
- throw DeadlyExportError("unable to serialize into Model 3D");
- // Write out serialized model
- outfile->Write(output, size, 1);
- // explicitly release file pointer,
- // so we don't have to rely on class destruction.
- outfile.reset();
+ bool toAscii) {
+ // TODO: convert mProperties into M3D_EXP_* flags
+ (void)mProperties;
+ // open the indicated file for writing (in binary / ASCII mode)
+ outfile.reset(pIOSystem->Open(pFile, toAscii ? "wt" : "wb"));
+ if (!outfile) {
+ throw DeadlyExportError("could not open output .m3d file: " + std::string(pFile));
+ M3DWrapper m3d;
+ if (!m3d) {
+ m3d->name = SafeStr(mScene->mRootNode->mName, false);
+ // Create a model from assimp structures
+ aiMatrix4x4 m;
+ NodeWalk(m3d, mScene->mRootNode, m);
+ // serialize the structures
+ unsigned int size;
+ unsigned char *output = m3d.Save(M3D_EXP_FLOAT, M3D_EXP_EXTRA | (toAscii ? M3D_EXP_ASCII : 0), size);
+ if (!output || size < 8) {
+ throw DeadlyExportError("unable to serialize into Model 3D");
+ // Write out serialized model
+ outfile->Write(output, size, 1);
+ // explicitly release file pointer,
+ // so we don't have to rely on class destruction.
+ outfile.reset();
+ M3D_FREE(m3d->name);
+ m3d->name = nullptr;
// recursive node walker
void M3DExporter::NodeWalk(const M3DWrapper &m3d, const aiNode *pNode, aiMatrix4x4 m) {
- aiMatrix4x4 nm = m * pNode->mTransformation;
- for (unsigned int i = 0; i < pNode->mNumMeshes; i++) {
- const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]];
- if (mScene->mMaterials) {
- // get the material for this mesh
- mi = addMaterial(m3d, mScene->mMaterials[mesh->mMaterialIndex]);
- // iterate through the mesh faces
- for (unsigned int j = 0; j < mesh->mNumFaces; j++) {
- unsigned int n;
- const aiFace *face = &(mesh->mFaces[j]);
- // only triangle meshes supported for now
- if (face->mNumIndices != 3) {
- throw DeadlyExportError("use aiProcess_Triangulate before export");
- // add triangle to the output
- n = m3d->numface++;
- m3d->face = (m3df_t *)M3D_REALLOC(m3d->face,
- m3d->numface * sizeof(m3df_t));
- if (!m3d->face) {
- /* set all index to -1 by default */
- m3d->face[n].vertex[0] = m3d->face[n].vertex[1] = m3d->face[n].vertex[2] =
- m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] =
- m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = M3D_UNDEF;
- m3d->face[n].materialid = mi;
- for (unsigned int k = 0; k < face->mNumIndices; k++) {
- // get the vertex's index
- unsigned int l = face->mIndices[k];
- unsigned int idx;
- m3dv_t vertex;
- m3dti_t ti;
- // multiply the position vector by the transformation matrix
- aiVector3D v = mesh->mVertices[l];
- v *= nm;
- vertex.x = v.x;
- vertex.y = v.y;
- vertex.z = v.z;
- vertex.w = 1.0;
- vertex.color = 0;
- vertex.skinid = M3D_UNDEF;
- // add color if defined
- if (mesh->HasVertexColors(0))
- vertex.color = mkColor(&mesh->mColors[0][l]);
- // save the vertex to the output
- m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex,
- &vertex, &idx);
- m3d->face[n].vertex[k] = (M3D_INDEX)idx;
- // do we have texture coordinates?
- if (mesh->HasTextureCoords(0)) {
- ti.u = mesh->mTextureCoords[0][l].x;
- ti.v = mesh->mTextureCoords[0][l].y;
- m3d->tmap = AddTmap(m3d->tmap, &m3d->numtmap, &ti, &idx);
- m3d->face[n].texcoord[k] = (M3D_INDEX)idx;
- // do we have normal vectors?
- if (mesh->HasNormals()) {
- vertex.x = mesh->mNormals[l].x;
- vertex.y = mesh->mNormals[l].y;
- vertex.z = mesh->mNormals[l].z;
- m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx);
- m3d->face[n].normal[k] = (M3D_INDEX)idx;
- // repeat for the children nodes
- for (unsigned int i = 0; i < pNode->mNumChildren; i++) {
- NodeWalk(m3d, pNode->mChildren[i], nm);
+ aiMatrix4x4 nm = m * pNode->mTransformation;
+ for (unsigned int i = 0; i < pNode->mNumMeshes; i++) {
+ const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]];
+ if (mScene->mMaterials) {
+ // get the material for this mesh
+ mi = addMaterial(m3d, mScene->mMaterials[mesh->mMaterialIndex]);
+ // iterate through the mesh faces
+ for (unsigned int j = 0; j < mesh->mNumFaces; j++) {
+ unsigned int n;
+ const aiFace *face = &(mesh->mFaces[j]);
+ // only triangle meshes supported for now
+ if (face->mNumIndices != 3) {
+ throw DeadlyExportError("use aiProcess_Triangulate before export");
+ // add triangle to the output
+ n = m3d->numface++;
+ m3d->face = (m3df_t *)M3D_REALLOC(m3d->face,
+ m3d->numface * sizeof(m3df_t));
+ if (!m3d->face) {
+ /* set all index to -1 by default */
+ m3d->face[n].vertex[0] = m3d->face[n].vertex[1] = m3d->face[n].vertex[2] =
+ m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] =
+ m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = M3D_UNDEF;
+ m3d->face[n].materialid = mi;
+ for (unsigned int k = 0; k < face->mNumIndices; k++) {
+ // get the vertex's index
+ unsigned int l = face->mIndices[k];
+ unsigned int idx;
+ m3dv_t vertex;
+ m3dti_t ti;
+ // multiply the position vector by the transformation matrix
+ aiVector3D v = mesh->mVertices[l];
+ v *= nm;
+ vertex.x = v.x;
+ vertex.y = v.y;
+ vertex.z = v.z;
+ vertex.w = 1.0;
+ vertex.color = 0;
+ vertex.skinid = M3D_UNDEF;
+ // add color if defined
+ if (mesh->HasVertexColors(0))
+ vertex.color = mkColor(&mesh->mColors[0][l]);
+ // save the vertex to the output
+ m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex,
+ &vertex, &idx);
+ m3d->face[n].vertex[k] = (M3D_INDEX)idx;
+ // do we have texture coordinates?
+ if (mesh->HasTextureCoords(0)) {
+ ti.u = mesh->mTextureCoords[0][l].x;
+ ti.v = mesh->mTextureCoords[0][l].y;
+ m3d->tmap = AddTmap(m3d->tmap, &m3d->numtmap, &ti, &idx);
+ m3d->face[n].texcoord[k] = (M3D_INDEX)idx;
+ // do we have normal vectors?
+ if (mesh->HasNormals()) {
+ vertex.x = mesh->mNormals[l].x;
+ vertex.y = mesh->mNormals[l].y;
+ vertex.z = mesh->mNormals[l].z;
+ m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx);
+ m3d->face[n].normal[k] = (M3D_INDEX)idx;
+ // repeat for the children nodes
+ for (unsigned int i = 0; i < pNode->mNumChildren; i++) {
+ NodeWalk(m3d, pNode->mChildren[i], nm);
} // namespace Assimp
@@ -50,15 +50,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ASSIMP_USE_M3D_READFILECB
-# if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
-# define threadlocal thread_local
-# else
-# if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
-# define threadlocal __declspec(thread)
-# define threadlocal
-# endif
+#if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
+#define threadlocal thread_local
+#else
+#if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
+#define threadlocal __declspec(thread)
+#define threadlocal
extern "C" {
@@ -66,76 +66,81 @@ extern "C" {
threadlocal void *m3dimporter_pIOHandler;
unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
- ai_assert(nullptr != fn);
- ai_assert(nullptr != size);
- std::string file(fn);
- std::unique_ptr<Assimp::IOStream> pStream(
- (reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
- size_t fileSize = 0;
- unsigned char *data = NULL;
- // sometimes pStream is nullptr in a single-threaded scenario too for some reason
- // (should be an empty object returning nothing I guess)
- if (pStream) {
- fileSize = pStream->FileSize();
- // should be allocated with malloc(), because the library will call free() to deallocate
- data = (unsigned char *)malloc(fileSize);
- if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
- pStream.reset();
- *size = 0;
- // don't throw a deadly exception, it's not fatal if we can't read an external asset
- *size = (int)fileSize;
- return data;
+ ai_assert(nullptr != fn);
+ ai_assert(nullptr != size);
+ std::string file(fn);
+ std::unique_ptr<Assimp::IOStream> pStream(
+ (reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
+ size_t fileSize = 0;
+ unsigned char *data = NULL;
+ // sometimes pStream is nullptr in a single-threaded scenario too for some reason
+ // (should be an empty object returning nothing I guess)
+ if (pStream) {
+ fileSize = pStream->FileSize();
+ // should be allocated with malloc(), because the library will call free() to deallocate
+ data = (unsigned char *)malloc(fileSize);
+ if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
+ pStream.reset();
+ *size = 0;
+ // don't throw a deadly exception, it's not fatal if we can't read an external asset
+ *size = (int)fileSize;
+ return data;
M3DWrapper::M3DWrapper() {
- // use malloc() here because m3d_free() will call free()
- m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
+ // use malloc() here because m3d_free() will call free()
+ m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) {
+ if (nullptr == pIOHandler) {
+ ai_assert(nullptr != pIOHandler);
- // pass this IOHandler to the C callback in a thread-local pointer
- m3dimporter_pIOHandler = pIOHandler;
- m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
- // Clear the C callback
- m3dimporter_pIOHandler = nullptr;
+ // pass this IOHandler to the C callback in a thread-local pointer
+ m3dimporter_pIOHandler = pIOHandler;
+ m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
+ // Clear the C callback
+ m3dimporter_pIOHandler = nullptr;
- m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
+ m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
M3DWrapper::~M3DWrapper() {
- reset();
+ reset();
void M3DWrapper::reset() {
- ClearSave();
- if (m3d_)
- m3d_free(m3d_);
- m3d_ = nullptr;
+ ClearSave();
+ if (m3d_) {
+ m3d_free(m3d_);
+ m3d_ = nullptr;
unsigned char *M3DWrapper::Save(int quality, int flags, unsigned int &size) {
#if (!(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER))
- saved_output_ = m3d_save(m3d_, quality, flags, &size);
- return saved_output_;
+ saved_output_ = m3d_save(m3d_, quality, flags, &size);
+ return saved_output_;
void M3DWrapper::ClearSave() {
- if (saved_output_)
- M3D_FREE(saved_output_);
- saved_output_ = nullptr;
+ if (saved_output_)
+ M3D_FREE(saved_output_);
+ saved_output_ = nullptr;
@@ -45,21 +45,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the MD5 importer class
#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
-#include <assimp/RemoveComments.h>
#include "MD5Loader.h"
-#include <assimp/StringComparison.h>
#include <assimp/MathFunctions.h>
+#include <assimp/RemoveComments.h>
+#include <assimp/StringComparison.h>
#include <assimp/DefaultLogger.hpp>
@@ -67,7 +66,6 @@ using namespace Assimp;
// Minimum weight value. Weights inside [-n ... n] are ignored
#define AI_MD5_WEIGHT_EPSILON Math::getEpsilon<float>()
static const aiImporterDesc desc = {
"Doom 3 / MD5 Mesh Importer",
"",
@@ -83,93 +81,78 @@ static const aiImporterDesc desc = {
-MD5Importer::MD5Importer()
- : mIOHandler()
- , mBuffer()
- , fileSize()
- , iLineNumber()
- , pScene()
- , pIOHandler()
- , bHadMD5Mesh()
- , bHadMD5Anim()
- , bHadMD5Camera()
- , configNoAutoLoad (false)
-{}
+MD5Importer::MD5Importer() :
+ mIOHandler(nullptr), mBuffer(), fileSize(), iLineNumber(), pScene(), bHadMD5Mesh(), bHadMD5Anim(), bHadMD5Camera(), configNoAutoLoad(false) {
-MD5Importer::~MD5Importer()
+MD5Importer::~MD5Importer() {
-bool MD5Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
if (extension == "md5anim" || extension == "md5mesh" || extension == "md5camera")
- else if (!extension.length() || checkSig) {
+ else if (!extension.length() || checkSig) {
if (!pIOHandler) {
- const char* tokens[] = {"MD5Version"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ const char *tokens[] = { "MD5Version" };
+ return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
// Get list of all supported extensions
-const aiImporterDesc* MD5Importer::GetInfo () const
+const aiImporterDesc *MD5Importer::GetInfo() const {
// Setup import properties
-void MD5Importer::SetupProperties(const Importer* pImp)
+void MD5Importer::SetupProperties(const Importer *pImp) {
// AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD
- configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD,0));
+ configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0));
// Imports the given file into the given scene structure.
-void MD5Importer::InternReadFile( const std::string& pFile,
- aiScene* _pScene, IOSystem* _pIOHandler)
- pScene = _pScene;
+void MD5Importer::InternReadFile(const std::string &pFile,
+ aiScene *_pScene, IOSystem *pIOHandler) {
+ mIOHandler = pIOHandler;
+ pScene = _pScene;
bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false;
// remove the file extension
const std::string::size_type pos = pFile.find_last_of('.');
- mFile = (std::string::npos == pos ? pFile : pFile.substr(0,pos+1));
+ mFile = (std::string::npos == pos ? pFile : pFile.substr(0, pos + 1));
try {
if (extension == "md5camera") {
LoadMD5CameraFile();
- else if (configNoAutoLoad || extension == "md5anim") {
+ } else if (configNoAutoLoad || extension == "md5anim") {
// determine file extension and process just *one* file
if (extension.length() == 0) {
throw DeadlyImportError("Failure, need file extension to determine MD5 part type");
if (extension == "md5anim") {
LoadMD5AnimFile();
- else if (extension == "md5mesh") {
+ } else if (extension == "md5mesh") {
LoadMD5MeshFile();
- catch ( ... ) { // std::exception, Assimp::DeadlyImportError
+ } catch (...) { // std::exception, Assimp::DeadlyImportError
UnloadFileFromMemory();
throw;
@@ -180,8 +163,8 @@ void MD5Importer::InternReadFile( const std::string& pFile,
// Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system
- pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
- 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
+ pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
// the output scene wouldn't pass the validation without this flag
if (!bHadMD5Mesh) {
@@ -194,8 +177,7 @@ void MD5Importer::InternReadFile( const std::string& pFile,
// Load a file into a memory buffer
-void MD5Importer::LoadFileIntoMemory (IOStream* file)
+void MD5Importer::LoadFileIntoMemory(IOStream *file) {
// unload the previous buffer, if any
@@ -204,21 +186,20 @@ void MD5Importer::LoadFileIntoMemory (IOStream* file)
ai_assert(fileSize);
// allocate storage and copy the contents of the file to a memory buffer
- mBuffer = new char[fileSize+1];
- file->Read( (void*)mBuffer, 1, fileSize);
+ mBuffer = new char[fileSize + 1];
+ file->Read((void *)mBuffer, 1, fileSize);
iLineNumber = 1;
// append a terminal 0
mBuffer[fileSize] = '\0';
// now remove all line comments from the file
- CommentRemover::RemoveLineComments("//",mBuffer,' ');
+ CommentRemover::RemoveLineComments("//", mBuffer, ' ');
// Unload the current memory buffer
-void MD5Importer::UnloadFileFromMemory ()
+void MD5Importer::UnloadFileFromMemory() {
// delete the file buffer
delete[] mBuffer;
mBuffer = NULL;
@@ -227,57 +208,55 @@ void MD5Importer::UnloadFileFromMemory ()
// Build unique vertices
-void MD5Importer::MakeDataUnique (MD5::MeshDesc& meshSrc)
- std::vector<bool> abHad(meshSrc.mVertices.size(),false);
+void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) {
+ std::vector<bool> abHad(meshSrc.mVertices.size(), false);
// allocate enough storage to keep the output structures
- const unsigned int iNewNum = static_cast<unsigned int>(meshSrc.mFaces.size()*3);
+ const unsigned int iNewNum = static_cast<unsigned int>(meshSrc.mFaces.size() * 3);
unsigned int iNewIndex = static_cast<unsigned int>(meshSrc.mVertices.size());
meshSrc.mVertices.resize(iNewNum);
// try to guess how much storage we'll need for new weights
const float fWeightsPerVert = meshSrc.mWeights.size() / (float)iNewIndex;
- const unsigned int guess = (unsigned int)(fWeightsPerVert*iNewNum);
+ const unsigned int guess = (unsigned int)(fWeightsPerVert * iNewNum);
meshSrc.mWeights.reserve(guess + (guess >> 3)); // + 12.5% as buffer
- for (FaceList::const_iterator iter = meshSrc.mFaces.begin(),iterEnd = meshSrc.mFaces.end();iter != iterEnd;++iter){
- const aiFace& face = *iter;
- for (unsigned int i = 0; i < 3;++i) {
+ for (FaceList::const_iterator iter = meshSrc.mFaces.begin(), iterEnd = meshSrc.mFaces.end(); iter != iterEnd; ++iter) {
+ const aiFace &face = *iter;
+ for (unsigned int i = 0; i < 3; ++i) {
if (face.mIndices[0] >= meshSrc.mVertices.size()) {
throw DeadlyImportError("MD5MESH: Invalid vertex index");
- if (abHad[face.mIndices[i]]) {
+ if (abHad[face.mIndices[i]]) {
// generate a new vertex
meshSrc.mVertices[iNewIndex] = meshSrc.mVertices[face.mIndices[i]];
face.mIndices[i] = iNewIndex++;
- else abHad[face.mIndices[i]] = true;
+ abHad[face.mIndices[i]] = true;
// swap face order
- std::swap(face.mIndices[0],face.mIndices[2]);
+ std::swap(face.mIndices[0], face.mIndices[2]);
// Recursive node graph construction from a MD5MESH
-void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bones)
+void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones) {
ai_assert(NULL != piParent && !piParent->mNumChildren);
// First find out how many children we'll have
- for (int i = 0; i < (int)bones.size();++i) {
- if (iParentID != i && bones[i].mParentIndex == iParentID) {
+ for (int i = 0; i < (int)bones.size(); ++i) {
+ if (iParentID != i && bones[i].mParentIndex == iParentID) {
++piParent->mNumChildren;
if (piParent->mNumChildren) {
- piParent->mChildren = new aiNode*[piParent->mNumChildren];
+ piParent->mChildren = new aiNode *[piParent->mNumChildren];
// (avoid infinite recursion)
- aiNode* pc;
+ aiNode *pc;
// setup a new node
*piParent->mChildren++ = pc = new aiNode();
pc->mName = aiString(bones[i].mName);
@@ -285,9 +264,9 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo
// get the transformation matrix from rotation and translational components
aiQuaternion quat;
- MD5::ConvertQuaternion ( bones[i].mRotationQuat, quat );
+ MD5::ConvertQuaternion(bones[i].mRotationQuat, quat);
- bones[i].mTransform = aiMatrix4x4 ( quat.GetMatrix());
+ bones[i].mTransform = aiMatrix4x4(quat.GetMatrix());
bones[i].mTransform.a4 = bones[i].mPositionXYZ.x;
bones[i].mTransform.b4 = bones[i].mPositionXYZ.y;
bones[i].mTransform.c4 = bones[i].mPositionXYZ.z;
@@ -298,12 +277,12 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo
// the transformations for each bone are absolute, so we need to multiply them
// with the inverse of the absolute matrix of the parent joint
- if (-1 != iParentID) {
+ if (-1 != iParentID) {
pc->mTransformation = bones[iParentID].mInvTransform * pc->mTransformation;
// add children to this node, too
- AttachChilds_Mesh( i, pc, bones);
+ AttachChilds_Mesh(i, pc, bones);
// undo offset computations
@@ -313,37 +292,36 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo
// Recursive node graph construction from a MD5ANIM
-void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList& bones,const aiNodeAnim** node_anims)
+void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneList &bones, const aiNodeAnim **node_anims) {
- if (iParentID != i && bones[i].mParentIndex == iParentID)
pc->mParent = piParent;
// get the corresponding animation channel and its first frame
- const aiNodeAnim** cur = node_anims;
- while ((**cur).mNodeName != pc->mName)++cur;
+ const aiNodeAnim **cur = node_anims;
+ while ((**cur).mNodeName != pc->mName)
+ ++cur;
- aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue,pc->mTransformation);
- pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix()) ;
+ aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue, pc->mTransformation);
+ pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix());
- AttachChilds_Anim( i, pc, bones,node_anims);
+ AttachChilds_Anim(i, pc, bones, node_anims);
@@ -353,13 +331,12 @@ void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList
// Load a MD5MESH file
-void MD5Importer::LoadMD5MeshFile ()
+void MD5Importer::LoadMD5MeshFile() {
std::string pFile = mFile + "md5mesh";
+ std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb"));
- if( file.get() == NULL || !file->FileSize()) {
+ if (file.get() == nullptr || !file->FileSize()) {
ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile);
@@ -367,7 +344,7 @@ void MD5Importer::LoadMD5MeshFile ()
LoadFileIntoMemory(file.get());
// now construct a parser and parse the file
- MD5::MD5Parser parser(mBuffer,fileSize);
+ MD5::MD5Parser parser(mBuffer, fileSize);
// load the mesh information from it
MD5::MD5MeshParser meshParser(parser.mSections);
@@ -375,13 +352,13 @@ void MD5Importer::LoadMD5MeshFile ()
// create the bone hierarchy - first the root node and dummy nodes for all meshes
pScene->mRootNode = new aiNode("<MD5_Root>");
pScene->mRootNode->mNumChildren = 2;
- pScene->mRootNode->mChildren = new aiNode*[2];
+ pScene->mRootNode->mChildren = new aiNode *[2];
// build the hierarchy from the MD5MESH file
- aiNode* pcNode = pScene->mRootNode->mChildren[1] = new aiNode();
+ aiNode *pcNode = pScene->mRootNode->mChildren[1] = new aiNode();
pcNode->mName.Set("<MD5_Hierarchy>");
pcNode->mParent = pScene->mRootNode;
- AttachChilds_Mesh(-1,pcNode,meshParser.mJoints);
+ AttachChilds_Mesh(-1, pcNode, meshParser.mJoints);
pcNode = pScene->mRootNode->mChildren[0] = new aiNode();
pcNode->mName.Set("<MD5_Mesh>");
@@ -393,96 +370,94 @@ void MD5Importer::LoadMD5MeshFile ()
// FIX: MD5 files exported from Blender can have empty meshes
- for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) {
+ for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) {
if (!(*it).mFaces.empty() && !(*it).mVertices.empty())
++pScene->mNumMaterials;
// generate all meshes
pScene->mNumMeshes = pScene->mNumMaterials;
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
+ pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
+ pScene->mMaterials = new aiMaterial *[pScene->mNumMeshes];
// storage for node mesh indices
pcNode->mNumMeshes = pScene->mNumMeshes;
pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
- for (unsigned int m = 0; m < pcNode->mNumMeshes;++m)
+ for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m)
pcNode->mMeshes[m] = m;
unsigned int n = 0;
- for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) {
- MD5::MeshDesc& meshSrc = *it;
+ for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) {
+ MD5::MeshDesc &meshSrc = *it;
if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty())
- aiMesh* mesh = pScene->mMeshes[n] = new aiMesh();
+ aiMesh *mesh = pScene->mMeshes[n] = new aiMesh();
// generate unique vertices in our internal verbose format
MakeDataUnique(meshSrc);
- std::string name( meshSrc.mShader.C_Str() );
+ std::string name(meshSrc.mShader.C_Str());
name += ".msh";
mesh->mName = name;
- mesh->mNumVertices = (unsigned int) meshSrc.mVertices.size();
+ mesh->mNumVertices = (unsigned int)meshSrc.mVertices.size();
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
mesh->mNumUVComponents[0] = 2;
// copy texture coordinates
- aiVector3D* pv = mesh->mTextureCoords[0];
- for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
+ aiVector3D *pv = mesh->mTextureCoords[0];
+ for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) {
pv->x = (*iter).mUV.x;
- pv->y = 1.0f-(*iter).mUV.y; // D3D to OpenGL
+ pv->y = 1.0f - (*iter).mUV.y; // D3D to OpenGL
pv->z = 0.0f;
// sort all bone weights - per bone
- unsigned int* piCount = new unsigned int[meshParser.mJoints.size()];
- ::memset(piCount,0,sizeof(unsigned int)*meshParser.mJoints.size());
+ unsigned int *piCount = new unsigned int[meshParser.mJoints.size()];
+ ::memset(piCount, 0, sizeof(unsigned int) * meshParser.mJoints.size());
- for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
- MD5::WeightDesc& weightDesc = meshSrc.mWeights[w];
+ for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) {
+ MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
/* FIX for some invalid exporters */
- if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON ))
+ if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON))
++piCount[weightDesc.mBone];
// check how many we will need
- for (unsigned int p = 0; p < meshParser.mJoints.size();++p)
- if (piCount[p])mesh->mNumBones++;
+ for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p)
+ if (piCount[p]) mesh->mNumBones++;
if (mesh->mNumBones) // just for safety
- mesh->mBones = new aiBone*[mesh->mNumBones];
- for (unsigned int q = 0,h = 0; q < meshParser.mJoints.size();++q)
- if (!piCount[q])continue;
- aiBone* p = mesh->mBones[h] = new aiBone();
+ mesh->mBones = new aiBone *[mesh->mNumBones];
+ for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) {
+ if (!piCount[q]) continue;
+ aiBone *p = mesh->mBones[h] = new aiBone();
p->mNumWeights = piCount[q];
p->mWeights = new aiVertexWeight[p->mNumWeights];
p->mName = aiString(meshParser.mJoints[q].mName);
p->mOffsetMatrix = meshParser.mJoints[q].mInvTransform;
// store the index for later use
- MD5::BoneDesc& boneSrc = meshParser.mJoints[q];
+ MD5::BoneDesc &boneSrc = meshParser.mJoints[q];
boneSrc.mMap = h++;
// compute w-component of quaternion
- MD5::ConvertQuaternion( boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted );
+ MD5::ConvertQuaternion(boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted);
pv = mesh->mVertices;
// compute the final vertex position from all single weights
*pv = aiVector3D();
// there are models which have weights which don't sum to 1 ...
ai_real fSum = 0.0;
+ for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w)
fSum += meshSrc.mWeights[w].mWeight;
if (!fSum) {
ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0");
@@ -490,32 +465,32 @@ void MD5Importer::LoadMD5MeshFile ()
// process bone weights
- for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) {
if (w >= meshSrc.mWeights.size())
throw DeadlyImportError("MD5MESH: Invalid weight index");
- if ( weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
+ if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
const ai_real fNewWeight = weightDesc.mWeight / fSum;
// transform the local position into worldspace
- MD5::BoneDesc& boneSrc = meshParser.mJoints[weightDesc.mBone];
- const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (weightDesc.vOffsetPosition);
+ MD5::BoneDesc &boneSrc = meshParser.mJoints[weightDesc.mBone];
+ const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate(weightDesc.vOffsetPosition);
// use the original weight to compute the vertex position
// (some MD5s seem to depend on the invalid weight values ...)
- *pv += ((boneSrc.mPositionXYZ+v)* (ai_real)weightDesc.mWeight);
+ *pv += ((boneSrc.mPositionXYZ + v) * (ai_real)weightDesc.mWeight);
- aiBone* bone = mesh->mBones[boneSrc.mMap];
- *bone->mWeights++ = aiVertexWeight((unsigned int)(pv-mesh->mVertices),fNewWeight);
+ aiBone *bone = mesh->mBones[boneSrc.mMap];
+ *bone->mWeights++ = aiVertexWeight((unsigned int)(pv - mesh->mVertices), fNewWeight);
// undo our nice offset tricks ...
- for (unsigned int p = 0; p < mesh->mNumBones;++p) {
+ for (unsigned int p = 0; p < mesh->mNumBones; ++p) {
mesh->mBones[p]->mWeights -= mesh->mBones[p]->mNumWeights;
@@ -526,14 +501,14 @@ void MD5Importer::LoadMD5MeshFile ()
// (however, take care that the aiFace destructor doesn't delete the mIndices array)
mesh->mNumFaces = (unsigned int)meshSrc.mFaces.size();
- for (unsigned int c = 0; c < mesh->mNumFaces;++c) {
+ for (unsigned int c = 0; c < mesh->mNumFaces; ++c) {
mesh->mFaces[c].mNumIndices = 3;
mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices;
meshSrc.mFaces[c].mIndices = NULL;
// generate a material for the mesh
- aiMaterial* mat = new aiMaterial();
+ aiMaterial *mat = new aiMaterial();
pScene->mMaterials[n] = mat;
// insert the typical doom3 textures:
@@ -541,28 +516,27 @@ void MD5Importer::LoadMD5MeshFile ()
// nnn_h.tga - height map
// nnn_s.tga - specular map
// nnn_d.tga - diffuse map
- if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data,'.')) {
+ if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data, '.')) {
aiString temp(meshSrc.mShader);
temp.Append("_local.tga");
- mat->AddProperty(&temp,AI_MATKEY_TEXTURE_NORMALS(0));
+ mat->AddProperty(&temp, AI_MATKEY_TEXTURE_NORMALS(0));
- temp = aiString(meshSrc.mShader);
+ temp = aiString(meshSrc.mShader);
temp.Append("_s.tga");
- mat->AddProperty(&temp,AI_MATKEY_TEXTURE_SPECULAR(0));
+ mat->AddProperty(&temp, AI_MATKEY_TEXTURE_SPECULAR(0));
temp.Append("_d.tga");
- mat->AddProperty(&temp,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ mat->AddProperty(&temp, AI_MATKEY_TEXTURE_DIFFUSE(0));
temp.Append("_h.tga");
- mat->AddProperty(&temp,AI_MATKEY_TEXTURE_HEIGHT(0));
+ mat->AddProperty(&temp, AI_MATKEY_TEXTURE_HEIGHT(0));
// set this also as material name
- mat->AddProperty(&meshSrc.mShader,AI_MATKEY_NAME);
+ mat->AddProperty(&meshSrc.mShader, AI_MATKEY_NAME);
mat->AddProperty(&meshSrc.mShader, AI_MATKEY_TEXTURE_DIFFUSE(0));
mesh->mMaterialIndex = n++;
@@ -572,39 +546,37 @@ void MD5Importer::LoadMD5MeshFile ()
// Load an MD5ANIM file
-void MD5Importer::LoadMD5AnimFile ()
+void MD5Importer::LoadMD5AnimFile() {
std::string pFile = mFile + "md5anim";
- if( !file.get() || !file->FileSize()) {
+ if (!file.get() || !file->FileSize()) {
ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile);
// parse the basic file structure
// load the animation information from the parse tree
MD5::MD5AnimParser animParser(parser.mSections);
// generate and fill the output animation
if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() ||
- animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
+ animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded");
bHadMD5Anim = true;
- pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations = 1];
- aiAnimation* anim = pScene->mAnimations[0] = new aiAnimation();
+ pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations = 1];
+ aiAnimation *anim = pScene->mAnimations[0] = new aiAnimation();
anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size();
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
- for (unsigned int i = 0; i < anim->mNumChannels;++i) {
- aiNodeAnim* node = anim->mChannels[i] = new aiNodeAnim();
- node->mNodeName = aiString( animParser.mAnimatedBones[i].mName );
+ for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
+ aiNodeAnim *node = anim->mChannels[i] = new aiNodeAnim();
+ node->mNodeName = aiString(animParser.mAnimatedBones[i].mName);
// allocate storage for the keyframes
node->mPositionKeys = new aiVectorKey[animParser.mFrames.size()];
@@ -614,46 +586,44 @@ void MD5Importer::LoadMD5AnimFile ()
// 1 tick == 1 frame
anim->mTicksPerSecond = animParser.fFrameRate;
- for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end();iter != iterEnd;++iter){
+ for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end(); iter != iterEnd; ++iter) {
double dTime = (double)(*iter).iIndex;
- aiNodeAnim** pcAnimNode = anim->mChannels;
+ aiNodeAnim **pcAnimNode = anim->mChannels;
if (!(*iter).mValues.empty() || iter == animParser.mFrames.begin()) /* be sure we have at least one frame */
// now process all values in there ... read all joints
- MD5::BaseFrameDesc* pcBaseFrame = &animParser.mBaseFrames[0];
- for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end();++iter2,
- ++pcAnimNode,++pcBaseFrame)
- if((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) {
+ MD5::BaseFrameDesc *pcBaseFrame = &animParser.mBaseFrames[0];
+ for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end(); ++iter2,
+ ++pcAnimNode, ++pcBaseFrame) {
+ if ((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) {
// Allow for empty frames
if ((*iter2).iFlags != 0) {
throw DeadlyImportError("MD5: Keyframe index is out of range");
- const float* fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex];
- aiNodeAnim* pcCurAnimBone = *pcAnimNode;
+ const float *fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex];
+ aiNodeAnim *pcCurAnimBone = *pcAnimNode;
- aiVectorKey* vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++];
- aiQuatKey* qKey = &pcCurAnimBone->mRotationKeys [pcCurAnimBone->mNumRotationKeys++];
+ aiVectorKey *vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++];
+ aiQuatKey *qKey = &pcCurAnimBone->mRotationKeys[pcCurAnimBone->mNumRotationKeys++];
aiVector3D vTemp;
// translational component
for (unsigned int i = 0; i < 3; ++i) {
if ((*iter2).iFlags & (1u << i)) {
- vKey->mValue[i] = *fpCur++;
- else vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i];
+ vKey->mValue[i] = *fpCur++;
+ vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i];
// orientation component
if ((*iter2).iFlags & (8u << i)) {
- vTemp[i] = *fpCur++;
- else vTemp[i] = pcBaseFrame->vRotationQuat[i];
+ vTemp[i] = *fpCur++;
+ vTemp[i] = pcBaseFrame->vRotationQuat[i];
MD5::ConvertQuaternion(vTemp, qKey->mValue);
@@ -662,7 +632,7 @@ void MD5Importer::LoadMD5AnimFile ()
// compute the duration of the animation
- anim->mDuration = std::max(dTime,anim->mDuration);
+ anim->mDuration = std::max(dTime, anim->mDuration);
// If we didn't build the hierarchy yet (== we didn't load a MD5MESH),
@@ -671,11 +641,11 @@ void MD5Importer::LoadMD5AnimFile ()
pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<MD5_Hierarchy>");
- AttachChilds_Anim(-1,pScene->mRootNode,animParser.mAnimatedBones,(const aiNodeAnim**)anim->mChannels);
+ AttachChilds_Anim(-1, pScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels);
// Call SkeletonMeshBuilder to construct a mesh to represent the shape
if (pScene->mRootNode->mNumChildren) {
- SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[0]);
+ SkeletonMeshBuilder skeleton_maker(pScene, pScene->mRootNode->mChildren[0]);
@@ -683,20 +653,19 @@ void MD5Importer::LoadMD5AnimFile ()
// Load an MD5CAMERA file
-void MD5Importer::LoadMD5CameraFile ()
+void MD5Importer::LoadMD5CameraFile() {
std::string pFile = mFile + "md5camera";
throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile);
bHadMD5Camera = true;
// load the camera animation data from the parse tree
MD5::MD5CameraParser cameraParser(parser.mSections);
@@ -705,56 +674,55 @@ void MD5Importer::LoadMD5CameraFile ()
throw DeadlyImportError("MD5CAMERA: No frames parsed");
- std::vector<unsigned int>& cuts = cameraParser.cuts;
- std::vector<MD5::CameraAnimFrameDesc>& frames = cameraParser.frames;
+ std::vector<unsigned int> &cuts = cameraParser.cuts;
+ std::vector<MD5::CameraAnimFrameDesc> &frames = cameraParser.frames;
// Construct output graph - a simple root with a dummy child.
// The root node performs the coordinate system conversion
- aiNode* root = pScene->mRootNode = new aiNode("<MD5CameraRoot>");
- root->mChildren = new aiNode*[root->mNumChildren = 1];
+ aiNode *root = pScene->mRootNode = new aiNode("<MD5CameraRoot>");
+ root->mChildren = new aiNode *[root->mNumChildren = 1];
root->mChildren[0] = new aiNode("<MD5Camera>");
root->mChildren[0]->mParent = root;
// ... but with one camera assigned to it
- pScene->mCameras = new aiCamera*[pScene->mNumCameras = 1];
- aiCamera* cam = pScene->mCameras[0] = new aiCamera();
+ pScene->mCameras = new aiCamera *[pScene->mNumCameras = 1];
+ aiCamera *cam = pScene->mCameras[0] = new aiCamera();
cam->mName = "<MD5Camera>";
// FIXME: Fov is currently set to the first frame's value
- cam->mHorizontalFOV = AI_DEG_TO_RAD( frames.front().fFOV );
+ cam->mHorizontalFOV = AI_DEG_TO_RAD(frames.front().fFOV);
// every cut is written to a separate aiAnimation
if (!cuts.size()) {
cuts.push_back(0);
- cuts.push_back(static_cast<unsigned int>(frames.size()-1));
- cuts.insert(cuts.begin(),0);
+ cuts.push_back(static_cast<unsigned int>(frames.size() - 1));
+ cuts.insert(cuts.begin(), 0);
- if (cuts.back() < frames.size()-1)
+ if (cuts.back() < frames.size() - 1)
- pScene->mNumAnimations = static_cast<unsigned int>(cuts.size()-1);
- aiAnimation** tmp = pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations];
- for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end()-1; ++it) {
+ pScene->mNumAnimations = static_cast<unsigned int>(cuts.size() - 1);
+ aiAnimation **tmp = pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations];
+ for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) {
- aiAnimation* anim = *tmp++ = new aiAnimation();
- anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u",(unsigned int)(it-cuts.begin()),(*it),*(it+1));
+ aiAnimation *anim = *tmp++ = new aiAnimation();
+ anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u", (unsigned int)(it - cuts.begin()), (*it), *(it + 1));
anim->mTicksPerSecond = cameraParser.fFrameRate;
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels = 1];
- aiNodeAnim* nd = anim->mChannels[0] = new aiNodeAnim();
+ anim->mChannels = new aiNodeAnim *[anim->mNumChannels = 1];
+ aiNodeAnim *nd = anim->mChannels[0] = new aiNodeAnim();
nd->mNodeName.Set("<MD5Camera>");
- nd->mNumPositionKeys = nd->mNumRotationKeys = *(it+1) - (*it);
+ nd->mNumPositionKeys = nd->mNumRotationKeys = *(it + 1) - (*it);
- nd->mRotationKeys = new aiQuatKey [nd->mNumRotationKeys];
+ nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
for (unsigned int i = 0; i < nd->mNumPositionKeys; ++i) {
- nd->mPositionKeys[i].mValue = frames[*it+i].vPositionXYZ;
- MD5::ConvertQuaternion(frames[*it+i].vRotationQuat,nd->mRotationKeys[i].mValue);
- nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it+i;
+ nd->mPositionKeys[i].mValue = frames[*it + i].vPositionXYZ;
+ MD5::ConvertQuaternion(frames[*it + i].vRotationQuat, nd->mRotationKeys[i].mValue);
+ nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it + i;
@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
/** @file MD5Loader.h
* @brief Definition of the .MD5 importer class.
* http://www.modwiki.net/wiki/MD5_(file_format)
@@ -48,15 +47,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MD5LOADER_H_INCLUDED
#define AI_MD5LOADER_H_INCLUDED
#include "MD5Parser.h"
#include <assimp/types.h>
struct aiNode;
struct aiNodeAnim;
class IOStream;
using namespace Assimp::MD5;
@@ -64,61 +63,53 @@ using namespace Assimp::MD5;
/** Importer class for the MD5 file format
-class MD5Importer : public BaseImporter
+class MD5Importer : public BaseImporter {
MD5Importer();
~MD5Importer();
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
/** Return importer meta information.
* See #BaseImporter::GetInfo for the details
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
-protected:
+ void InternReadFile(const std::string &pFile, aiScene *pScene,
/** Load a *.MD5MESH file.
- void LoadMD5MeshFile ();
+ void LoadMD5MeshFile();
/** Load a *.MD5ANIM file.
- void LoadMD5AnimFile ();
+ void LoadMD5AnimFile();
/** Load a *.MD5CAMERA file.
- void LoadMD5CameraFile ();
+ void LoadMD5CameraFile();
/** Construct node hierarchy from a given MD5ANIM
@@ -127,8 +118,8 @@ protected:
* @param bones Input bones
* @param node_anims Generated node animations
- void AttachChilds_Anim(int iParentID,aiNode* piParent,
- AnimBoneList& bones,const aiNodeAnim** node_anims);
+ void AttachChilds_Anim(int iParentID, aiNode *piParent,
+ AnimBoneList &bones, const aiNodeAnim **node_anims);
/** Construct node hierarchy from a given MD5MESH
@@ -136,13 +127,13 @@ protected:
* @param piParent Parent node to attach to
- void AttachChilds_Mesh(int iParentID,aiNode* piParent,BoneList& bones);
+ void AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones);
/** Build unique vertex buffers from a given MD5ANIM
* @param meshSrc Input data
- void MakeDataUnique (MD5::MeshDesc& meshSrc);
+ void MakeDataUnique(MD5::MeshDesc &meshSrc);
/** Load the contents of a specific file into memory and
@@ -151,19 +142,18 @@ protected:
* mBuffer is modified to point to this buffer.
* @param pFile File stream to be read
- void LoadFileIntoMemory (IOStream* pFile);
- void UnloadFileFromMemory ();
+ void LoadFileIntoMemory(IOStream *pFile);
+ void UnloadFileFromMemory();
/** IOSystem to be used to access files */
- IOSystem* mIOHandler;
+ IOSystem *mIOHandler;
/** Path to the file, excluding the file extension but
with the dot */
std::string mFile;
/** Buffer to hold the loaded file */
- char* mBuffer;
+ char *mBuffer;
/** Size of the file */
@@ -172,10 +162,7 @@ protected:
unsigned int iLineNumber;
/** Scene to be filled */
- /** (Custom) I/O handler implementation */
- IOSystem* pIOHandler;
+ aiScene *pScene;
/** true if a MD5MESH file has already been parsed */
bool bHadMD5Mesh;
/** @file Implementation of the MDC importer class */
#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
@@ -51,11 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "MD3/MD3FileData.h"
#include "MDC/MDCNormalTable.h" // shouldn't be included by other units
@@ -76,12 +73,11 @@ static const aiImporterDesc desc = {
-void MDC::BuildVertex(const Frame& frame,
- const BaseVertex& bvert,
- const CompressedVertex& cvert,
- aiVector3D& vXYZOut,
- aiVector3D& vNorOut)
+void MDC::BuildVertex(const Frame &frame,
+ const BaseVertex &bvert,
+ const CompressedVertex &cvert,
+ aiVector3D &vXYZOut,
+ aiVector3D &vNorOut) {
// compute the position
const float xd = (cvert.xd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
const float yd = (cvert.yd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
@@ -98,66 +94,65 @@ void MDC::BuildVertex(const Frame& frame,
-MDCImporter::MDCImporter()
- : configFrameID(),
- pcHeader(),
- mBuffer(),
- fileSize()
+MDCImporter::MDCImporter() :
+ configFrameID(),
+ pcHeader(),
+ mBuffer(),
+ fileSize() {
-MDCImporter::~MDCImporter()
+MDCImporter::~MDCImporter() {
-bool MDCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
- if (extension == "mdc")
+ if (extension == "mdc") {
// if check for extension is not enough, check for the magic tokens
if (!extension.length() || checkSig) {
uint32_t tokens[1];
tokens[0] = AI_MDC_MAGIC_NUMBER_LE;
- return CheckMagicToken(pIOHandler,pFile,tokens,1);
+ return CheckMagicToken(pIOHandler, pFile, tokens, 1);
-const aiImporterDesc* MDCImporter::GetInfo () const
+const aiImporterDesc *MDCImporter::GetInfo() const {
// Validate the header of the given MDC file
-void MDCImporter::ValidateHeader()
- AI_SWAP4( this->pcHeader->ulVersion );
- AI_SWAP4( this->pcHeader->ulFlags );
- AI_SWAP4( this->pcHeader->ulNumFrames );
- AI_SWAP4( this->pcHeader->ulNumTags );
- AI_SWAP4( this->pcHeader->ulNumSurfaces );
- AI_SWAP4( this->pcHeader->ulNumSkins );
- AI_SWAP4( this->pcHeader->ulOffsetBorderFrames );
+void MDCImporter::ValidateHeader() {
+ AI_SWAP4(this->pcHeader->ulVersion);
+ AI_SWAP4(this->pcHeader->ulFlags);
+ AI_SWAP4(this->pcHeader->ulNumFrames);
+ AI_SWAP4(this->pcHeader->ulNumTags);
+ AI_SWAP4(this->pcHeader->ulNumSurfaces);
+ AI_SWAP4(this->pcHeader->ulNumSkins);
+ AI_SWAP4(this->pcHeader->ulOffsetBorderFrames);
if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
- pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE)
+ pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE) {
char szBuffer[5];
- szBuffer[0] = ((char*)&pcHeader->ulIdent)[0];
- szBuffer[1] = ((char*)&pcHeader->ulIdent)[1];
- szBuffer[2] = ((char*)&pcHeader->ulIdent)[2];
- szBuffer[3] = ((char*)&pcHeader->ulIdent)[3];
+ szBuffer[0] = ((char *)&pcHeader->ulIdent)[0];
+ szBuffer[1] = ((char *)&pcHeader->ulIdent)[1];
+ szBuffer[2] = ((char *)&pcHeader->ulIdent)[2];
+ szBuffer[3] = ((char *)&pcHeader->ulIdent)[3];
szBuffer[4] = '\0';
throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the "
- "magic word found is " + std::string( szBuffer ));
+ "magic word found is " +
+ std::string(szBuffer));
if (pcHeader->ulVersion != AI_MDC_VERSION) {
@@ -165,10 +160,9 @@ void MDCImporter::ValidateHeader()
if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize ||
- pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize)
+ pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize) {
throw DeadlyImportError("Some of the offset values in the MDC header are invalid "
- "and point to something behind the file.");
+ "and point to something behind the file.");
if (this->configFrameID >= this->pcHeader->ulNumFrames) {
@@ -178,8 +172,7 @@ void MDCImporter::ValidateHeader()
// Validate the header of a given MDC file surface
-void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf)
+void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface *pcSurf) {
AI_SWAP4(pcSurf->ulFlags);
AI_SWAP4(pcSurf->ulNumCompFrames);
AI_SWAP4(pcSurf->ulNumBaseFrames);
@@ -194,230 +187,216 @@ void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf)
AI_SWAP4(pcSurf->ulOffsetFrameCompFrames);
AI_SWAP4(pcSurf->ulOffsetEnd);
- const unsigned int iMax = this->fileSize - (unsigned int)((int8_t*)pcSurf-(int8_t*)pcHeader);
+ const unsigned int iMax = this->fileSize - (unsigned int)((int8_t *)pcSurf - (int8_t *)pcHeader);
- if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex) > iMax ||
- (pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex) > iMax) ||
- pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle) > iMax ||
- pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord) > iMax ||
- pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader) > iMax ||
- pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2 > iMax ||
- (pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2 > iMax))
+ if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex) > iMax ||
+ (pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex) > iMax) ||
+ pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle) > iMax ||
+ pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord) > iMax ||
+ pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader) > iMax ||
+ pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2 > iMax ||
+ (pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2 > iMax)) {
throw DeadlyImportError("Some of the offset values in the MDC surface header "
- "are invalid and point somewhere behind the file.");
+ "are invalid and point somewhere behind the file.");
-void MDCImporter::SetupProperties(const Importer* pImp)
+void MDCImporter::SetupProperties(const Importer *pImp) {
// The AI_CONFIG_IMPORT_MDC_KEYFRAME option overrides the
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
- if(static_cast<unsigned int>(-1) == (configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDC_KEYFRAME,-1))){
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+ if (static_cast<unsigned int>(-1) == (configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDC_KEYFRAME, -1))) {
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME, 0);
void MDCImporter::InternReadFile(
- const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+ const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
+ std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
- throw DeadlyImportError( "Failed to open MDC file " + pFile + ".");
+ if (file.get() == nullptr) {
+ throw DeadlyImportError("Failed to open MDC file " + pFile + ".");
// check whether the mdc file is large enough to contain the file header
- fileSize = (unsigned int)file->FileSize();
- if( fileSize < sizeof(MDC::Header))
- throw DeadlyImportError( "MDC File is too small.");
+ fileSize = static_cast<unsigned int>(file->FileSize());
+ if (fileSize < sizeof(MDC::Header)) {
+ throw DeadlyImportError("MDC File is too small.");
std::vector<unsigned char> mBuffer2(fileSize);
- file->Read( &mBuffer2[0], 1, fileSize);
+ file->Read(&mBuffer2[0], 1, fileSize);
mBuffer = &mBuffer2[0];
// validate the file header
- this->pcHeader = (BE_NCONST MDC::Header*)this->mBuffer;
+ this->pcHeader = (BE_NCONST MDC::Header *)this->mBuffer;
this->ValidateHeader();
std::vector<std::string> aszShaders;
// get a pointer to the frame we want to read
- BE_NCONST MDC::Frame* pcFrame = (BE_NCONST MDC::Frame*)(this->mBuffer+
- this->pcHeader->ulOffsetBorderFrames);
+ BE_NCONST MDC::Frame *pcFrame = (BE_NCONST MDC::Frame *)(this->mBuffer +
+ this->pcHeader->ulOffsetBorderFrames);
// no need to swap the other members, we won't need them
pcFrame += configFrameID;
- AI_SWAP4( pcFrame->localOrigin[0] );
- AI_SWAP4( pcFrame->localOrigin[1] );
- AI_SWAP4( pcFrame->localOrigin[2] );
+ AI_SWAP4(pcFrame->localOrigin[0]);
+ AI_SWAP4(pcFrame->localOrigin[1]);
+ AI_SWAP4(pcFrame->localOrigin[2]);
// get the number of valid surfaces
- BE_NCONST MDC::Surface* pcSurface, *pcSurface2;
+ BE_NCONST MDC::Surface *pcSurface, *pcSurface2;
pcSurface = pcSurface2 = new (mBuffer + pcHeader->ulOffsetSurfaces) MDC::Surface;
unsigned int iNumShaders = 0;
- for (unsigned int i = 0; i < pcHeader->ulNumSurfaces;++i)
+ for (unsigned int i = 0; i < pcHeader->ulNumSurfaces; ++i) {
// validate the surface header
this->ValidateSurfaceHeader(pcSurface2);
- if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles)++pScene->mNumMeshes;
+ if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles) {
+ ++pScene->mNumMeshes;
iNumShaders += pcSurface2->ulNumShaders;
- pcSurface2 = new ((int8_t*)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface;
+ pcSurface2 = new ((int8_t *)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface;
aszShaders.reserve(iNumShaders);
// necessary that we don't crash if an exception occurs
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
pScene->mMeshes[i] = NULL;
// now read all surfaces
unsigned int iDefaultMatIndex = UINT_MAX;
- for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces;++i)
- if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles)continue;
- aiMesh* pcMesh = pScene->mMeshes[iNum++] = new aiMesh();
+ for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces; ++i) {
+ if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles) continue;
+ aiMesh *pcMesh = pScene->mMeshes[iNum++] = new aiMesh();
pcMesh->mNumFaces = pcSurface->ulNumTriangles;
pcMesh->mNumVertices = pcMesh->mNumFaces * 3;
// store the name of the surface for use as node name.
- pcMesh->mName.Set(std::string(pcSurface->ucName
- , strnlen(pcSurface->ucName, AI_MDC_MAXQPATH - 1)));
+ pcMesh->mName.Set(std::string(pcSurface->ucName, strnlen(pcSurface->ucName, AI_MDC_MAXQPATH - 1)));
// go to the first shader in the file. ignore the others.
- if (pcSurface->ulNumShaders)
- const MDC::Shader* pcShader = (const MDC::Shader*)((int8_t*)pcSurface + pcSurface->ulOffsetShaders);
+ if (pcSurface->ulNumShaders) {
+ const MDC::Shader *pcShader = (const MDC::Shader *)((int8_t *)pcSurface + pcSurface->ulOffsetShaders);
pcMesh->mMaterialIndex = (unsigned int)aszShaders.size();
// create a new shader
- aszShaders.push_back(std::string( pcShader->ucName,
- ::strnlen(pcShader->ucName, sizeof(pcShader->ucName)) ));
+ aszShaders.push_back(std::string(pcShader->ucName,
+ ::strnlen(pcShader->ucName, sizeof(pcShader->ucName))));
// need to create a default material
- else if (UINT_MAX == iDefaultMatIndex)
+ else if (UINT_MAX == iDefaultMatIndex) {
pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size();
aszShaders.push_back(std::string());
// otherwise assign a reference to the default material
- else pcMesh->mMaterialIndex = iDefaultMatIndex;
+ pcMesh->mMaterialIndex = iDefaultMatIndex;
// allocate output storage for the mesh
- aiVector3D* pcVertCur = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- aiVector3D* pcNorCur = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
- aiVector3D* pcUVCur = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- aiFace* pcFaceCur = pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+ aiVector3D *pcVertCur = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ aiVector3D *pcNorCur = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+ aiVector3D *pcUVCur = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ aiFace *pcFaceCur = pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
// create all vertices/faces
- BE_NCONST MDC::Triangle* pcTriangle = (BE_NCONST MDC::Triangle*)
- ((int8_t*)pcSurface+pcSurface->ulOffsetTriangles);
+ BE_NCONST MDC::Triangle *pcTriangle = (BE_NCONST MDC::Triangle *)((int8_t *)pcSurface + pcSurface->ulOffsetTriangles);
- BE_NCONST MDC::TexturCoord* const pcUVs = (BE_NCONST MDC::TexturCoord*)
- ((int8_t*)pcSurface+pcSurface->ulOffsetTexCoords);
+ BE_NCONST MDC::TexturCoord *const pcUVs = (BE_NCONST MDC::TexturCoord *)((int8_t *)pcSurface + pcSurface->ulOffsetTexCoords);
// get a pointer to the uncompressed vertices
- int16_t iOfs = *((int16_t*) ((int8_t*) pcSurface +
- pcSurface->ulOffsetFrameBaseFrames) + this->configFrameID);
+ int16_t iOfs = *((int16_t *)((int8_t *)pcSurface +
+ pcSurface->ulOffsetFrameBaseFrames) +
+ this->configFrameID);
AI_SWAP2(iOfs);
- BE_NCONST MDC::BaseVertex* const pcVerts = (BE_NCONST MDC::BaseVertex*)
- ((int8_t*)pcSurface+pcSurface->ulOffsetBaseVerts) +
- ((int)iOfs * pcSurface->ulNumVertices * 4);
+ BE_NCONST MDC::BaseVertex *const pcVerts = (BE_NCONST MDC::BaseVertex *)((int8_t *)pcSurface + pcSurface->ulOffsetBaseVerts) +
+ ((int)iOfs * pcSurface->ulNumVertices * 4);
// do the main swapping stuff ...
#if (defined AI_BUILD_BIG_ENDIAN)
// swap all triangles
- for (unsigned int i = 0; i < pcSurface->ulNumTriangles;++i)
- AI_SWAP4( pcTriangle[i].aiIndices[0] );
- AI_SWAP4( pcTriangle[i].aiIndices[1] );
- AI_SWAP4( pcTriangle[i].aiIndices[2] );
+ for (unsigned int i = 0; i < pcSurface->ulNumTriangles; ++i) {
+ AI_SWAP4(pcTriangle[i].aiIndices[0]);
+ AI_SWAP4(pcTriangle[i].aiIndices[1]);
+ AI_SWAP4(pcTriangle[i].aiIndices[2]);
// swap all vertices
- for (unsigned int i = 0; i < pcSurface->ulNumVertices*pcSurface->ulNumBaseFrames;++i)
- AI_SWAP2( pcVerts->normal );
- AI_SWAP2( pcVerts->x );
- AI_SWAP2( pcVerts->y );
- AI_SWAP2( pcVerts->z );
+ for (unsigned int i = 0; i < pcSurface->ulNumVertices * pcSurface->ulNumBaseFrames; ++i) {
+ AI_SWAP2(pcVerts->normal);
+ AI_SWAP2(pcVerts->x);
+ AI_SWAP2(pcVerts->y);
+ AI_SWAP2(pcVerts->z);
// swap all texture coordinates
- for (unsigned int i = 0; i < pcSurface->ulNumVertices;++i)
- AI_SWAP4( pcUVs->u );
- AI_SWAP4( pcUVs->v );
+ for (unsigned int i = 0; i < pcSurface->ulNumVertices; ++i) {
+ AI_SWAP4(pcUVs->u);
+ AI_SWAP4(pcUVs->v);
- const MDC::CompressedVertex* pcCVerts = NULL;
- int16_t* mdcCompVert = NULL;
+ const MDC::CompressedVertex *pcCVerts = NULL;
+ int16_t *mdcCompVert = NULL;
// access compressed frames for large frame numbers, but never for the first
- if( this->configFrameID && pcSurface->ulNumCompFrames > 0 )
- mdcCompVert = (int16_t*) ((int8_t*)pcSurface+pcSurface->ulOffsetFrameCompFrames) + this->configFrameID;
+ if (this->configFrameID && pcSurface->ulNumCompFrames > 0) {
+ mdcCompVert = (int16_t *)((int8_t *)pcSurface + pcSurface->ulOffsetFrameCompFrames) + this->configFrameID;
AI_SWAP2P(mdcCompVert);
- if( *mdcCompVert >= 0 )
- pcCVerts = (const MDC::CompressedVertex*)((int8_t*)pcSurface +
- pcSurface->ulOffsetCompVerts) + *mdcCompVert * pcSurface->ulNumVertices;
- else mdcCompVert = NULL;
+ if (*mdcCompVert >= 0) {
+ pcCVerts = (const MDC::CompressedVertex *)((int8_t *)pcSurface +
+ pcSurface->ulOffsetCompVerts) +
+ *mdcCompVert * pcSurface->ulNumVertices;
+ mdcCompVert = NULL;
// copy all faces
- for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles;++iFace,
- ++pcTriangle,++pcFaceCur)
- const unsigned int iOutIndex = iFace*3;
+ for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles; ++iFace,
+ ++pcTriangle, ++pcFaceCur) {
+ const unsigned int iOutIndex = iFace * 3;
pcFaceCur->mNumIndices = 3;
pcFaceCur->mIndices = new unsigned int[3];
- for (unsigned int iIndex = 0; iIndex < 3;++iIndex,
- ++pcVertCur,++pcUVCur,++pcNorCur)
+ for (unsigned int iIndex = 0; iIndex < 3; ++iIndex,
+ ++pcVertCur, ++pcUVCur, ++pcNorCur) {
uint32_t quak = pcTriangle->aiIndices[iIndex];
- if (quak >= pcSurface->ulNumVertices)
+ if (quak >= pcSurface->ulNumVertices) {
ASSIMP_LOG_ERROR("MDC vertex index is out of range");
- quak = pcSurface->ulNumVertices-1;
+ quak = pcSurface->ulNumVertices - 1;
// compressed vertices?
- if (mdcCompVert)
- MDC::BuildVertex(*pcFrame,pcVerts[quak],pcCVerts[quak],
- *pcVertCur,*pcNorCur);
+ if (mdcCompVert) {
+ MDC::BuildVertex(*pcFrame, pcVerts[quak], pcCVerts[quak],
+ *pcVertCur, *pcNorCur);
// copy position
pcVertCur->x = pcVerts[quak].x * AI_MDC_BASE_SCALING;
pcVertCur->y = pcVerts[quak].y * AI_MDC_BASE_SCALING;
pcVertCur->z = pcVerts[quak].z * AI_MDC_BASE_SCALING;
// copy normals
- MD3::LatLngNormalToVec3( pcVerts[quak].normal, &pcNorCur->x );
+ MD3::LatLngNormalToVec3(pcVerts[quak].normal, &pcNorCur->x);
pcUVCur->x = pcUVs[quak].u;
- pcUVCur->y = ai_real( 1.0 )-pcUVs[quak].v; // DX to OGL
+ pcUVCur->y = ai_real(1.0) - pcUVs[quak].v; // DX to OGL
- pcVertCur->x += pcFrame->localOrigin[0] ;
- pcVertCur->y += pcFrame->localOrigin[1] ;
- pcVertCur->z += pcFrame->localOrigin[2] ;
+ pcVertCur->x += pcFrame->localOrigin[0];
+ pcVertCur->y += pcFrame->localOrigin[1];
+ pcVertCur->z += pcFrame->localOrigin[2];
// swap the face order - DX to OGL
@@ -426,31 +405,27 @@ void MDCImporter::InternReadFile(
pcFaceCur->mIndices[2] = iOutIndex + 0;
- pcSurface = new ((int8_t*)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface;
+ pcSurface = new ((int8_t *)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface;
// create a flat node graph with a root node and one child for each surface
if (!pScene->mNumMeshes)
- throw DeadlyImportError( "Invalid MDC file: File contains no valid mesh");
- else if (1 == pScene->mNumMeshes)
+ throw DeadlyImportError("Invalid MDC file: File contains no valid mesh");
+ else if (1 == pScene->mNumMeshes) {
- if ( nullptr != pScene->mMeshes[0] ) {
+ if (nullptr != pScene->mMeshes[0]) {
pScene->mRootNode->mName = pScene->mMeshes[0]->mName;
pScene->mRootNode->mNumMeshes = 1;
pScene->mRootNode->mMeshes = new unsigned int[1];
pScene->mRootNode->mMeshes[0] = 0;
pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
- pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
+ pScene->mRootNode->mChildren = new aiNode *[pScene->mNumMeshes];
pScene->mRootNode->mName.Set("<root>");
- aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
+ aiNode *pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
pcNode->mName = pScene->mMeshes[i]->mName;
pcNode->mNumMeshes = 1;
@@ -461,13 +436,12 @@ void MDCImporter::InternReadFile(
// create materials
pScene->mNumMaterials = (unsigned int)aszShaders.size();
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
- aiMaterial* pcMat = new aiMaterial();
+ pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
+ for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
+ aiMaterial *pcMat = new aiMaterial();
pScene->mMaterials[i] = pcMat;
- const std::string& name = aszShaders[i];
+ const std::string &name = aszShaders[i];
int iMode = (int)aiShadingMode_Gouraud;
pcMat->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
@@ -475,19 +449,20 @@ void MDCImporter::InternReadFile(
// add a small ambient color value - RtCW seems to have one
aiColor3D clr;
clr.b = clr.g = clr.r = 0.05f;
- pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+ pcMat->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
- if (name.length())clr.b = clr.g = clr.r = 1.0f;
- else clr.b = clr.g = clr.r = 0.6f;
+ if (name.length())
+ clr.b = clr.g = clr.r = 1.0f;
+ clr.b = clr.g = clr.r = 0.6f;
- pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+ pcMat->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
- if (name.length())
+ if (name.length()) {
aiString path;
path.Set(name);
- pcMat->AddProperty(&path,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ pcMat->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
@@ -68,6 +68,10 @@ namespace Assimp {
namespace MDL {
namespace HalfLife {
+# pragma warning(disable : 4706)
HL1MDLLoader::HL1MDLLoader(
aiScene *scene,
@@ -817,25 +821,25 @@ void HL1MDLLoader::read_meshes() {
mesh_faces.reserve(num_faces);
if (is_triangle_fan) {
- for (int i = 0; i < num_faces; ++i) {
+ for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) {
mesh_faces.push_back(HL1MeshFace{
tricmds[0],
- tricmds[i + 1],
- tricmds[i + 2] });
+ tricmds[faceIdx + 1],
+ tricmds[faceIdx + 2] });
if (i & 1) {
// Preserve winding order.
- tricmds[i],
+ tricmds[faceIdx],
@@ -1122,10 +1126,10 @@ void HL1MDLLoader::read_sequence_infos() {
aiNode *blend_controller_node = blend_controllers_node->mChildren[j] = new aiNode();
blend_controller_node->mParent = blend_controllers_node;
- aiMetadata *md = blend_controller_node->mMetaData = aiMetadata::Alloc(3);
- md->Set(0, "Start", pseqdesc->blendstart[j]);
- md->Set(1, "End", pseqdesc->blendend[j]);
- md->Set(2, "MotionFlags", pseqdesc->blendtype[j]);
+ aiMetadata *metaData = blend_controller_node->mMetaData = aiMetadata::Alloc(3);
+ metaData->Set(0, "Start", pseqdesc->blendstart[j]);
+ metaData->Set(1, "End", pseqdesc->blendend[j]);
+ metaData->Set(2, "MotionFlags", pseqdesc->blendtype[j]);
@@ -1151,10 +1155,10 @@ void HL1MDLLoader::read_sequence_infos() {
aiNode *pEvent = pEventsNode->mChildren[j] = new aiNode();
pEvent->mParent = pEventsNode;
- aiMetadata *md = pEvent->mMetaData = aiMetadata::Alloc(3);
- md->Set(0, "Frame", pevent->frame);
- md->Set(1, "ScriptEvent", pevent->event);
- md->Set(2, "Options", aiString(pevent->options));
+ aiMetadata *metaData = pEvent->mMetaData = aiMetadata::Alloc(3);
+ metaData->Set(0, "Frame", pevent->frame);
+ metaData->Set(1, "ScriptEvent", pevent->event);
+ metaData->Set(2, "Options", aiString(pevent->options));
@@ -56,27 +56,27 @@ namespace HalfLife {
/* A class to help map model triverts to mesh triverts. */
struct HL1MeshTrivert {
HL1MeshTrivert() :
- vertindex(-1),
- normindex(-1),
- s(0),
- t(0),
- localindex(-1) {
+ vertindex(-1),
+ normindex(-1),
+ s(0),
+ t(0),
+ localindex(-1) {
HL1MeshTrivert(short vertindex, short normindex, short s, short t, short localindex) :
- vertindex(vertindex),
- normindex(normindex),
- s(s),
- t(t),
- localindex() {
+ vertindex(vertindex),
+ normindex(normindex),
+ s(s),
+ t(t),
+ localindex(localindex) {
HL1MeshTrivert(const Trivert &a) :
- vertindex(a.vertindex),
- normindex(a.normindex),
- s(a.s),
- t(a.t),
+ vertindex(a.vertindex),
+ normindex(a.normindex),
+ s(a.s),
+ t(a.t),
inline bool operator==(const Trivert &a) const {
@@ -58,7 +57,6 @@ struct aiTexture;
using namespace MDL;
// --------------------------------------------------------------------------------------
@@ -436,7 +434,7 @@ protected:
unsigned int iGSFileVersion;
/** Output I/O handler. used to load external lmp files */
+ IOSystem* mIOHandler;
/** Output scene to be filled */
aiScene* pScene;
@@ -43,85 +41,77 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the material part of the MDL importer class */
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
-#include "MDLLoader.h"
#include "MDLDefaultColorMap.h"
+#include "MDLLoader.h"
+#include <assimp/Defines.h>
#include <assimp/texture.h>
-#include <assimp/Defines.h>
-static aiTexel* const bad_texel = reinterpret_cast<aiTexel*>(SIZE_MAX);
+static aiTexel *const bad_texel = reinterpret_cast<aiTexel *>(SIZE_MAX);
// Find a suitable palette file or take the default one
-void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
+void MDLImporter::SearchPalette(const unsigned char **pszColorMap) {
// now try to find the color map in the current directory
- IOStream* pcStream = pIOHandler->Open(configPalette,"rb");
+ IOStream *pcStream = mIOHandler->Open(configPalette, "rb");
- const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
- if(pcStream)
- if (pcStream->FileSize() >= 768)
+ const unsigned char *szColorMap = (const unsigned char *)::g_aclrDefaultColorMap;
+ if (pcStream) {
+ if (pcStream->FileSize() >= 768) {
size_t len = 256 * 3;
- unsigned char* colorMap = new unsigned char[len];
+ unsigned char *colorMap = new unsigned char[len];
szColorMap = colorMap;
- pcStream->Read(colorMap, len,1);
+ pcStream->Read(colorMap, len, 1);
ASSIMP_LOG_INFO("Found valid colormap.lmp in directory. "
- "It will be used to decode embedded textures in palletized formats.");
+ "It will be used to decode embedded textures in palletized formats.");
delete pcStream;
- pcStream = NULL;
+ pcStream = nullptr;
*pszColorMap = szColorMap;
// Free the palette again
-void MDLImporter::FreePalette(const unsigned char* szColorMap)
- if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap)
+void MDLImporter::FreePalette(const unsigned char *szColorMap) {
+ if (szColorMap != (const unsigned char *)::g_aclrDefaultColorMap) {
delete[] szColorMap;
// Check whether we can replace a texture with a single color
-aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture)
- ai_assert(NULL != pcTexture);
+aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture *pcTexture) {
+ ai_assert(nullptr != pcTexture);
aiColor4D clrOut;
clrOut.r = get_qnan();
if (!pcTexture->mHeight || !pcTexture->mWidth)
return clrOut;
- const unsigned int iNumPixels = pcTexture->mHeight*pcTexture->mWidth;
- const aiTexel* pcTexel = pcTexture->pcData+1;
- const aiTexel* const pcTexelEnd = &pcTexture->pcData[iNumPixels];
+ const unsigned int iNumPixels = pcTexture->mHeight * pcTexture->mWidth;
+ const aiTexel *pcTexel = pcTexture->pcData + 1;
+ const aiTexel *const pcTexelEnd = &pcTexture->pcData[iNumPixels];
- while (pcTexel != pcTexelEnd)
- if (*pcTexel != *(pcTexel-1))
- pcTexel = NULL;
+ while (pcTexel != pcTexelEnd) {
+ if (*pcTexel != *(pcTexel - 1)) {
+ pcTexel = nullptr;
++pcTexel;
- if (pcTexel)
+ if (pcTexel) {
clrOut.r = pcTexture->pcData->r / 255.0f;
clrOut.g = pcTexture->pcData->g / 255.0f;
clrOut.b = pcTexture->pcData->b / 255.0f;
@@ -132,28 +122,26 @@ aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture)
// Read a texture from a MDL3 file
-void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData)
- const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function
+void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char *szData) {
+ const MDL::Header *pcHeader = (const MDL::Header *)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function
VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth *
- pcHeader->skinheight);
+ pcHeader->skinheight);
// allocate a new texture object
- aiTexture* pcNew = new aiTexture();
+ aiTexture *pcNew = new aiTexture();
pcNew->mWidth = pcHeader->skinwidth;
pcNew->mHeight = pcHeader->skinheight;
pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
- const unsigned char* szColorMap;
+ const unsigned char *szColorMap;
this->SearchPalette(&szColorMap);
// copy texture data
- for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+ for (unsigned int i = 0; i < pcNew->mWidth * pcNew->mHeight; ++i) {
const unsigned char val = szData[i];
- const unsigned char* sz = &szColorMap[val*3];
+ const unsigned char *sz = &szColorMap[val * 3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].r = *sz++;
@@ -164,29 +152,26 @@ void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData)
FreePalette(szColorMap);
// store the texture
- aiTexture** pc = this->pScene->mTextures;
- this->pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
- for (unsigned int i = 0; i <pScene->mNumTextures;++i)
+ aiTexture **pc = this->pScene->mTextures;
+ this->pScene->mTextures = new aiTexture *[pScene->mNumTextures + 1];
+ for (unsigned int i = 0; i < pScene->mNumTextures; ++i)
pScene->mTextures[i] = pc[i];
pScene->mTextures[this->pScene->mNumTextures] = pcNew;
pScene->mNumTextures++;
delete[] pc;
// Read a texture from a MDL4 file
-void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip)
- ai_assert(NULL != piSkip);
+void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char *szData,
+ unsigned int iType,
+ unsigned int *piSkip) {
+ ai_assert(nullptr != piSkip);
- if (iType == 1 || iType > 3)
+ if (iType == 1 || iType > 3) {
ASSIMP_LOG_ERROR("Unsupported texture file format");
@@ -194,35 +179,30 @@ void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
const bool bNoRead = *piSkip == UINT_MAX;
- if (bNoRead)pcNew->pcData = bad_texel;
- ParseTextureColorData(szData,iType,piSkip,pcNew);
+ if (bNoRead) pcNew->pcData = bad_texel;
+ ParseTextureColorData(szData, iType, piSkip, pcNew);
- if (!bNoRead)
- if (!this->pScene->mNumTextures)
+ if (!bNoRead) {
+ if (!this->pScene->mNumTextures) {
pScene->mNumTextures = 1;
- pScene->mTextures = new aiTexture*[1];
+ pScene->mTextures = new aiTexture *[1];
pScene->mTextures[0] = pcNew;
- aiTexture** pc = pScene->mTextures;
- pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
- for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
+ aiTexture **pc = pScene->mTextures;
+ pScene->mTextures = new aiTexture *[pScene->mNumTextures + 1];
+ for (unsigned int i = 0; i < this->pScene->mNumTextures; ++i)
pScene->mTextures[pScene->mNumTextures] = pcNew;
- pcNew->pcData = NULL;
+ pcNew->pcData = nullptr;
delete pcNew;
@@ -230,11 +210,10 @@ void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
// Load color data of a texture and convert it to our output format
-void MDLImporter::ParseTextureColorData(const unsigned char* szData,
- unsigned int* piSkip,
- aiTexture* pcNew)
+void MDLImporter::ParseTextureColorData(const unsigned char *szData,
+ unsigned int *piSkip,
+ aiTexture *pcNew) {
const bool do_read = bad_texel != pcNew->pcData;
// allocate storage for the texture image
@@ -244,17 +223,14 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
// R5G6B5 format (with or without MIPs)
// ****************************************************************
- if (2 == iType || 10 == iType)
- VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*2);
+ if (2 == iType || 10 == iType) {
+ VALIDATE_FILE_SIZE(szData + pcNew->mWidth * pcNew->mHeight * 2);
unsigned int i;
- if (do_read)
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
+ if (do_read) {
+ for (i = 0; i < pcNew->mWidth * pcNew->mHeight; ++i) {
+ MDL::RGB565 val = ((MDL::RGB565 *)szData)[i];
AI_SWAP2(val);
@@ -262,30 +238,27 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
pcNew->pcData[i].g = (unsigned char)val.g << 2;
pcNew->pcData[i].b = (unsigned char)val.r << 3;
+ i = pcNew->mWidth * pcNew->mHeight;
- else i = pcNew->mWidth*pcNew->mHeight;
*piSkip = i * 2;
// apply MIP maps
- if (10 == iType)
+ if (10 == iType) {
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
VALIDATE_FILE_SIZE(szData + *piSkip);
// ARGB4 format (with or without MIPs)
- else if (3 == iType || 11 == iType)
- VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
+ else if (3 == iType || 11 == iType) {
+ VALIDATE_FILE_SIZE(szData + pcNew->mWidth * pcNew->mHeight * 4);
- MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
+ MDL::ARGB4 val = ((MDL::ARGB4 *)szData)[i];
pcNew->pcData[i].a = (unsigned char)val.a << 4;
@@ -293,95 +266,83 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
pcNew->pcData[i].g = (unsigned char)val.g << 4;
pcNew->pcData[i].b = (unsigned char)val.b << 4;
- if (11 == iType)
+ if (11 == iType) {
// RGB8 format (with or without MIPs)
- else if (4 == iType || 12 == iType)
- VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*3);
+ else if (4 == iType || 12 == iType) {
+ VALIDATE_FILE_SIZE(szData + pcNew->mWidth * pcNew->mHeight * 3);
- const unsigned char* _szData = &szData[i*3];
+ const unsigned char *_szData = &szData[i * 3];
pcNew->pcData[i].b = *_szData++;
pcNew->pcData[i].g = *_szData++;
pcNew->pcData[i].r = *_szData;
*piSkip = i * 3;
- if (12 == iType)
- *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3;
+ if (12 == iType) {
+ *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) * 3;
// ARGB8 format (with ir without MIPs)
- else if (5 == iType || 13 == iType)
+ else if (5 == iType || 13 == iType) {
- const unsigned char* _szData = &szData[i*4];
+ const unsigned char *_szData = &szData[i * 4];
pcNew->pcData[i].r = *_szData++;
pcNew->pcData[i].a = *_szData;
*piSkip = i << 2;
- if (13 == iType)
+ if (13 == iType) {
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 2;
// palletized 8 bit texture. As for Quake 1
- else if (0 == iType)
- VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight);
+ else if (0 == iType) {
+ VALIDATE_FILE_SIZE(szData + pcNew->mWidth * pcNew->mHeight);
SearchPalette(&szColorMap);
@@ -390,8 +351,8 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
this->FreePalette(szColorMap);
*piSkip = i;
// FIXME: Also support for MIP maps?
@@ -400,24 +361,23 @@ void MDLImporter::ParseTextureColorData(const unsigned char* szData,
// Get a texture from a MDL5 file
-void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
+void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData,
ai_assert(NULL != piSkip);
bool bNoRead = *piSkip == UINT_MAX;
- VALIDATE_FILE_SIZE(szData+8);
+ VALIDATE_FILE_SIZE(szData + 8);
// first read the size of the texture
- pcNew->mWidth = *((uint32_t*)szData);
+ pcNew->mWidth = *((uint32_t *)szData);
AI_SWAP4(pcNew->mWidth);
szData += sizeof(uint32_t);
- pcNew->mHeight = *((uint32_t*)szData);
+ pcNew->mHeight = *((uint32_t *)szData);
AI_SWAP4(pcNew->mHeight);
@@ -429,14 +389,12 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
// however, one can easily try out what MED does if you have
// a model with a DDS texture and export it to MDL5 ...
// yeah, it embedds the DDS file.
- if (6 == iType)
+ if (6 == iType) {
// this is a compressed texture in DDS format
*piSkip = pcNew->mWidth;
// place a hint and let the application know that this is a DDS file
pcNew->mHeight = 0;
pcNew->achFormatHint[0] = 'd';
@@ -444,39 +402,32 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
pcNew->achFormatHint[2] = 's';
pcNew->achFormatHint[3] = '\0';
- pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
- ::memcpy(pcNew->pcData,szData,pcNew->mWidth);
+ pcNew->pcData = (aiTexel *)new unsigned char[pcNew->mWidth];
+ ::memcpy(pcNew->pcData, szData, pcNew->mWidth);
// parse the color data of the texture
*piSkip += sizeof(uint32_t) * 2;
- for (unsigned int i = 0; i < pScene->mNumTextures;++i)
this->pScene->mTextures[i] = pc[i];
pcNew->pcData = NULL;
@@ -486,31 +437,26 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
// Get a skin from a MDL7 file - more complex than all other subformats
void MDLImporter::ParseSkinLump_3DGS_MDL7(
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut,
- aiMaterial* pcMatOut,
- unsigned int iWidth,
- unsigned int iHeight)
+ const unsigned char *szCurrent,
+ const unsigned char **szCurrentOut,
+ aiMaterial *pcMatOut,
+ unsigned int iWidth,
+ unsigned int iHeight) {
std::unique_ptr<aiTexture> pcNew;
// get the type of the skin
unsigned int iMasked = (unsigned int)(iType & 0xF);
- if (0x1 == iMasked)
+ if (0x1 == iMasked) {
// ***** REFERENCE TO ANOTHER SKIN INDEX *****
int referrer = (int)iWidth;
- pcMatOut->AddProperty<int>(&referrer,1,AI_MDL7_REFERRER_MATERIAL);
- else if (0x6 == iMasked)
+ pcMatOut->AddProperty<int>(&referrer, 1, AI_MDL7_REFERRER_MATERIAL);
+ } else if (0x6 == iMasked) {
// ***** EMBEDDED DDS FILE *****
- if (1 != iHeight)
+ if (1 != iHeight) {
ASSIMP_LOG_WARN("Found a reference to an embedded DDS texture, "
- "but texture height is not equal to 1, which is not supported by MED");
+ "but texture height is not equal to 1, which is not supported by MED");
pcNew.reset(new aiTexture());
@@ -523,57 +469,47 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
- memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
+ memcpy(pcNew->pcData, szCurrent, pcNew->mWidth);
szCurrent += iWidth;
- else if (0x7 == iMasked)
+ } else if (0x7 == iMasked) {
// ***** REFERENCE TO EXTERNAL FILE *****
ASSIMP_LOG_WARN("Found a reference to an external texture, "
aiString szFile;
- const size_t iLen = strlen((const char*)szCurrent);
- size_t iLen2 = iLen+1;
+ const size_t iLen = strlen((const char *)szCurrent);
+ size_t iLen2 = iLen + 1;
iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
- memcpy(szFile.data,(const char*)szCurrent,iLen2);
+ memcpy(szFile.data, (const char *)szCurrent, iLen2);
szFile.length = (ai_uint32)iLen;
szCurrent += iLen2;
// place this as diffuse texture
- pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
- else if (iMasked || !iType || (iType && iWidth && iHeight))
+ pcMatOut->AddProperty(&szFile, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ } else if (iMasked || !iType || (iType && iWidth && iHeight)) {
- if (!iHeight || !iWidth)
+ if (!iHeight || !iWidth) {
ASSIMP_LOG_WARN("Found embedded texture, but its width "
- "an height are both 0. Is this a joke?");
+ "an height are both 0. Is this a joke?");
// generate an empty chess pattern
pcNew->mWidth = pcNew->mHeight = 8;
pcNew->pcData = new aiTexel[64];
- for (unsigned int x = 0; x < 8;++x)
- for (unsigned int y = 0; y < 8;++y)
+ for (unsigned int x = 0; x < 8; ++x) {
+ for (unsigned int y = 0; y < 8; ++y) {
const bool bSet = ((0 == x % 2 && 0 != y % 2) ||
- (0 != x % 2 && 0 == y % 2));
+ (0 != x % 2 && 0 == y % 2));
- aiTexel* pc = &pcNew->pcData[y * 8 + x];
- pc->r = pc->b = pc->g = (bSet?0xFF:0);
+ aiTexel *pc = &pcNew->pcData[y * 8 + x];
+ pc->r = pc->b = pc->g = (bSet ? 0xFF : 0);
pc->a = 0xFF;
// it is a standard color texture. Fill in width and height
// and call the same function we used for loading MDL5 files
@@ -581,7 +517,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
pcNew->mHeight = iHeight;
unsigned int iSkip = 0;
- ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew.get());
+ ParseTextureColorData(szCurrent, iMasked, &iSkip, pcNew.get());
// skip length of texture data
szCurrent += iSkip;
@@ -592,25 +528,25 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
// texture instead of material colors ... posssible they have
// been converted to MDL7 from other formats, such as MDL5
aiColor4D clrTexture;
- if (pcNew)clrTexture = ReplaceTextureWithColor(pcNew.get());
- else clrTexture.r = get_qnan();
+ if (pcNew)
+ clrTexture = ReplaceTextureWithColor(pcNew.get());
+ clrTexture.r = get_qnan();
// check whether a material definition is contained in the skin
- if (iType & AI_MDL7_SKINTYPE_MATERIAL)
- BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent;
- szCurrent = (unsigned char*)(pcMatIn+1);
+ if (iType & AI_MDL7_SKINTYPE_MATERIAL) {
+ BE_NCONST MDL::Material_MDL7 *pcMatIn = (BE_NCONST MDL::Material_MDL7 *)szCurrent;
+ szCurrent = (unsigned char *)(pcMatIn + 1);
VALIDATE_FILE_SIZE(szCurrent);
aiColor3D clrTemp;
-#define COLOR_MULTIPLY_RGB() \
- if (is_not_qnan(clrTexture.r)) \
- { \
- clrTemp.r *= clrTexture.r; \
- clrTemp.g *= clrTexture.g; \
- clrTemp.b *= clrTexture.b; \
+#define COLOR_MULTIPLY_RGB() \
+ if (is_not_qnan(clrTexture.r)) { \
+ clrTemp.r *= clrTexture.r; \
+ clrTemp.g *= clrTexture.g; \
+ clrTemp.b *= clrTexture.b; \
// read diffuse color
clrTemp.r = pcMatIn->Diffuse.r;
@@ -620,7 +556,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
clrTemp.b = pcMatIn->Diffuse.b;
AI_SWAP4(clrTemp.b);
COLOR_MULTIPLY_RGB();
- pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE);
+ pcMatOut->AddProperty<aiColor3D>(&clrTemp, 1, AI_MATKEY_COLOR_DIFFUSE);
// read specular color
clrTemp.r = pcMatIn->Specular.r;
@@ -630,7 +566,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
clrTemp.b = pcMatIn->Specular.b;
- pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR);
+ pcMatOut->AddProperty<aiColor3D>(&clrTemp, 1, AI_MATKEY_COLOR_SPECULAR);
// read ambient color
clrTemp.r = pcMatIn->Ambient.r;
@@ -640,7 +576,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
clrTemp.b = pcMatIn->Ambient.b;
- pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT);
+ pcMatOut->AddProperty<aiColor3D>(&clrTemp, 1, AI_MATKEY_COLOR_AMBIENT);
// read emissive color
clrTemp.r = pcMatIn->Emissive.r;
@@ -649,7 +585,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
AI_SWAP4(clrTemp.g);
clrTemp.b = pcMatIn->Emissive.b;
- pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE);
+ pcMatOut->AddProperty<aiColor3D>(&clrTemp, 1, AI_MATKEY_COLOR_EMISSIVE);
#undef COLOR_MULITPLY_RGB
@@ -661,38 +597,33 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
if (is_not_qnan(clrTexture.r)) {
clrTemp.r *= clrTexture.a;
- pcMatOut->AddProperty<ai_real>(&clrTemp.r,1,AI_MATKEY_OPACITY);
+ pcMatOut->AddProperty<ai_real>(&clrTemp.r, 1, AI_MATKEY_OPACITY);
// read phong power
int iShadingMode = (int)aiShadingMode_Gouraud;
AI_SWAP4(pcMatIn->Power);
- if (0.0f != pcMatIn->Power)
+ if (0.0f != pcMatIn->Power) {
iShadingMode = (int)aiShadingMode_Phong;
// pcMatIn is packed, we can't form pointers to its members
float power = pcMatIn->Power;
- pcMatOut->AddProperty<float>(&power,1,AI_MATKEY_SHININESS);
+ pcMatOut->AddProperty<float>(&power, 1, AI_MATKEY_SHININESS);
- pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
- else if (is_not_qnan(clrTexture.r))
- pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_DIFFUSE);
- pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_SPECULAR);
+ pcMatOut->AddProperty<int>(&iShadingMode, 1, AI_MATKEY_SHADING_MODEL);
+ } else if (is_not_qnan(clrTexture.r)) {
+ pcMatOut->AddProperty<aiColor4D>(&clrTexture, 1, AI_MATKEY_COLOR_DIFFUSE);
+ pcMatOut->AddProperty<aiColor4D>(&clrTexture, 1, AI_MATKEY_COLOR_SPECULAR);
// if the texture could be replaced by a single material color
// we don't need the texture anymore
- if (is_not_qnan(clrTexture.r))
+ if (is_not_qnan(clrTexture.r)) {
pcNew.reset();
// If an ASCII effect description (HLSL?) is contained in the file,
// we can simply ignore it ...
- if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
+ if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) {
- int32_t iMe = *((int32_t*)szCurrent);
+ int32_t iMe = *((int32_t *)szCurrent);
AI_SWAP4(iMe);
szCurrent += sizeof(char) * iMe + sizeof(int32_t);
@@ -700,32 +631,27 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
// If an embedded texture has been loaded setup the corresponding
// data structures in the aiScene instance
- if (pcNew && pScene->mNumTextures <= 999)
+ if (pcNew && pScene->mNumTextures <= 999) {
- char szCurrent[5];
- ai_snprintf(szCurrent,5,"*%i",this->pScene->mNumTextures);
+ char current[5];
+ ai_snprintf(current, 5, "*%i", this->pScene->mNumTextures);
- ::memcpy(szFile.data,(const char*)szCurrent,iLen+1);
+ const size_t iLen = strlen((const char *)current);
+ ::memcpy(szFile.data, (const char *)current, iLen + 1);
- if (!pScene->mNumTextures)
+ if (!pScene->mNumTextures) {
pScene->mTextures[0] = pcNew.release();
- for (unsigned int i = 0; i < pScene->mNumTextures;++i) {
+ for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {
@@ -741,28 +667,22 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
// Skip a skin lump
void MDLImporter::SkipSkinLump_3DGS_MDL7(
const unsigned int iMasked = (unsigned int)(iType & 0xF);
- if (0x6 == iMasked)
+ if (0x6 == iMasked) {
- if (0x7 == iMasked)
- const size_t iLen = ::strlen((const char*)szCurrent);
- szCurrent += iLen+1;
- else if (iMasked || !iType)
- if (iMasked || !iType || (iType && iWidth && iHeight))
+ if (0x7 == iMasked) {
+ const size_t iLen = std::strlen((const char *)szCurrent);
+ szCurrent += iLen + 1;
+ } else if (iMasked || !iType) {
+ if (iMasked || !iType || (iType && iWidth && iHeight)) {
// ParseTextureColorData(..., aiTexture::pcData == bad_texel) will simply
// return the size of the color data in bytes in iSkip
@@ -771,10 +691,10 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
tex.pcData = bad_texel;
tex.mHeight = iHeight;
tex.mWidth = iWidth;
- ParseTextureColorData(szCurrent,iMasked,&iSkip,&tex);
+ ParseTextureColorData(szCurrent, iMasked, &iSkip, &tex);
// FIX: Important, otherwise the destructor will crash
- tex.pcData = NULL;
+ tex.pcData = nullptr;
@@ -782,17 +702,15 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
// if an ASCII effect description (HLSL?) is contained in the file,
@@ -801,39 +719,37 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
- std::vector<aiMaterial*>& pcMats)
- ai_assert(NULL != szCurrent);
- ai_assert(NULL != szCurrentOut);
+ std::vector<aiMaterial *> &pcMats) {
+ ai_assert(nullptr != szCurrent);
+ ai_assert(nullptr != szCurrentOut);
*szCurrentOut = szCurrent;
- BE_NCONST MDL::Skin_MDL7* pcSkin = (BE_NCONST MDL::Skin_MDL7*)szCurrent;
+ BE_NCONST MDL::Skin_MDL7 *pcSkin = (BE_NCONST MDL::Skin_MDL7 *)szCurrent;
AI_SWAP4(pcSkin->width);
AI_SWAP4(pcSkin->height);
szCurrent += 12;
// allocate an output material
- aiMaterial* pcMatOut = new aiMaterial();
+ aiMaterial *pcMatOut = new aiMaterial();
pcMats.push_back(pcMatOut);
// skip length of file name
szCurrent += AI_MDL7_MAX_TEXNAMESIZE;
- ParseSkinLump_3DGS_MDL7(szCurrent,szCurrentOut,pcMatOut,
- pcSkin->typ,pcSkin->width,pcSkin->height);
+ ParseSkinLump_3DGS_MDL7(szCurrent, szCurrentOut, pcMatOut,
+ pcSkin->typ, pcSkin->width, pcSkin->height);
// place the name of the skin in the material
- if (pcSkin->texture_name[0])
+ if (pcSkin->texture_name[0]) {
// the 0 termination could be there or not - we can't know
- ::memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
+ ::memcpy(szFile.data, pcSkin->texture_name, sizeof(pcSkin->texture_name));
szFile.data[sizeof(pcSkin->texture_name)] = '\0';
szFile.length = (ai_uint32)::strlen(szFile.data);
- pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
+ pcMatOut->AddProperty(&szFile, AI_MATKEY_NAME);
@@ -199,9 +199,9 @@ namespace vmd
stream->write((char*)&ik_count, sizeof(int));
for (int i = 0; i < ik_count; i++)
- const VmdIkEnable& ik_enable = this->ik_enable.at(i);
- stream->write(ik_enable.ik_name.c_str(), 20);
- stream->write((char*)&ik_enable.enable, sizeof(uint8_t));
+ const VmdIkEnable& ik_enable_ref = this->ik_enable.at(i);
+ stream->write(ik_enable_ref.ik_name.c_str(), 20);
+ stream->write((char *)&ik_enable_ref.enable, sizeof(uint8_t));
@@ -261,19 +261,19 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
TempTriangle& t = triangles[i];
stream.IncPtr(2);
- for (unsigned int i = 0; i < 3; ++i) {
- t.indices[i] = stream.GetI2();
+ for (unsigned int j = 0; j < 3; ++j) {
+ t.indices[j] = stream.GetI2();
- ReadVector(stream,t.normals[i]);
+ ReadVector(stream,t.normals[j]);
- stream >> (float&)(t.uv[i].x); // see note in ReadColor()
+ stream >> (float&)(t.uv[j].x); // see note in ReadColor()
- stream >> (float&)(t.uv[i].y);
+ stream >> (float&)(t.uv[j].y);
t.sg = stream.GetI1();
@@ -296,8 +296,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
stream >> num;
t.triangles.resize(num);
- for (unsigned int i = 0; i < num; ++i) {
- t.triangles[i] = stream.GetI2();
+ for (unsigned int j = 0; j < num; ++j) {
+ t.triangles[j] = stream.GetI2();
t.mat = stream.GetI1();
if (t.mat == UINT_MAX) {
@@ -309,8 +309,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
stream >> mat;
std::vector<TempMaterial> materials(mat);
- for (unsigned int i = 0;i < mat; ++i) {
- TempMaterial& t = materials[i];
+ for (unsigned int j = 0;j < mat; ++j) {
+ TempMaterial& t = materials[j];
stream.CopyAndAdvance(t.name,32);
t.name[32] = '\0';
@@ -338,8 +338,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
stream >> joint;
std::vector<TempJoint> joints(joint);
- for(unsigned int i = 0; i < joint; ++i) {
- TempJoint& j = joints[i];
+ for(unsigned int ii = 0; ii < joint; ++ii) {
+ TempJoint& j = joints[ii];
stream.IncPtr(1);
stream.CopyAndAdvance(j.name,32);
@@ -494,17 +494,17 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
typedef std::map<unsigned int,unsigned int> BoneSet;
BoneSet mybones;
- for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) {
- aiFace& f = m->mFaces[i];
- if (g.triangles[i]>triangles.size()) {
+ for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) {
+ aiFace& f = m->mFaces[j];
+ if (g.triangles[j]>triangles.size()) {
throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
TempTriangle& t = triangles[g.triangles[i]];
f.mIndices = new unsigned int[f.mNumIndices=3];
- for (unsigned int i = 0; i < 3; ++i,++n) {
- if (t.indices[i]>vertices.size()) {
+ for (unsigned int k = 0; k < 3; ++k,++n) {
+ if (t.indices[k]>vertices.size()) {
throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
@@ -545,11 +545,11 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
// .. and collect bone weights
- TempTriangle& t = triangles[g.triangles[i]];
+ TempTriangle& t = triangles[g.triangles[j]];
- const TempVertex& v = vertices[t.indices[i]];
+ const TempVertex& v = vertices[t.indices[k]];
for(unsigned int a = 0; a < 4; ++a) {
const unsigned int bone = v.bone_id[a];
if(bone==UINT_MAX){
@@ -332,8 +332,7 @@ unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat,
aiMaterialProperty* prop = pMat->mProperties[i];
if ( prop /* just a sanity check ... */
- && 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE )
- && prop->mSemantic == type) {
+ && 0 == strcmp(prop->mKey.data, _AI_MATKEY_TEXTURE_BASE) && static_cast < aiTextureType>(prop->mSemantic) == type) {
max = std::max(max,prop->mIndex+1);
@@ -504,7 +503,7 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
pcNew->mData = new char[pSizeInBytes];
memcpy (pcNew->mData,pInput,pSizeInBytes);
- pcNew->mKey.length = (ai_uint32)::strlen(pKey);
+ pcNew->mKey.length = static_cast<ai_uint32>( ::strlen(pKey) );
ai_assert ( MAXLEN > pcNew->mKey.length);
strcpy( pcNew->mKey.data, pKey );
@@ -562,7 +561,8 @@ uint32_t Assimp::ComputeMaterialHash(const aiMaterial* mat, bool includeMatName
// Exclude all properties whose first character is '?' from the hash
// See doc for aiMaterialProperty.
- if ((prop = mat->mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?')) {
+ prop = mat->mProperties[ i ];
+ if ( nullptr != prop && (includeMatName || prop->mKey.data[0] != '?')) {
hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash);
hash = SuperFastHash(prop->mData,prop->mDataLength,hash);
@@ -185,8 +185,8 @@ private:
// for spheres, cones and cylinders: center point of the object
aiVector3D center, radius, dir;
- char name[128];
+ static const size_t MaxNameLen = 128;
+ char name[MaxNameLen];
std::vector<aiVector3D> vertices, normals, uvs;
std::vector<unsigned int> faces;