Merge pull request #1 from assimp/master

Update
pull/493/head
Madrich 2014-12-29 16:01:18 +01:00
commit 45988cd238
440 changed files with 11222 additions and 94797 deletions

19
.gitignore vendored
View File

@ -32,3 +32,22 @@ test/results
# Python
__pycache__
*.log
*.vcxproj
*.filters
*.tlog
Assimp.sdf
test/gtest/tmp/gtest-gitupdate.cmake
test/gtest/tmp/gtest-gitclone.cmake
test/gtest/tmp/gtest-cfgcmd.txt.in
test/gtest/tmp/gtest-cfgcmd.txt
test/gtest/src/gtest-stamp/gtest-download.cmake
test/gtest/src/gtest-stamp/gtest-configure.cmake
test/gtest/src/gtest-stamp/gtest-build.cmake
test/gtest/src/gtest-stamp/Debug/gtest-patch
*.cache
test/gtest/src/gtest-stamp/Debug/gtest-build
*.suo
*.lib
test/gtest/src/gtest-stamp/Debug/
tools/assimp_view/assimp_viewer.vcxproj.user

View File

@ -1,11 +1,16 @@
before_install:
- sudo apt-get install cmake
- sudo apt-get install cmake python3
env:
- TRAVIS_NO_EXPORT=YES
- TRAVIS_NO_EXPORT=NO
- TRAVIS_STATIC_BUILD=ON
- TRAVIS_STATIC_BUILD=OFF
matrix:
- LINUX=1 TRAVIS_NO_EXPORT=YES
- LINUX=1 TRAVIS_NO_EXPORT=NO
- LINUX=1 TRAVIS_STATIC_BUILD=ON
- LINUX=1 TRAVIS_STATIC_BUILD=OFF
- WINDOWS=1 TRAVIS_NO_EXPORT=YES
- WINDOWS=1 TRAVIS_NO_EXPORT=NO
- WINDOWS=1 TRAVIS_STATIC_BUILD=ON
- WINDOWS=1 TRAVIS_STATIC_BUILD=OFF
language: cpp
@ -13,7 +18,20 @@ compiler:
- gcc
- clang
script: cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD && make
install:
- if [ $WINDOWS ]; then travis_retry sudo apt-get install -q -y gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64; fi
script:
- cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD
- make
- sudo make install
- sudo ldconfig
- cd test/unit
- ../../bin/unit
- cd ../regression
- chmod 755 run.py
- ./run.py
- echo "=========================================================="
- echo "REGRESSION TEST FAILS (results/run_regression_suite_failures.csv)"
- cat ../results/run_regression_suite_failures.csv

23
CHANGES
View File

@ -2,6 +2,29 @@
CHANGELOG
----------------------------------------------------------------------
3.1.1 (2014-06-15)
FEATURES:
- Support for FBX 2013 and newer, binary and ASCII (this is partly
work from Google Summer of Code 2012)
- Support for OGRE binary mesh and skeleton format
- Updated BLEND support for newer Blender versions
- Support for arbitrary meta data, used to hold FBX and DAE metadata
- OBJ Export now produces smaller files
- Meshes can now have names, this is supported by the major importers
- Improved IFC geometry generation
- M3 support has been removed
FIXES/HOUSEKEEPING:
- Hundreds of bugfixes in all parts of the library
- CMake is now the primary build system
API COMPATIBILITY:
- 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData
and aiMesh::mName
- Export interface has been cleaned up and unified
- Other than that no relevant changes
3.0 (2012-07-07)

View File

@ -3,7 +3,7 @@ PROJECT( Assimp )
# Define here the needed parameters
set (ASSIMP_VERSION_MAJOR 3)
set (ASSIMP_VERSION_MINOR 0)
set (ASSIMP_VERSION_MINOR 1)
set (ASSIMP_VERSION_PATCH 1) # subversion revision?
set (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
set (ASSIMP_SOVERSION 3)
@ -32,11 +32,11 @@ if(NOT GIT_COMMIT_HASH)
endif(NOT GIT_COMMIT_HASH)
configure_file(
${CMAKE_SOURCE_DIR}/revision.h.in
${CMAKE_BINARY_DIR}/revision.h
${CMAKE_CURRENT_SOURCE_DIR}/revision.h.in
${CMAKE_CURRENT_BINARY_DIR}/revision.h
)
include_directories(${CMAKE_BINARY_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
option(ASSIMP_OPT_BUILD_PACKAGES "Set to ON to generate CPack configuration files and packaging targets" OFF)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
@ -45,6 +45,8 @@ 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")
option(ASSIMP_ANDROID_JNIIOSYSTEM "Android JNI IOSystem support is active" OFF)
if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW)
add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it....
# hide all not-exported symbols
@ -52,7 +54,7 @@ if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_
elseif(MSVC)
# enable multi-core compilation with MSVC
add_definitions(/MP)
endif()
endif()
INCLUDE (FindPkgConfig)
INCLUDE_DIRECTORIES( include )
@ -79,13 +81,9 @@ SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
SET(ASSIMP_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools")
# Allow the user to build a static library
# Allow the user to build a shared or static library
option ( BUILD_SHARED_LIBS "Build a shared version of the library" ON )
# Generate a pkg-config .pc for the Assimp library.
CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
# Only generate this target if no higher-level project already has
IF (NOT TARGET uninstall)
# add make uninstall capability
@ -95,8 +93,9 @@ ENDIF()
# Globally enable Boost resp. the Boost workaround – it is also needed by the
# tools which include the Assimp headers.
SET ( ASSIMP_ENABLE_BOOST_WORKAROUND ON CACHE BOOL
option ( ASSIMP_ENABLE_BOOST_WORKAROUND
"If a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available."
ON
)
IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
INCLUDE_DIRECTORIES( code/BoostWorkaround )
@ -104,7 +103,7 @@ IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
MESSAGE( STATUS "Building a non-boost version of Assimp." )
ELSE ( ASSIMP_ENABLE_BOOST_WORKAROUND )
SET( Boost_DETAILED_FAILURE_MSG ON )
SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52.0" "1.53.0" "1.54.0")
SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52.0" "1.53.0" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" "1.57" "1.57.0" )
FIND_PACKAGE( Boost )
IF ( NOT Boost_FOUND )
MESSAGE( FATAL_ERROR
@ -122,10 +121,15 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${C
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
SET ( ASSIMP_NO_EXPORT OFF CACHE BOOL
option ( ASSIMP_NO_EXPORT
"Disable Assimp's export functionality."
OFF
)
if( CMAKE_COMPILER_IS_GNUCXX )
set(LIBSTDC++_LIBRARIES -lstdc++)
endif( CMAKE_COMPILER_IS_GNUCXX )
# Search for external dependencies, and build them from source if not found
# Search for zlib
find_package(ZLIB)
@ -141,6 +145,7 @@ if( NOT ZLIB_FOUND )
set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
else(NOT ZLIB_FOUND)
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
set(ZLIB_LIBRARIES_LINKED -lz)
endif(NOT ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
@ -154,11 +159,6 @@ IF ( ASSIMP_NO_EXPORT )
MESSAGE( STATUS "Build an import-only version of Assimp." )
ENDIF( ASSIMP_NO_EXPORT )
# if(CMAKE_CL_64)
# set(ASSIMP_BUILD_ARCHITECTURE "amd64")
# else(CMAKE_CL_64)
# set(ASSIMP_BUILD_ARCHITECTURE "x86")
# endif(CMAKE_CL_64)
SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING
"describe the current architecture."
)
@ -179,8 +179,9 @@ ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
ADD_SUBDIRECTORY( code/ )
SET ( ASSIMP_BUILD_ASSIMP_TOOLS ON CACHE BOOL
option ( ASSIMP_BUILD_ASSIMP_TOOLS
"If the supplementary tools for Assimp are built in addition to the library."
ON
)
IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
IF ( WIN32 )
@ -189,8 +190,9 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
ADD_SUBDIRECTORY( tools/assimp_cmd/ )
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
SET ( ASSIMP_BUILD_SAMPLES OFF CACHE BOOL
option ( ASSIMP_BUILD_SAMPLES
"If the official samples are built as well (needs Glut)."
OFF
)
IF ( ASSIMP_BUILD_SAMPLES)
@ -200,22 +202,26 @@ IF ( ASSIMP_BUILD_SAMPLES)
ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
ENDIF ( ASSIMP_BUILD_SAMPLES )
IF ( WIN32 )
SET ( ASSIMP_BUILD_TESTS ON CACHE BOOL
option ( ASSIMP_BUILD_TESTS
"If the test suite for Assimp is built in addition to the library."
)
ON
)
IF ( ASSIMP_BUILD_TESTS )
IF ( ASSIMP_BUILD_TESTS )
ADD_SUBDIRECTORY( test/ )
ENDIF ( ASSIMP_BUILD_TESTS )
ENDIF ( WIN32 )
ENDIF ( ASSIMP_BUILD_TESTS )
IF(MSVC)
SET ( ASSIMP_INSTALL_PDB ON CACHE BOOL
option ( ASSIMP_INSTALL_PDB
"Install MSVC debug files."
ON
)
ENDIF(MSVC)
# Generate a pkg-config .pc for the Assimp library.
CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
if(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
# Packing information
set(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}")
@ -228,7 +234,6 @@ if(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
set(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
#set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
string(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER")

View File

@ -148,3 +148,6 @@ Bugfixes for uv-tanget calculation.
- Jonne Nauha
Ogre Binary format support
- Filip Wasil, Tieto Poland Sp. z o.o.
Android JNI asset extraction support

View File

@ -1,10 +1,12 @@
Open Asset Import Library (assimp)
========
Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __30 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials_ and many more.
Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __40 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials_ and many more.
This is the development trunk of assimp containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories. According to [Travis-CI] (https://travis-ci.org/), the current build status of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
[open3mod](https://github.com/acgessler/open3mod) is an Open Source 3D model viewer based off Assimp's import and export abilities.
#### Supported file formats ####
The library provides importers for a lot of file formats, including:
@ -44,6 +46,7 @@ The library provides importers for a lot of file formats, including:
- Ogre Binary
- Ogre XML
- Q3D
- ASSBIN (Assimp scene serialization)
Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries.
@ -55,7 +58,10 @@ Exporters include:
- STL
- OBJ
- PLY
- X
- 3DS
- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
- ASSBIN
See [the full list here](http://assimp.sourceforge.net/main_features_formats.html).
@ -77,7 +83,7 @@ C++ish interface). The directory structure is:
/scripts Scripts used to generate the loading code for some formats
/port Ports to other languages and scripts to maintain those.
/test Unit- and regression tests, test suite of models
/tools Tools (viewer, command line `assimp`)
/tools Tools (old assimp viewer, command line `assimp`)
/samples A small number of samples to illustrate possible
use cases for Assimp
/workspaces Build enviroments for vc,xcode,... (deprecated,

View File

@ -44,20 +44,20 @@ if (CMAKE_BUILD_TYPE EQUAL "DEBUG")
set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}D)
endif (CMAKE_BUILD_TYPE EQUAL "DEBUG")
# search for the boost version assimp was compiled with
#set(Boost_USE_MULTITHREAD ON)
#set(Boost_USE_STATIC_LIBS OFF)
#set(Boost_USE_STATIC_RUNTIME OFF)
#find_package(Boost ${ASSIMP_Boost_VERSION} EXACT COMPONENTS thread date_time)
#if(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# set( ASSIMP_INCLUDE_DIRS "${ASSIMP_INCLUDE_DIRS}" ${Boost_INCLUDE_DIRS})
#else(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# message(WARNING "Failed to find Boost ${ASSIMP_Boost_VERSION} necessary for assimp")
#endif(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# the boost version assimp was compiled with
set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@")
# search for the boost version assimp was compiled with
set(Boost_USE_MULTITHREAD ON)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost ${ASSIMP_Boost_VERSION} EXACT COMPONENTS thread date_time)
if(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
set( ASSIMP_INCLUDE_DIRS "${ASSIMP_INCLUDE_DIRS}" ${Boost_INCLUDE_DIRS})
else(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
message(WARNING "Failed to find Boost ${ASSIMP_Boost_VERSION} necessary for assimp")
endif(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# for compatibility wiht pkg-config
set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}")

View File

@ -7,4 +7,5 @@ Name: @CMAKE_PROJECT_NAME@
Description: Import various well-known 3D model formats in an uniform manner.
Version: @PROJECT_VERSION@
Libs: -L${libdir} -lassimp@ASSIMP_LIBRARY_SUFFIX@
Libs.private: @LIBSTDC++_LIBRARIES@ @ZLIB_LIBRARIES_LINKED@
Cflags: -I${includedir}

View File

@ -0,0 +1,64 @@
find_package(Threads REQUIRED)
include(ExternalProject)
if(MSYS OR MINGW)
set(DISABLE_PTHREADS ON)
else()
set(DISABLE_PTHREADS OFF)
endif()
if (MSVC)
set(RELEASE_LIB_DIR ReleaseLibs)
set(DEBUG_LIB_DIR DebugLibs)
else()
set(RELEASE_LIB_DIR "")
set(DEBUG_LIB_DIR "")
endif()
set(GTEST_CMAKE_ARGS
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-Dgtest_force_shared_crt=ON"
"-Dgtest_disable_pthreads:BOOL=${DISABLE_PTHREADS}")
set(GTEST_RELEASE_LIB_DIR "")
set(GTEST_DEBUGLIB_DIR "")
if (MSVC)
set(GTEST_CMAKE_ARGS ${GTEST_CMAKE_ARGS}
"-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG:PATH=${DEBUG_LIB_DIR}"
"-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=${RELEASE_LIB_DIR}")
set(GTEST_LIB_DIR)
endif()
set(GTEST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/gtest")
ExternalProject_Add(gtest
GIT_REPOSITORY https://chromium.googlesource.com/external/googletest
TIMEOUT 10
PREFIX "${GTEST_PREFIX}"
CMAKE_ARGS "${GTEST_CMAKE_ARGS}"
LOG_DOWNLOAD ON
LOG_CONFIGURE ON
LOG_BUILD ON
# Disable install
INSTALL_COMMAND ""
)
set(LIB_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}")
set(LIB_SUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(GTEST_LOCATION "${GTEST_PREFIX}/src/gtest-build")
set(GTEST_DEBUG_LIBRARIES
"${GTEST_LOCATION}/${DEBUG_LIB_DIR}/${LIB_PREFIX}gtest${LIB_SUFFIX}"
"${CMAKE_THREAD_LIBS_INIT}")
SET(GTEST_RELEASE_LIBRARIES
"${GTEST_LOCATION}/${RELEASE_LIB_DIR}/${LIB_PREFIX}gtest${LIB_SUFFIX}"
"${CMAKE_THREAD_LIBS_INIT}")
if(MSVC_VERSION EQUAL 1700)
add_definitions(-D_VARIADIC_MAX=10)
endif()
ExternalProject_Get_Property(gtest source_dir)
include_directories(${source_dir}/include)
include_directories(${source_dir}/gtest/include)
ExternalProject_Get_Property(gtest binary_dir)
link_directories(${binary_dir})

View File

@ -0,0 +1,560 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
#include "3DSExporter.h"
#include "3DSLoader.h"
#include "SceneCombiner.h"
#include "SplitLargeMeshes.h"
using namespace Assimp;
namespace Assimp {
namespace {
//////////////////////////////////////////////////////////////////////////////////////
// Scope utility to write a 3DS file chunk.
//
// Upon construction, the chunk header is written with the chunk type (flags)
// filled out, but the chunk size left empty. Upon destruction, the correct chunk
// size based on the then-position of the output stream cursor is filled in.
class ChunkWriter {
enum {
CHUNK_SIZE_NOT_SET = 0xdeadbeef
, SIZE_OFFSET = 2
};
public:
ChunkWriter(StreamWriterLE& writer, uint16_t chunk_type)
: writer(writer)
{
chunk_start_pos = writer.GetCurrentPos();
writer.PutU2(chunk_type);
writer.PutU4(CHUNK_SIZE_NOT_SET);
}
~ChunkWriter() {
std::size_t head_pos = writer.GetCurrentPos();
ai_assert(head_pos > chunk_start_pos);
const std::size_t chunk_size = head_pos - chunk_start_pos;
writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
writer.PutU4(chunk_size);
writer.SetCurrentPos(head_pos);
}
private:
StreamWriterLE& writer;
std::size_t chunk_start_pos;
};
// Return an unique name for a given |mesh| attached to |node| that
// preserves the mesh's given name if it has one. |index| is the index
// of the mesh in |aiScene::mMeshes|.
std::string GetMeshName(const aiMesh& mesh, unsigned int index, const aiNode& node) {
static const std::string underscore = "_";
char postfix[10] = {0};
ASSIMP_itoa10(postfix, index);
std::string result = node.mName.C_Str();
if (mesh.mName.length > 0) {
result += underscore + mesh.mName.C_Str();
}
return result + underscore + postfix;
}
// Return an unique name for a given |mat| with original position |index|
// in |aiScene::mMaterials|. The name preserves the original material
// name if possible.
std::string GetMaterialName(const aiMaterial& mat, unsigned int index) {
static const std::string underscore = "_";
char postfix[10] = {0};
ASSIMP_itoa10(postfix, index);
aiString mat_name;
if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
return mat_name.C_Str() + underscore + postfix;
}
return "Material" + underscore + postfix;
}
// Collect world transformations for each node
void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) {
const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4();
trafos[node] = parent * node->mTransformation;
for (unsigned int i = 0; i < node->mNumChildren; ++i) {
CollectTrafos(node->mChildren[i], trafos);
}
}
// Generate a flat list of the meshes (by index) assigned to each node
void CollectMeshes(const aiNode* node, std::multimap<const aiNode*, unsigned int>& meshes) {
for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
meshes.insert(std::make_pair(node, node->mMeshes[i]));
}
for (unsigned int i = 0; i < node->mNumChildren; ++i) {
CollectMeshes(node->mChildren[i], meshes);
}
}
}
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
if(!outfile) {
throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile));
}
// TODO: This extra copy should be avoided and all of this made a preprocess
// requirement of the 3DS exporter.
//
// 3DS meshes can be max 0xffff (16 Bit) vertices and faces, respectively.
// SplitLargeMeshes can do this, but it requires the correct limit to be set
// which is not possible with the current way of specifying preprocess steps
// in |Exporter::ExportFormatEntry|.
aiScene* scenecopy_tmp;
SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
SplitLargeMeshesProcess_Triangle tri_splitter;
tri_splitter.SetLimit(0xffff);
tri_splitter.Execute(scenecopy.get());
SplitLargeMeshesProcess_Vertex vert_splitter;
vert_splitter.SetLimit(0xffff);
vert_splitter.Execute(scenecopy.get());
// Invoke the actual exporter
Discreet3DSExporter exporter(outfile, scenecopy.get());
}
} // end of namespace Assimp
// ------------------------------------------------------------------------------------------------
Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* scene)
: scene(scene)
, writer(outfile)
{
CollectTrafos(scene->mRootNode, trafos);
CollectMeshes(scene->mRootNode, meshes);
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
WriteMeshes();
WriteMaterials();
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
writer.PutF4(1.0f);
}
}
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
WriteHierarchy(*scene->mRootNode, -1, -1);
}
}
// ------------------------------------------------------------------------------------------------
int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level)
{
// 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
{
ChunkWriter chunk(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
WriteString(node.mName);
// Two unknown int16 values - it is even unclear if 0 is a safe value
// but luckily importers do not know better either.
writer.PutI4(0);
int16_t hierarchy_pos = static_cast<int16_t>(seq);
if (sibling_level != -1) {
hierarchy_pos = sibling_level;
}
// Write the hierarchy position
writer.PutI2(hierarchy_pos);
}
}
// TODO: write transformation chunks
++seq;
sibling_level = seq;
// Write all children
for (unsigned int i = 0; i < node.mNumChildren; ++i) {
seq = WriteHierarchy(*node.mChildren[i], seq, i == 0 ? -1 : sibling_level);
}
// Write all meshes as separate nodes to be able to reference the meshes by name
for (unsigned int i = 0; i < node.mNumMeshes; ++i) {
const bool first_child = node.mNumChildren == 0 && i == 0;
const unsigned int mesh_idx = node.mMeshes[i];
const aiMesh& mesh = *scene->mMeshes[mesh_idx];
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
WriteString(GetMeshName(mesh, mesh_idx, node));
writer.PutI4(0);
writer.PutI2(static_cast<int16_t>(first_child ? seq : sibling_level));
++seq;
}
}
return seq;
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteMaterials()
{
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
const aiMaterial& mat = *scene->mMaterials[i];
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME);
const std::string& name = GetMaterialName(mat, i);
WriteString(name);
}
aiColor3D color;
if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
WriteColor(color);
}
if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
WriteColor(color);
}
if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
WriteColor(color);
}
if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
WriteColor(color);
}
aiShadingMode shading_mode;
if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
Discreet3DS::shadetype3ds shading_mode_out;
switch(shading_mode) {
case aiShadingMode_Flat:
case aiShadingMode_NoShading:
shading_mode_out = Discreet3DS::Flat;
break;
case aiShadingMode_Gouraud:
case aiShadingMode_Toon:
case aiShadingMode_OrenNayar:
case aiShadingMode_Minnaert:
shading_mode_out = Discreet3DS::Gouraud;
break;
case aiShadingMode_Phong:
case aiShadingMode_Blinn:
case aiShadingMode_CookTorrance:
case aiShadingMode_Fresnel:
shading_mode_out = Discreet3DS::Phong;
break;
default:
ai_assert(false);
};
writer.PutU2(static_cast<uint16_t>(shading_mode_out));
}
float f;
if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS);
WritePercentChunk(f);
}
if (mat.Get(AI_MATKEY_SHININESS_STRENGTH, f) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS_PERCENT);
WritePercentChunk(f);
}
int twosided;
if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
writer.PutI2(1);
}
WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE);
WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP);
WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP);
WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP);
WriteTexture(mat, aiTextureType_SPECULAR, Discreet3DS::CHUNK_MAT_SPECMAP);
WriteTexture(mat, aiTextureType_EMISSIVE, Discreet3DS::CHUNK_MAT_SELFIMAP);
WriteTexture(mat, aiTextureType_REFLECTION, Discreet3DS::CHUNK_MAT_REFLMAP);
}
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags)
{
aiString path;
aiTextureMapMode map_mode[2] = {
aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
};
float blend = 1.0f;
if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
return;
}
// TODO: handle embedded textures properly
if (path.data[0] == '*') {
DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
return;
}
ChunkWriter chunk(writer, chunk_flags);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE);
WriteString(path);
}
WritePercentChunk(blend);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
uint16_t val = 0; // WRAP
if (map_mode[0] == aiTextureMapMode_Mirror) {
val = 0x2;
}
else if (map_mode[0] == aiTextureMapMode_Decal) {
val = 0x10;
}
writer.PutU2(val);
}
// TODO: export texture transformation (i.e. UV offset, scale, rotation)
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteMeshes()
{
// NOTE: 3DS allows for instances. However:
// i) not all importers support reading them
// ii) instances are not as flexible as they are in assimp, in particular,
// nodes can carry (and instance) only one mesh.
//
// This exporter currently deep clones all instanced meshes, i.e. for each mesh
// attached to a node a full TRIMESH chunk is written to the file.
//
// Furthermore, the TRIMESH is transformed into world space so that it will
// appear correctly if importers don't read the scene hierarchy at all.
for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) {
const aiNode& node = *(*it).first;
const unsigned int mesh_idx = (*it).second;
const aiMesh& mesh = *scene->mMeshes[mesh_idx];
// This should not happen if the SLM step is correctly executed
// before the scene is handed to the exporter
ai_assert(mesh.mNumVertices <= 0xffff);
ai_assert(mesh.mNumFaces <= 0xffff);
const aiMatrix4x4& trafo = trafos[&node];
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK);
// Mesh name is tied to the node it is attached to so it can later be referenced
const std::string& name = GetMeshName(mesh, mesh_idx, node);
WriteString(name);
// TRIMESH chunk
ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH);
// Vertices in world space
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST);
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D& v = trafo * mesh.mVertices[i];
writer.PutF4(v.x);
writer.PutF4(v.y);
writer.PutF4(v.z);
}
}
// UV coordinates
if (mesh.HasTextureCoords(0)) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST);
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D& v = mesh.mTextureCoords[0][i];
writer.PutF4(v.x);
writer.PutF4(v.y);
}
}
// Faces (indices)
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST);
ai_assert(mesh.mNumFaces <= 0xffff);
// Count triangles, discard lines and points
uint16_t count = 0;
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
const aiFace& f = mesh.mFaces[i];
if (f.mNumIndices < 3) {
continue;
}
// TRIANGULATE step is a pre-requisite so we should not see polys here
ai_assert(f.mNumIndices == 3);
++count;
}
writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
const aiFace& f = mesh.mFaces[i];
if (f.mNumIndices < 3) {
continue;
}
for (unsigned int j = 0; j < 3; ++j) {
ai_assert(f.mIndices[j] <= 0xffff);
writer.PutI2(static_cast<uint16_t>(f.mIndices[j]));
}
// Edge visibility flag
writer.PutI2(0x0);
}
// TODO: write smoothing groups (CHUNK_SMOOLIST)
WriteFaceMaterialChunk(mesh);
}
// Transformation matrix by which the mesh vertices have been pre-transformed with.
{
ChunkWriter chunk(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]);
}
}
}
}
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh)
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT);
const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex);
WriteString(name);
// Because assimp splits meshes by material, only a single
// FACEMAT chunk needs to be written
ai_assert(mesh.mNumFaces <= 0xffff);
const uint16_t count = static_cast<uint16_t>(mesh.mNumFaces);
writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
writer.PutU2(static_cast<uint16_t>(i));
}
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteString(const std::string& s) {
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
writer.PutI1(*it);
}
writer.PutI1('\0');
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteString(const aiString& s) {
for (std::size_t i = 0; i < s.length; ++i) {
writer.PutI1(s.data[i]);
}
writer.PutI1('\0');
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF);
writer.PutF4(color.r);
writer.PutF4(color.g);
writer.PutF4(color.b);
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WritePercentChunk(float f) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF);
writer.PutF4(f);
}
#endif // ASSIMP_BUILD_NO_3DS_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

94
code/3DSExporter.h 100644
View File

@ -0,0 +1,94 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file 3DSExporter.h
* 3DS Exporter Main Header
*/
#ifndef AI_3DSEXPORTER_H_INC
#define AI_3DSEXPORTER_H_INC
#include <map>
#include "StreamWriter.h"
struct aiScene;
struct aiNode;
namespace Assimp
{
// ------------------------------------------------------------------------------------------------
/** Helper class to export a given scene to a 3DS file. */
// ------------------------------------------------------------------------------------------------
class Discreet3DSExporter
{
public:
Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* pScene);
private:
void WriteMeshes();
void WriteMaterials();
void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
void WriteFaceMaterialChunk(const aiMesh& mesh);
int WriteHierarchy(const aiNode& node, int level, int sibling_level);
void WriteString(const std::string& s);
void WriteString(const aiString& s);
void WriteColor(const aiColor3D& color);
void WritePercentChunk(float f);
private:
const aiScene* const scene;
StreamWriterLE writer;
std::map<const aiNode*, aiMatrix4x4> trafos;
typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
MeshesByNodeMap meshes;
};
}
#endif

View File

@ -468,7 +468,7 @@ struct aiFloatKey
{return mTime < o.mTime;}
bool operator > (const aiFloatKey& o) const
{return mTime < o.mTime;}
{return mTime > o.mTime;}
#endif
};

View File

@ -273,8 +273,8 @@ protected:
bool bIsPrj;
};
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
} // end of namespace Assimp
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
#endif // AI_3DSIMPORTER_H_INC

View File

@ -1525,7 +1525,7 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
continue;
}
// Number of bones
if (TokenMatch(filePtr,"MESH_NUMBONE" ,11))
if (TokenMatch(filePtr,"MESH_NUMBONE" ,12))
{
ParseLV4MeshLong(iNumBones);
continue;
@ -1559,7 +1559,7 @@ void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
++filePtr;
// Mesh bone with name ...
if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16))
if (TokenMatch(filePtr,"MESH_BONE_NAME" ,14))
{
// parse an index ...
if(SkipSpaces(&filePtr))

View File

@ -0,0 +1,765 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssbinExporter.cpp
* ASSBIN exporter main code
*/
#include "AssimpPCH.h"
#include "assbin_chunks.h"
#include "./../include/assimp/version.h"
#include "ProcessHelper.h"
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
#else
# include "../contrib/zlib/zlib.h"
#endif
#include <time.h>
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
using namespace Assimp;
namespace Assimp {
template <typename T>
size_t Write(IOStream * stream, const T& v)
{
return stream->Write( &v, sizeof(T), 1 );
}
// -----------------------------------------------------------------------------------
// Serialize an aiString
template <>
inline size_t Write<aiString>(IOStream * stream, const aiString& s)
{
const size_t s2 = (uint32_t)s.length;
stream->Write(&s,4,1);
stream->Write(s.data,s2,1);
return s2+4;
}
// -----------------------------------------------------------------------------------
// Serialize an unsigned int as uint32_t
template <>
inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w)
{
const uint32_t t = (uint32_t)w;
if (w > t) {
// this shouldn't happen, integers in Assimp data structures never exceed 2^32
throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion");
}
stream->Write(&t,4,1);
return 4;
}
// -----------------------------------------------------------------------------------
// Serialize an unsigned int as uint16_t
template <>
inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w)
{
BOOST_STATIC_ASSERT(sizeof(uint16_t)==2);
stream->Write(&w,2,1);
return 2;
}
// -----------------------------------------------------------------------------------
// Serialize a float
template <>
inline size_t Write<float>(IOStream * stream, const float& f)
{
BOOST_STATIC_ASSERT(sizeof(float)==4);
stream->Write(&f,4,1);
return 4;
}
// -----------------------------------------------------------------------------------
// Serialize a double
template <>
inline size_t Write<double>(IOStream * stream, const double& f)
{
BOOST_STATIC_ASSERT(sizeof(double)==8);
stream->Write(&f,8,1);
return 8;
}
// -----------------------------------------------------------------------------------
// Serialize a vec3
template <>
inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
{
size_t t = Write<float>(stream,v.x);
t += Write<float>(stream,v.y);
t += Write<float>(stream,v.z);
return t;
}
// -----------------------------------------------------------------------------------
// Serialize a color value
template <>
inline size_t Write<aiColor4D>(IOStream * stream, const aiColor4D& v)
{
size_t t = Write<float>(stream,v.r);
t += Write<float>(stream,v.g);
t += Write<float>(stream,v.b);
t += Write<float>(stream,v.a);
return t;
}
// -----------------------------------------------------------------------------------
// Serialize a quaternion
template <>
inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v)
{
size_t t = Write<float>(stream,v.w);
t += Write<float>(stream,v.x);
t += Write<float>(stream,v.y);
t += Write<float>(stream,v.z);
return 16;
}
// -----------------------------------------------------------------------------------
// Serialize a vertex weight
template <>
inline size_t Write<aiVertexWeight>(IOStream * stream, const aiVertexWeight& v)
{
size_t t = Write<unsigned int>(stream,v.mVertexId);
return t+Write<float>(stream,v.mWeight);
}
// -----------------------------------------------------------------------------------
// Serialize a mat4x4
template <>
inline size_t Write<aiMatrix4x4>(IOStream * stream, const aiMatrix4x4& m)
{
for (unsigned int i = 0; i < 4;++i) {
for (unsigned int i2 = 0; i2 < 4;++i2) {
Write<float>(stream,m[i][i2]);
}
}
return 64;
}
// -----------------------------------------------------------------------------------
// Serialize an aiVectorKey
template <>
inline size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v)
{
const size_t t = Write<double>(stream,v.mTime);
return t + Write<aiVector3D>(stream,v.mValue);
}
// -----------------------------------------------------------------------------------
// Serialize an aiQuatKey
template <>
inline size_t Write<aiQuatKey>(IOStream * stream, const aiQuatKey& v)
{
const size_t t = Write<double>(stream,v.mTime);
return t + Write<aiQuaternion>(stream,v.mValue);
}
template <typename T>
inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size)
{
T minc,maxc;
ArrayBounds(in,size,minc,maxc);
const size_t t = Write<T>(stream,minc);
return t + Write<T>(stream,maxc);
}
// We use this to write out non-byte arrays so that we write using the specializations.
// This way we avoid writing out extra bytes that potentially come from struct alignment.
template <typename T>
inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
{
size_t n = 0;
for (unsigned int i=0; i<size; i++) n += Write<T>(stream,in[i]);
return n;
}
// ----------------------------------------------------------------------------------
/** @class AssbinChunkWriter
* @brief Chunk writer mechanism for the .assbin file structure
*
* This is a standard in-memory IOStream (most of the code is based on BlobIOStream),
* the difference being that this takes another IOStream as a "container" in the
* constructor, and when it is destroyed, it appends the magic number, the chunk size,
* and the chunk contents to the container stream. This allows relatively easy chunk
* chunk construction, even recursively.
*/
class AssbinChunkWriter : public IOStream
{
private:
uint8_t* buffer;
uint32_t magic;
IOStream * container;
size_t cur_size, cursor, initial;
private:
// -------------------------------------------------------------------
void Grow(size_t need = 0)
{
size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
const uint8_t* const old = buffer;
buffer = new uint8_t[new_size];
if (old) {
memcpy(buffer,old,cur_size);
delete[] old;
}
cur_size = new_size;
}
public:
AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096)
: buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial)
{
}
virtual ~AssbinChunkWriter()
{
if (container) {
container->Write( &magic, sizeof(uint32_t), 1 );
container->Write( &cursor, sizeof(uint32_t), 1 );
container->Write( buffer, 1, cursor );
}
if (buffer) delete[] buffer;
}
void * GetBufferPointer() { return buffer; };
// -------------------------------------------------------------------
virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; };
virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; };
virtual size_t Tell() const { return cursor; };
virtual void Flush() { };
virtual size_t FileSize() const
{
return cursor;
}
// -------------------------------------------------------------------
virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount)
{
pSize *= pCount;
if (cursor + pSize > cur_size) {
Grow(cursor + pSize);
}
memcpy(buffer+cursor, pvBuffer, pSize);
cursor += pSize;
return pCount;
}
};
// ----------------------------------------------------------------------------------
/** @class AssbinExport
* @brief Assbin exporter class
*
* This class performs the .assbin exporting, and is responsible for the file layout.
*/
class AssbinExport
{
private:
bool shortened;
bool compressed;
protected:
// -----------------------------------------------------------------------------------
void WriteBinaryNode( IOStream * container, const aiNode* node)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
Write<aiString>(&chunk,node->mName);
Write<aiMatrix4x4>(&chunk,node->mTransformation);
Write<unsigned int>(&chunk,node->mNumChildren);
Write<unsigned int>(&chunk,node->mNumMeshes);
for (unsigned int i = 0; i < node->mNumMeshes;++i) {
Write<unsigned int>(&chunk,node->mMeshes[i]);
}
for (unsigned int i = 0; i < node->mNumChildren;++i) {
WriteBinaryNode( &chunk, node->mChildren[i] );
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryTexture(IOStream * container, const aiTexture* tex)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE );
Write<unsigned int>(&chunk,tex->mWidth);
Write<unsigned int>(&chunk,tex->mHeight);
chunk.Write( tex->achFormatHint, sizeof(char), 4 );
if(!shortened) {
if (!tex->mHeight) {
chunk.Write(tex->pcData,1,tex->mWidth);
}
else {
chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4);
}
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryBone(IOStream * container, const aiBone* b)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE );
Write<aiString>(&chunk,b->mName);
Write<unsigned int>(&chunk,b->mNumWeights);
Write<aiMatrix4x4>(&chunk,b->mOffsetMatrix);
// 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) {
WriteBounds(&chunk,b->mWeights,b->mNumWeights);
} // else write as usual
else WriteArray<aiVertexWeight>(&chunk,b->mWeights,b->mNumWeights);
}
// -----------------------------------------------------------------------------------
void WriteBinaryMesh(IOStream * container, const aiMesh* mesh)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH );
Write<unsigned int>(&chunk,mesh->mPrimitiveTypes);
Write<unsigned int>(&chunk,mesh->mNumVertices);
Write<unsigned int>(&chunk,mesh->mNumFaces);
Write<unsigned int>(&chunk,mesh->mNumBones);
Write<unsigned int>(&chunk,mesh->mMaterialIndex);
// first of all, write bits for all existent vertex components
unsigned int c = 0;
if (mesh->mVertices) {
c |= ASSBIN_MESH_HAS_POSITIONS;
}
if (mesh->mNormals) {
c |= ASSBIN_MESH_HAS_NORMALS;
}
if (mesh->mTangents && mesh->mBitangents) {
c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS;
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
if (!mesh->mTextureCoords[n]) {
break;
}
c |= ASSBIN_MESH_HAS_TEXCOORD(n);
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
if (!mesh->mColors[n]) {
break;
}
c |= ASSBIN_MESH_HAS_COLOR(n);
}
Write<unsigned int>(&chunk,c);
aiVector3D minVec, maxVec;
if (mesh->mVertices) {
if (shortened) {
WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices);
} // else write as usual
else WriteArray<aiVector3D>(&chunk,mesh->mVertices,mesh->mNumVertices);
}
if (mesh->mNormals) {
if (shortened) {
WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices);
} // else write as usual
else WriteArray<aiVector3D>(&chunk,mesh->mNormals,mesh->mNumVertices);
}
if (mesh->mTangents && mesh->mBitangents) {
if (shortened) {
WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices);
WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices);
} // else write as usual
else {
WriteArray<aiVector3D>(&chunk,mesh->mTangents,mesh->mNumVertices);
WriteArray<aiVector3D>(&chunk,mesh->mBitangents,mesh->mNumVertices);
}
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
if (!mesh->mColors[n])
break;
if (shortened) {
WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices);
} // else write as usual
else WriteArray<aiColor4D>(&chunk,mesh->mColors[n],mesh->mNumVertices);
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
if (!mesh->mTextureCoords[n])
break;
// write number of UV components
Write<unsigned int>(&chunk,mesh->mNumUVComponents[n]);
if (shortened) {
WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
} // else write as usual
else WriteArray<aiVector3D>(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
}
// write faces. There are no floating-point calculations involved
// in these, so we can write a simple hash over the face data
// to the dump file. We generate a single 32 Bit hash for 512 faces
// using Assimp's standard hashing function.
if (shortened) {
unsigned int processed = 0;
for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) {
uint32_t hash = 0;
for (unsigned int a = 0; a < job;++a) {
const aiFace& f = mesh->mFaces[processed+a];
uint32_t tmp = f.mNumIndices;
hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
for (unsigned int i = 0; i < f.mNumIndices; ++i) {
BOOST_STATIC_ASSERT(AI_MAX_VERTICES <= 0xffffffff);
tmp = static_cast<uint32_t>( f.mIndices[i] );
hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
}
}
Write<unsigned int>(&chunk,hash);
}
}
else // else write as usual
{
// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
const aiFace& f = mesh->mFaces[i];
BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff);
Write<uint16_t>(&chunk,f.mNumIndices);
for (unsigned int a = 0; a < f.mNumIndices;++a) {
if (mesh->mNumVertices < (1u<<16)) {
Write<uint16_t>(&chunk,f.mIndices[a]);
}
else Write<unsigned int>(&chunk,f.mIndices[a]);
}
}
}
// write bones
if (mesh->mNumBones) {
for (unsigned int a = 0; a < mesh->mNumBones;++a) {
const aiBone* b = mesh->mBones[a];
WriteBinaryBone(&chunk,b);
}
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY );
Write<aiString>(&chunk,prop->mKey);
Write<unsigned int>(&chunk,prop->mSemantic);
Write<unsigned int>(&chunk,prop->mIndex);
Write<unsigned int>(&chunk,prop->mDataLength);
Write<unsigned int>(&chunk,(unsigned int)prop->mType);
chunk.Write(prop->mData,1,prop->mDataLength);
}
// -----------------------------------------------------------------------------------
void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL);
Write<unsigned int>(&chunk,mat->mNumProperties);
for (unsigned int i = 0; i < mat->mNumProperties;++i) {
WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]);
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM );
Write<aiString>(&chunk,nd->mNodeName);
Write<unsigned int>(&chunk,nd->mNumPositionKeys);
Write<unsigned int>(&chunk,nd->mNumRotationKeys);
Write<unsigned int>(&chunk,nd->mNumScalingKeys);
Write<unsigned int>(&chunk,nd->mPreState);
Write<unsigned int>(&chunk,nd->mPostState);
if (nd->mPositionKeys) {
if (shortened) {
WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
} // else write as usual
else WriteArray<aiVectorKey>(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
}
if (nd->mRotationKeys) {
if (shortened) {
WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
} // else write as usual
else WriteArray<aiQuatKey>(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
}
if (nd->mScalingKeys) {
if (shortened) {
WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
} // else write as usual
else WriteArray<aiVectorKey>(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryAnim( IOStream * container, const aiAnimation* anim )
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION );
Write<aiString>(&chunk,anim->mName);
Write<double>(&chunk,anim->mDuration);
Write<double>(&chunk,anim->mTicksPerSecond);
Write<unsigned int>(&chunk,anim->mNumChannels);
for (unsigned int a = 0; a < anim->mNumChannels;++a) {
const aiNodeAnim* nd = anim->mChannels[a];
WriteBinaryNodeAnim(&chunk,nd);
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryLight( IOStream * container, const aiLight* l )
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT );
Write<aiString>(&chunk,l->mName);
Write<unsigned int>(&chunk,l->mType);
if (l->mType != aiLightSource_DIRECTIONAL) {
Write<float>(&chunk,l->mAttenuationConstant);
Write<float>(&chunk,l->mAttenuationLinear);
Write<float>(&chunk,l->mAttenuationQuadratic);
}
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse);
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular);
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient);
if (l->mType == aiLightSource_SPOT) {
Write<float>(&chunk,l->mAngleInnerCone);
Write<float>(&chunk,l->mAngleOuterCone);
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryCamera( IOStream * container, const aiCamera* cam )
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA );
Write<aiString>(&chunk,cam->mName);
Write<aiVector3D>(&chunk,cam->mPosition);
Write<aiVector3D>(&chunk,cam->mLookAt);
Write<aiVector3D>(&chunk,cam->mUp);
Write<float>(&chunk,cam->mHorizontalFOV);
Write<float>(&chunk,cam->mClipPlaneNear);
Write<float>(&chunk,cam->mClipPlaneFar);
Write<float>(&chunk,cam->mAspect);
}
// -----------------------------------------------------------------------------------
void WriteBinaryScene( IOStream * container, const aiScene* scene)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE );
// basic scene information
Write<unsigned int>(&chunk,scene->mFlags);
Write<unsigned int>(&chunk,scene->mNumMeshes);
Write<unsigned int>(&chunk,scene->mNumMaterials);
Write<unsigned int>(&chunk,scene->mNumAnimations);
Write<unsigned int>(&chunk,scene->mNumTextures);
Write<unsigned int>(&chunk,scene->mNumLights);
Write<unsigned int>(&chunk,scene->mNumCameras);
// write node graph
WriteBinaryNode( &chunk, scene->mRootNode );
// write all meshes
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
const aiMesh* mesh = scene->mMeshes[i];
WriteBinaryMesh( &chunk,mesh);
}
// write materials
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
const aiMaterial* mat = scene->mMaterials[i];
WriteBinaryMaterial(&chunk,mat);
}
// write all animations
for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
const aiAnimation* anim = scene->mAnimations[i];
WriteBinaryAnim(&chunk,anim);
}
// write all textures
for (unsigned int i = 0; i < scene->mNumTextures;++i) {
const aiTexture* mesh = scene->mTextures[i];
WriteBinaryTexture(&chunk,mesh);
}
// write lights
for (unsigned int i = 0; i < scene->mNumLights;++i) {
const aiLight* l = scene->mLights[i];
WriteBinaryLight(&chunk,l);
}
// write cameras
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
const aiCamera* cam = scene->mCameras[i];
WriteBinaryCamera(&chunk,cam);
}
}
public:
AssbinExport()
: shortened(false), compressed(false) // temporary settings until properties are introduced for exporters
{
}
// -----------------------------------------------------------------------------------
// Write a binary model dump
void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
IOStream * out = pIOSystem->Open( pFile, "wb" );
if (!out) return;
time_t tt = time(NULL);
tm* p = gmtime(&tt);
// header
char s[64];
memset( s, 0, 64 );
#if _MSC_VER >= 1400
sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p));
#else
snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p));
#endif
out->Write( s, 44, 1 );
// == 44 bytes
Write<unsigned int>( out, ASSBIN_VERSION_MAJOR );
Write<unsigned int>( out, ASSBIN_VERSION_MINOR );
Write<unsigned int>( out, aiGetVersionRevision() );
Write<unsigned int>( out, aiGetCompileFlags() );
Write<uint16_t>( out, shortened );
Write<uint16_t>( out, compressed );
// == 20 bytes
char buff[256];
strncpy(buff,pFile,256);
out->Write(buff,sizeof(char),256);
char cmd[] = "\0";
strncpy(buff,cmd,128);
out->Write(buff,sizeof(char),128);
// leave 64 bytes free for future extensions
memset(buff,0xcd,64);
out->Write(buff,sizeof(char),64);
// == 435 bytes
// ==== total header size: 512 bytes
ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH );
// Up to here the data is uncompressed. For compressed files, the rest
// is compressed using standard DEFLATE from zlib.
if (compressed)
{
AssbinChunkWriter uncompressedStream( NULL, 0 );
WriteBinaryScene( &uncompressedStream, pScene );
uLongf uncompressedSize = uncompressedStream.Tell();
uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.);
uint8_t* compressedBuffer = new uint8_t[ compressedSize ];
compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 );
out->Write( &uncompressedSize, sizeof(uint32_t), 1 );
out->Write( compressedBuffer, sizeof(char), compressedSize );
delete[] compressedBuffer;
}
else
{
WriteBinaryScene( out, pScene );
}
pIOSystem->Close( out );
}
};
void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
AssbinExport exporter;
exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
}
} // end of namespace Assimp
#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -0,0 +1,49 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssbinExporter.h
* ASSBIN Exporter Main Header
*/
#ifndef AI_ASSBINEXPORTER_H_INC
#define AI_ASSBINEXPORTER_H_INC
// nothing really needed here - reserved for future use like properties
#endif

View File

@ -0,0 +1,672 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file AssbinLoader.cpp
* @brief Implementation of the .assbin importer class
*
* see assbin_chunks.h
*/
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
// internal headers
#include "AssbinLoader.h"
#include "assbin_chunks.h"
#include "MemoryIOWrapper.h"
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
#else
# include "../contrib/zlib/zlib.h"
#endif
using namespace Assimp;
static const aiImporterDesc desc = {
".assbin Importer",
"Gargaj / Conspiracy",
"",
"",
aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
0,
0,
0,
0,
"assbin"
};
const aiImporterDesc* AssbinImporter::GetInfo() const
{
return &desc;
}
bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const
{
IOStream * in = pIOHandler->Open(pFile);
if (!in)
return false;
char s[32];
in->Read( s, sizeof(char), 32 );
pIOHandler->Close(in);
return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0;
}
template <typename T>
T Read(IOStream * stream)
{
T t;
stream->Read( &t, sizeof(T), 1 );
return t;
}
template <>
aiVector3D Read<aiVector3D>(IOStream * stream)
{
aiVector3D v;
v.x = Read<float>(stream);
v.y = Read<float>(stream);
v.z = Read<float>(stream);
return v;
}
template <>
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);
return c;
}
template <>
aiQuaternion Read<aiQuaternion>(IOStream * stream)
{
aiQuaternion v;
v.w = Read<float>(stream);
v.x = Read<float>(stream);
v.y = Read<float>(stream);
v.z = Read<float>(stream);
return v;
}
template <>
aiString Read<aiString>(IOStream * stream)
{
aiString s;
stream->Read(&s.length,4,1);
stream->Read(s.data,s.length,1);
s.data[s.length] = 0;
return s;
}
template <>
aiVertexWeight Read<aiVertexWeight>(IOStream * stream)
{
aiVertexWeight w;
w.mVertexId = Read<unsigned int>(stream);
w.mWeight = Read<float>(stream);
return w;
}
template <>
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);
}
}
return m;
}
template <>
aiVectorKey Read<aiVectorKey>(IOStream * stream)
{
aiVectorKey v;
v.mTime = Read<double>(stream);
v.mValue = Read<aiVector3D>(stream);
return v;
}
template <>
aiQuatKey Read<aiQuatKey>(IOStream * stream)
{
aiQuatKey v;
v.mTime = Read<double>(stream);
v.mValue = Read<aiQuaternion>(stream);
return v;
}
template <typename T>
void ReadArray(IOStream * stream, T * out, unsigned int size)
{
for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream);
}
template <typename T> 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 );
}
void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODE);
/*uint32_t size =*/ Read<uint32_t>(stream);
*node = new aiNode();
(*node)->mName = Read<aiString>(stream);
(*node)->mTransformation = Read<aiMatrix4x4>(stream);
(*node)->mNumChildren = Read<unsigned int>(stream);
(*node)->mNumMeshes = Read<unsigned int>(stream);
if ((*node)->mNumMeshes)
{
(*node)->mMeshes = new unsigned int[(*node)->mNumMeshes];
for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) {
(*node)->mMeshes[i] = Read<unsigned int>(stream);
}
}
if ((*node)->mNumChildren)
{
(*node)->mChildren = new aiNode*[(*node)->mNumChildren];
for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) {
ReadBinaryNode( stream, &(*node)->mChildren[i] );
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIBONE );
/*uint32_t size =*/ Read<uint32_t>(stream);
b->mName = Read<aiString>(stream);
b->mNumWeights = Read<unsigned int>(stream);
b->mOffsetMatrix = Read<aiMatrix4x4>(stream);
// 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);
} // else write as usual
else
{
b->mWeights = new aiVertexWeight[b->mNumWeights];
ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights);
}
}
void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMESH);
/*uint32_t size =*/ Read<uint32_t>(stream);
mesh->mPrimitiveTypes = Read<unsigned int>(stream);
mesh->mNumVertices = Read<unsigned int>(stream);
mesh->mNumFaces = Read<unsigned int>(stream);
mesh->mNumBones = Read<unsigned int>(stream);
mesh->mMaterialIndex = Read<unsigned int>(stream);
// first of all, write bits for all existent vertex components
unsigned int c = Read<unsigned int>(stream);
if (c & ASSBIN_MESH_HAS_POSITIONS)
{
if (shortened) {
ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
} // else write as usual
else
{
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices);
}
}
if (c & ASSBIN_MESH_HAS_NORMALS)
{
if (shortened) {
ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
} // else write as usual
else
{
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices);
}
}
if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS)
{
if (shortened) {
ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
} // else write as usual
else
{
mesh->mTangents = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices);
mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices);
}
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n)
{
if (!(c & ASSBIN_MESH_HAS_COLOR(n)))
break;
if (shortened)
{
ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
} // else write as usual
else
{
mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices);
}
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
{
if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n)))
break;
// write number of UV components
mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
if (shortened) {
ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
} // else write as usual
else
{
mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
}
}
// write faces. There are no floating-point calculations involved
// in these, so we can write a simple hash over the face data
// to the dump file. We generate a single 32 Bit hash for 512 faces
// using Assimp's standard hashing function.
if (shortened) {
Read<unsigned int>(stream);
}
else // else write as usual
{
// 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];
BOOST_STATIC_ASSERT(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) {
if (mesh->mNumVertices < (1u<<16))
{
f.mIndices[a] = Read<uint16_t>(stream);
}
else
{
f.mIndices[a] = Read<unsigned int>(stream);
}
}
}
}
// write bones
if (mesh->mNumBones) {
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]);
}
}
}
void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop)
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIALPROPERTY);
/*uint32_t size =*/ Read<uint32_t>(stream);
prop->mKey = Read<aiString>(stream);
prop->mSemantic = Read<unsigned int>(stream);
prop->mIndex = Read<unsigned int>(stream);
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);
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIAL);
/*uint32_t size =*/ Read<uint32_t>(stream);
mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
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[i] = new aiMaterialProperty();
ReadBinaryMaterialProperty( stream, mat->mProperties[i]);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODEANIM);
/*uint32_t size =*/ Read<uint32_t>(stream);
nd->mNodeName = Read<aiString>(stream);
nd->mNumPositionKeys = Read<unsigned int>(stream);
nd->mNumRotationKeys = Read<unsigned int>(stream);
nd->mNumScalingKeys = Read<unsigned int>(stream);
nd->mPreState = (aiAnimBehaviour)Read<unsigned int>(stream);
nd->mPostState = (aiAnimBehaviour)Read<unsigned int>(stream);
if (nd->mNumPositionKeys) {
if (shortened) {
ReadBounds(stream,nd->mPositionKeys,nd->mNumPositionKeys);
} // else write as usual
else {
nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
ReadArray<aiVectorKey>(stream,nd->mPositionKeys,nd->mNumPositionKeys);
}
}
if (nd->mNumRotationKeys) {
if (shortened) {
ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
} // else write as usual
else
{
nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys);
}
}
if (nd->mNumScalingKeys) {
if (shortened) {
ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
} // else write as usual
else
{
nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIANIMATION);
/*uint32_t size =*/ Read<uint32_t>(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[a] = new aiNodeAnim();
ReadBinaryNodeAnim(stream,anim->mChannels[a]);
}
}
}
void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AITEXTURE);
/*uint32_t size =*/ Read<uint32_t>(stream);
tex->mWidth = Read<unsigned int>(stream);
tex->mHeight = Read<unsigned int>(stream);
stream->Read( tex->achFormatHint, sizeof(char), 4 );
if(!shortened) {
if (!tex->mHeight) {
tex->pcData = new aiTexel[ tex->mWidth ];
stream->Read(tex->pcData,1,tex->mWidth);
}
else {
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 )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AILIGHT);
/*uint32_t size =*/ Read<uint32_t>(stream);
l->mName = Read<aiString>(stream);
l->mType = (aiLightSourceType)Read<unsigned int>(stream);
if (l->mType != aiLightSource_DIRECTIONAL) {
l->mAttenuationConstant = Read<float>(stream);
l->mAttenuationLinear = Read<float>(stream);
l->mAttenuationQuadratic = Read<float>(stream);
}
l->mColorDiffuse = Read<aiColor3D>(stream);
l->mColorSpecular = Read<aiColor3D>(stream);
l->mColorAmbient = Read<aiColor3D>(stream);
if (l->mType == aiLightSource_SPOT) {
l->mAngleInnerCone = Read<float>(stream);
l->mAngleOuterCone = Read<float>(stream);
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AICAMERA);
/*uint32_t size =*/ Read<uint32_t>(stream);
cam->mName = Read<aiString>(stream);
cam->mPosition = Read<aiVector3D>(stream);
cam->mLookAt = Read<aiVector3D>(stream);
cam->mUp = Read<aiVector3D>(stream);
cam->mHorizontalFOV = Read<float>(stream);
cam->mClipPlaneNear = Read<float>(stream);
cam->mClipPlaneFar = Read<float>(stream);
cam->mAspect = Read<float>(stream);
}
void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AISCENE);
/*uint32_t size =*/ Read<uint32_t>(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);
// Read node graph
scene->mRootNode = new aiNode[1];
ReadBinaryNode( stream, &scene->mRootNode );
// Read all meshes
if (scene->mNumMeshes)
{
scene->mMeshes = new aiMesh*[scene->mNumMeshes];
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
scene->mMeshes[i] = new aiMesh();
ReadBinaryMesh( stream,scene->mMeshes[i]);
}
}
// Read materials
if (scene->mNumMaterials)
{
scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
scene->mMaterials[i] = new aiMaterial();
ReadBinaryMaterial(stream,scene->mMaterials[i]);
}
}
// Read all animations
if (scene->mNumAnimations)
{
scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
scene->mAnimations[i] = new aiAnimation();
ReadBinaryAnim(stream,scene->mAnimations[i]);
}
}
// Read all textures
if (scene->mNumTextures)
{
scene->mTextures = new aiTexture*[scene->mNumTextures];
for (unsigned int i = 0; i < scene->mNumTextures;++i) {
scene->mTextures[i] = new aiTexture();
ReadBinaryTexture(stream,scene->mTextures[i]);
}
}
// Read lights
if (scene->mNumLights)
{
scene->mLights = new aiLight*[scene->mNumLights];
for (unsigned int i = 0; i < scene->mNumLights;++i) {
scene->mLights[i] = new aiLight();
ReadBinaryLight(stream,scene->mLights[i]);
}
}
// Read cameras
if (scene->mNumCameras)
{
scene->mCameras = new aiCamera*[scene->mNumCameras];
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
scene->mCameras[i] = new aiCamera();
ReadBinaryCamera(stream,scene->mCameras[i]);
}
}
}
void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
{
IOStream * stream = pIOHandler->Open(pFile,"rb");
if (!stream)
return;
stream->Seek( 44, aiOrigin_CUR ); // signature
/*unsigned int versionMajor =*/ Read<unsigned int>(stream);
/*unsigned int versionMinor =*/ 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!" );
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 = stream->FileSize() - stream->Tell();
unsigned char * compressedData = new unsigned char[ compressedSize ];
stream->Read( compressedData, 1, compressedSize );
unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize );
MemoryIOStream io( uncompressedData, uncompressedSize );
ReadBinaryScene(&io,pScene);
delete[] uncompressedData;
delete[] compressedData;
}
else
{
ReadBinaryScene(stream,pScene);
}
pIOHandler->Close(stream);
}
#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER

View File

@ -0,0 +1,94 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssbinLoader.h
* @brief .assbin File format loader
*/
#ifndef AI_ASSBINIMPORTER_H_INC
#define AI_ASSBINIMPORTER_H_INC
#include "BaseImporter.h"
#include "../include/assimp/types.h"
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
namespace Assimp {
// ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files
*/
class AssbinImporter : public BaseImporter
{
private:
bool shortened;
bool compressed;
protected:
public:
virtual bool CanRead(
const std::string& pFile,
IOSystem* pIOHandler,
bool checkSig
) const;
virtual const aiImporterDesc* GetInfo() const;
virtual void InternReadFile(
const std::string& pFile,
aiScene* pScene,
IOSystem* pIOHandler
);
void ReadBinaryScene( IOStream * stream, aiScene* pScene );
void ReadBinaryNode( IOStream * stream, aiNode** mRootNode );
void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
void ReadBinaryBone( IOStream * stream, aiBone* bone );
void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);
void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop);
void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd);
void ReadBinaryAnim( IOStream * stream, aiAnimation* anim );
void ReadBinaryTexture(IOStream * stream, aiTexture* tex);
void ReadBinaryLight( IOStream * stream, aiLight* l );
void ReadBinaryCamera( IOStream * stream, aiCamera* cam );
};
} // end of namespace Assimp
#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER
#endif // AI_ASSBINIMPORTER_H_INC

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "GenericProperty.h"
#include "CInterfaceIOWrapper.h"
#include "../include/assimp/importerdesc.h"
#include "Importer.h"
// ------------------------------------------------------------------------------------------------
@ -84,7 +85,11 @@ namespace Assimp
/** Verbose logging active or not? */
static aiBool gVerboseLogging = false;
}
/** will return all registered importers. */
void GetImporterInstanceList(std::vector< BaseImporter* >& out);
} // namespace assimp
#ifndef ASSIMP_BUILD_SINGLETHREADED
@ -606,4 +611,22 @@ ASSIMP_API void aiIdentityMatrix4(
*mat = aiMatrix4x4();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) {
if( NULL == extension ) {
return NULL;
}
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();
break;
}
}
return desc;
}
// ------------------------------------------------------------------------------------------------

View File

@ -61,6 +61,8 @@ ASSIMP_API size_t aiGetExportFormatCount(void)
// ------------------------------------------------------------------------------------------------
ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex)
{
// Note: this is valid as the index always pertains to a builtin exporter,
// for which the returned structure is guaranteed to be of static storage duration.
return Exporter().GetExportFormatDescription(pIndex);
}

View File

@ -0,0 +1,638 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssxmlExporter.cpp
* ASSXML exporter main code
*/
#include <stdarg.h>
#include "AssimpPCH.h"
#include "./../include/assimp/version.h"
#include "ProcessHelper.h"
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
#else
# include "../contrib/zlib/zlib.h"
#endif
#include <time.h>
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
using namespace Assimp;
namespace Assimp {
namespace AssxmlExport {
int ioprintf( IOStream * io, const char * format, ... )
{
char sz[4096];
va_list va;
va_start( va, format );
int nSize = vsnprintf( sz, 4096, format, va );
ai_assert( nSize < 4096 );
va_end( va );
io->Write( sz, sizeof(char), nSize );
return nSize;
}
// -----------------------------------------------------------------------------------
// Convert a name to standard XML format
void ConvertName(aiString& out, const aiString& in)
{
out.length = 0;
for (unsigned int i = 0; i < in.length; ++i) {
switch (in.data[i]) {
case '<':
out.Append("&lt;");break;
case '>':
out.Append("&gt;");break;
case '&':
out.Append("&amp;");break;
case '\"':
out.Append("&quot;");break;
case '\'':
out.Append("&apos;");break;
default:
out.data[out.length++] = in.data[i];
}
}
out.data[out.length] = 0;
}
// -----------------------------------------------------------------------------------
// Write a single node as text dump
void WriteNode(const aiNode* node, IOStream * io, unsigned int depth)
{
char prefix[512];
for (unsigned int i = 0; i < depth;++i)
prefix[i] = '\t';
prefix[depth] = '\0';
const aiMatrix4x4& m = node->mTransformation;
aiString name;
ConvertName(name,node->mName);
ioprintf(io,"%s<Node name=\"%s\"> \n"
"%s\t<Matrix4> \n"
"%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
"%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
"%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
"%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
"%s\t</Matrix4> \n",
prefix,name.data,prefix,
prefix,m.a1,m.a2,m.a3,m.a4,
prefix,m.b1,m.b2,m.b3,m.b4,
prefix,m.c1,m.c2,m.c3,m.c4,
prefix,m.d1,m.d2,m.d3,m.d4,prefix);
if (node->mNumMeshes) {
ioprintf(io, "%s\t<MeshRefs num=\"%i\">\n%s\t",
prefix,node->mNumMeshes,prefix);
for (unsigned int i = 0; i < node->mNumMeshes;++i) {
ioprintf(io,"%i ",node->mMeshes[i]);
}
ioprintf(io,"\n%s\t</MeshRefs>\n",prefix);
}
if (node->mNumChildren) {
ioprintf(io,"%s\t<NodeList num=\"%i\">\n",
prefix,node->mNumChildren);
for (unsigned int i = 0; i < node->mNumChildren;++i) {
WriteNode(node->mChildren[i],io,depth+2);
}
ioprintf(io,"%s\t</NodeList>\n",prefix);
}
ioprintf(io,"%s</Node>\n",prefix);
}
// -----------------------------------------------------------------------------------
// Some chuncks of text will need to be encoded for XML
// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377
static std::string encodeXML(const std::string& data) {
std::string buffer;
buffer.reserve(data.size());
for(size_t pos = 0; pos != data.size(); ++pos) {
switch(data[pos]) {
case '&': buffer.append("&amp;"); break;
case '\"': buffer.append("&quot;"); break;
case '\'': buffer.append("&apos;"); break;
case '<': buffer.append("&lt;"); break;
case '>': buffer.append("&gt;"); break;
default: buffer.append(&data[pos], 1); break;
}
}
return buffer;
}
// -----------------------------------------------------------------------------------
// Write a text model dump
void WriteDump(const aiScene* scene, IOStream* io, bool shortened)
{
time_t tt = ::time(NULL);
tm* p = ::gmtime(&tt);
aiString name;
// write header
ioprintf(io,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<ASSIMP format_id=\"1\">\n\n"
"<!-- XML Model dump produced by assimp dump\n"
" Library version: %i.%i.%i\n"
" %s\n"
"-->"
" \n\n"
"<Scene flags=\"%i\" postprocessing=\"%i\">\n",
aiGetVersionMajor(),aiGetVersionMinor(),aiGetVersionRevision(),asctime(p),
scene->mFlags,
0 /*globalImporter->GetEffectivePostProcessing()*/);
// write the node graph
WriteNode(scene->mRootNode, io, 0);
#if 0
// write cameras
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
aiCamera* cam = scene->mCameras[i];
ConvertName(name,cam->mName);
// camera header
ioprintf(io,"\t<Camera parent=\"%s\">\n"
"\t\t<Vector3 name=\"up\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Float name=\"fov\" > %f </Float>\n"
"\t\t<Float name=\"aspect\" > %f </Float>\n"
"\t\t<Float name=\"near_clip\" > %f </Float>\n"
"\t\t<Float name=\"far_clip\" > %f </Float>\n"
"\t</Camera>\n",
name.data,
cam->mUp.x,cam->mUp.y,cam->mUp.z,
cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z,
cam->mPosition.x,cam->mPosition.y,cam->mPosition.z,
cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i);
}
// write lights
for (unsigned int i = 0; i < scene->mNumLights;++i) {
aiLight* l = scene->mLights[i];
ConvertName(name,l->mName);
// light header
ioprintf(io,"\t<Light parent=\"%s\"> type=\"%s\"\n"
"\t\t<Vector3 name=\"diffuse\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"specular\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"ambient\" > %0 8f %0 8f %0 8f </Vector3>\n",
name.data,
(l->mType == aiLightSource_DIRECTIONAL ? "directional" :
(l->mType == aiLightSource_POINT ? "point" : "spot" )),
l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b,
l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b,
l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b);
if (l->mType != aiLightSource_DIRECTIONAL) {
ioprintf(io,
"\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Float name=\"atten_cst\" > %f </Float>\n"
"\t\t<Float name=\"atten_lin\" > %f </Float>\n"
"\t\t<Float name=\"atten_sqr\" > %f </Float>\n",
l->mPosition.x,l->mPosition.y,l->mPosition.z,
l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic);
}
if (l->mType != aiLightSource_POINT) {
ioprintf(io,
"\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n",
l->mDirection.x,l->mDirection.y,l->mDirection.z);
}
if (l->mType == aiLightSource_SPOT) {
ioprintf(io,
"\t\t<Float name=\"cone_out\" > %f </Float>\n"
"\t\t<Float name=\"cone_inn\" > %f </Float>\n",
l->mAngleOuterCone,l->mAngleInnerCone);
}
ioprintf(io,"\t</Light>\n");
}
#endif
// write textures
if (scene->mNumTextures) {
ioprintf(io,"<TextureList num=\"%i\">\n",scene->mNumTextures);
for (unsigned int i = 0; i < scene->mNumTextures;++i) {
aiTexture* tex = scene->mTextures[i];
bool compressed = (tex->mHeight == 0);
// mesh header
ioprintf(io,"\t<Texture width=\"%i\" height=\"%i\" compressed=\"%s\"> \n",
(compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight),
(compressed ? "true" : "false"));
if (compressed) {
ioprintf(io,"\t\t<Data length=\"%i\"> \n",tex->mWidth);
if (!shortened) {
for (unsigned int n = 0; n < tex->mWidth;++n) {
ioprintf(io,"\t\t\t%2x",reinterpret_cast<uint8_t*>(tex->pcData)[n]);
if (n && !(n % 50)) {
ioprintf(io,"\n");
}
}
}
}
else if (!shortened){
ioprintf(io,"\t\t<Data length=\"%i\"> \n",tex->mWidth*tex->mHeight*4);
// const unsigned int width = (unsigned int)log10((double)std::max(tex->mHeight,tex->mWidth))+1;
for (unsigned int y = 0; y < tex->mHeight;++y) {
for (unsigned int x = 0; x < tex->mWidth;++x) {
aiTexel* tx = tex->pcData + y*tex->mWidth+x;
unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a;
ioprintf(io,"\t\t\t%2x %2x %2x %2x",r,g,b,a);
// group by four for readibility
if (0 == (x+y*tex->mWidth) % 4)
ioprintf(io,"\n");
}
}
}
ioprintf(io,"\t\t</Data>\n\t</Texture>\n");
}
ioprintf(io,"</TextureList>\n");
}
// write materials
if (scene->mNumMaterials) {
ioprintf(io,"<MaterialList num=\"%i\">\n",scene->mNumMaterials);
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
const aiMaterial* mat = scene->mMaterials[i];
ioprintf(io,"\t<Material>\n");
ioprintf(io,"\t\t<MatPropertyList num=\"%i\">\n",mat->mNumProperties);
for (unsigned int n = 0; n < mat->mNumProperties;++n) {
const aiMaterialProperty* prop = mat->mProperties[n];
const char* sz = "";
if (prop->mType == aiPTI_Float) {
sz = "float";
}
else if (prop->mType == aiPTI_Integer) {
sz = "integer";
}
else if (prop->mType == aiPTI_String) {
sz = "string";
}
else if (prop->mType == aiPTI_Buffer) {
sz = "binary_buffer";
}
ioprintf(io,"\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%i\"",
prop->mKey.data, sz,
::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex);
if (prop->mType == aiPTI_Float) {
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))));
}
}
else if (prop->mType == aiPTI_Integer) {
ioprintf(io," size=\"%i\">\n\t\t\t\t",
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))));
}
}
else if (prop->mType == aiPTI_Buffer) {
ioprintf(io," size=\"%i\">\n\t\t\t\t",
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) {
ioprintf(io,"\n\t\t\t\t");
}
}
}
else if (prop->mType == aiPTI_String) {
ioprintf(io,">\n\t\t\t\t\"%s\"",encodeXML(prop->mData+4).c_str() /* skip length */);
}
ioprintf(io,"\n\t\t\t</MatProperty>\n");
}
ioprintf(io,"\t\t</MatPropertyList>\n");
ioprintf(io,"\t</Material>\n");
}
ioprintf(io,"</MaterialList>\n");
}
// write animations
if (scene->mNumAnimations) {
ioprintf(io,"<AnimationList num=\"%i\">\n",scene->mNumAnimations);
for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
aiAnimation* anim = scene->mAnimations[i];
// anim header
ConvertName(name,anim->mName);
ioprintf(io,"\t<Animation name=\"%s\" duration=\"%e\" tick_cnt=\"%e\">\n",
name.data, anim->mDuration, anim->mTicksPerSecond);
// write bone animation channels
if (anim->mNumChannels) {
ioprintf(io,"\t\t<NodeAnimList num=\"%i\">\n",anim->mNumChannels);
for (unsigned int n = 0; n < anim->mNumChannels;++n) {
aiNodeAnim* nd = anim->mChannels[n];
// node anim header
ConvertName(name,nd->mNodeName);
ioprintf(io,"\t\t\t<NodeAnim node=\"%s\">\n",name.data);
if (!shortened) {
// write position keys
if (nd->mNumPositionKeys) {
ioprintf(io,"\t\t\t\t<PositionKeyList num=\"%i\">\n",nd->mNumPositionKeys);
for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) {
aiVectorKey* vc = nd->mPositionKeys+a;
ioprintf(io,"\t\t\t\t\t<PositionKey time=\"%e\">\n"
"\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</PositionKey>\n",
vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
}
ioprintf(io,"\t\t\t\t</PositionKeyList>\n");
}
// write scaling keys
if (nd->mNumScalingKeys) {
ioprintf(io,"\t\t\t\t<ScalingKeyList num=\"%i\">\n",nd->mNumScalingKeys);
for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) {
aiVectorKey* vc = nd->mScalingKeys+a;
ioprintf(io,"\t\t\t\t\t<ScalingKey time=\"%e\">\n"
"\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</ScalingKey>\n",
vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
}
ioprintf(io,"\t\t\t\t</ScalingKeyList>\n");
}
// write rotation keys
if (nd->mNumRotationKeys) {
ioprintf(io,"\t\t\t\t<RotationKeyList num=\"%i\">\n",nd->mNumRotationKeys);
for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) {
aiQuatKey* vc = nd->mRotationKeys+a;
ioprintf(io,"\t\t\t\t\t<RotationKey time=\"%e\">\n"
"\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t</RotationKey>\n",
vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w);
}
ioprintf(io,"\t\t\t\t</RotationKeyList>\n");
}
}
ioprintf(io,"\t\t\t</NodeAnim>\n");
}
ioprintf(io,"\t\t</NodeAnimList>\n");
}
ioprintf(io,"\t</Animation>\n");
}
ioprintf(io,"</AnimationList>\n");
}
// write meshes
if (scene->mNumMeshes) {
ioprintf(io,"<MeshList num=\"%i\">\n",scene->mNumMeshes);
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
aiMesh* mesh = scene->mMeshes[i];
// const unsigned int width = (unsigned int)log10((double)mesh->mNumVertices)+1;
// mesh header
ioprintf(io,"\t<Mesh types=\"%s %s %s %s\" material_index=\"%i\">\n",
(mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""),
(mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""),
(mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""),
(mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""),
mesh->mMaterialIndex);
// bones
if (mesh->mNumBones) {
ioprintf(io,"\t\t<BoneList num=\"%i\">\n",mesh->mNumBones);
for (unsigned int n = 0; n < mesh->mNumBones;++n) {
aiBone* bone = mesh->mBones[n];
ConvertName(name,bone->mName);
// bone header
ioprintf(io,"\t\t\t<Bone name=\"%s\">\n"
"\t\t\t\t<Matrix4> \n"
"\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
"\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
"\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
"\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
"\t\t\t\t</Matrix4> \n",
name.data,
bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4,
bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4,
bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4,
bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4);
if (!shortened && bone->mNumWeights) {
ioprintf(io,"\t\t\t\t<WeightList num=\"%i\">\n",bone->mNumWeights);
// bone weights
for (unsigned int a = 0; a < bone->mNumWeights;++a) {
aiVertexWeight* wght = bone->mWeights+a;
ioprintf(io,"\t\t\t\t\t<Weight index=\"%i\">\n\t\t\t\t\t\t%f\n\t\t\t\t\t</Weight>\n",
wght->mVertexId,wght->mWeight);
}
ioprintf(io,"\t\t\t\t</WeightList>\n");
}
ioprintf(io,"\t\t\t</Bone>\n");
}
ioprintf(io,"\t\t</BoneList>\n");
}
// faces
if (!shortened && mesh->mNumFaces) {
ioprintf(io,"\t\t<FaceList num=\"%i\">\n",mesh->mNumFaces);
for (unsigned int n = 0; n < mesh->mNumFaces; ++n) {
aiFace& f = mesh->mFaces[n];
ioprintf(io,"\t\t\t<Face num=\"%i\">\n"
"\t\t\t\t",f.mNumIndices);
for (unsigned int j = 0; j < f.mNumIndices;++j)
ioprintf(io,"%i ",f.mIndices[j]);
ioprintf(io,"\n\t\t\t</Face>\n");
}
ioprintf(io,"\t\t</FaceList>\n");
}
// vertex positions
if (mesh->HasPositions()) {
ioprintf(io,"\t\t<Positions num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mVertices[n].x,
mesh->mVertices[n].y,
mesh->mVertices[n].z);
}
}
ioprintf(io,"\t\t</Positions>\n");
}
// vertex normals
if (mesh->HasNormals()) {
ioprintf(io,"\t\t<Normals num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mNormals[n].x,
mesh->mNormals[n].y,
mesh->mNormals[n].z);
}
}
else {
}
ioprintf(io,"\t\t</Normals>\n");
}
// vertex tangents and bitangents
if (mesh->HasTangentsAndBitangents()) {
ioprintf(io,"\t\t<Tangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mTangents[n].x,
mesh->mTangents[n].y,
mesh->mTangents[n].z);
}
}
ioprintf(io,"\t\t</Tangents>\n");
ioprintf(io,"\t\t<Bitangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mBitangents[n].x,
mesh->mBitangents[n].y,
mesh->mBitangents[n].z);
}
}
ioprintf(io,"\t\t</Bitangents>\n");
}
// texture coordinates
for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (!mesh->mTextureCoords[a])
break;
ioprintf(io,"\t\t<TextureCoords num=\"%i\" set=\"%i\" num_components=\"%i\"> \n",mesh->mNumVertices,
a,mesh->mNumUVComponents[a]);
if (!shortened) {
if (mesh->mNumUVComponents[a] == 3) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mTextureCoords[a][n].x,
mesh->mTextureCoords[a][n].y,
mesh->mTextureCoords[a][n].z);
}
}
else {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f\n",
mesh->mTextureCoords[a][n].x,
mesh->mTextureCoords[a][n].y);
}
}
}
ioprintf(io,"\t\t</TextureCoords>\n");
}
// vertex colors
for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) {
if (!mesh->mColors[a])
break;
ioprintf(io,"\t\t<Colors num=\"%i\" set=\"%i\" num_components=\"4\"> \n",mesh->mNumVertices,a);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f %0 8f\n",
mesh->mColors[a][n].r,
mesh->mColors[a][n].g,
mesh->mColors[a][n].b,
mesh->mColors[a][n].a);
}
}
ioprintf(io,"\t\t</Colors>\n");
}
ioprintf(io,"\t</Mesh>\n");
}
ioprintf(io,"</MeshList>\n");
}
ioprintf(io,"</Scene>\n</ASSIMP>");
}
} // end of namespace AssxmlExport
void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
IOStream * out = pIOSystem->Open( pFile, "wt" );
if (!out) return;
bool shortened = false;
AssxmlExport::WriteDump( pScene, out, shortened );
pIOSystem->Close( out );
}
} // end of namespace Assimp
#endif // ASSIMP_BUILD_NO_ASSXML_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -0,0 +1,49 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssxmlExporter.h
* ASSXML Exporter Main Header
*/
#ifndef AI_ASSXMLEXPORTER_H_INC
#define AI_ASSXMLEXPORTER_H_INC
// nothing really needed here - reserved for future use like properties
#endif

View File

@ -548,7 +548,7 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
void B3DImporter::ReadBB3D( aiScene *scene ){
_textures.clear();
_materials.size();
_materials.clear();
_vertices.clear();
_meshes.clear();

View File

@ -90,6 +90,11 @@ struct ScopeGuard
}
private:
// no copying allowed.
ScopeGuard();
ScopeGuard( const ScopeGuard & );
ScopeGuard &operator = ( const ScopeGuard & );
T* obj;
bool mdismiss;
};

View File

@ -65,7 +65,6 @@ BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
BMesh( mesh ),
triMesh( NULL )
{
AssertValidMesh( );
}
// ------------------------------------------------------------------------------------------------
@ -143,9 +142,21 @@ void BlenderBMeshConverter::DestroyTriMesh( )
void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly )
{
const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
if ( poly.totloop == 3 || poly.totloop == 4 )
{
AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 );
// UVs are optional, so only convert when present.
if ( BMesh->mloopuv.size() )
{
if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) )
{
ThrowException( "BMesh uv loop array has incorrect size" );
}
const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ];
AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 );
}
}
else if ( poly.totloop > 4 )
{
@ -173,4 +184,20 @@ void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
triMesh->totface = triMesh->mface.size( );
}
// ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 )
{
MTFace mtface;
memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 );
memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 );
memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 );
if ( uv4 )
{
memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 );
}
triMesh->mtface.push_back( mtface );
}
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -80,6 +80,7 @@ namespace Assimp
void DestroyTriMesh( );
void ConvertPolyToFaces( const Blender::MPoly& poly );
void AddFace( int v1, int v2, int v3, int v4 = 0 );
void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 );
const Blender::Mesh* BMesh;
Blender::Mesh* triMesh;

View File

@ -659,11 +659,15 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp
)
{
// TODO: Resolve various problems with BMesh triangluation before re-enabling.
// See issues #400, #373, #318 #315 and #132.
#if defined(TODO_FIX_BMESH_CONVERSION)
BlenderBMeshConverter BMeshConverter( mesh );
if ( BMeshConverter.ContainsBMesh( ) )
{
mesh = BMeshConverter.TriangulateBMesh( );
}
#endif
typedef std::pair<const int,size_t> MyPair;
if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) {
@ -999,7 +1003,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
}
// ------------------------------------------------------------------------------------------------
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/)
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* /*camera*/, ConversionData& /*conv_data*/)
{
ScopeGuard<aiCamera> out(new aiCamera());
out->mName = obj->id.name+2;
@ -1010,7 +1014,7 @@ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj,
}
// ------------------------------------------------------------------------------------------------
aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data)
aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/)
{
ScopeGuard<aiLight> out(new aiLight());
out->mName = obj->id.name+2;

View File

@ -324,7 +324,7 @@ void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCou
aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
{
aiVector3D sideA( 1.0f, 0.0f, 0.0f );
if ( fabs( plane.normal * sideA ) > 0.999f )
if ( std::fabs( plane.normal * sideA ) > 0.999f )
{
sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
}
@ -420,7 +420,7 @@ float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) con
{
for ( int y = 0; y < 3; ++y )
{
result = p2tMax( fabs( mtx[ x ][ y ] ), result );
result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
}
}

View File

@ -100,7 +100,7 @@ namespace boost {
};
// dummy
list_elem& operator = (const list_elem& other) {
list_elem& operator = (const list_elem& /*other*/) {
return *this;
}
@ -142,7 +142,7 @@ namespace boost {
return me.me;
}
};
};
}
// A very minimal implementation for up to 5 elements
template <typename T0 = detail::nulltype,
@ -278,6 +278,6 @@ namespace boost {
tuple <> t;
return t;
}
};
}
#endif // !! BOOST_TUPLE_INCLUDED

View File

@ -111,6 +111,7 @@ SET( Common_SRCS
MemoryIOWrapper.h
ParsingUtils.h
StreamReader.h
StreamWriter.h
StringComparison.h
SGSpatialSort.cpp
SGSpatialSort.h
@ -143,6 +144,7 @@ SET( Common_SRCS
LogAux.h
Bitmap.cpp
Bitmap.h
XMLTools.h
)
SOURCE_GROUP(Common FILES ${Common_SRCS})
@ -151,6 +153,8 @@ SET( 3DS_SRCS
3DSHelper.h
3DSLoader.cpp
3DSLoader.h
3DSExporter.h
3DSExporter.cpp
)
SOURCE_GROUP(3DS FILES ${3DS_SRCS})
@ -168,6 +172,20 @@ SET( ASE_SRCS
)
SOURCE_GROUP( ASE FILES ${ASE_SRCS})
SET( ASSBIN_SRCS
AssbinExporter.h
AssbinExporter.cpp
AssbinLoader.h
AssbinLoader.cpp
)
SOURCE_GROUP( Assbin FILES ${ASSBIN_SRCS})
SET( ASSXML_SRCS
AssxmlExporter.h
AssxmlExporter.cpp
)
SOURCE_GROUP( Assxml FILES ${ASSXML_SRCS})
SET( B3D_SRCS
B3DImporter.cpp
B3DImporter.h
@ -612,7 +630,7 @@ SOURCE_GROUP( unzip FILES ${unzip_SRCS})
# VC2010 fixes
if(MSVC10)
OPTION( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
if( VC10_STDINT_FIX )
ADD_DEFINITIONS( -D_STDINT )
endif( VC10_STDINT_FIX )
@ -643,6 +661,8 @@ SET( assimp_src
${3DS_SRCS}
${AC_SRCS}
${ASE_SRCS}
${ASSBIN_SRCS}
${ASSXML_SRCS}
${B3D_SRCS}
${BVH_SRCS}
${Collada_SRCS}
@ -705,6 +725,13 @@ ADD_LIBRARY( assimp ${assimp_src} )
SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES})
if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
add_subdirectory(../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/ ../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/)
target_link_libraries(assimp android_jniiosystem)
endif(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
SET_TARGET_PROPERTIES( assimp PROPERTIES
VERSION ${ASSIMP_VERSION}
SOVERSION ${ASSIMP_SOVERSION} # use full version
@ -731,6 +758,11 @@ INSTALL( TARGETS assimp
COMPONENT ${LIBASSIMP_COMPONENT})
INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)
INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev)
if (ASSIMP_ANDROID_JNIIOSYSTEM)
INSTALL(FILES ${HEADER_PATH}/../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h
DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
COMPONENT assimp-dev)
endif(ASSIMP_ANDROID_JNIIOSYSTEM)
if(MSVC AND ASSIMP_INSTALL_PDB)
install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${ASSIMP_DEBUG_POSTFIX}.pdb

View File

@ -115,9 +115,9 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// we assume that the mesh is still in the verbose vertex format where each face has its own set
// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
// assert() it here.
//assert( must be verbose, dammit);
// assert( must be verbose, dammit);
if (pMesh->mTangents) // thisimplies that mBitangents is also there
if (pMesh->mTangents) // this implies that mBitangents is also there
return false;
// If the mesh consists of lines and/or points but not of
@ -271,7 +271,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
const aiVector3D& origNorm = pMesh->mNormals[a];
const aiVector3D& origTang = pMesh->mTangents[a];
const aiVector3D& origBitang = pMesh->mBitangents[a];
closeVertices.clear();
closeVertices.resize( 0 );
// find all vertices close to that position
vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Bitmap.h"
#include "fast_atof.h"
#include "SceneCombiner.h"
#include "XMLTools.h"
#include <ctime>
#include <set>
@ -93,6 +94,7 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p
} // end of namespace Assimp
// ------------------------------------------------------------------------------------------------
// Constructor for a specific scene to export
ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file)
@ -140,7 +142,7 @@ void ColladaExporter::WriteFile()
// useless Collada fu at the end, just in case we haven't had enough indirections, yet.
mOutput << startstr << "<scene>" << endstr;
PushTag();
mOutput << startstr << "<instance_visual_scene url=\"#" + std::string(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
mOutput << startstr << "<instance_visual_scene url=\"#" + XMLEscape(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
PopTag();
mOutput << startstr << "</scene>" << endstr;
PopTag();
@ -236,12 +238,12 @@ void ColladaExporter::WriteHeader()
if (!meta || !meta->Get("Author", value))
mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
else
mOutput << startstr << "<author>" << value.C_Str() << "</author>" << endstr;
mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
if (!meta || !meta->Get("AuthoringTool", value))
mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
else
mOutput << startstr << "<authoring_tool>" << value.C_Str() << "</authoring_tool>" << endstr;
mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
//mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr;
//mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr;
@ -342,16 +344,20 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin
{
if( !pSurface.texture.empty() )
{
mOutput << startstr << "<image id=\"" << pNameAdd << "\">" << endstr;
mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr;
PushTag();
mOutput << startstr << "<init_from>";
// URL encode image file name first, then XML encode on top
std::stringstream imageUrlEncoded;
for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it )
{
if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
mOutput << *it;
imageUrlEncoded << *it;
else
mOutput << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
}
mOutput << XMLEscape(imageUrlEncoded.str());
mOutput << "</init_from>" << endstr;
PopTag();
mOutput << startstr << "</image>" << endstr;
@ -371,7 +377,7 @@ void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std
}
else
{
mOutput << startstr << "<texture texture=\"" << pImageName << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
mOutput << startstr << "<texture texture=\"" << XMLEscape(pImageName) << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
}
PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr;
@ -385,21 +391,21 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std
// if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
if( !pSurface.texture.empty() )
{
mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-surface\">" << endstr;
mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-surface\">" << endstr;
PushTag();
mOutput << startstr << "<surface type=\"2D\">" << endstr;
PushTag();
mOutput << startstr << "<init_from>" << pMatName << "-" << pTypeName << "-image</init_from>" << endstr;
mOutput << startstr << "<init_from>" << XMLEscape(pMatName) << "-" << pTypeName << "-image</init_from>" << endstr;
PopTag();
mOutput << startstr << "</surface>" << endstr;
PopTag();
mOutput << startstr << "</newparam>" << endstr;
mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-sampler\">" << endstr;
mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-sampler\">" << endstr;
PushTag();
mOutput << startstr << "<sampler2D>" << endstr;
PushTag();
mOutput << startstr << "<source>" << pMatName << "-" << pTypeName << "-surface</source>" << endstr;
mOutput << startstr << "<source>" << XMLEscape(pMatName) << "-" << pTypeName << "-surface</source>" << endstr;
PopTag();
mOutput << startstr << "</sampler2D>" << endstr;
PopTag();
@ -439,7 +445,7 @@ void ColladaExporter::WriteMaterials()
name = "mat";
materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
// isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion
// isalnum on MSVC asserts for code points outside [0,255]. Thus prevent unwanted promotion
// of char to signed int and take the unsigned char value.
if( !isalnum( static_cast<uint8_t>(*it) ) ) {
*it = '_';
@ -510,7 +516,7 @@ void ColladaExporter::WriteMaterials()
{
const Material& mat = *it;
// this is so ridiculous it must be right
mOutput << startstr << "<effect id=\"" << mat.name << "-fx\" name=\"" << mat.name << "\">" << endstr;
mOutput << startstr << "<effect id=\"" << XMLEscape(mat.name) << "-fx\" name=\"" << XMLEscape(mat.name) << "\">" << endstr;
PushTag();
mOutput << startstr << "<profile_COMMON>" << endstr;
PushTag();
@ -561,9 +567,9 @@ void ColladaExporter::WriteMaterials()
for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it )
{
const Material& mat = *it;
mOutput << startstr << "<material id=\"" << mat.name << "\" name=\"" << mat.name << "\">" << endstr;
mOutput << startstr << "<material id=\"" << XMLEscape(mat.name) << "\" name=\"" << mat.name << "\">" << endstr;
PushTag();
mOutput << startstr << "<instance_effect url=\"#" << mat.name << "-fx\"/>" << endstr;
mOutput << startstr << "<instance_effect url=\"#" << XMLEscape(mat.name) << "-fx\"/>" << endstr;
PopTag();
mOutput << startstr << "</material>" << endstr;
}
@ -591,13 +597,14 @@ void ColladaExporter::WriteGeometryLibrary()
void ColladaExporter::WriteGeometry( size_t pIndex)
{
const aiMesh* mesh = mScene->mMeshes[pIndex];
std::string idstr = GetMeshId( pIndex);
const std::string idstr = GetMeshId( pIndex);
const std::string idstrEscaped = XMLEscape(idstr);
if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
return;
// opening tag
mOutput << startstr << "<geometry id=\"" << idstr << "\" name=\"" << idstr << "_name\" >" << endstr;
mOutput << startstr << "<geometry id=\"" << idstrEscaped << "\" name=\"" << idstrEscaped << "_name\" >" << endstr;
PushTag();
mOutput << startstr << "<mesh>" << endstr;
@ -627,20 +634,20 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
}
// assemble vertex structure
mOutput << startstr << "<vertices id=\"" << idstr << "-vertices" << "\">" << endstr;
mOutput << startstr << "<vertices id=\"" << idstrEscaped << "-vertices" << "\">" << endstr;
PushTag();
mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstr << "-positions\" />" << endstr;
mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstrEscaped << "-positions\" />" << endstr;
if( mesh->HasNormals() )
mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstr << "-normals\" />" << endstr;
mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstrEscaped << "-normals\" />" << endstr;
for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
{
if( mesh->HasTextureCoords( a) )
mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstr << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr;
mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr;
}
for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
{
if( mesh->HasVertexColors( a) )
mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstr << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
}
PopTag();
@ -660,7 +667,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
{
mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
PushTag();
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstr << "-vertices\" />" << endstr;
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
mOutput << startstr << "<p>";
for( size_t a = 0; a < mesh->mNumFaces; ++a )
{
@ -681,7 +688,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
{
mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr;
PushTag();
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstr << "-vertices\" />" << endstr;
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
mOutput << startstr << "<vcount>";
for( size_t a = 0; a < mesh->mNumFaces; ++a )
@ -728,11 +735,11 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
std::string arrayId = pIdString + "-array";
mOutput << startstr << "<source id=\"" << pIdString << "\" name=\"" << pIdString << "\">" << endstr;
mOutput << startstr << "<source id=\"" << XMLEscape(pIdString) << "\" name=\"" << XMLEscape(pIdString) << "\">" << endstr;
PushTag();
// source array
mOutput << startstr << "<float_array id=\"" << arrayId << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
mOutput << startstr << "<float_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
PushTag();
if( pType == FloatType_TexCoord2 )
@ -804,11 +811,11 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
// Writes the scene library
void ColladaExporter::WriteSceneLibrary()
{
std::string scene_name = mScene->mRootNode->mName.C_Str();
const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str());
mOutput << startstr << "<library_visual_scenes>" << endstr;
PushTag();
mOutput << startstr << "<visual_scene id=\"" + scene_name + "\" name=\"" + scene_name + "\">" << endstr;
mOutput << startstr << "<visual_scene id=\"" + scene_name_escaped + "\" name=\"" + scene_name_escaped + "\">" << endstr;
PushTag();
// start recursive write at the root node
@ -833,7 +840,8 @@ void ColladaExporter::WriteNode(aiNode* pNode)
pNode->mName.Set(ss.str());
}
mOutput << startstr << "<node id=\"" << pNode->mName.data << "\" name=\"" << pNode->mName.data << "\">" << endstr;
const std::string node_name_escaped = XMLEscape(pNode->mName.data);
mOutput << startstr << "<node id=\"" << node_name_escaped << "\" name=\"" << node_name_escaped << "\">" << endstr;
PushTag();
// write transformation - we can directly put the matrix there
@ -854,13 +862,13 @@ void ColladaExporter::WriteNode(aiNode* pNode)
if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
continue;
mOutput << startstr << "<instance_geometry url=\"#" << GetMeshId( pNode->mMeshes[a]) << "\">" << endstr;
mOutput << startstr << "<instance_geometry url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "\">" << endstr;
PushTag();
mOutput << startstr << "<bind_material>" << endstr;
PushTag();
mOutput << startstr << "<technique_common>" << endstr;
PushTag();
mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << materials[mesh->mMaterialIndex].name << "\" />" << endstr;
mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLEscape(materials[mesh->mMaterialIndex].name) << "\" />" << endstr;
PopTag();
mOutput << startstr << "</technique_common>" << endstr;
PopTag();

View File

@ -118,7 +118,6 @@ struct Camera
float mZNear, mZFar;
};
#define aiLightSource_AMBIENT 0xdeaddead
#define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
/** A collada light source. */

View File

@ -73,7 +73,7 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ColladaLoader::ColladaLoader()
: noSkeletonMesh(), ignoreUpDirection(false)
: noSkeletonMesh(), ignoreUpDirection(false), mNodeNameCounter()
{}
// ------------------------------------------------------------------------------------------------
@ -133,6 +133,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
mLights.clear();
mCameras.clear();
mTextures.clear();
mAnims.clear();
// parse the input file
ColladaParser parser( pIOHandler, pFile);
@ -307,10 +308,6 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
continue;
}
const Collada::Light* srcLight = &srcLightIt->second;
if (srcLight->mType == aiLightSource_AMBIENT) {
DefaultLogger::get()->error("Collada: Skipping ambient light for the moment");
continue;
}
// now fill our ai data structure
aiLight* out = new aiLight();
@ -340,7 +337,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
{
// Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
// epsilon chosen to be 0.1
out->mAngleOuterCone = AI_DEG_TO_RAD (acos(pow(0.1f,1.f/srcLight->mFalloffExponent))+
out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
srcLight->mFalloffAngle);
}
else {
@ -904,6 +901,8 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
pScene->mAnimations = new aiAnimation*[mAnims.size()];
std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations);
}
mAnims.clear();
}
// ------------------------------------------------------------------------------------------------
@ -1544,7 +1543,7 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
// ------------------------------------------------------------------------------------------------
// Finds a proper name for a node derived from the collada-node's properties
std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode) const
std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
{
// now setup the name of the node. We take the name if not empty, otherwise the collada ID
// FIX: Workaround for XSI calling the instanced visual scene 'untitled' by default.
@ -1558,7 +1557,7 @@ std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode) const
{
// No need to worry. Unnamed nodes are no problem at all, except
// if cameras or lights need to be assigned to them.
return boost::str( boost::format( "$ColladaAutoName$_%d") % clock());
return boost::str( boost::format( "$ColladaAutoName$_%d") % mNodeNameCounter++);
}
}

View File

@ -203,7 +203,7 @@ protected:
const Collada::Node* FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const;
/** Finds a proper name for a node derived from the collada-node's properties */
std::string FindNameForNode( const Collada::Node* pNode) const;
std::string FindNameForNode( const Collada::Node* pNode);
protected:
/** Filename, for a verbose error message */
@ -235,6 +235,9 @@ protected:
bool noSkeletonMesh;
bool ignoreUpDirection;
/** Used by FindNameForNode() to generate unique node names */
unsigned int mNodeNameCounter;
};
} // end of namespace Assimp

View File

@ -1163,6 +1163,19 @@ void ColladaParser::ReadEffectProfileCommon( Collada::Effect& pEffect)
// just syntactic sugar
}
else if( mFormat == FV_1_4_n && IsElement( "image"))
{
// read ID. Another entry which is "optional" by design but obligatory in reality
int attrID = GetAttribute( "id");
std::string id = mReader->getAttributeValue( attrID);
// create an entry and store it in the library under its ID
mImageLibrary[id] = Image();
// read on from there
ReadImage( mImageLibrary[id]);
}
/* Shading modes */
else if( IsElement( "phong"))
pEffect.mShadeType = Shade_Phong;
@ -1854,14 +1867,15 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
// read primitive count from the attribute
int attrCount = GetAttribute( "count");
size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount);
// some mesh types (e.g. tristrips) don't specify primitive count upfront,
// so we need to sum up the actual number of primitives while we read the <p>-tags
size_t actualPrimitives = 0;
// material subgroup
int attrMaterial = TestAttribute( "material");
SubMesh subgroup;
if( attrMaterial > -1)
subgroup.mMaterial = mReader->getAttributeValue( attrMaterial);
subgroup.mNumFaces = numPrimitives;
pMesh->mSubMeshes.push_back( subgroup);
// distinguish between polys and triangles
std::string elementName = mReader->getNodeName();
@ -1920,7 +1934,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
if( !mReader->isEmptyElement())
{
// now here the actual fun starts - these are the indices to construct the mesh data from
ReadPrimitives( pMesh, perIndexData, numPrimitives, vcount, primType);
actualPrimitives += ReadPrimitives(pMesh, perIndexData, numPrimitives, vcount, primType);
}
} else
{
@ -1935,6 +1949,14 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
break;
}
}
// small sanity check
if (primType != Prim_TriFans && primType != Prim_TriStrips)
ai_assert(actualPrimitives == numPrimitives);
// only when we're done reading all <p> tags (and thus know the final vertex count) can we commit the submesh
subgroup.mNumFaces = actualPrimitives;
pMesh->mSubMeshes.push_back(subgroup);
}
// ------------------------------------------------------------------------------------------------
@ -1982,7 +2004,7 @@ void ColladaParser::ReadInputChannel( std::vector<InputChannel>& poChannels)
// ------------------------------------------------------------------------------------------------
// Reads a <p> primitive index list and assembles the mesh data into the given mesh
void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels,
size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels,
size_t pNumPrimitives, const std::vector<size_t>& pVCount, PrimitiveType pPrimType)
{
// determine number of indices coming per vertex
@ -2080,19 +2102,21 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
}
// now assemble vertex data according to those indices
std::vector<size_t>::const_iterator idx = indices.begin();
// For continued primitives, the given count does not come all in one <p>, but only one primitive per <p>
size_t numPrimitives = pNumPrimitives;
if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon)
numPrimitives = 1;
// For continued primitives, the given count is actually the number of <p>'s inside the parent tag
if ( pPrimType == Prim_TriStrips){
size_t numberOfVertices = indices.size() / numOffsets;
numPrimitives = numberOfVertices - 2;
}
pMesh->mFaceSize.reserve( numPrimitives);
pMesh->mFacePosIndices.reserve( indices.size() / numOffsets);
for( size_t a = 0; a < numPrimitives; a++)
size_t polylistStartVertex = 0;
for (size_t currentPrimitive = 0; currentPrimitive < numPrimitives; currentPrimitive++)
{
// determine number of points for this primitive
size_t numPoints = 0;
@ -2100,50 +2124,76 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
{
case Prim_Lines:
numPoints = 2;
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break;
case Prim_Triangles:
numPoints = 3;
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break;
case Prim_TriStrips:
numPoints = 3;
ReadPrimTriStrips(numOffsets, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break;
case Prim_Polylist:
numPoints = pVCount[a];
numPoints = pVCount[currentPrimitive];
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(polylistStartVertex + currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, 0, indices);
polylistStartVertex += numPoints;
break;
case Prim_TriFans:
case Prim_Polygon:
numPoints = indices.size() / numOffsets;
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break;
default:
// LineStrip and TriStrip not supported due to expected index unmangling
// LineStrip is not supported due to expected index unmangling
ThrowException( "Unsupported primitive type.");
break;
}
// store the face size to later reconstruct the face from
pMesh->mFaceSize.push_back( numPoints);
// gather that number of vertices
for( size_t b = 0; b < numPoints; b++)
{
// read all indices for this vertex. Yes, in a hacky local array
ai_assert( numOffsets < 20 && perVertexOffset < 20);
size_t vindex[20];
for( size_t offsets = 0; offsets < numOffsets; ++offsets)
vindex[offsets] = *idx++;
// extract per-vertex channels using the global per-vertex offset
for( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
ExtractDataObjectFromChannel( *it, vindex[perVertexOffset], pMesh);
// and extract per-index channels using there specified offset
for( std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
ExtractDataObjectFromChannel( *it, vindex[it->mOffset], pMesh);
// store the vertex-data index for later assignment of bone vertex weights
pMesh->mFacePosIndices.push_back( vindex[perVertexOffset]);
}
}
// if I ever get my hands on that guy who invented this steaming pile of indirection...
TestClosing( "p");
return numPrimitives;
}
void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices){
// calculate the base offset of the vertex whose attributes we ant to copy
size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets;
// don't overrun the boundaries of the index list
size_t maxIndexRequested = baseOffset + numOffsets - 1;
ai_assert(maxIndexRequested < indices.size());
// extract per-vertex channels using the global per-vertex offset
for (std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh);
// and extract per-index channels using there specified offset
for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh);
// store the vertex-data index for later assignment of bone vertex weights
pMesh->mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]);
}
void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices){
if (currentPrimitive % 2 != 0){
//odd tristrip triangles need their indices mangled, to preserve winding direction
CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
}
else {//for non tristrips or even tristrip triangles
CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
}
}
// ------------------------------------------------------------------------------------------------

View File

@ -177,9 +177,18 @@ protected:
void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
void ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
/** Copies the data for a single primitive into the mesh, based on the InputChannels */
void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
size_t currentPrimitive, const std::vector<size_t>& indices);
/** Reads one triangle of a tristrip into the mesh */
void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh,
std::vector<Collada::InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices);
/** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);

View File

@ -207,7 +207,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
out[pnt] = aiVector3D((atan2 (diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
(std::asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
}
}
else if (axis * base_axis_y >= angle_epsilon) {
@ -215,7 +215,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
out[pnt] = aiVector3D((atan2 (diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
(std::asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
}
}
else if (axis * base_axis_z >= angle_epsilon) {
@ -223,7 +223,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
(std::asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
}
}
// slower code path in case the mapping axis is not one of the coordinate system axes

View File

@ -57,12 +57,15 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MakeLeftHandedProcess::MakeLeftHandedProcess()
{}
: BaseProcess() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
MakeLeftHandedProcess::~MakeLeftHandedProcess()
{}
MakeLeftHandedProcess::~MakeLeftHandedProcess() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
@ -121,8 +124,9 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare
pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
// continue for all children
for( size_t a = 0; a < pNode->mNumChildren; ++a)
ProcessNode( pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation);
for( size_t a = 0; a < pNode->mNumChildren; ++a ) {
ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation );
}
}
// ------------------------------------------------------------------------------------------------
@ -244,6 +248,10 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
aiMaterial* mat = (aiMaterial*)_mat;
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
aiMaterialProperty* prop = mat->mProperties[a];
if( !prop ) {
DefaultLogger::get()->debug( "Property is null" );
continue;
}
// UV transformation key?
if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) {
@ -263,11 +271,13 @@ void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
{
// mirror texture y coordinate
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
if( !pMesh->HasTextureCoords( a))
if( !pMesh->HasTextureCoords( a ) ) {
break;
}
for( unsigned int b = 0; b < pMesh->mNumVertices; b++)
pMesh->mTextureCoords[a][b].y = 1.0f - pMesh->mTextureCoords[a][b].y;
for( unsigned int b = 0; b < pMesh->mNumVertices; b++ ) {
pMesh->mTextureCoords[ a ][ b ].y = 1.0f - pMesh->mTextureCoords[ a ][ b ].y;
}
}
}

View File

@ -111,8 +111,8 @@ void DeboneProcess::Execute( aiScene* pScene)
if(numSplits) {
// we need to do something. Let's go.
mSubMeshIndices.clear();
mSubMeshIndices.resize(pScene->mNumMeshes);
//mSubMeshIndices.clear(); // really needed?
mSubMeshIndices.resize(pScene->mNumMeshes); // because we're doing it here anyway
// build a new array of meshes for the scene
std::vector<aiMesh*> meshes;

View File

@ -56,52 +56,59 @@ namespace Assimp {
class DefaultIOStream : public IOStream
{
friend class DefaultIOSystem;
#if __ANDROID__
#if __ANDROID_API__ > 9
#if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
friend class AndroidJNIIOSystem;
#endif // defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
#endif // __ANDROID_API__ > 9
#endif // __ANDROID__
protected:
DefaultIOStream ();
DefaultIOStream (FILE* pFile, const std::string &strFilename);
DefaultIOStream();
DefaultIOStream(FILE* pFile, const std::string &strFilename);
public:
/** Destructor public to allow simple deletion to close the file. */
~DefaultIOStream ();
// -------------------------------------------------------------------
// Read from stream
/// Read from stream
size_t Read(void* pvBuffer,
size_t pSize,
size_t pCount);
// -------------------------------------------------------------------
// Write to stream
/// Write to stream
size_t Write(const void* pvBuffer,
size_t pSize,
size_t pCount);
// -------------------------------------------------------------------
// Seek specific position
/// Seek specific position
aiReturn Seek(size_t pOffset,
aiOrigin pOrigin);
// -------------------------------------------------------------------
// Get current seek position
/// Get current seek position
size_t Tell() const;
// -------------------------------------------------------------------
// Get size of file
/// Get size of file
size_t FileSize() const;
// -------------------------------------------------------------------
// Flush file contents
/// Flush file contents
void Flush();
private:
//! File datastructure, using clib
// File datastructure, using clib
FILE* mFile;
//! Filename
// Filename
std::string mFilename;
//! Cached file size
// Cached file size
mutable size_t cachedSize;
};

View File

@ -78,7 +78,10 @@ void ExportSceneObj(const char*,IOSystem*, const aiScene*);
void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
void ExportScenePly(const char*,IOSystem*, const aiScene*);
void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*);
void ExportScene3DS(const char*, IOSystem*, const aiScene*);
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*);
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*);
// ------------------------------------------------------------------------------------------------
// global array of all export formats which Assimp supports in its current build
@ -111,11 +114,23 @@ Exporter::ExportFormatEntry gExporters[] =
Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly,
aiProcess_PreTransformVertices
),
Exporter::ExportFormatEntry( "plyb", "Stanford Polygon Library (binary)", "ply", &ExportScenePlyBinary,
aiProcess_PreTransformVertices
),
#endif
//#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
// ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS),
//#endif
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
#endif
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
#endif
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0),
#endif
};
#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
@ -444,6 +459,11 @@ const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex
return NULL;
}
// Return from static storage if the requested index is built-in.
if (pIndex < sizeof(gExporters) / sizeof(gExporters[0])) {
return &gExporters[pIndex].mDescription;
}
return &pimpl->mExporters[pIndex].mDescription;
}

View File

@ -59,7 +59,7 @@ namespace FBX {
using namespace Util;
// ------------------------------------------------------------------------------------------------
AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc)
AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
: Object(id, element, name)
{
const Scope& sc = GetRequiredScope(element);

View File

@ -55,14 +55,15 @@ namespace FBX {
// ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
: sbegin(sbegin)
:
#ifdef DEBUG
contents(sbegin, static_cast<size_t>(send-sbegin)),
#endif
sbegin(sbegin)
, send(send)
, type(type)
, line(offset)
, column(BINARY_MARKER)
#ifdef DEBUG
, contents(sbegin, static_cast<size_t>(send-sbegin))
#endif
{
ai_assert(sbegin);
ai_assert(send);

View File

@ -381,8 +381,6 @@ private:
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
out_camera->mPosition = cam.Position();
out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition;
// BUG HERE cam.FieldOfView() returns 1.0f every time. 1.0f is default value.
out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
}
@ -499,15 +497,15 @@ private:
bool is_id[3] = { true, true, true };
aiMatrix4x4 temp[3];
if(fabs(rotation.z) > angle_epsilon) {
if(std::fabs(rotation.z) > angle_epsilon) {
aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z),temp[2]);
is_id[2] = false;
}
if(fabs(rotation.y) > angle_epsilon) {
if(std::fabs(rotation.y) > angle_epsilon) {
aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y),temp[1]);
is_id[1] = false;
}
if(fabs(rotation.x) > angle_epsilon) {
if(std::fabs(rotation.x) > angle_epsilon) {
aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x),temp[0]);
is_id[0] = false;
}
@ -676,7 +674,7 @@ private:
}
const aiVector3D& Scaling = PropertyGet<aiVector3D>(props,"Lcl Scaling",ok);
if(ok && fabs(Scaling.SquareLength()-1.0f) > zero_epsilon) {
if(ok && std::fabs(Scaling.SquareLength()-1.0f) > zero_epsilon) {
aiMatrix4x4::Scaling(Scaling,chain[TransformationComp_Scaling]);
}
@ -686,7 +684,7 @@ private:
}
const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok);
if (ok && fabs(GeometricScaling.SquareLength() - 1.0f) > zero_epsilon) {
if (ok && std::fabs(GeometricScaling.SquareLength() - 1.0f) > zero_epsilon) {
aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]);
}
@ -767,7 +765,6 @@ private:
// find user defined properties (3ds Max)
data->Set(index++, "UserProperties", aiString(PropertyGet<std::string>(props, "UDP3DSMAX", "")));
unparsedProperties.erase("UDP3DSMAX");
// preserve the info that a node was marked as Null node in the original file.
data->Set(index++, "IsNull", model.IsNull() ? true : false);
@ -1320,7 +1317,7 @@ private:
// ------------------------------------------------------------------------------------------------
void ConvertCluster(std::vector<aiBone*>& bones, const Model& model, const Cluster& cl,
void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
std::vector<size_t>& out_indices,
std::vector<size_t>& index_out_indices,
std::vector<size_t>& count_out_indices,
@ -2348,7 +2345,7 @@ private:
// ------------------------------------------------------------------------------------------------
aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
const Model& target,
const Model& /*target*/,
const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map,
double& max_time,
@ -2379,7 +2376,7 @@ private:
// ------------------------------------------------------------------------------------------------
aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
const Model& target,
const Model& /*target*/,
const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map,
double& max_time,
@ -2831,7 +2828,7 @@ private:
// ------------------------------------------------------------------------------------------------
void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& layers,
void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
double& maxTime,
double& minTime)
{
@ -2852,7 +2849,7 @@ private:
// ------------------------------------------------------------------------------------------------
void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& layers,
const LayerMap& /*layers*/,
double& maxTime,
double& minTime)
{
@ -2870,7 +2867,7 @@ private:
// ------------------------------------------------------------------------------------------------
void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& layers,
const LayerMap& /*layers*/,
double& maxTime,
double& minTime,
Model::RotOrder order)

View File

@ -253,8 +253,8 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
: settings(settings)
, parser(parser)
{
// cannot use array default initialization syntax because vc8 fails on it
for (unsigned int i = 0; i < 7; ++i) {
// Cannot use array default initialization syntax because vc8 fails on it
for (unsigned int i = 0; i < sizeof(creationTimeStamp) / sizeof(creationTimeStamp[0]); ++i) {
creationTimeStamp[i] = 0;
}
@ -263,7 +263,7 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
ReadGlobalSettings();
// this order is important, connections need parsed objects to check
// This order is important, connections need parsed objects to check
// whether connections are ok or not. Objects may not be evaluated yet,
// though, since this may require valid connections.
ReadObjects();
@ -277,13 +277,18 @@ Document::~Document()
BOOST_FOREACH(ObjectMap::value_type& v, objects) {
delete v.second;
}
BOOST_FOREACH(ConnectionMap::value_type& v, src_connections) {
delete v.second;
}
// |dest_connections| contain the same Connection objects as the |src_connections|
}
// ------------------------------------------------------------------------------------------------
void Document::ReadHeader()
{
// read ID objects from "Objects" section
// Read ID objects from "Objects" section
const Scope& sc = parser.GetRootScope();
const Element* const ehead = sc["FBXHeaderExtension"];
if(!ehead || !ehead->Compound()) {
@ -293,7 +298,7 @@ void Document::ReadHeader()
const Scope& shead = *ehead->Compound();
fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
// while we maye have some success with newer files, we don't support
// While we maye have some success with newer files, we don't support
// the older 6.n fbx format
if(fbxVersion < 7100) {
DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");

View File

@ -696,7 +696,7 @@ public:
public:
/** Get the Skin attached to this geometry or NULL */
const Skin* const DeformerSkin() const {
const Skin* DeformerSkin() const {
return skin;
}
@ -1096,7 +1096,7 @@ public:
return transformLink;
}
const Model* const TargetNode() const {
const Model* TargetNode() const {
return node;
}

View File

@ -105,7 +105,7 @@ bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
else if ((!extension.length() || checkSig) && pIOHandler) {
// at least ascii FBX files usually have a 'FBX' somewhere in their head
const char* tokens[] = {"FBX"};
const char* tokens[] = {"fbx"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
@ -179,6 +179,8 @@ void FBXImporter::InternReadFile( const std::string& pFile,
// convert the FBX DOM to aiScene
ConvertToAssimpScene(pScene,doc);
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
}
catch(std::exception&) {
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());

View File

@ -207,7 +207,7 @@ Texture::~Texture()
}
LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
: Object(id,element,name)
,texture(0)
,blendMode(BlendMode_Modulate)

View File

@ -466,8 +466,9 @@ void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out,
const std::string& MappingInformationType,
const std::string& ReferenceInformationType)
{
const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
"Tangent",
str,
"TangentIndex",
vertices.size(),
mapping_counts,
@ -481,8 +482,9 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_ou
const std::string& MappingInformationType,
const std::string& ReferenceInformationType)
{
const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
"Binormal",
str,
"BinormalIndex",
vertices.size(),
mapping_counts,

View File

@ -93,7 +93,7 @@ namespace {
}
// ------------------------------------------------------------------------------------------------
void ParseWarning(const std::string& message, const Element* element = NULL)
/* void ParseWarning(const std::string& message, const Element* element = NULL)
{
if(element) {
ParseWarning(message,element->KeyToken());
@ -103,7 +103,7 @@ namespace {
DefaultLogger::get()->warn("FBX-Parser: " + message);
}
}
*/
// ------------------------------------------------------------------------------------------------
void ParseError(const std::string& message, TokenPtr token)
{
@ -113,6 +113,18 @@ namespace {
ParseError(message);
}
// Initially, we did reinterpret_cast, breaking strict aliasing rules.
// This actually caused trouble on Android, so let's be safe this time.
// https://github.com/assimp/assimp/issues/24
template <typename T>
T SafeParse(const char* data, const char* end) {
// Actual size validation happens during Tokenization so
// this is valid as an assertion.
ai_assert(static_cast<size_t>(end - data) >= sizeof(T));
T result = static_cast<T>(0);
::memcpy(&result, data, sizeof(T));
return result;
}
}
namespace Assimp {
@ -275,9 +287,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
return 0L;
}
ai_assert(t.end() - data == 9);
BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
AI_SWAP8(id);
return id;
}
@ -316,8 +326,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
return 0;
}
ai_assert(t.end() - data == 9);
BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
AI_SWAP8(id);
return static_cast<size_t>(id);
}
@ -364,24 +373,10 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
}
if (data[0] == 'F') {
// Actual size validation happens during Tokenization so
// this is valid as an assertion.
ai_assert(t.end() - data == sizeof(float) + 1);
// Initially, we did reinterpret_cast, breaking strict aliasing rules.
// This actually caused trouble on Android, so let's be safe this time.
// https://github.com/assimp/assimp/issues/24
float out_float;
::memcpy(&out_float, data+1, sizeof(float));
return out_float;
return SafeParse<float>(data+1, t.end());
}
else {
ai_assert(t.end() - data == sizeof(double) + 1);
// Same
double out_double;
::memcpy(&out_double, data+1, sizeof(double));
return out_double;
return static_cast<float>( SafeParse<double>(data+1, t.end()) );
}
}
@ -416,8 +411,7 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
return 0;
}
ai_assert(t.end() - data == 5);
BE_NCONST int32_t ival = *reinterpret_cast<const int32_t*>(data+1);
BE_NCONST int32_t ival = SafeParse<int32_t>(data+1, t.end());
AI_SWAP4(ival);
return static_cast<int>(ival);
}
@ -453,10 +447,8 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
return "";
}
ai_assert(t.end() - data >= 5);
// read string length
BE_NCONST int32_t len = *reinterpret_cast<const int32_t*>(data+1);
BE_NCONST int32_t len = SafeParse<int32_t>(data+1, t.end());
AI_SWAP4(len);
ai_assert(t.end() - data == 5 + len);
@ -494,7 +486,7 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
type = *data;
// read number of elements
BE_NCONST uint32_t len = *reinterpret_cast<const uint32_t*>(data+1);
BE_NCONST uint32_t len = SafeParse<uint32_t>(data+1, end);
AI_SWAP4(len);
count = len;
@ -506,16 +498,14 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
std::vector<char>& buff,
const Element& el)
const Element& /*el*/)
{
ai_assert(static_cast<size_t>(end-data) >= 4); // runtime check for this happens at tokenization stage
BE_NCONST uint32_t encmode = *reinterpret_cast<const uint32_t*>(data);
BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
AI_SWAP4(encmode);
data += 4;
// next comes the compressed length
BE_NCONST uint32_t comp_len = *reinterpret_cast<const uint32_t*>(data);
BE_NCONST uint32_t comp_len = SafeParse<uint32_t>(data, end);
AI_SWAP4(comp_len);
data += 4;

View File

@ -85,7 +85,7 @@ Property* ReadTypedProperty(const Element& element)
else if (!strcmp(cs,"bool") || !strcmp(cs,"Bool")) {
return new TypedProperty<bool>(ParseTokenAsInt(*tok[4]) != 0);
}
else if (!strcmp(cs,"int") || !strcmp(cs,"enum")) {
else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum")) {
return new TypedProperty<int>(ParseTokenAsInt(*tok[4]));
}
else if (!strcmp(cs,"ULongLong")) {
@ -105,7 +105,7 @@ Property* ReadTypedProperty(const Element& element)
ParseTokenAsFloat(*tok[6]))
);
}
else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"KTime") || !strcmp(cs,"Float")) {
else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"KTime") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView")) {
return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
}
return NULL;

View File

@ -143,8 +143,7 @@ private:
// ------------------------------------------------------------------------------------------------
template <typename T>
inline T PropertyGet(const PropertyTable& in, const std::string& name,
const T& defaultValue,
bool ignoreTemplate = false)
const T& defaultValue)
{
const Property* const prop = in.Get(name);
if(!prop) {
@ -164,8 +163,7 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
// ------------------------------------------------------------------------------------------------
template <typename T>
inline T PropertyGet(const PropertyTable& in, const std::string& name,
bool& result,
bool ignoreTemplate = false)
bool& result)
{
const Property* const prop = in.Get(name);
if(!prop) {

View File

@ -58,14 +58,15 @@ namespace FBX {
// ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column)
: sbegin(sbegin)
:
#ifdef DEBUG
contents(sbegin, static_cast<size_t>(send-sbegin)),
#endif
sbegin(sbegin)
, send(send)
, type(type)
, line(line)
, column(column)
#ifdef DEBUG
, contents(sbegin, static_cast<size_t>(send-sbegin))
#endif
{
ai_assert(sbegin);
ai_assert(send);

View File

@ -85,8 +85,7 @@ bool CompareBones(const aiMesh* orig, const aiMesh* inst)
aiBone* oha = inst->mBones[i];
if (aha->mNumWeights != oha->mNumWeights ||
aha->mOffsetMatrix != oha->mOffsetMatrix ||
aha->mNumWeights != oha->mNumWeights) {
aha->mOffsetMatrix != oha->mOffsetMatrix) {
return false;
}
@ -174,7 +173,6 @@ void FindInstancesProcess::Execute( aiScene* pScene)
// use a constant epsilon for colors and UV coordinates
static const float uvEpsilon = 10e-4f;
{
unsigned int i, end = orig->GetNumUVChannels();
for(i = 0; i < end; ++i) {
@ -260,7 +258,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
pScene->mMeshes[real++] = pScene->mMeshes[i];
}
// And update the nodegraph with our nice lookup table
// And update the node graph with our nice lookup table
UpdateMeshIndices(pScene->mRootNode,remapping.get());
// write to log

View File

@ -221,7 +221,7 @@ AI_FORCE_INLINE bool EpsilonCompare(const T& n, const T& s, float epsilon);
// ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE bool EpsilonCompare(float n, float s, float epsilon) {
return fabs(n-s)>epsilon;
return std::fabs(n-s)>epsilon;
}
// ------------------------------------------------------------------------------------------------

View File

@ -149,8 +149,8 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false;
// now compare the volumes of the bounding boxes
if (::fabsf(fDelta0_x * fDelta1_yz) <
::fabsf(fDelta1_x * fDelta1_y * fDelta1_z))
if (std::fabs(fDelta0_x * fDelta1_yz) <
std::fabs(fDelta1_x * fDelta1_y * fDelta1_z))
{
if (!DefaultLogger::isNullLogger())
{

View File

@ -204,7 +204,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
// Slower code path if a smooth angle is set. There are many ways to achieve
// the effect, this one is the most straightforward one.
else {
const float fLimit = ::cos(configMaxAngle);
const float fLimit = std::cos(configMaxAngle);
for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
// Get all vertices that share this one ...
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);

View File

@ -53,7 +53,7 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** The GenFaceNormalsProcess computes vertex normals for all vertizes
*/
class ASSIMP_API_WINONLY GenVertexNormalsProcess : public BaseProcess
class ASSIMP_API GenVertexNormalsProcess : public BaseProcess
{
public:

View File

@ -69,8 +69,8 @@ Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const I
const IfcVector3 pdelta = e0 - p, seg = e1-e0;
const IfcFloat dotOne = n*seg, dotTwo = -(n*pdelta);
if (fabs(dotOne) < 1e-6) {
return fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No;
if (std::fabs(dotOne) < 1e-6) {
return std::fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No;
}
const IfcFloat t = dotTwo/dotOne;
@ -85,7 +85,7 @@ Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const I
// ------------------------------------------------------------------------------------------------
void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
const TempMesh& first_operand,
ConversionData& conv)
ConversionData& /*conv*/)
{
ai_assert(hs != NULL);
@ -210,7 +210,7 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons
// segment-segment intersection
// solve b0 + b*s = e0 + e*t for (s,t)
const IfcFloat det = (-b.x * e.y + e.x * b.y);
if(fabs(det) < 1e-6) {
if(std::fabs(det) < 1e-6) {
// no solutions (parallel lines)
continue;
}
@ -234,7 +234,7 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons
if (t >= -epsilon && (t <= 1.0+epsilon || half_open) && s >= -epsilon && s <= 1.0) {
if (e0_hits_border && !*e0_hits_border) {
*e0_hits_border = fabs(t) < 1e-5f;
*e0_hits_border = std::fabs(t) < 1e-5f;
}
const IfcVector3& p = e0 + e*t;
@ -419,7 +419,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBounded
#ifdef ASSIMP_BUILD_DEBUG
if (isect == Intersect_Yes) {
const IfcFloat f = fabs((isectpos - p)*n);
const IfcFloat f = std::fabs((isectpos - p)*n);
ai_assert(f < 1e-5);
}
#endif

View File

@ -88,10 +88,10 @@ public:
a *= conv.angle_scale;
b *= conv.angle_scale;
a = fmod(a,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
b = fmod(b,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
a = std::fmod(a,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
b = std::fmod(b,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
const IfcFloat setting = static_cast<IfcFloat>( AI_MATH_PI * conv.settings.conicSamplingAngle / 180.0 );
return static_cast<size_t>( ceil(abs( b-a)) / setting);
return static_cast<size_t>( std::ceil(abs( b-a)) / setting);
}
// --------------------------------------------------
@ -124,8 +124,8 @@ public:
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const {
u = -conv.angle_scale * u;
return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(::cos(u))*p[0] +
static_cast<IfcFloat>(::sin(u))*p[1]);
return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(std::cos(u))*p[0] +
static_cast<IfcFloat>(std::sin(u))*p[1]);
}
private:
@ -153,8 +153,8 @@ public:
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const {
u = -conv.angle_scale * u;
return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(::cos(u))*p[0] +
static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(::sin(u))*p[1];
return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(std::cos(u))*p[0] +
static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(std::sin(u))*p[1];
}
private:
@ -486,7 +486,7 @@ public:
IfcVector3 Eval(IfcFloat p) const {
ai_assert(InRange(p));
const size_t b = static_cast<size_t>(floor(p));
const size_t b = static_cast<size_t>(std::floor(p));
if (b == points.size()-1) {
return points.back();
}
@ -498,7 +498,7 @@ public:
// --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
ai_assert(InRange(a) && InRange(b));
return static_cast<size_t>( ceil(b) - floor(a) );
return static_cast<size_t>( std::ceil(b) - std::floor(a) );
}
// --------------------------------------------------
@ -558,7 +558,7 @@ bool Curve :: InRange(IfcFloat u) const
if (IsClosed()) {
return true;
//ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
//u = range.first + fmod(u-range.first,range.second-range.first);
//u = range.first + std::fmod(u-range.first,range.second-range.first);
}
const IfcFloat epsilon = 1e-5;
return u - range.first > -epsilon && range.second - u > -epsilon;
@ -606,12 +606,12 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
}
ai_assert(min_diff[0] != inf && min_diff[1] != inf);
if ( fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
return min_point[0];
}
// fix for closed curves to take their wrap-over into account
if (cv->IsClosed() && fabs(min_point[0]-min_point[1]) > cv->GetParametricRangeDelta()*0.5 ) {
if (cv->IsClosed() && std::fabs(min_point[0]-min_point[1]) > cv->GetParametricRangeDelta()*0.5 ) {
const Curve::ParamRange& range = cv->GetParametricRange();
const IfcFloat wrapdiff = (cv->Eval(range.first)-val).SquareLength();

View File

@ -250,17 +250,17 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul
bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
const IfcFloat max_angle = solid.Angle*conv.angle_scale;
if(fabs(max_angle) < 1e-3) {
if(std::fabs(max_angle) < 1e-3) {
if(has_area) {
result = meshout;
}
return;
}
const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(16 * fabs(max_angle)/AI_MATH_HALF_PI_F));
const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(16 * std::fabs(max_angle)/AI_MATH_HALF_PI_F));
const IfcFloat delta = max_angle/cnt_segments;
has_area = has_area && fabs(max_angle) < AI_MATH_TWO_PI_F*0.99;
has_area = has_area && std::fabs(max_angle) < AI_MATH_TWO_PI_F*0.99;
result.verts.reserve(size*((cnt_segments+1)*4+(has_area?2:0)));
result.vertcnt.reserve(size*cnt_segments+2);
@ -480,7 +480,7 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
for (i = 0; !done && i < s-2; done || ++i) {
for (j = i+1; j < s-1; ++j) {
nor = -((out[i]-any_point)^(out[j]-any_point));
if(fabs(nor.Length()) > 1e-8f) {
if(std::fabs(nor.Length()) > 1e-8f) {
done = true;
break;
}

View File

@ -259,7 +259,7 @@ BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly)
// ------------------------------------------------------------------------------------------------
void InsertWindowContours(const ContourVector& contours,
const std::vector<TempOpening>& openings,
const std::vector<TempOpening>& /*openings*/,
TempMesh& curmesh)
{
// fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
@ -303,20 +303,20 @@ void InsertWindowContours(const ContourVector& contours,
const IfcVector2& v = contour[n];
bool hit = false;
if (fabs(v.x-bb.first.x)<epsilon) {
if (std::fabs(v.x-bb.first.x)<epsilon) {
edge.x = bb.first.x;
hit = true;
}
else if (fabs(v.x-bb.second.x)<epsilon) {
else if (std::fabs(v.x-bb.second.x)<epsilon) {
edge.x = bb.second.x;
hit = true;
}
if (fabs(v.y-bb.first.y)<epsilon) {
if (std::fabs(v.y-bb.first.y)<epsilon) {
edge.y = bb.first.y;
hit = true;
}
else if (fabs(v.y-bb.second.y)<epsilon) {
else if (std::fabs(v.y-bb.second.y)<epsilon) {
edge.y = bb.second.y;
hit = true;
}
@ -343,17 +343,17 @@ void InsertWindowContours(const ContourVector& contours,
IfcVector2 corner = edge;
if (fabs(contour[last_hit].x-bb.first.x)<epsilon) {
if (std::fabs(contour[last_hit].x-bb.first.x)<epsilon) {
corner.x = bb.first.x;
}
else if (fabs(contour[last_hit].x-bb.second.x)<epsilon) {
else if (std::fabs(contour[last_hit].x-bb.second.x)<epsilon) {
corner.x = bb.second.x;
}
if (fabs(contour[last_hit].y-bb.first.y)<epsilon) {
if (std::fabs(contour[last_hit].y-bb.first.y)<epsilon) {
corner.y = bb.first.y;
}
else if (fabs(contour[last_hit].y-bb.second.y)<epsilon) {
else if (std::fabs(contour[last_hit].y-bb.second.y)<epsilon) {
corner.y = bb.second.y;
}
@ -590,10 +590,10 @@ bool BoundingBoxesAdjacent(const BoundingBox& bb, const BoundingBox& ibb)
{
// TODO: I'm pretty sure there is a much more compact way to check this
const IfcFloat epsilon = 1e-5f;
return (fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
(fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) ||
(fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.first.x) ||
(fabs(bb.first.y - ibb.second.y) < epsilon && ibb.first.x <= bb.second.x && ibb.second.x >= bb.first.x);
return (std::fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
(std::fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) ||
(std::fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.first.x) ||
(std::fabs(bb.first.y - ibb.second.y) < epsilon && ibb.first.x <= bb.second.x && ibb.second.x >= bb.first.x);
}
// ------------------------------------------------------------------------------------------------
@ -615,11 +615,11 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
static const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity();
if (!(n0_to_m0.SquareLength() < e*e || fabs(n0_to_m0 * n0_to_n1) / (n0_to_m0.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
if (!(n0_to_m0.SquareLength() < e*e || std::fabs(n0_to_m0 * n0_to_n1) / (n0_to_m0.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
return false;
}
if (!(n1_to_m1.SquareLength() < e*e || fabs(n1_to_m1 * n0_to_n1) / (n1_to_m1.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
if (!(n1_to_m1.SquareLength() < e*e || std::fabs(n1_to_m1 * n0_to_n1) / (n1_to_m1.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
return false;
}
@ -631,14 +631,14 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
// the higher absolute difference is big enough as to avoid
// divisions by zero, the case 0/0 ~ infinity is detected and
// handled separately.
if(fabs(n0_to_n1.x) > fabs(n0_to_n1.y)) {
if(std::fabs(n0_to_n1.x) > std::fabs(n0_to_n1.y)) {
s0 = n0_to_m0.x / n0_to_n1.x;
s1 = n0_to_m1.x / n0_to_n1.x;
if (fabs(s0) == inf && fabs(n0_to_m0.x) < smalle) {
if (std::fabs(s0) == inf && std::fabs(n0_to_m0.x) < smalle) {
s0 = 0.;
}
if (fabs(s1) == inf && fabs(n0_to_m1.x) < smalle) {
if (std::fabs(s1) == inf && std::fabs(n0_to_m1.x) < smalle) {
s1 = 0.;
}
}
@ -646,10 +646,10 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
s0 = n0_to_m0.y / n0_to_n1.y;
s1 = n0_to_m1.y / n0_to_n1.y;
if (fabs(s0) == inf && fabs(n0_to_m0.y) < smalle) {
if (std::fabs(s0) == inf && std::fabs(n0_to_m0.y) < smalle) {
s0 = 0.;
}
if (fabs(s1) == inf && fabs(n0_to_m1.y) < smalle) {
if (std::fabs(s1) == inf && std::fabs(n0_to_m1.y) < smalle) {
s1 = 0.;
}
}
@ -664,7 +664,7 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
s0 = std::min(1.0,s0);
s1 = std::min(1.0,s1);
if (fabs(s1-s0) < e) {
if (std::fabs(s1-s0) < e) {
return false;
}
@ -755,7 +755,7 @@ void FindAdjacentContours(ContourVector::iterator current, const ContourVector&
AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta)
{
const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(1e-5);
return fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
return std::fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
}
// ------------------------------------------------------------------------------------------------
@ -812,9 +812,9 @@ void FindBorderContours(ContourVector::iterator current)
// ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE bool LikelyDiagonal(IfcVector2 vdelta)
{
vdelta.x = fabs(vdelta.x);
vdelta.y = fabs(vdelta.y);
return (fabs(vdelta.x-vdelta.y) < 0.8 * std::max(vdelta.x, vdelta.y));
vdelta.x = std::fabs(vdelta.x);
vdelta.y = std::fabs(vdelta.y);
return (std::fabs(vdelta.x-vdelta.y) < 0.8 * std::max(vdelta.x, vdelta.y));
}
// ------------------------------------------------------------------------------------------------
@ -926,7 +926,7 @@ size_t CloseWindows(ContourVector& contours,
/* debug code to check for unwanted diagonal lines in window contours
if (cit != cbegin) {
const IfcVector2& vdelta = proj_point - last_proj;
if (fabs(vdelta.x-vdelta.y) < 0.5 * std::max(vdelta.x, vdelta.y)) {
if (std::fabs(vdelta.x-vdelta.y) < 0.5 * std::max(vdelta.x, vdelta.y)) {
//continue;
}
} */
@ -1065,7 +1065,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
}
#ifdef ASSIMP_BUILD_DEBUG
const IfcFloat det = m.Determinant();
ai_assert(fabs(det-1) < 1e-5);
ai_assert(std::fabs(det-1) < 1e-5);
#endif
IfcFloat zcoord = 0;
@ -1085,7 +1085,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
// XXX this should be guarded, but we somehow need to pick a suitable
// epsilon
// if(coord != -1.0f) {
// assert(fabs(coord - vv.z) < 1e-3f);
// assert(std::fabs(coord - vv.z) < 1e-3f);
// }
zcoord += vv.z;
vmin = std::min(vv, vmin);
@ -1125,7 +1125,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
const IfcVector3& vv = m * x;
out_contour2.push_back(IfcVector2(vv.x,vv.y));
ai_assert(fabs(vv.z) < vmax.z + 1e-8);
ai_assert(std::fabs(vv.z) < vmax.z + 1e-8);
}
for(size_t i = 0; i < out_contour.size(); ++i) {
@ -1188,9 +1188,9 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
bool is_2d_source = false;
if (opening.profileMesh2D && norm_extrusion_dir.SquareLength() > 0) {
if(fabs(norm_extrusion_dir * wall_extrusion_axis_norm) < 0.1) {
if(std::fabs(norm_extrusion_dir * wall_extrusion_axis_norm) < 0.1) {
// horizontal extrusion
if (fabs(norm_extrusion_dir * nor) > 0.9) {
if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
profile_data = opening.profileMesh2D.get();
is_2d_source = true;
}
@ -1200,7 +1200,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
}
else {
// vertical extrusion
if (fabs(norm_extrusion_dir * nor) > 0.9) {
if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
continue;
}
continue;
@ -1289,7 +1289,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
ai_assert(!is_2d_source);
const IfcVector2 area = vpmax-vpmin;
const IfcVector2 area2 = vpmax2-vpmin2;
if (temp_contour.size() <= 2 || fabs(area2.x * area2.y) > fabs(area.x * area.y)) {
if (temp_contour.size() <= 2 || std::fabs(area2.x * area2.y) > std::fabs(area.x * area.y)) {
temp_contour.swap(temp_contour2);
vpmax = vpmax2;
@ -1301,7 +1301,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
}
// TODO: This epsilon may be too large
const IfcFloat epsilon = fabs(dmax-dmin) * 0.0001;
const IfcFloat epsilon = std::fabs(dmax-dmin) * 0.0001;
if (!is_2d_source && check_intersection && (0 < dmin-epsilon || 0 > dmax+epsilon)) {
continue;
}
@ -1310,7 +1310,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
// Skip over very small openings - these are likely projection errors
// (i.e. they don't belong to this side of the wall)
if(fabs(vpmax.x - vpmin.x) * fabs(vpmax.y - vpmin.y) < static_cast<IfcFloat>(1e-10)) {
if(std::fabs(vpmax.x - vpmin.x) * std::fabs(vpmax.y - vpmin.y) < static_cast<IfcFloat>(1e-10)) {
continue;
}
std::vector<TempOpening*> joined_openings(1, &opening);
@ -1480,7 +1480,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
// XXX this should be guarded, but we somehow need to pick a suitable
// epsilon
// if(coord != -1.0f) {
// assert(fabs(coord - vv.z) < 1e-3f);
// assert(std::fabs(coord - vv.z) < 1e-3f);
// }
coord = vv.z;
@ -1515,7 +1515,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
BOOST_FOREACH(const TempOpening& t,openings) {
const IfcVector3& outernor = nors[c++];
const IfcFloat dot = nor * outernor;
if (fabs(dot)<1.f-1e-6f) {
if (std::fabs(dot)<1.f-1e-6f) {
continue;
}
@ -1529,7 +1529,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
BOOST_FOREACH(const IfcVector3& xx, t.profileMesh->verts) {
IfcVector3 vv = m * xx, vv_extr = m * (xx + t.extrusionDir);
const bool is_extruded_side = fabs(vv.z - coord) > fabs(vv_extr.z - coord);
const bool is_extruded_side = std::fabs(vv.z - coord) > std::fabs(vv_extr.z - coord);
if (first) {
first = false;
if (dot > 0.f) {

View File

@ -101,7 +101,7 @@ void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout
}
// ------------------------------------------------------------------------------------------------
void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv)
void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& /*conv*/)
{
if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
@ -124,7 +124,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh&
IfcFloat angle = 0.f;
for(size_t i = 0; i < segments; ++i, angle += delta) {
meshout.verts.push_back( IfcVector3( cos(angle)*radius, sin(angle)*radius, 0.f ));
meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ));
}
meshout.vertcnt.push_back(segments);

View File

@ -1045,7 +1045,7 @@ void IFC::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;
}
@ -1253,7 +1253,7 @@ template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST&
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcRepresentationItem>(const DB& db, const LIST& params, IfcRepresentationItem* in)
template <> size_t GenericFill<IfcRepresentationItem>(const DB& /*db*/, const LIST& /*params*/, IfcRepresentationItem* /*in*/)
{
size_t base = 0;
return base;
@ -1715,7 +1715,7 @@ template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, I
return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in)
template <> size_t GenericFill<IfcObjectPlacement>(const DB& /*db*/, const LIST& /*params*/, IfcObjectPlacement* /*in*/)
{
size_t base = 0;
return base;

View File

@ -278,7 +278,7 @@ void TempMesh::RemoveAdjacentDuplicates()
// continue;
// }
// const IfcFloat d = (d0/sqrt(l0))*(d1/sqrt(l1));
// const IfcFloat d = (d0/std::sqrt(l0))*(d1/std::sqrt(l1));
// if ( d >= 1.f-dotepsilon ) {
// v1 = v0;

View File

@ -220,7 +220,7 @@ struct FuzzyVectorCompare {
FuzzyVectorCompare(IfcFloat epsilon) : epsilon(epsilon) {}
bool operator()(const IfcVector3& a, const IfcVector3& b) {
return fabs((a-b).SquareLength()) < epsilon;
return std::fabs((a-b).SquareLength()) < epsilon;
}
const IfcFloat epsilon;

View File

@ -12,8 +12,6 @@
namespace Assimp {
namespace IFF {
#include "./../include/assimp/Compiler/pushpack1.h"
/////////////////////////////////////////////////////////////////////////////////
//! Describes an IFF chunk header
/////////////////////////////////////////////////////////////////////////////////
@ -24,7 +22,7 @@ struct ChunkHeader
//! Length of the chunk data, in bytes
uint32_t length;
} PACK_STRUCT;
};
/////////////////////////////////////////////////////////////////////////////////
@ -37,9 +35,7 @@ struct SubChunkHeader
//! Length of the chunk data, in bytes
uint16_t length;
} PACK_STRUCT;
#include "./../include/assimp/Compiler/poppack1.h"
};
#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \
@ -52,28 +48,34 @@ struct SubChunkHeader
/////////////////////////////////////////////////////////////////////////////////
//! Load a chunk header
//! @param outFile Pointer to the file data - points to the chunk data afterwards
//! @return Pointer to the chunk header
//! @return Copy of the chunk header
/////////////////////////////////////////////////////////////////////////////////
inline ChunkHeader* LoadChunk(uint8_t*& outFile)
inline ChunkHeader LoadChunk(uint8_t*& outFile)
{
ChunkHeader* head = (ChunkHeader*) outFile;
AI_LSWAP4(head->length);
AI_LSWAP4(head->type);
outFile += sizeof(ChunkHeader);
ChunkHeader head;
::memcpy(&head.type, outFile, 4);
outFile += 4;
::memcpy(&head.length, outFile, 4);
outFile += 4;
AI_LSWAP4(head.length);
AI_LSWAP4(head.type);
return head;
}
/////////////////////////////////////////////////////////////////////////////////
//! Load a sub chunk header
//! @param outFile Pointer to the file data - points to the chunk data afterwards
//! @return Pointer to the sub chunk header
//! @return Copy of the sub chunk header
/////////////////////////////////////////////////////////////////////////////////
inline SubChunkHeader* LoadSubChunk(uint8_t*& outFile)
inline SubChunkHeader LoadSubChunk(uint8_t*& outFile)
{
SubChunkHeader* head = (SubChunkHeader*) outFile;
AI_LSWAP2(head->length);
AI_LSWAP4(head->type);
outFile += sizeof(SubChunkHeader);
SubChunkHeader head;
::memcpy(&head.type, outFile, 4);
outFile += 4;
::memcpy(&head.length, outFile, 2);
outFile += 2;
AI_LSWAP2(head.length);
AI_LSWAP4(head.type);
return head;
}
@ -84,14 +86,14 @@ inline SubChunkHeader* LoadSubChunk(uint8_t*& outFile)
//! @param fileType Receives the type of the file
//! @return 0 if everything was OK, otherwise an error message
/////////////////////////////////////////////////////////////////////////////////
inline const char* ReadHeader(uint8_t* outFile,uint32_t& fileType)
inline const char* ReadHeader(uint8_t* outFile, uint32_t& fileType)
{
ChunkHeader* head = LoadChunk(outFile);
if(AI_IFF_FOURCC_FORM != head->type)
ChunkHeader head = LoadChunk(outFile);
if(AI_IFF_FOURCC_FORM != head.type)
{
return "The file is not an IFF file: FORM chunk is missing";
}
fileType = *((uint32_t*)(head+1));
::memcpy(&fileType, outFile, 4);
AI_LSWAP4(fileType);
return 0;
}

View File

@ -470,7 +470,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
key.mTime = i * tdelta;
const float t = (float) ( in.speed * key.mTime );
key.mValue = in.circleCenter + in.circleRadius * ((vecU*::cosf(t)) + (vecV*::sinf(t)));
key.mValue = in.circleCenter + in.circleRadius * ((vecU * std::cos(t)) + (vecV * std::sin(t)));
}
// This animation is repeated and repeated ...
@ -533,8 +533,8 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
aiVectorKey& key = anim->mPositionKeys[i];
const float dt = (i * in.speed * 0.001f );
const float u = dt - floor(dt);
const int idx = (int)floor(dt) % size;
const float u = dt - std::floor(dt);
const int idx = (int)std::floor(dt) % size;
// get the 4 current points to evaluate the spline
const aiVector3D& p0 = in.splineKeys[ ClampSpline( idx - 1, size ) ].mValue;

View File

@ -640,16 +640,25 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
}
}
// Get file size for progress handler
IOStream * fileIO = pimpl->mIOHandler->Open( pFile );
uint32_t fileSize = 0;
if (fileIO)
{
fileSize = fileIO->FileSize();
pimpl->mIOHandler->Close( fileIO );
}
// Dispatch the reading to the worker class for this format
DefaultLogger::get()->info("Found a matching importer for this file format");
pimpl->mProgressHandler->Update();
pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
if (profiler) {
profiler->BeginRegion("import");
}
pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
pimpl->mProgressHandler->Update();
pimpl->mProgressHandler->UpdateFileRead( fileSize, fileSize );
if (profiler) {
profiler->EndRegion("import");
@ -678,7 +687,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
ScenePreprocessor pre(pimpl->mScene);
pre.ProcessScene();
pimpl->mProgressHandler->Update();
if (profiler) {
profiler->EndRegion("preprocess");
}
@ -768,6 +776,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
BaseProcess* process = pimpl->mPostProcessingSteps[a];
pimpl->mProgressHandler->UpdatePostProcess( a, pimpl->mPostProcessingSteps.size() );
if( process->IsActive( pFlags)) {
if (profiler) {
@ -775,7 +784,6 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
}
process->ExecuteOnScene ( this );
pimpl->mProgressHandler->Update();
if (profiler) {
profiler->EndRegion("postprocess");
@ -803,6 +811,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
}
#endif // ! DEBUG
}
pimpl->mProgressHandler->UpdatePostProcess( pimpl->mPostProcessingSteps.size(), pimpl->mPostProcessingSteps.size() );
// update private scene flags
if( pimpl->mScene )

View File

@ -166,6 +166,9 @@ corresponding preprocessor flag to selectively disable formats.
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
# include "FBXImporter.h"
#endif
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
# include "AssbinLoader.h"
#endif
namespace Assimp {
@ -291,6 +294,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
#if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
out.push_back( new FBXImporter() );
#endif
#if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
out.push_back( new AssbinImporter() );
#endif
}
}

View File

@ -49,8 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp
{
class JoinVerticesTest;
// ---------------------------------------------------------------------------
/** The JoinVerticesProcess unites identical vertices in all imported meshes.
* By default the importer returns meshes where each face addressed its own
@ -59,7 +57,7 @@ class JoinVerticesTest;
* erases all but one of the copies. This usually reduces the number of vertices
* in a mesh by a serious amount and is the standard form to render a mesh.
*/
class ASSIMP_API_WINONLY JoinVerticesProcess : public BaseProcess
class ASSIMP_API JoinVerticesProcess : public BaseProcess
{
public:

View File

@ -58,30 +58,31 @@ void LWOImporter::LoadLWOBFile()
while (running)
{
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
if (mFileBuffer + head.length > end)
{
throw DeadlyImportError("LWOB: Invalid chunk length");
break;
}
uint8_t* const next = mFileBuffer+head->length;
switch (head->type)
uint8_t* const next = mFileBuffer+head.length;
switch (head.type)
{
// vertex list
case AI_LWO_PNTS:
{
if (!mCurLayer->mTempPoints.empty())
DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
else LoadLWOPoints(head->length);
else LoadLWOPoints(head.length);
break;
}
// face list
case AI_LWO_POLS:
{
if (!mCurLayer->mFaces.empty())
DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
else LoadLWOBPolygons(head->length);
else LoadLWOBPolygons(head.length);
break;
}
// list of tags
@ -89,14 +90,14 @@ void LWOImporter::LoadLWOBFile()
{
if (!mTags->empty())
DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
else LoadLWOTags(head->length);
else LoadLWOTags(head.length);
break;
}
// surface chunk
case AI_LWO_SURF:
{
LoadLWOBSurface(head->length);
LoadLWOBSurface(head.length);
break;
}
}
@ -137,14 +138,17 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face
{
while (cursor < end && max--)
{
uint16_t numIndices = *cursor++;
verts += numIndices;faces++;
uint16_t numIndices;
::memcpy(&numIndices, cursor++, 2);
verts += numIndices;
faces++;
cursor += numIndices;
int16_t surface = *cursor++;
int16_t surface;
::memcpy(&surface, cursor++, 2);
if (surface < 0)
{
// there are detail polygons
numIndices = *cursor++;
::memcpy(&numIndices, cursor++, 2);
CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
}
}
@ -159,13 +163,22 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
while (cursor < end && max--)
{
LWO::Face& face = *it;++it;
if((face.mNumIndices = *cursor++))
uint16_t numIndices;
::memcpy(&numIndices, cursor++, 2);
face.mNumIndices = numIndices;
if(face.mNumIndices)
{
if (cursor + face.mNumIndices >= end)break;
if (cursor + face.mNumIndices >= end)
{
break;
}
face.mIndices = new unsigned int[face.mNumIndices];
for (unsigned int i = 0; i < face.mNumIndices;++i)
{
unsigned int & mi = face.mIndices[i] = *cursor++;
unsigned int & mi = face.mIndices[i];
uint16_t index;
::memcpy(&index, cursor++, 2);
mi = index;
if (mi > mCurLayer->mTempPoints.size())
{
DefaultLogger::get()->warn("LWOB: face index is out of range");
@ -174,14 +187,19 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
}
}
else DefaultLogger::get()->warn("LWOB: Face has 0 indices");
int16_t surface = *cursor++;
int16_t surface;
::memcpy(&surface, cursor++, 2);
if (surface < 0)
{
surface = -surface;
// there are detail polygons.
const uint16_t numPolygons = *cursor++;
if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
uint16_t numPolygons;
::memcpy(&numPolygons, cursor++, 2);
if (cursor < end)
{
CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
}
}
face.surfaceIndex = surface-1;
}
@ -235,7 +253,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
if (mFileBuffer + 6 >= end)
break;
IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
/* A single test file (sonycam.lwo) seems to have invalid surface chunks.
* I'm assuming it's the fault of a single, unknown exporter so there are
@ -244,18 +262,18 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
* We don't break if the chunk limit is exceeded. Instead, we're computing
* how much storage is actually left and work with this value from now on.
*/
if (mFileBuffer + head->length > end) {
if (mFileBuffer + head.length > end) {
DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue.");
head->length = (uint16_t) (end - mFileBuffer);
head.length = (uint16_t) (end - mFileBuffer);
}
uint8_t* const next = mFileBuffer+head->length;
switch (head->type)
uint8_t* const next = mFileBuffer+head.length;
switch (head.type)
{
// diffuse color
case AI_LWO_COLR:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,3);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3);
surf.mColor.r = GetU1() / 255.0f;
surf.mColor.g = GetU1() / 255.0f;
surf.mColor.b = GetU1() / 255.0f;
@ -264,35 +282,35 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
// diffuse strength ...
case AI_LWO_DIFF:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2);
surf.mDiffuseValue = GetU2() / 255.0f;
break;
}
// specular strength ...
case AI_LWO_SPEC:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2);
surf.mSpecularValue = GetU2() / 255.0f;
break;
}
// luminosity ...
case AI_LWO_LUMI:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LUMI,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2);
surf.mLuminosity = GetU2() / 255.0f;
break;
}
// transparency
case AI_LWO_TRAN:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2);
surf.mTransparency = GetU2() / 255.0f;
break;
}
// surface flags
case AI_LWO_FLAG:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,FLAG,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2);
uint16_t flag = GetU2();
if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
if (flag & 0x8 ) surf.mColorHighlights = 1.f;
@ -302,14 +320,14 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
// maximum smoothing angle
case AI_LWO_SMAN:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
surf.mMaximumSmoothAngle = fabs( GetF4() );
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
surf.mMaximumSmoothAngle = std::fabs( GetF4() );
break;
}
// glossiness
case AI_LWO_GLOS:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2);
surf.mGlossiness = (float)GetU2();
break;
}
@ -317,42 +335,42 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
case AI_LWO_CTEX:
{
pTex = SetupNewTextureLWOB(surf.mColorTextures,
head->length);
head.length);
break;
}
// diffuse texture
case AI_LWO_DTEX:
{
pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
head->length);
head.length);
break;
}
// specular texture
case AI_LWO_STEX:
{
pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
head->length);
head.length);
break;
}
// bump texture
case AI_LWO_BTEX:
{
pTex = SetupNewTextureLWOB(surf.mBumpTextures,
head->length);
head.length);
break;
}
// transparency texture
case AI_LWO_TTEX:
{
pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
head->length);
head.length);
break;
}
// texture path
case AI_LWO_TIMG:
{
if (pTex) {
GetS0(pTex->mFileName,head->length);
GetS0(pTex->mFileName,head.length);
}
else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk");
break;
@ -360,7 +378,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
// texture strength
case AI_LWO_TVAL:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
if (pTex) {
pTex->mStrength = (float)GetU1()/ 255.f;
}
@ -370,7 +388,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
// texture flags
case AI_LWO_TFLG:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TFLG,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
if (pTex)
{

View File

@ -503,7 +503,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
// Generate vertex normals. We have O(logn) for the binary lookup, which we need
// for n elements, thus the EXPECTED complexity is O(nlogn)
if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag) {
const float fLimit = cos(surface.mMaximumSmoothAngle);
const float fLimit = std::cos(surface.mMaximumSmoothAngle);
for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
const aiFace& face = *begin;
@ -787,7 +787,8 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end);
// allocate the output array and copy face indices
if (iNumFaces) {
if (iNumFaces)
{
cursor = (uint16_t*)mFileBuffer;
mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type));
@ -802,14 +803,19 @@ void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& face
{
while (cursor < end && max--)
{
AI_LSWAP2P(cursor);
uint16_t numIndices = *cursor++;
uint16_t numIndices;
::memcpy(&numIndices, cursor++, 2);
AI_LSWAP2(numIndices);
numIndices &= 0x03FF;
verts += numIndices;++faces;
verts += numIndices;
++faces;
for(uint16_t i = 0; i < numIndices; i++)
{
ReadVSizedIntLWO2((uint8_t*&)cursor);
}
}
}
// ------------------------------------------------------------------------------------------------
@ -817,10 +823,16 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
uint16_t*& cursor,
const uint16_t* const end)
{
while (cursor < end) {
while (cursor < end)
{
LWO::Face& face = *it++;
uint16_t numIndices;
::memcpy(&numIndices, cursor++, 2);
AI_LSWAP2(numIndices);
face.mNumIndices = numIndices & 0x03FF;
LWO::Face& face = *it++;;
if((face.mNumIndices = (*cursor++) & 0x03FF)) /* byte swapping has already been done */ {
if(face.mNumIndices) /* byte swapping has already been done */
{
face.mIndices = new unsigned int[face.mNumIndices];
for(unsigned int i = 0; i < face.mNumIndices; i++)
{
@ -848,8 +860,8 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
if (type != AI_LWO_SURF && type != AI_LWO_SMGP)
return;
while (mFileBuffer < end) {
while (mFileBuffer < end)
{
unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
unsigned int j = GetU2();
@ -1106,19 +1118,19 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
// first - get the index of the clip
clip.idx = GetU4();
IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
switch (head->type)
IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
switch (head.type)
{
case AI_LWO_STIL:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,STIL,1);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,STIL,1);
// "Normal" texture
GetS0(clip.path,head->length);
GetS0(clip.path,head.length);
clip.type = Clip::STILL;
break;
case AI_LWO_ISEQ:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ISEQ,16);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ISEQ,16);
// Image sequence. We'll later take the first.
{
uint8_t digits = GetU1(); mFileBuffer++;
@ -1127,12 +1139,12 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
std::string s;
std::ostringstream ss;
GetS0(s,head->length);
GetS0(s,head.length);
head->length -= (unsigned int)s.length()+1;
head.length -= (unsigned int)s.length()+1;
ss << s;
ss << std::setw(digits) << offset + start;
GetS0(s,head->length);
GetS0(s,head.length);
ss << s;
clip.path = ss.str();
clip.type = Clip::SEQ;
@ -1148,7 +1160,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
break;
case AI_LWO_XREF:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,XREF,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,XREF,4);
// Just a cross-reference to another CLIp
clip.type = Clip::REF;
@ -1156,7 +1168,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
break;
case AI_LWO_NEGA:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,NEGA,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,NEGA,2);
clip.negate = (0 != GetU2());
break;
@ -1194,17 +1206,17 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
while (true)
{
if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid envelope chunk length");
uint8_t* const next = mFileBuffer+head->length;
switch (head->type)
uint8_t* const next = mFileBuffer+head.length;
switch (head.type)
{
// Type & representation of the envelope
case AI_LWO_TYPE:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TYPE,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TYPE,2);
mFileBuffer++; // skip user format
// Determine type of envelope
@ -1214,20 +1226,20 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
// precondition
case AI_LWO_PRE:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,PRE,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,PRE,2);
envelope.pre = (LWO::PrePostBehaviour)GetU2();
break;
// postcondition
case AI_LWO_POST:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,POST,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,POST,2);
envelope.post = (LWO::PrePostBehaviour)GetU2();
break;
// keyframe
case AI_LWO_KEY:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,KEY,8);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,KEY,8);
envelope.keys.push_back(LWO::Key());
LWO::Key& key = envelope.keys.back();
@ -1240,7 +1252,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
// interval interpolation
case AI_LWO_SPAN:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPAN,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPAN,4);
if (envelope.keys.size()<2)
DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk");
else {
@ -1286,22 +1298,22 @@ void LWOImporter::LoadLWO2File()
while (true)
{
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
if (mFileBuffer + head.length > end)
{
throw DeadlyImportError("LWO2: Chunk length points behind the file");
break;
}
uint8_t* const next = mFileBuffer+head->length;
uint8_t* const next = mFileBuffer+head.length;
unsigned int iUnnamed = 0;
if(!head->length) {
if(!head.length) {
mFileBuffer = next;
continue;
}
switch (head->type)
switch (head.type)
{
// new layer
case AI_LWO_LAYR:
@ -1311,7 +1323,7 @@ void LWOImporter::LoadLWO2File()
LWO::Layer& layer = mLayers->back();
mCurLayer = &layer;
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LAYR,16);
// layer index.
layer.mIndex = GetU2();
@ -1327,7 +1339,7 @@ void LWOImporter::LoadLWO2File()
mCurLayer->mPivot.x = GetF4();
mCurLayer->mPivot.y = GetF4();
mCurLayer->mPivot.z = GetF4();
GetS0(layer.mName,head->length-16);
GetS0(layer.mName,head.length-16);
// if the name is empty, generate a default name
if (layer.mName.empty()) {
@ -1360,7 +1372,7 @@ void LWOImporter::LoadLWO2File()
break;
unsigned int old = (unsigned int)mCurLayer->mTempPoints.size();
LoadLWOPoints(head->length);
LoadLWOPoints(head.length);
mCurLayer->mPointIDXOfs = old;
break;
}
@ -1379,7 +1391,7 @@ void LWOImporter::LoadLWO2File()
if (mCurLayer->mTempPoints.empty())
DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk");
else LoadLWO2VertexMap(head->length,head->type == AI_LWO_VMAD);
else LoadLWO2VertexMap(head.length,head.type == AI_LWO_VMAD);
break;
}
// face list
@ -1389,7 +1401,7 @@ void LWOImporter::LoadLWO2File()
break;
unsigned int old = (unsigned int)mCurLayer->mFaces.size();
LoadLWO2Polygons(head->length);
LoadLWO2Polygons(head.length);
mCurLayer->mFaceIDXOfs = old;
break;
}
@ -1401,7 +1413,7 @@ void LWOImporter::LoadLWO2File()
if (mCurLayer->mFaces.empty())
DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
else LoadLWO2PolygonTags(head->length);
else LoadLWO2PolygonTags(head.length);
break;
}
// list of tags
@ -1409,28 +1421,28 @@ void LWOImporter::LoadLWO2File()
{
if (!mTags->empty())
DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice");
else LoadLWOTags(head->length);
else LoadLWOTags(head.length);
break;
}
// surface chunk
case AI_LWO_SURF:
{
LoadLWO2Surface(head->length);
LoadLWO2Surface(head.length);
break;
}
// clip chunk
case AI_LWO_CLIP:
{
LoadLWO2Clip(head->length);
LoadLWO2Clip(head.length);
break;
}
// envelope chunk
case AI_LWO_ENVL:
{
LoadLWO2Envelope(head->length);
LoadLWO2Envelope(head.length);
break;
}
}

View File

@ -402,7 +402,9 @@ protected:
// ------------------------------------------------------------------------------------------------
inline float LWOImporter::GetF4()
{
float f = *((float*)mFileBuffer);mFileBuffer += 4;
float f;
::memcpy(&f, mFileBuffer, 4);
mFileBuffer += 4;
AI_LSWAP4(f);
return f;
}
@ -410,7 +412,9 @@ inline float LWOImporter::GetF4()
// ------------------------------------------------------------------------------------------------
inline uint32_t LWOImporter::GetU4()
{
uint32_t f = *((uint32_t*)mFileBuffer);mFileBuffer += 4;
uint32_t f;
::memcpy(&f, mFileBuffer, 4);
mFileBuffer += 4;
AI_LSWAP4(f);
return f;
}
@ -418,7 +422,9 @@ inline uint32_t LWOImporter::GetU4()
// ------------------------------------------------------------------------------------------------
inline uint16_t LWOImporter::GetU2()
{
uint16_t f = *((uint16_t*)mFileBuffer);mFileBuffer += 2;
uint16_t f;
::memcpy(&f, mFileBuffer, 2);
mFileBuffer += 2;
AI_LSWAP2(f);
return f;
}

View File

@ -285,7 +285,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
{
float fGloss;
if (mIsLWO2) {
fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
fGloss = std::pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
}
else
{
@ -527,13 +527,13 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
while (true)
{
if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
uint8_t* const next = mFileBuffer+head->length;
switch (head->type)
uint8_t* const next = mFileBuffer+head.length;
switch (head.type)
{
case AI_LWO_PROJ:
tex.mapMode = (Texture::MappingMode)GetU2();
@ -549,7 +549,7 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
tex.mClipIdx = GetU2();
break;
case AI_LWO_VMAP:
GetS0(tex.mUVChannelIndex,head->length);
GetS0(tex.mUVChannelIndex,head.length);
break;
case AI_LWO_WRPH:
tex.wrapAmountH = GetF4();
@ -595,13 +595,13 @@ void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
while (true)
{
if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid texture header chunk length");
uint8_t* const next = mFileBuffer+head->length;
switch (head->type)
uint8_t* const next = mFileBuffer+head.length;
switch (head.type)
{
case AI_LWO_CHAN:
tex.type = GetU4();
@ -698,20 +698,20 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u
while (true)
{
if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid shader header chunk length");
uint8_t* const next = mFileBuffer+head->length;
switch (head->type)
uint8_t* const next = mFileBuffer+head.length;
switch (head.type)
{
case AI_LWO_ENAB:
shader.enabled = GetU2() ? true : false;
break;
case AI_LWO_FUNC:
GetS0( shader.functionName, head->length );
GetS0( shader.functionName, head.length );
}
mFileBuffer = next;
}
@ -756,18 +756,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
{
if (mFileBuffer + 6 >= end)
break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid surface chunk length");
uint8_t* const next = mFileBuffer+head->length;
switch (head->type)
uint8_t* const next = mFileBuffer+head.length;
switch (head.type)
{
// diffuse color
case AI_LWO_COLR:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,12);
surf.mColor.r = GetF4();
surf.mColor.g = GetF4();
surf.mColor.b = GetF4();
@ -776,14 +776,14 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
// diffuse strength ... hopefully
case AI_LWO_DIFF:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,4);
surf.mDiffuseValue = GetF4();
break;
}
// specular strength ... hopefully
case AI_LWO_SPEC:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,4);
surf.mSpecularValue = GetF4();
break;
}
@ -794,21 +794,21 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
if (surf.mTransparency == 10e10f)
break;
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,4);
surf.mTransparency = GetF4();
break;
}
// additive transparency
case AI_LWO_ADTR:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ADTR,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ADTR,4);
surf.mAdditiveTransparency = GetF4();
break;
}
// wireframe mode
case AI_LWO_LINE:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LINE,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LINE,2);
if (GetU2() & 0x1)
surf.mWireframe = true;
break;
@ -816,49 +816,49 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
// glossiness
case AI_LWO_GLOS:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,4);
surf.mGlossiness = GetF4();
break;
}
// bump intensity
case AI_LWO_BUMP:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BUMP,4);
surf.mBumpIntensity = GetF4();
break;
}
// color highlights
case AI_LWO_CLRH:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,CLRH,4);
surf.mColorHighlights = GetF4();
break;
}
// index of refraction
case AI_LWO_RIND:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,RIND,4);
surf.mIOR = GetF4();
break;
}
// polygon sidedness
case AI_LWO_SIDE:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SIDE,2);
surf.bDoubleSided = (3 == GetU2());
break;
}
// maximum smoothing angle
case AI_LWO_SMAN:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
surf.mMaximumSmoothAngle = fabs( GetF4() );
break;
}
// vertex color channel to be applied to the surface
case AI_LWO_VCOL:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,VCOL,12);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,VCOL,12);
surf.mDiffuseValue *= GetF4(); // strength
ReadVSizedIntLWO2(mFileBuffer); // skip envelope
surf.mVCMapType = GetU4(); // type of the channel
@ -870,18 +870,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
// surface bock entry
case AI_LWO_BLOK:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4);
LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BLOK,4);
IFF::SubChunkHeader head2 = IFF::LoadSubChunk(mFileBuffer);
switch (head2->type)
switch (head2.type)
{
case AI_LWO_PROC:
case AI_LWO_GRAD:
case AI_LWO_IMAP:
LoadLWO2TextureBlock(head2, head->length);
LoadLWO2TextureBlock(&head2, head.length);
break;
case AI_LWO_SHDR:
LoadLWO2ShaderBlock(head2, head->length);
LoadLWO2ShaderBlock(&head2, head.length);
break;
default:

View File

@ -464,7 +464,7 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
std::string tmp;
if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
{
tmp = in[0] + (":\\" + in.substr(2));
tmp = in[0] + (std::string(":\\") + in.substr(2));
}
else tmp = in;
@ -480,12 +480,12 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
// <folder>\Scenes\<hh>\<*>.lws
// where <hh> is optional.
std::string test = ".." + (io->getOsSeparator() + tmp);
std::string test = std::string("..") + (io->getOsSeparator() + tmp);
if (io->Exists(test)) {
return test;
}
test = ".." + (io->getOsSeparator() + test);
test = std::string("..") + (io->getOsSeparator() + test);
if (io->Exists(test)) {
return test;
}

View File

@ -131,10 +131,15 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
// and renormalize the weights
float sum = 0.0f;
for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it)
for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
sum += it->mWeight;
for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it)
it->mWeight /= sum;
}
if( 0.0f != sum ) {
const float invSum = 1.0f / sum;
for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it ) {
it->mWeight *= invSum;
}
}
}
if (bChanged) {
@ -157,18 +162,6 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
const std::vector<aiVertexWeight>& bw = boneWeights[a];
aiBone* bone = pMesh->mBones[a];
// ignore the bone if no vertex weights were removed there
// FIX (Aramis, 07|22|08)
// NO! we can't ignore it in this case ... it is possible that
// the number of weights did not change, but the weight values did.
// if( bw.size() == bone->mNumWeights)
// continue;
// FIX (Aramis, 07|21|08)
// It is possible that all weights of a bone have been removed.
// This would naturally cause an exception in &bw[0].
if ( bw.empty() )
{
abNoNeed[a] = bChanged = true;
@ -177,7 +170,7 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
// copy the weight list. should always be less weights than before, so we don't need a new allocation
ai_assert( bw.size() <= bone->mNumWeights);
bone->mNumWeights = (unsigned int) bw.size();
bone->mNumWeights = static_cast<unsigned int>( bw.size() );
::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
}

View File

@ -263,9 +263,9 @@ inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut)
lat *= 3.141926f/128.0f;
lng *= 3.141926f/128.0f;
p_afOut[0] = cosf(lat) * sinf(lng);
p_afOut[1] = sinf(lat) * sinf(lng);
p_afOut[2] = cosf(lng);
p_afOut[0] = std::cos(lat) * std::sin(lng);
p_afOut[1] = std::sin(lat) * std::sin(lng);
p_afOut[2] = std::cos(lng);
return;
}

View File

@ -259,7 +259,7 @@ inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) {
if (t < 0.0f)
out.w = 0.0f;
else out.w = sqrt (t);
else out.w = std::sqrt (t);
}
// ---------------------------------------------------------------------------

View File

@ -75,6 +75,7 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
} // end of namespace Assimp
static const std::string MaterialExt = ".mtl";
// ------------------------------------------------------------------------------------------------
ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
@ -107,7 +108,7 @@ std::string ObjExporter :: GetMaterialLibName()
// ------------------------------------------------------------------------------------------------
std::string ObjExporter :: GetMaterialLibFileName()
{
return filename + ".mtl";
return filename + MaterialExt;
}
// ------------------------------------------------------------------------------------------------
@ -132,7 +133,7 @@ std::string ObjExporter :: GetMaterialName(unsigned int index)
}
// ------------------------------------------------------------------------------------------------
void ObjExporter :: WriteMaterialFile()
void ObjExporter::WriteMaterialFile()
{
WriteHeader(mOutputMat);
@ -144,16 +145,16 @@ void ObjExporter :: WriteMaterialFile()
aiColor4D c;
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) {
mOutputMat << "kd " << c.r << " " << c.g << " " << c.b << endl;
mOutputMat << "Kd " << c.r << " " << c.g << " " << c.b << endl;
}
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) {
mOutputMat << "ka " << c.r << " " << c.g << " " << c.b << endl;
mOutputMat << "Ka " << c.r << " " << c.g << " " << c.b << endl;
}
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) {
mOutputMat << "ks " << c.r << " " << c.g << " " << c.b << endl;
mOutputMat << "Ks " << c.r << " " << c.g << " " << c.b << endl;
}
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) {
mOutputMat << "ke " << c.r << " " << c.g << " " << c.b << endl;
mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl;
}
float o;
@ -170,16 +171,19 @@ void ObjExporter :: WriteMaterialFile()
aiString s;
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) {
mOutputMat << "map_kd " << s.data << endl;
mOutputMat << "map_Kd " << s.data << endl;
}
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) {
mOutputMat << "map_ka " << s.data << endl;
mOutputMat << "map_Ka " << s.data << endl;
}
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) {
mOutputMat << "map_ks " << s.data << endl;
mOutputMat << "map_Ks " << s.data << endl;
}
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) {
mOutputMat << "map_ns " << s.data << endl;
mOutputMat << "map_Ns " << s.data << endl;
}
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_OPACITY(0),s)) {
mOutputMat << "map_d " << s.data << endl;
}
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) {
// implementations seem to vary here, so write both variants
@ -199,7 +203,7 @@ void ObjExporter :: WriteGeometryFile()
// collect mesh geometry
aiMatrix4x4 mBase;
AddNode(pScene->mRootNode,mBase);
AddNode(pScene->mRootNode, mBase);
// write vertex positions
vpMap.getVectors(vp);
@ -228,7 +232,9 @@ void ObjExporter :: WriteGeometryFile()
// now write all mesh instances
BOOST_FOREACH(const MeshInstance& m, meshes) {
mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
if (!m.name.empty()) {
mOutput << "g " << m.name << endl;
}
mOutput << "usemtl " << m.matname << endl;
BOOST_FOREACH(const Face& f, m.faces) {
@ -243,11 +249,8 @@ void ObjExporter :: WriteGeometryFile()
if (fv.vt) {
mOutput << fv.vt;
}
if (f.kind == 'f') {
mOutput << '/';
if (fv.vn) {
mOutput << fv.vn;
}
if (f.kind == 'f' && fv.vn) {
mOutput << '/' << fv.vn;
}
}
}
@ -258,14 +261,12 @@ void ObjExporter :: WriteGeometryFile()
}
}
// ------------------------------------------------------------------------------------------------
int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
{
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
if(vertIt != vecMap.end()){// vertex already exists, so reference it
// vertex already exists, so reference it
if(vertIt != vecMap.end()){
return vertIt->second;
}
vecMap[vec] = mNextIndex;
@ -274,6 +275,7 @@ int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
return ret;
}
// ------------------------------------------------------------------------------------------------
void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
{
vecs.resize(vecMap.size());
@ -282,14 +284,13 @@ void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
}
}
// ------------------------------------------------------------------------------------------------
void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
{
meshes.push_back(MeshInstance());
MeshInstance& mesh = meshes.back();
mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_"+std::string(m->mName.data,m->mName.length) : "");
mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_" + std::string(m->mName.data,m->mName.length) : "");
mesh.matname = GetMaterialName(m->mMaterialIndex);
mesh.faces.resize(m->mNumFaces);
@ -317,7 +318,8 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
face.indices[a].vp = vpMap.getIndex(vert);
if (m->mNormals) {
face.indices[a].vn = vnMap.getIndex(m->mNormals[idx]);
aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
face.indices[a].vn = vnMap.getIndex(norm);
}
else{
face.indices[a].vn = 0;
@ -334,18 +336,20 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
}
// ------------------------------------------------------------------------------------------------
void ObjExporter :: AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
{
const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]],mAbs);
AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs);
}
for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
AddNode(nd->mChildren[i],mAbs);
AddNode(nd->mChildren[i], mAbs);
}
}
#endif
#endif
// ------------------------------------------------------------------------------------------------
#endif // ASSIMP_BUILD_NO_OBJ_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -110,8 +110,6 @@ const aiImporterDesc* ObjFileImporter::GetInfo () const
// Obj-file import implementation
void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
DefaultIOSystem io;
// Read file into memory
const std::string mode = "rb";
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
@ -140,6 +138,22 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
strModelName = pFile;
}
// process all '\'
std::vector<char> ::iterator iter = m_Buffer.begin();
while (iter != m_Buffer.end())
{
if (*iter == '\\')
{
// remove '\'
iter = m_Buffer.erase(iter);
// remove next character
while (*iter == '\r' || *iter == '\n')
iter = m_Buffer.erase(iter);
}
else
++iter;
}
// parse the file into a temporary representation
ObjFileParser parser(m_Buffer, strModelName, pIOHandler);
@ -216,16 +230,10 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ )
{
unsigned int meshId = pObject->m_Meshes[ i ];
aiMesh *pMesh = new aiMesh;
createTopology( pModel, pObject, meshId, pMesh );
if ( pMesh->mNumVertices > 0 )
{
aiMesh *pMesh = createTopology( pModel, pObject, meshId );
if( pMesh && pMesh->mNumFaces > 0 ) {
MeshArray.push_back( pMesh );
}
else
{
delete pMesh;
}
}
// Create all nodes from the sub-objects stored in the current object
@ -258,45 +266,44 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
// ------------------------------------------------------------------------------------------------
// Create topology data
void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
const ObjFile::Object* pData,
unsigned int uiMeshIndex,
aiMesh* pMesh )
aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
unsigned int uiMeshIndex )
{
// Checking preconditions
ai_assert( NULL != pModel );
if( NULL == pData ) {
return;
return NULL;
}
// Create faces
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
if( !pObjMesh ) {
return NULL;
}
ai_assert( NULL != pObjMesh );
pMesh->mNumFaces = 0;
aiMesh* pMesh = new aiMesh;
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
{
ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
ObjFile::Face *const inp = pObjMesh->m_Faces[ index ];
ai_assert( NULL != inp );
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
pMesh->mNumFaces += inp->m_pVertices->size() - 1;
pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
}
else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
} else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
pMesh->mNumFaces += inp->m_pVertices->size();
pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
} else {
++pMesh->mNumFaces;
if (inp->m_pVertices->size() > 3) {
pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
}
else {
} else {
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
}
}
}
unsigned int uiIdxCount = 0u;
unsigned int uiIdxCount( 0u );
if ( pMesh->mNumFaces > 0 )
{
pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
@ -305,7 +312,7 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
}
unsigned int outIndex = 0;
unsigned int outIndex( 0 );
// Copy all data from all stored meshes
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
@ -339,6 +346,8 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
// Create mesh vertices
createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount);
return pMesh;
}
// ------------------------------------------------------------------------------------------------

View File

@ -91,8 +91,8 @@ private:
aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
//! \brief Creates topology data like faces and meshes for the geometry.
void createTopology(const ObjFile::Model* pModel, const ObjFile::Object* pData,
unsigned int uiMeshIndex, aiMesh* pMesh);
aiMesh *createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
unsigned int uiMeshIndex );
//! \brief Creates vertices from model.
void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,

View File

@ -46,14 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ObjTools.h"
#include "ObjFileData.h"
#include "fast_atof.h"
#include "ParsingUtils.h"
namespace Assimp {
// Material specific token
static const std::string DiffuseTexture = "map_kd";
static const std::string AmbientTexture = "map_ka";
static const std::string SpecularTexture = "map_ks";
static const std::string DiffuseTexture = "map_Kd";
static const std::string AmbientTexture = "map_Ka";
static const std::string SpecularTexture = "map_Ks";
static const std::string OpacityTexture = "map_d";
static const std::string EmmissiveTexture = "map_emissive";
static const std::string BumpTexture1 = "map_bump";
static const std::string BumpTexture2 = "map_Bump";
static const std::string BumpTexture3 = "bump";
@ -128,6 +130,7 @@ void ObjFileMtlImporter::load()
{
switch (*m_DataIt)
{
case 'k':
case 'K':
{
++m_DataIt;
@ -163,26 +166,28 @@ void ObjFileMtlImporter::load()
}
break;
case 'N': // Shineness
case 'N':
case 'n':
{
++m_DataIt;
switch(*m_DataIt)
{
case 's':
case 's': // Specular exponent
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->shineness);
break;
case 'i': //Index Of refraction
case 'i': // Index Of refraction
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->ior);
break;
case 'e': // New material
createMaterial();
break;
}
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
break;
}
break;
case 'm': // Texture
case 'b': // quick'n'dirty - for 'bump' sections
{
@ -191,13 +196,6 @@ void ObjFileMtlImporter::load()
}
break;
case 'n': // New material name
{
createMaterial();
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
case 'i': // Illumination model
{
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
@ -221,14 +219,16 @@ void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor )
{
ai_assert( NULL != pColor );
float r, g, b;
float r( 0.0f ), g( 0.0f ), b( 0.0f );
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r );
pColor->r = r;
// we have to check if color is default 0 with only one token
if( !IsLineEnd( *m_DataIt ) ) {
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
pColor->g = g;
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
}
pColor->g = g;
pColor->b = b;
}
@ -253,7 +253,7 @@ void ObjFileMtlImporter::getFloatValue( float &value )
void ObjFileMtlImporter::createMaterial()
{
std::string line( "" );
while ( !isNewLine( *m_DataIt ) ) {
while( !IsLineEnd( *m_DataIt ) ) {
line += *m_DataIt;
++m_DataIt;
}
@ -303,11 +303,7 @@ void ObjFileMtlImporter::getTexture() {
// Opacity texture
out = & m_pModel->m_pCurrentMaterial->textureOpacity;
clampIndex = ObjFile::Material::TextureOpacityType;
} else if (!ASSIMP_strincmp( pPtr,"map_ka",6)) {
// Ambient texture
out = & m_pModel->m_pCurrentMaterial->textureAmbient;
clampIndex = ObjFile::Material::TextureAmbientType;
} else if (!ASSIMP_strincmp(&(*m_DataIt),"map_emissive",6)) {
} else if (!ASSIMP_strincmp( pPtr, EmmissiveTexture.c_str(), EmmissiveTexture.size())) {
// Emissive texture
out = & m_pModel->m_pCurrentMaterial->textureEmissive;
clampIndex = ObjFile::Material::TextureEmissiveType;

View File

@ -186,12 +186,12 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
{
size_t index = 0;
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
{
while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
pBuffer[index] = *m_DataIt;
index++;
if (index == length-1)
if( index == length - 1 ) {
break;
}
++m_DataIt;
}
@ -233,12 +233,13 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
// -------------------------------------------------------------------
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
size_t numComponents( 0 );
DataArrayIt tmp( m_DataIt );
const char* tmp( &m_DataIt[0] );
while( !IsLineEnd( *tmp ) ) {
if( *tmp == ' ' ) {
++numComponents;
if ( !SkipSpaces( &tmp ) ) {
break;
}
tmp++;
SkipToken( tmp );
++numComponents;
}
float x, y, z;
if( 2 == numComponents ) {
@ -344,7 +345,7 @@ void ObjFileParser::getFace(aiPrimitiveType type)
}
iPos++;
}
else if ( isSeparator(*pPtr) )
else if( IsSpaceOrNewLine( *pPtr ) )
{
iPos = 0;
}
@ -462,8 +463,9 @@ void ObjFileParser::getMaterialDesc()
return;
char *pStart = &(*m_DataIt);
while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
++m_DataIt;
}
// Get name
std::string strName(pStart, &(*m_DataIt));
@ -517,12 +519,14 @@ void ObjFileParser::getMaterialLib()
{
// Translate tuple
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
if (m_DataIt == m_DataItEnd)
if( m_DataIt == m_DataItEnd ) {
return;
}
char *pStart = &(*m_DataIt);
while (m_DataIt != m_DataItEnd && !isNewLine(*m_DataIt))
m_DataIt++;
while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
++m_DataIt;
}
// Check for existence
const std::string strMatName(pStart, &(*m_DataIt));
@ -550,13 +554,15 @@ void ObjFileParser::getNewMaterial()
{
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
if ( m_DataIt == m_DataItEnd )
if( m_DataIt == m_DataItEnd ) {
return;
}
char *pStart = &(*m_DataIt);
std::string strMat( pStart, *m_DataIt );
while ( m_DataIt != m_DataItEnd && isSeparator( *m_DataIt ) )
m_DataIt++;
while( m_DataIt != m_DataItEnd && IsSpaceOrNewLine( *m_DataIt ) ) {
++m_DataIt;
}
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
if ( it == m_pModel->m_MaterialMap.end() )
{
@ -581,8 +587,9 @@ void ObjFileParser::getNewMaterial()
int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
{
int mat_index = -1;
if ( strMaterialName.empty() )
if( strMaterialName.empty() ) {
return mat_index;
}
for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
{
if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
@ -601,8 +608,9 @@ void ObjFileParser::getGroupName()
std::string strGroupName;
m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) )
if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
return;
}
// Change active group, if necessary
if ( m_pModel->m_strActiveGroup != strGroupName )
@ -653,11 +661,13 @@ void ObjFileParser::getGroupNumberAndResolution()
void ObjFileParser::getObjectName()
{
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
if (m_DataIt == m_DataItEnd)
if( m_DataIt == m_DataItEnd ) {
return;
}
char *pStart = &(*m_DataIt);
while ( m_DataIt != m_DataItEnd && !isSeparator( *m_DataIt ) )
while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
++m_DataIt;
}
std::string strObjectName(pStart, &(*m_DataIt));
if (!strObjectName.empty())
@ -678,8 +688,9 @@ void ObjFileParser::getObjectName()
}
// Allocate a new object, if current one was not found before
if ( NULL == m_pModel->m_pCurrent )
createObject(strObjectName);
if( NULL == m_pModel->m_pCurrent ) {
createObject( strObjectName );
}
}
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
@ -694,7 +705,6 @@ void ObjFileParser::createObject(const std::string &strObjectName)
m_pModel->m_pCurrent->m_strObjName = strObjectName;
m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
createMesh();
if( m_pModel->m_pCurrentMaterial )

View File

@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define OBJ_TOOLS_H_INC
#include "fast_atof.h"
#include "ParsingUtils.h"
namespace Assimp
{
@ -68,28 +69,6 @@ inline bool isEndOfBuffer( char_t it, char_t end )
return ( it == end );
}
/** @brief Returns true, if token is a space on any supported platform
* @param token Token to search in
* @return true, if token is a space
*/
inline bool isSeparator( char token )
{
return ( token == ' ' ||
token == '\n' ||
token == '\f' ||
token == '\r' ||
token == '\t' );
}
/** @brief Returns true, fi token id a new line marking token.
* @param token Token to search in
* @return true, if token is a newline token.
*/
inline bool isNewLine( char token )
{
return ( token == '\n' || token == '\f' || token == '\r' );
}
/** @brief Returns next word separated by a space
* @param pBuffer Pointer to data buffer
* @param pEnd Pointer to end of buffer
@ -100,7 +79,7 @@ inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd )
{
while ( !isEndOfBuffer( pBuffer, pEnd ) )
{
if ( !isSeparator( *pBuffer ) || isNewLine( *pBuffer ) )
if( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) )
break;
pBuffer++;
}
@ -117,7 +96,7 @@ inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
{
while ( !isEndOfBuffer( pBuffer, pEnd ) )
{
if ( isSeparator( *pBuffer ) )
if( IsSpaceOrNewLine( *pBuffer ) )
break;
pBuffer++;
}
@ -127,14 +106,14 @@ inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
/** @brief Skips a line
* @param it Iterator set to current position
* @param end Iterator set to end of scratch buffer for readout
* @param uiLine Current linenumber in format
* @param uiLine Current line number in format
* @return Current-iterator with new position
*/
template<class char_t>
inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine )
{
while ( !isEndOfBuffer( it, end ) && !isNewLine( *it ) )
inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
++it;
}
if ( it != end )
{
++it;
@ -157,15 +136,16 @@ template<class char_t>
inline char_t getName( char_t it, char_t end, std::string &name )
{
name = "";
if ( isEndOfBuffer( it, end ) )
if( isEndOfBuffer( it, end ) ) {
return end;
}
char *pStart = &( *it );
while ( !isEndOfBuffer( it, end ) && !isNewLine( *it ) ) {
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
++it;
}
while(isEndOfBuffer( it, end ) || isNewLine( *it ) || isSeparator(*it)) {
while( isEndOfBuffer( it, end ) || IsLineEnd( *it ) || IsSpaceOrNewLine( *it ) ) {
--it;
}
++it;
@ -196,7 +176,7 @@ inline char_t CopyNextWord( char_t it, char_t end, char *pBuffer, size_t length
{
size_t index = 0;
it = getNextWord<char_t>( it, end );
while ( !isSeparator( *it ) && !isEndOfBuffer( it, end ) )
while( !IsSpaceOrNewLine( *it ) && !isEndOfBuffer( it, end ) )
{
pBuffer[index] = *it ;
index++;
@ -259,4 +239,4 @@ unsigned int tokenize( const string_type& str, std::vector<string_type>& tokens,
} // Namespace Assimp
#endif
#endif // OBJ_TOOLS_H_INC

View File

@ -376,14 +376,14 @@ void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
mesh->skeletonRef = ReadLine();
}
void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh)
void OgreBinarySerializer::ReadMeshBounds(Mesh * /*mesh*/)
{
// Skip bounds, not compatible with Assimp.
// 2x float vec3 + 1x float sphere radius
SkipBytes(sizeof(float) * 7);
}
void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh)
void OgreBinarySerializer::ReadMeshExtremes(Mesh * /*mesh*/)
{
// Skip extremes, not compatible with Assimp.
size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
@ -534,7 +534,6 @@ void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh *submesh)
void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
{
uint16_t id = 0;
uint16_t submeshIndex = 0;
if (!AtEnd())
{
@ -644,7 +643,7 @@ void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest)
DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
}
void OgreBinarySerializer::ReadEdgeList(Mesh *mesh)
void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/)
{
// Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
@ -1055,7 +1054,7 @@ void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton)
DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
}
void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest)
void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest)
{
uint16_t boneId = Read<uint16_t>();
Bone *bone = dest->parentSkeleton->BoneById(boneId);
@ -1097,7 +1096,7 @@ void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *d
dest->transformKeyFrames.push_back(keyframe);
}
void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton *skeleton)
void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton * /*skeleton*/)
{
// Skip bounds, not compatible with Assimp.
ReadLine(); // skeleton name

View File

@ -75,8 +75,8 @@ private:
};
OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
m_reader(reader),
m_currentLen(0),
m_reader(reader),
assetMode(mode)
{
}
@ -301,11 +301,12 @@ enum MeshChunkId
// unsigned short poseIndex
// float influence
// Optional submesh extreme vertex list chink
M_TABLE_EXTREMES = 0xE000,
M_TABLE_EXTREMES = 0xE000
// unsigned short submesh_index;
// float extremes [n_extremes][3];
};
/*
static std::string MeshHeaderToString(MeshChunkId id)
{
switch(id)
@ -347,6 +348,7 @@ static std::string MeshHeaderToString(MeshChunkId id)
}
return "Unknown_MeshChunkId";
}
*/
enum SkeletonChunkId
{
@ -393,6 +395,7 @@ enum SkeletonChunkId
// float scale : scale to apply to trans/scale keys
};
/*
static std::string SkeletonHeaderToString(SkeletonChunkId id)
{
switch(id)
@ -409,6 +412,7 @@ static std::string SkeletonHeaderToString(SkeletonChunkId id)
}
return "Unknown_SkeletonChunkId";
}
*/
} // Ogre
} // Assimp

View File

@ -108,10 +108,10 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
MemoryStreamReader reader(f);
// Import mesh
boost::scoped_ptr<Mesh> mesh = OgreBinarySerializer::ImportMesh(&reader);
boost::scoped_ptr<Mesh> mesh(OgreBinarySerializer::ImportMesh(&reader));
// Import skeleton
OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh);
OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh.get());
// Import mesh referenced materials
ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
@ -128,10 +128,10 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
// Import mesh
boost::scoped_ptr<MeshXml> mesh = OgreXmlSerializer::ImportMesh(reader.get());
boost::scoped_ptr<MeshXml> mesh(OgreXmlSerializer::ImportMesh(reader.get()));
// Import skeleton
OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh);
OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh.get());
// Import mesh referenced materials
ReadMaterials(pFile, pIOHandler, pScene, mesh.get());

View File

@ -325,7 +325,7 @@ uint32_t VertexData::VertexSize(uint16_t source) const
MemoryStream *VertexData::VertexBuffer(uint16_t source)
{
if (vertexBindings.find(source) != vertexBindings.end())
return vertexBindings[source];
return vertexBindings[source].get();
return 0;
}
@ -404,9 +404,9 @@ size_t IndexData::FaceSize() const
// Mesh
Mesh::Mesh() :
sharedVertexData(0),
skeleton(0),
hasSkeletalAnimations(false)
hasSkeletalAnimations(false),
skeleton(NULL),
sharedVertexData(NULL)
{
}
@ -712,8 +712,8 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
// MeshXml
MeshXml::MeshXml() :
sharedVertexData(0),
skeleton(0)
skeleton(0),
sharedVertexData(0)
{
}
@ -797,8 +797,8 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest)
// SubMeshXml
SubMeshXml::SubMeshXml() :
vertexData(0),
indexData(new IndexDataXml())
indexData(new IndexDataXml()),
vertexData(0)
{
}
@ -912,8 +912,8 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent)
// Animation
Animation::Animation(Skeleton *parent) :
parentMesh(NULL),
parentSkeleton(parent),
parentMesh(0),
length(0.0f),
baseTime(-1.0f)
{
@ -963,6 +963,8 @@ aiAnimation *Animation::ConvertToAssimpAnimation()
// Skeleton
Skeleton::Skeleton() :
bones(),
animations(),
blendMode(ANIMBLEND_AVERAGE)
{
}
@ -1103,7 +1105,7 @@ aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
return node;
}
aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights)
aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector<aiVertexWeight> &boneWeights)
{
aiBone *bone = new aiBone();
bone->mName = name;
@ -1122,8 +1124,8 @@ aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWe
// VertexAnimationTrack
VertexAnimationTrack::VertexAnimationTrack() :
target(0),
type(VAT_NONE)
type(VAT_NONE),
target(0)
{
}

View File

@ -47,22 +47,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
using namespace Assimp;
#include "OptimizeMeshes.h"
#include "ProcessHelper.h"
#include "SceneCombiner.h"
static const unsigned int NotSet = 0xffffffff;
static const unsigned int DeadBeef = 0xdeadbeef;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
OptimizeMeshesProcess::OptimizeMeshesProcess()
: pts (false)
, max_verts (0xffffffff)
, max_faces (0xffffffff)
{}
, max_verts( NotSet )
, max_faces( NotSet ) {
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
OptimizeMeshesProcess::~OptimizeMeshesProcess()
{}
OptimizeMeshesProcess::~OptimizeMeshesProcess() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
@ -74,17 +80,17 @@ bool OptimizeMeshesProcess::IsActive( unsigned int pFlags) const
// That's a serious design flaw, consider redesign.
if( 0 != (pFlags & aiProcess_OptimizeMeshes) ) {
pts = (0 != (pFlags & aiProcess_SortByPType));
max_verts = (0 != (pFlags & aiProcess_SplitLargeMeshes)) ? 0xdeadbeef : max_verts;
max_verts = ( 0 != ( pFlags & aiProcess_SplitLargeMeshes ) ) ? DeadBeef : max_verts;
return true;
}
return false;
}
// ------------------------------------------------------------------------------------------------
// Setup properties for the postprocessing step
// Setup properties for the post-processing step
void OptimizeMeshesProcess::SetupProperties(const Importer* pImp)
{
if (max_verts == 0xdeadbeef /* magic hack */) {
if( max_verts == DeadBeef /* magic hack */ ) {
max_faces = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
max_verts = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
}
@ -104,35 +110,36 @@ void OptimizeMeshesProcess::Execute( aiScene* pScene)
mScene = pScene;
// need to clear persistent members from previous runs
merge_list.clear();
output.clear();
merge_list.resize( 0 );
output.resize( 0 );
// ensure we have the right sizes
merge_list.reserve(pScene->mNumMeshes);
output.reserve(pScene->mNumMeshes);
// Prepare lookup tables
meshes.resize(pScene->mNumMeshes);
FindInstancedMeshes(pScene->mRootNode);
if (max_verts == 0xdeadbeef) /* undo the magic hack */
max_verts = 0xffffffff;
if( max_verts == DeadBeef ) /* undo the magic hack */
max_verts = NotSet;
// ... instanced meshes are immediately processed and added to the output list
for (unsigned int i = 0, n = 0; i < pScene->mNumMeshes;++i) {
meshes[i].vertex_format = GetMeshVFormatUnique(pScene->mMeshes[i]);
if (meshes[i].instance_cnt > 1 && meshes[i].output_id == 0xffffffff) {
if (meshes[i].instance_cnt > 1 && meshes[i].output_id == NotSet ) {
meshes[i].output_id = n++;
output.push_back(mScene->mMeshes[i]);
}
}
// and process all nodes in the scenegraoh recursively
// and process all nodes in the scenegraph recursively
ProcessNode(pScene->mRootNode);
if (!output.size()) {
throw DeadlyImportError("OptimizeMeshes: No meshes remaining; there's definitely something wrong");
}
meshes.clear();
meshes.resize( 0 );
ai_assert(output.size() <= num_old);
mScene->mNumMeshes = output.size();
@ -142,8 +149,9 @@ void OptimizeMeshesProcess::Execute( aiScene* pScene)
char tmp[512];
::sprintf(tmp,"OptimizeMeshesProcess finished. Input meshes: %i, Output meshes: %i",num_old,pScene->mNumMeshes);
DefaultLogger::get()->info(tmp);
} else {
DefaultLogger::get()->debug( "OptimizeMeshesProcess finished" );
}
else DefaultLogger::get()->debug("OptimizeMeshesProcess finished");
}
// ------------------------------------------------------------------------------------------------
@ -157,7 +165,7 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
im = meshes[im].output_id;
}
else {
merge_list.clear();
merge_list.resize( 0 );
unsigned int verts = 0, faces = 0;
// Find meshes to merge with us
@ -170,8 +178,9 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
faces += mScene->mMeshes[am]->mNumFaces;
--pNode->mNumMeshes;
for (unsigned int n = a; n < pNode->mNumMeshes; ++n)
pNode->mMeshes[n] = pNode->mMeshes[n+1];
for( unsigned int n = a; n < pNode->mNumMeshes; ++n ) {
pNode->mMeshes[ n ] = pNode->mMeshes[ n + 1 ];
}
--a;
}
@ -184,8 +193,7 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
aiMesh* out;
SceneCombiner::MergeMeshes(&out,0,merge_list.begin(),merge_list.end());
output.push_back(out);
}
else {
} else {
output.push_back(mScene->mMeshes[im]);
}
im = output.size()-1;
@ -193,8 +201,9 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
}
for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
ProcessNode(pNode->mChildren[i]);
for( unsigned int i = 0; i < pNode->mNumChildren; ++i ) {
ProcessNode( pNode->mChildren[ i ] );
}
}
// ------------------------------------------------------------------------------------------------
@ -206,8 +215,8 @@ bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned i
aiMesh* ma = mScene->mMeshes[a], *mb = mScene->mMeshes[b];
if ((0xffffffff != max_verts && verts+mb->mNumVertices > max_verts) ||
(0xffffffff != max_faces && faces+mb->mNumFaces > max_faces)) {
if ((NotSet != max_verts && verts+mb->mNumVertices > max_verts) ||
(NotSet != max_faces && faces+mb->mNumFaces > max_faces)) {
return false;
}
@ -221,7 +230,7 @@ bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned i
return false;
// If both meshes are skinned, check whether we have many bones defined in both meshes.
// If yes, we can savely join them.
// If yes, we can join them.
if (ma->HasBones()) {
// TODO
return false;
@ -230,14 +239,18 @@ bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned i
}
// ------------------------------------------------------------------------------------------------
// Buidl a LUT of all instanced meshes
// Build a LUT of all instanced meshes
void OptimizeMeshesProcess::FindInstancedMeshes (aiNode* pNode)
{
for (unsigned int i = 0; i < pNode->mNumMeshes;++i)
++meshes[pNode->mMeshes[i]].instance_cnt;
for( unsigned int i = 0; i < pNode->mNumMeshes; ++i ) {
++meshes[ pNode->mMeshes[ i ] ].instance_cnt;
}
for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
FindInstancedMeshes(pNode->mChildren[i]);
for( unsigned int i = 0; i < pNode->mNumChildren; ++i ) {
FindInstancedMeshes( pNode->mChildren[ i ] );
}
}
// ------------------------------------------------------------------------------------------------
#endif // !! ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS

View File

@ -46,16 +46,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_PARSING_UTILS_H_INC
#include "StringComparison.h"
namespace Assimp {
// NOTE: the functions below are mostly intended as replacement for
// std::upper, std::lower, std::isupper, std::islower, std::isspace.
// we don't bother of locales. We don't want them. We want reliable
// (i.e. identical) results across all locales.
// NOTE: the functions below are mostly intended as replacement for
// std::upper, std::lower, std::isupper, std::islower, std::isspace.
// we don't bother of locales. We don't want them. We want reliable
// (i.e. identical) results across all locales.
// The functions below accept any character type, but know only
// about ASCII. However, UTF-32 is the only safe ASCII superset to
// use since it doesn't have multibyte sequences.
// The functions below accept any character type, but know only
// about ASCII. However, UTF-32 is the only safe ASCII superset to
// use since it doesn't have multi-byte sequences.
static const unsigned int BufferSize = 4096;
// ---------------------------------------------------------------------------------
template <class char_t>
@ -63,118 +66,145 @@ AI_FORCE_INLINE char_t ToLower( char_t in)
{
return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE char_t ToUpper( char_t in)
{
AI_FORCE_INLINE char_t ToUpper( char_t in) {
return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsUpper( char_t in)
{
return (in >= (char_t)'A' && in <= (char_t)'Z');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLower( char_t in)
{
return (in >= (char_t)'a' && in <= (char_t)'z');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpace( char_t in)
{
return (in == (char_t)' ' || in == (char_t)'\t');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLineEnd( char_t in)
{
return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0');
return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
{
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out)
{
while (*in == (char_t)' ' || *in == (char_t)'\t')in++;
while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
++in;
}
*out = in;
return !IsLineEnd<char_t>(*in);
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipSpaces( const char_t** inout)
{
return SkipSpaces<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out)
{
while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0')in++;
while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
++in;
}
// files are opened in binary mode. Ergo there are both NL and CR
while (*in == (char_t)'\r' || *in == (char_t)'\n')in++;
while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
++in;
}
*out = in;
return *in != (char_t)'\0';
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipLine( const char_t** inout)
{
return SkipLine<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
{
while (*in == (char_t)' ' || *in == (char_t)'\t' ||
*in == (char_t)'\r' || *in == (char_t)'\n')in++;
while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
++in;
}
*out = in;
return *in != '\0';
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout)
{
return SkipSpacesAndLineEnd<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool GetNextLine(const char_t*& buffer, char_t out[4096])
AI_FORCE_INLINE bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] )
{
if ((char_t)'\0' == *buffer)return false;
if( ( char_t )'\0' == *buffer ) {
return false;
}
char* _out = out;
char* const end = _out+4096;
while (!IsLineEnd( *buffer ) && _out < end)
char* const end = _out + BufferSize;
while( !IsLineEnd( *buffer ) && _out < end ) {
*_out++ = *buffer++;
}
*_out = (char_t)'\0';
while (IsLineEnd( *buffer ) && '\0' != *buffer)++buffer;
while( IsLineEnd( *buffer ) && '\0' != *buffer ) {
++buffer;
}
return true;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsNumeric( char_t in)
{
return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len)
{
if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len]))
{
if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
in += len+1;
return true;
}
return false;
}
// ---------------------------------------------------------------------------------
@ -185,8 +215,7 @@ AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len
*/
AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len)
{
if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len]))
{
if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
in += len+1;
return true;
}
@ -206,5 +235,9 @@ AI_FORCE_INLINE std::string GetNextToken(const char*& in)
while (!IsSpaceOrNewLine(*in))++in;
return std::string(cur,(size_t)(in-cur));
}
// ---------------------------------------------------------------------------------
} // ! namespace Assimp
#endif // ! AI_PARSING_UTILS_H_INC

View File

@ -64,6 +64,20 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
}
void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
// invoke the exporter
PlyExporter exporter(pFile, pScene, true);
// we're still here - export successfully completed. Write the file.
boost::scoped_ptr<IOStream> outfile(pIOSystem->Open(pFile, "wb"));
if (outfile == NULL) {
throw DeadlyExportError("could not open output .ply file: " + std::string(pFile));
}
outfile->Write(exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()), 1);
}
} // end of namespace Assimp
#define PLY_EXPORT_HAS_NORMALS 0x1
@ -72,7 +86,7 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
#define PLY_EXPORT_HAS_COLORS (PLY_EXPORT_HAS_TEXCOORDS << AI_MAX_NUMBER_OF_TEXTURECOORDS)
// ------------------------------------------------------------------------------------------------
PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool binary)
: filename(_filename)
, pScene(pScene)
, endl("\n")
@ -102,7 +116,16 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
}
mOutput << "ply" << endl;
if (binary) {
#if (defined AI_BUILD_BIG_ENDIAN)
mOutput << "format binary_big_endian 1.0" << endl;
#else
mOutput << "format binary_little_endian 1.0" << endl;
#endif
}
else {
mOutput << "format ascii 1.0" << endl;
}
mOutput << "comment Created by Open Asset Import Library - http://assimp.sf.net (v"
<< aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
<< aiGetVersionRevision() << ")" << endl;
@ -163,17 +186,29 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
mOutput << "end_header" << endl;
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
WriteMeshVerts(pScene->mMeshes[i],components);
if (binary) {
WriteMeshVertsBinary(pScene->mMeshes[i], components);
}
else {
WriteMeshVerts(pScene->mMeshes[i], components);
}
}
for (unsigned int i = 0, ofs = 0; i < pScene->mNumMeshes; ++i) {
WriteMeshIndices(pScene->mMeshes[i],ofs);
if (binary) {
WriteMeshIndicesBinary(pScene->mMeshes[i], ofs);
}
else {
WriteMeshIndices(pScene->mMeshes[i], ofs);
}
ofs += pScene->mMeshes[i]->mNumVertices;
}
}
// ------------------------------------------------------------------------------------------------
void PlyExporter :: WriteMeshVerts(const aiMesh* m, unsigned int components)
void PlyExporter::WriteMeshVerts(const aiMesh* m, unsigned int components)
{
// If a component (for instance normal vectors) is present in at least one mesh in the scene,
// then default values are written for meshes that do not contain this component.
for (unsigned int i = 0; i < m->mNumVertices; ++i) {
mOutput <<
m->mVertices[i].x << " " <<
@ -237,7 +272,57 @@ void PlyExporter :: WriteMeshVerts(const aiMesh* m, unsigned int components)
}
// ------------------------------------------------------------------------------------------------
void PlyExporter :: WriteMeshIndices(const aiMesh* m, unsigned int offset)
void PlyExporter::WriteMeshVertsBinary(const aiMesh* m, unsigned int components)
{
// If a component (for instance normal vectors) is present in at least one mesh in the scene,
// then default values are written for meshes that do not contain this component.
aiVector3D defaultNormal(0, 0, 0);
aiVector2D defaultUV(-1, -1);
aiColor4D defaultColor(-1, -1, -1, -1);
for (unsigned int i = 0; i < m->mNumVertices; ++i) {
mOutput.write(reinterpret_cast<const char*>(&m->mVertices[i].x), 12);
if (components & PLY_EXPORT_HAS_NORMALS) {
if (m->HasNormals()) {
mOutput.write(reinterpret_cast<const char*>(&m->mNormals[i].x), 12);
}
else {
mOutput.write(reinterpret_cast<const char*>(&defaultNormal.x), 12);
}
}
for (unsigned int n = PLY_EXPORT_HAS_TEXCOORDS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_TEXTURECOORDS; n <<= 1, ++c) {
if (m->HasTextureCoords(c)) {
mOutput.write(reinterpret_cast<const char*>(&m->mTextureCoords[c][i].x), 6);
}
else {
mOutput.write(reinterpret_cast<const char*>(&defaultUV.x), 6);
}
}
for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
if (m->HasVertexColors(c)) {
mOutput.write(reinterpret_cast<const char*>(&m->mColors[c][i].r), 16);
}
else {
mOutput.write(reinterpret_cast<const char*>(&defaultColor.r), 16);
}
}
if (components & PLY_EXPORT_HAS_TANGENTS_BITANGENTS) {
if (m->HasTangentsAndBitangents()) {
mOutput.write(reinterpret_cast<const char*>(&m->mTangents[i].x), 12);
mOutput.write(reinterpret_cast<const char*>(&m->mBitangents[i].x), 12);
}
else {
mOutput.write(reinterpret_cast<const char*>(&defaultNormal.x), 12);
mOutput.write(reinterpret_cast<const char*>(&defaultNormal.x), 12);
}
}
}
}
// ------------------------------------------------------------------------------------------------
void PlyExporter::WriteMeshIndices(const aiMesh* m, unsigned int offset)
{
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
const aiFace& f = m->mFaces[i];
@ -248,4 +333,16 @@ void PlyExporter :: WriteMeshIndices(const aiMesh* m, unsigned int offset)
}
}
void PlyExporter::WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset)
{
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
const aiFace& f = m->mFaces[i];
mOutput.write(reinterpret_cast<const char*>(&f.mNumIndices), 4);
for (unsigned int c = 0; c < f.mNumIndices; ++c) {
unsigned int index = f.mIndices[c] + offset;
mOutput.write(reinterpret_cast<const char*>(&index), 4);
}
}
}
#endif

View File

@ -59,7 +59,7 @@ class PlyExporter
{
public:
/// Constructor for a specific scene to export
PlyExporter(const char* filename, const aiScene* pScene);
PlyExporter(const char* filename, const aiScene* pScene, bool binary = false);
public:
@ -71,6 +71,9 @@ private:
void WriteMeshVerts(const aiMesh* m, unsigned int components);
void WriteMeshIndices(const aiMesh* m, unsigned int ofs);
void WriteMeshVertsBinary(const aiMesh* m, unsigned int components);
void WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset);
private:
const std::string filename;

View File

@ -182,7 +182,7 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* pCur,const char** pCurOu
{
eOut = PLY::EST_Opacity;
}
else if (TokenMatch(pCur,"specular_power",6))
else if (TokenMatch(pCur,"specular_power",14))
{
eOut = PLY::EST_PhongPower;
}

View File

@ -118,9 +118,9 @@ inline bool IsCCW(T* in, size_t npoints) {
((-in[i+2].y + in[i+1].y) *
(-in[i+2].y + in[i+1].y));
b = sqrt(bb);
c = sqrt(cc);
theta = acos((bb + cc - aa) / (2 * b * c));
b = std::sqrt(bb);
c = std::sqrt(cc);
theta = std::acos((bb + cc - aa) / (2 * b * c));
if (OnLeftSideOfLine2D(in[i],in[i+2],in[i+1])) {
// if (convex(in[i].x, in[i].y,
@ -146,9 +146,9 @@ inline bool IsCCW(T* in, size_t npoints) {
cc = ((in[1].x - in[0].x) * (in[1].x - in[0].x)) +
((-in[1].y + in[0].y) * (-in[1].y + in[0].y));
b = sqrt(bb);
c = sqrt(cc);
theta = acos((bb + cc - aa) / (2 * b * c));
b = std::sqrt(bb);
c = std::sqrt(cc);
theta = std::acos((bb + cc - aa) / (2 * b * c));
//if (convex(in[npoints-2].x, in[npoints-2].y,
// in[0].x, in[0].y,

View File

@ -73,11 +73,13 @@ static const aiImporterDesc desc = {
namespace Assimp {
/*
static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
supportedExtensions.push_back( ".jpg" );
supportedExtensions.push_back( ".png" );
supportedExtensions.push_back( ".tga" );
}
*/
using namespace Q3BSP;
@ -628,7 +630,7 @@ aiFace *Q3BSPFileImporter::getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx )
bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel,
Q3BSP::Q3BSPZipArchive *pArchive, aiScene*,
aiMaterial *pMatHelper, int textureId ) {
if ( NULL == pArchive || NULL == pArchive || NULL == pMatHelper ) {
if ( NULL == pArchive || NULL == pMatHelper ) {
return false;
}
@ -649,7 +651,7 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pMode
std::string textureName, ext;
if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) ) {
IOStream *pTextureStream = pArchive->Open( textureName.c_str() );
if ( !pTextureStream ) {
if ( pTextureStream ) {
size_t texSize = pTextureStream->FileSize();
aiTexture *pTexture = new aiTexture;
pTexture->mHeight = 0;

View File

@ -68,25 +68,25 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
return (voidpf) io_system->Open(filename, mode_fopen);
}
uLong IOSystem2Unzip::read(voidpf opaque, voidpf stream, void* buf, uLong size) {
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
IOStream* io_stream = (IOStream*) stream;
return io_stream->Read(buf, 1, size);
}
uLong IOSystem2Unzip::write(voidpf opaque, voidpf stream, const void* buf, uLong size) {
uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
IOStream* io_stream = (IOStream*) stream;
return io_stream->Write(buf, 1, size);
}
long IOSystem2Unzip::tell(voidpf opaque, voidpf stream) {
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
IOStream* io_stream = (IOStream*) stream;
return io_stream->Tell();
}
long IOSystem2Unzip::seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
IOStream* io_stream = (IOStream*) stream;
aiOrigin assimp_origin;
@ -115,7 +115,7 @@ int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
return 0;
}
int IOSystem2Unzip::testerror(voidpf opaque, voidpf stream) {
int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
return 0;
}

View File

@ -348,8 +348,8 @@ bool STLImporter::LoadBinaryFile()
bool bIsMaterialise = false;
// search for an occurence of "COLOR=" in the header
const char* sz2 = (const char*)mBuffer;
const char* const szEnd = sz2+80;
const unsigned char* sz2 = (const unsigned char*)mBuffer;
const unsigned char* const szEnd = sz2+80;
while (sz2 < szEnd) {
if ('C' == *sz2++ && 'O' == *sz2++ && 'L' == *sz2++ &&

View File

@ -38,6 +38,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
// TODO: refactor entire file to get rid of the "flat-copy" first approach
// to copying structures. This easily breaks in the most unintuitive way
// possible as new fields are added to assimp structures.
// ----------------------------------------------------------------------------
/** @file Implements Assimp::SceneCombiner. This is a smart utility
@ -1194,10 +1197,53 @@ void SceneCombiner::Copy (aiNode** _dest, const aiNode* src)
// get a flat copy
::memcpy(dest,src,sizeof(aiNode));
if (src->mMetaData) {
Copy(&dest->mMetaData, src->mMetaData);
}
// and reallocate all arrays
GetArrayCopy( dest->mMeshes, dest->mNumMeshes );
CopyPtrArray( dest->mChildren, src->mChildren,dest->mNumChildren);
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::Copy (aiMetadata** _dest, const aiMetadata* src)
{
ai_assert(NULL != _dest && NULL != src);
aiMetadata* dest = *_dest = new aiMetadata();
dest->mNumProperties = src->mNumProperties;
dest->mKeys = new aiString[src->mNumProperties];
std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys);
dest->mValues = new aiMetadataEntry[src->mNumProperties];
for (unsigned int i = 0; i < src->mNumProperties; ++i) {
aiMetadataEntry& in = src->mValues[i];
aiMetadataEntry& out = dest->mValues[i];
out.mType = in.mType;
switch (dest->mValues[i].mType) {
case AI_BOOL:
out.mData = new bool(*static_cast<bool*>(in.mData));
break;
case AI_INT:
out.mData = new int(*static_cast<int*>(in.mData));
break;
case AI_UINT64:
out.mData = new uint64_t(*static_cast<uint64_t*>(in.mData));
break;
case AI_FLOAT:
out.mData = new float(*static_cast<float*>(in.mData));
break;
case AI_AISTRING:
out.mData = new aiString(*static_cast<aiString*>(in.mData));
break;
case AI_AIVECTOR3D:
out.mData = new aiVector3D(*static_cast<aiVector3D*>(in.mData));
break;
default:
ai_assert(false);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More