Merge branch 'master' into fix_gltf2_export_componentType_error

pull/1925/head
Kim Kulling 2018-09-22 07:54:10 +02:00 committed by GitHub
commit cc0b3e1249
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
238 changed files with 31028 additions and 15924 deletions

9
.gitignore vendored
View File

@ -12,6 +12,8 @@ build
bin/ bin/
lib/ lib/
# QtCreator
CMakeLists.txt.user
# Generated # Generated
assimp.pc assimp.pc
@ -19,6 +21,7 @@ revision.h
contrib/zlib/zconf.h contrib/zlib/zconf.h
contrib/zlib/zlib.pc contrib/zlib/zlib.pc
include/assimp/config.h include/assimp/config.h
unit.vcxproj.user
# CMake # CMake
CMakeCache.txt CMakeCache.txt
@ -85,3 +88,9 @@ lib64/assimp-vc120-mt.exp
xcuserdata xcuserdata
cmake-build-debug cmake-build-debug
install_manifest.txt
tools/assimp_qt_viewer/moc_glview.cpp
tools/assimp_qt_viewer/moc_glview.cpp_parameters
tools/assimp_qt_viewer/moc_mainwindow.cpp
tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters
tools/assimp_qt_viewer/ui_mainwindow.h

7
Build.md 100644
View File

@ -0,0 +1,7 @@
# Build instructions
> cmake CMakeLists.txt
make -j4
##UWP
See https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app

View File

@ -39,10 +39,12 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
PROJECT( Assimp ) PROJECT( Assimp )
# All supported options ############################################### # All supported options ###############################################
OPTION( BUILD_SHARED_LIBS OPTION( BUILD_SHARED_LIBS
"Build package with shared libraries." "Build package with shared libraries."
ON ON
) )
OPTION( BUILD_FRAMEWORK OPTION( BUILD_FRAMEWORK
"Build package as Mac OS X Framework bundle." "Build package as Mac OS X Framework bundle."
OFF OFF
@ -103,6 +105,16 @@ OPTION ( BUILD_DOCS
"Build documentation using Doxygen." "Build documentation using Doxygen."
OFF OFF
) )
OPTION( INJECT_DEBUG_POSTFIX
"Inject debug postfix in .a/.so lib names"
ON
)
IF (IOS)
IF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release")
ENDIF (NOT CMAKE_BUILD_TYPE)
ENDIF (IOS)
# Use subset of Windows.h # Use subset of Windows.h
if (WIN32) if (WIN32)
@ -152,7 +164,7 @@ EXECUTE_PROCESS(
# Get the latest abbreviated commit hash of the working branch # Get the latest abbreviated commit hash of the working branch
EXECUTE_PROCESS( EXECUTE_PROCESS(
COMMAND git log -1 --format=%h COMMAND git log -1 --format=%h --no-show-signature
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
@ -198,13 +210,13 @@ ENDIF( UNIX )
# Grouped compiler settings # Grouped compiler settings
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW) IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
# hide all not-exported symbols # hide all not-exported symbols
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -std=c++0x") SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fPIC -fno-strict-aliasing -Wall -std=c++0x ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") SET(CMAKE_C_FLAGS "-fPIC -fno-strict-aliasing ${CMAKE_C_FLAGS}")
SET(LIBSTDC++_LIBRARIES -lstdc++) SET(LIBSTDC++_LIBRARIES -lstdc++)
ELSEIF(MSVC) ELSEIF(MSVC)
# enable multi-core compilation with MSVC # enable multi-core compilation with MSVC
ADD_COMPILE_OPTIONS(/MP) ADD_COMPILE_OPTIONS(/MP)
IF("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)") if(CMAKE_SIZEOF_VOID_P EQUAL 8)
ADD_COMPILE_OPTIONS( /bigobj ) ADD_COMPILE_OPTIONS( /bigobj )
ENDIF() ENDIF()
# disable "elements of array '' will be default initialized" warning on MSVC2013 # disable "elements of array '' will be default initialized" warning on MSVC2013
@ -212,19 +224,26 @@ ELSEIF(MSVC)
ADD_COMPILE_OPTIONS(/wd4351) ADD_COMPILE_OPTIONS(/wd4351)
ENDIF() ENDIF()
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" ) SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fPIC -fno-strict-aliasing -Wall -Wno-long-long -std=c++11 ${CMAKE_CXX_FLAGS}" )
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") SET(CMAKE_C_FLAGS "-fPIC -fno-strict-aliasing ${CMAKE_C_FLAGS}")
ELSEIF( CMAKE_COMPILER_IS_MINGW ) ELSEIF( CMAKE_COMPILER_IS_MINGW )
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -std=c++11" ) SET( CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -std=c++11 -Wa,-mbig-obj ${CMAKE_CXX_FLAGS}" )
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") SET(CMAKE_C_FLAGS "-fPIC -fno-strict-aliasing ${CMAKE_C_FLAGS} ")
ADD_DEFINITIONS( -U__STRICT_ANSI__ ) ADD_DEFINITIONS( -U__STRICT_ANSI__ )
ENDIF() ENDIF()
IF (IOS) IF ( IOS )
IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -Og")
ELSE()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
ENDIF() ENDIF()
ENDIF( IOS )
IF (ASSIMP_COVERALLS) IF (ASSIMP_COVERALLS)
MESSAGE(STATUS "Coveralls enabled") MESSAGE(STATUS "Coveralls enabled")
INCLUDE(Coveralls) INCLUDE(Coveralls)
@ -320,6 +339,8 @@ IF( NOT ZLIB_FOUND )
SET(ZLIB_FOUND 1) SET(ZLIB_FOUND 1)
SET(ZLIB_LIBRARIES zlibstatic) SET(ZLIB_LIBRARIES zlibstatic)
SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib) SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
# need to ensure we don't link with system zlib or minizip as well.
SET(ASSIMP_BUILD_MINIZIP 1)
ELSE(NOT ZLIB_FOUND) ELSE(NOT ZLIB_FOUND)
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB) ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
SET(ZLIB_LIBRARIES_LINKED -lz) SET(ZLIB_LIBRARIES_LINKED -lz)
@ -327,7 +348,17 @@ ENDIF(NOT ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
# Search for unzip # Search for unzip
use_pkgconfig(UNZIP minizip) IF ( NOT IOS )
IF( NOT ASSIMP_BUILD_MINIZIP )
use_pkgconfig(UNZIP minizip)
ENDIF( NOT ASSIMP_BUILD_MINIZIP )
ELSE ( NOT IOS )
IF(NOT BUILD_SHARED_LIBS)
IF( NOT ASSIMP_BUILD_MINIZIP )
use_pkgconfig(UNZIP minizip)
ENDIF( NOT ASSIMP_BUILD_MINIZIP )
ENDIF (NOT BUILD_SHARED_LIBS)
ENDIF ( NOT IOS )
IF ( ASSIMP_NO_EXPORT ) IF ( ASSIMP_NO_EXPORT )
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
@ -412,32 +443,9 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY ) ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
ADD_SUBDIRECTORY( tools/assimp_cmd/ ) ADD_SUBDIRECTORY( tools/assimp_cmd/ )
IF (NOT IOS)
# Check dependencies for assimp_qt_viewer.
# Why here? Maybe user do not want Qt viewer and have no Qt.
# Why assimp_qt_viewer/CMakeLists.txt still contain similar check?
# Because viewer can be build independently of Assimp.
FIND_PACKAGE(Qt5Widgets QUIET)
FIND_PACKAGE(DevIL QUIET)
FIND_PACKAGE(OpenGL QUIET)
IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ ) ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
ELSE() ENDIF (NOT IOS)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
IF (NOT Qt5_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5")
ENDIF (NOT Qt5_FOUND)
IF (NOT IL_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL")
ENDIF (NOT IL_FOUND)
IF (NOT OPENGL_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL")
ENDIF (NOT OPENGL_FOUND)
MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}")
ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS ) ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
IF ( ASSIMP_BUILD_SAMPLES) IF ( ASSIMP_BUILD_SAMPLES)

View File

@ -1,11 +1,10 @@
#How to contribute # How to contribute
If you want to contribute you can follow these setps:
- Fist create your own clone of assimp
- When you want to fix a bug or add a new feature create a branch on your own fork ( just follow https://help.github.com/articles/creating-a-pull-request-from-a-fork/ )
- Push it to the repo and open a pull request
- A pull request will start our CI-service, which checks if the build works for linux and windows.
It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fails: fix it and the tests will be reastarted automatically
- At the end we will perform a code review and merge your branch to the master branch.
If you want to contribute, follow these steps:
- First, create your own clone of assimp.
- When you want to fix a bug or add a new feature, create a branch on your own fork following [these instructions](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
- Push it to your fork of the repository and open a pull request.
- A pull request will start our continuous integration service, which checks if the build works for Linux and Windows.
It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fail, fix it and the tests will be restarted automatically.
- At the end, we will perform a code review and merge your branch to the master branch.

View File

@ -42,3 +42,6 @@ For Windows:
1. Open a command prompt 1. Open a command prompt
2. cmake CMakeLists.txt 2. cmake CMakeLists.txt
2. Open your default IDE and build it 2. Open your default IDE and build it
For iOS:
Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS

View File

@ -30,6 +30,8 @@ One-off donations via PayPal:
Please check our Wiki as well: https://github.com/assimp/assimp/wiki Please check our Wiki as well: https://github.com/assimp/assimp/wiki
If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
#### Supported file formats #### #### Supported file formats ####
__Importers__: __Importers__:

View File

@ -32,6 +32,9 @@ install:
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017 - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
- if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64 - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
- cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%"
- set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe
cache: cache:
- code\assimp.dir\%CONFIGURATION% - code\assimp.dir\%CONFIGURATION%
@ -50,6 +53,7 @@ build:
project: Assimp.sln project: Assimp.sln
after_build: after_build:
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss
- 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\* - 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\*
test_script: test_script:

View File

@ -204,8 +204,9 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
// Setup the texture mapping mode // Setup the texture mapping mode
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0)); int mapMode = static_cast<int>(texture.mMapMode);
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0)); mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
// Mirroring - double the scaling values // Mirroring - double the scaling values
// FIXME: this is not really correct ... // FIXME: this is not really correct ...
@ -313,7 +314,8 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
case D3DS::Discreet3DS::Blinn : case D3DS::Discreet3DS::Blinn :
eShading = aiShadingMode_Blinn; break; eShading = aiShadingMode_Blinn; break;
} }
mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); int eShading_ = static_cast<int>(eShading);
mat.AddProperty<int>(&eShading_, 1, AI_MATKEY_SHADING_MODEL);
// DIFFUSE texture // DIFFUSE texture
if( oldMat.sTexDiffuse.mMapName.length() > 0) if( oldMat.sTexDiffuse.mMapName.length() > 0)

View File

@ -66,7 +66,7 @@ namespace D3DS {
*/ */
class Discreet3DS { class Discreet3DS {
private: private:
Discreet3DS() { Discreet3DS() AI_NO_EXCEPT {
// empty // empty
} }
@ -328,10 +328,9 @@ struct Face : public FaceWithSmoothingGroup
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing a texture */ /** Helper structure representing a texture */
struct Texture struct Texture {
{
//! Default constructor //! Default constructor
Texture() Texture() AI_NO_EXCEPT
: mOffsetU (0.0) : mOffsetU (0.0)
, mOffsetV (0.0) , mOffsetV (0.0)
, mScaleU (1.0) , mScaleU (1.0)
@ -339,8 +338,7 @@ struct Texture
, mRotation (0.0) , mRotation (0.0)
, mMapMode (aiTextureMapMode_Wrap) , mMapMode (aiTextureMapMode_Wrap)
, bPrivate() , bPrivate()
, iUVSrc (0) , iUVSrc (0) {
{
mTextureBlend = get_qnan(); mTextureBlend = get_qnan();
} }
@ -394,7 +392,7 @@ struct Material
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
Material(Material &&other) Material(Material &&other) AI_NO_EXCEPT
: mName(std::move(other.mName)) : mName(std::move(other.mName))
, mDiffuse(std::move(other.mDiffuse)) , mDiffuse(std::move(other.mDiffuse))
, mSpecularExponent(std::move(other.mSpecularExponent)) , mSpecularExponent(std::move(other.mSpecularExponent))
@ -418,7 +416,7 @@ struct Material
} }
Material &operator=(Material &&other) { Material &operator=(Material &&other) AI_NO_EXCEPT {
if (this == &other) { if (this == &other) {
return *this; return *this;
} }
@ -447,7 +445,7 @@ struct Material
} }
~Material() {} virtual ~Material() {}
//! Name of the material //! Name of the material

View File

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

View File

@ -63,8 +63,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Header files, stdlib. // Header files, stdlib.
#include <set> #include <set>
namespace Assimp namespace Assimp {
{
/// \class AMFImporter /// \class AMFImporter
/// Class that holding scene graph which include: geometry, metadata, materials etc. /// Class that holding scene graph which include: geometry, metadata, materials etc.
/// ///
@ -99,34 +99,25 @@ namespace Assimp
/// new - <texmap> and children <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3> /// new - <texmap> and children <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>
/// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3> /// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3>
/// ///
class AMFImporter : public BaseImporter class AMFImporter : public BaseImporter {
{
/***********************************************/
/******************** Types ********************/
/***********************************************/
private: private:
struct SPP_Material;// forward declaration struct SPP_Material;// forward declaration
/// \struct SPP_Composite /// \struct SPP_Composite
/// Data type for postprocessing step. More suitable container for part of material's composition. /// Data type for post-processing step. More suitable container for part of material's composition.
struct SPP_Composite struct SPP_Composite {
{
SPP_Material* Material;///< Pointer to material - part of composition. SPP_Material* Material;///< Pointer to material - part of composition.
std::string Formula;///< Formula for calculating ratio of \ref Material. std::string Formula;///< Formula for calculating ratio of \ref Material.
}; };
/// \struct SPP_Material /// \struct SPP_Material
/// Data type for postprocessing step. More suitable container for material. /// Data type for post-processing step. More suitable container for material.
struct SPP_Material struct SPP_Material {
{
std::string ID;///< Material ID. std::string ID;///< Material ID.
std::list<CAMFImporter_NodeElement_Metadata*> Metadata;///< Metadata of material. std::list<CAMFImporter_NodeElement_Metadata*> Metadata;///< Metadata of material.
CAMFImporter_NodeElement_Color* Color;///< Color of material. CAMFImporter_NodeElement_Color* Color;///< Color of material.
std::list<SPP_Composite> Composition;///< List of child materials if current material is composition of few another. std::list<SPP_Composite> Composition;///< List of child materials if current material is composition of few another.
/// \fn aiColor4D GetColor(const float pX, const float pY, const float pZ) const
/// Return color calculated for specified coordinate. /// Return color calculated for specified coordinate.
/// \param [in] pX - "x" coordinate. /// \param [in] pX - "x" coordinate.
/// \param [in] pY - "y" coordinate. /// \param [in] pY - "y" coordinate.
@ -135,64 +126,22 @@ private:
aiColor4D GetColor(const float pX, const float pY, const float pZ) const; aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
}; };
/// \struct SPP_Texture
/// Data type for post-processing step. More suitable container for texture. /// Data type for post-processing step. More suitable container for texture.
struct SPP_Texture struct SPP_Texture {
{
std::string ID; std::string ID;
size_t Width, Height, Depth; size_t Width, Height, Depth;
bool Tiled; bool Tiled;
char FormatHint[ 9 ];// 8 for string + 1 for terminator. char FormatHint[9];// 8 for string + 1 for terminator.
uint8_t *Data; uint8_t *Data;
}; };
/// \struct SComplexFace
/// Data type for post-processing step. Contain face data. /// Data type for post-processing step. Contain face data.
struct SComplexFace struct SComplexFace {
{
aiFace Face;///< Face vertices. aiFace Face;///< Face vertices.
const CAMFImporter_NodeElement_Color* Color;///< Face color. Equal to nullptr if color is not set for the face. const CAMFImporter_NodeElement_Color* Color;///< Face color. Equal to nullptr if color is not set for the face.
const CAMFImporter_NodeElement_TexMap* TexMap;///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face. const CAMFImporter_NodeElement_TexMap* TexMap;///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
}; };
/***********************************************/
/****************** Constants ******************/
/***********************************************/
private:
static const aiImporterDesc Description;
/***********************************************/
/****************** Variables ******************/
/***********************************************/
private:
CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element.
std::list<CAMFImporter_NodeElement*> mNodeElement_List;///< All elements of scene graph.
irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
std::string mUnit;
std::list<SPP_Material> mMaterial_Converted;///< List of converted materials for postprocessing step.
std::list<SPP_Texture> mTexture_Converted;///< List of converted textures for postprocessing step.
/***********************************************/
/****************** Functions ******************/
/***********************************************/
private:
/// \fn AMFImporter(const AMFImporter& pScene)
/// Disabled copy constructor.
AMFImporter(const AMFImporter& pScene);
/// \fn AMFImporter& operator=(const AMFImporter& pScene)
/// Disabled assign operator.
AMFImporter& operator=(const AMFImporter& pScene);
/// \fn void Clear()
/// Clear all temporary data. /// Clear all temporary data.
void Clear(); void Clear();
@ -200,7 +149,6 @@ private:
/************* Functions: find set *************/ /************* Functions: find set *************/
/***********************************************/ /***********************************************/
/// \fn bool Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, aiNode** pNode) const
/// Find specified node element in node elements list ( \ref mNodeElement_List). /// Find specified node element in node elements list ( \ref mNodeElement_List).
/// \param [in] pID - ID(name) of requested node element. /// \param [in] pID - ID(name) of requested node element.
/// \param [in] pType - type of node element. /// \param [in] pType - type of node element.
@ -208,7 +156,6 @@ private:
/// \return true - if the node element is found, else - false. /// \return true - if the node element is found, else - false.
bool Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const; bool Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const;
/// \fn bool Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const
/// Find requested aiNode in node list. /// Find requested aiNode in node list.
/// \param [in] pID - ID(name) of requested node. /// \param [in] pID - ID(name) of requested node.
/// \param [in] pNodeList - list of nodes where to find the node. /// \param [in] pNodeList - list of nodes where to find the node.
@ -216,14 +163,12 @@ private:
/// \return true - if the node is found, else - false. /// \return true - if the node is found, else - false.
bool Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const; bool Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const;
/// \fn bool Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const
/// Find material in list for converted materials. Use at postprocessing step. /// Find material in list for converted materials. Use at postprocessing step.
/// \param [in] pID - material ID. /// \param [in] pID - material ID.
/// \param [out] pConvertedMaterial - pointer to found converted material (\ref SPP_Material). /// \param [out] pConvertedMaterial - pointer to found converted material (\ref SPP_Material).
/// \return true - if the material is found, else - false. /// \return true - if the material is found, else - false.
bool Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const; bool Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const;
/// \fn bool Find_ConvertedTexture(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A, uint32_t* pConvertedTextureIndex = nullptr) const
/// Find texture in list of converted textures. Use at postprocessing step, /// Find texture in list of converted textures. Use at postprocessing step,
/// \param [in] pID_R - ID of source "red" texture. /// \param [in] pID_R - ID of source "red" texture.
/// \param [in] pID_G - ID of source "green" texture. /// \param [in] pID_G - ID of source "green" texture.
@ -235,11 +180,7 @@ private:
bool Find_ConvertedTexture(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A, bool Find_ConvertedTexture(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A,
uint32_t* pConvertedTextureIndex = nullptr) const; uint32_t* pConvertedTextureIndex = nullptr) const;
/***********************************************/
/********* Functions: postprocess set **********/
/***********************************************/
/// \fn void PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray, std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const
/// Get data stored in <vertices> and place it to arrays. /// Get data stored in <vertices> and place it to arrays.
/// \param [in] pNodeElement - reference to node element which kept <object> data. /// \param [in] pNodeElement - reference to node element which kept <object> data.
/// \param [in] pVertexCoordinateArray - reference to vertices coordinates kept in <vertices>. /// \param [in] pVertexCoordinateArray - reference to vertices coordinates kept in <vertices>.
@ -248,7 +189,6 @@ private:
void PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray, void PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray,
std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const; std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const;
/// \fn size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A)
/// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new /// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new
/// converted texture will be returned. Conversion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it /// converted texture will be returned. Conversion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it
/// to converted textures list. /// to converted textures list.
@ -260,27 +200,23 @@ private:
/// \return index of the texture in array of the converted textures. /// \return index of the texture in array of the converted textures.
size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A); size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A);
/// \fn void PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> > pOutputList_Separated)
/// Separate input list by texture IDs. This step is needed because aiMesh can contain mesh which is use only one texture (or set: diffuse, bump etc). /// Separate input list by texture IDs. This step is needed because aiMesh can contain mesh which is use only one texture (or set: diffuse, bump etc).
/// \param [in] pInputList - input list with faces. Some of them can contain color or texture mapping, or both of them, or nothing. Will be cleared after /// \param [in] pInputList - input list with faces. Some of them can contain color or texture mapping, or both of them, or nothing. Will be cleared after
/// processing. /// processing.
/// \param [out] pOutputList_Separated - output list of the faces lists. Separated faces list by used texture IDs. Will be cleared before processing. /// \param [out] pOutputList_Separated - output list of the faces lists. Separated faces list by used texture IDs. Will be cleared before processing.
void PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> >& pOutputList_Separated); void PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> >& pOutputList_Separated);
/// \fn void Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& pMetadataList, aiNode& pSceneNode) const
/// Check if child elements of node element is metadata and add it to scene node. /// Check if child elements of node element is metadata and add it to scene node.
/// \param [in] pMetadataList - reference to list with collected metadata. /// \param [in] pMetadataList - reference to list with collected metadata.
/// \param [out] pSceneNode - scene node in which metadata will be added. /// \param [out] pSceneNode - scene node in which metadata will be added.
void Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& pMetadataList, aiNode& pSceneNode) const; void Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& pMetadataList, aiNode& pSceneNode) const;
/// \fn void Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode)
/// To create aiMesh and aiNode for it from <object>. /// To create aiMesh and aiNode for it from <object>.
/// \param [in] pNodeElement - reference to node element which kept <object> data. /// \param [in] pNodeElement - reference to node element which kept <object> data.
/// \param [out] pMeshList - reference to a list with all aiMesh of the scene. /// \param [out] pMeshList - reference to a list with all aiMesh of the scene.
/// \param [out] pSceneNode - pointer to place where new aiNode will be created. /// \param [out] pSceneNode - pointer to place where new aiNode will be created.
void Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode); void Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode);
/// \fn void Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh& pNodeElement, const std::vector<aiVector3D>& pVertexCoordinateArray, const std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray, const CAMFImporter_NodeElement_Color* pObjectColor, std::list<aiMesh*>& pMeshList, aiNode& pSceneNode)
/// Create mesh for every <volume> in <mesh>. /// Create mesh for every <volume> in <mesh>.
/// \param [in] pNodeElement - reference to node element which kept <mesh> data. /// \param [in] pNodeElement - reference to node element which kept <mesh> data.
/// \param [in] pVertexCoordinateArray - reference to vertices coordinates for all <volume>'s. /// \param [in] pVertexCoordinateArray - reference to vertices coordinates for all <volume>'s.
@ -294,27 +230,20 @@ private:
const std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray, const CAMFImporter_NodeElement_Color* pObjectColor, const std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray, const CAMFImporter_NodeElement_Color* pObjectColor,
std::list<aiMesh*>& pMeshList, aiNode& pSceneNode); std::list<aiMesh*>& pMeshList, aiNode& pSceneNode);
/// \fn void Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial)
/// Convert material from \ref CAMFImporter_NodeElement_Material to \ref SPP_Material. /// Convert material from \ref CAMFImporter_NodeElement_Material to \ref SPP_Material.
/// \param [in] pMaterial - source CAMFImporter_NodeElement_Material. /// \param [in] pMaterial - source CAMFImporter_NodeElement_Material.
void Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial); void Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial);
/// \fn void Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list<aiNode*>& pNodeList) const
/// Create and add to aiNode's list new part of scene graph defined by <constellation>. /// Create and add to aiNode's list new part of scene graph defined by <constellation>.
/// \param [in] pConstellation - reference to <constellation> node. /// \param [in] pConstellation - reference to <constellation> node.
/// \param [out] pNodeList - reference to aiNode's list. /// \param [out] pNodeList - reference to aiNode's list.
void Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list<aiNode*>& pNodeList) const; void Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list<aiNode*>& pNodeList) const;
/// \fn void Postprocess_BuildScene()
/// Build Assimp scene graph in aiScene from collected data. /// Build Assimp scene graph in aiScene from collected data.
/// \param [out] pScene - pointer to aiScene where tree will be built. /// \param [out] pScene - pointer to aiScene where tree will be built.
void Postprocess_BuildScene(aiScene* pScene); void Postprocess_BuildScene(aiScene* pScene);
/***********************************************/
/************* Functions: throw set ************/
/***********************************************/
/// \fn void Throw_CloseNotFound(const std::string& pNode)
/// Call that function when close tag of node not found and exception must be raised. /// Call that function when close tag of node not found and exception must be raised.
/// E.g.: /// E.g.:
/// <amf> /// <amf>
@ -324,19 +253,16 @@ private:
/// \param [in] pNode - node name in which exception happened. /// \param [in] pNode - node name in which exception happened.
void Throw_CloseNotFound(const std::string& pNode); void Throw_CloseNotFound(const std::string& pNode);
/// \fn void Throw_IncorrectAttr(const std::string& pAttrName)
/// Call that function when attribute name is incorrect and exception must be raised. /// Call that function when attribute name is incorrect and exception must be raised.
/// \param [in] pAttrName - attribute name. /// \param [in] pAttrName - attribute name.
/// \throw DeadlyImportError. /// \throw DeadlyImportError.
void Throw_IncorrectAttr(const std::string& pAttrName); void Throw_IncorrectAttr(const std::string& pAttrName);
/// \fn void Throw_IncorrectAttrValue(const std::string& pAttrName)
/// Call that function when attribute value is incorrect and exception must be raised. /// Call that function when attribute value is incorrect and exception must be raised.
/// \param [in] pAttrName - attribute name. /// \param [in] pAttrName - attribute name.
/// \throw DeadlyImportError. /// \throw DeadlyImportError.
void Throw_IncorrectAttrValue(const std::string& pAttrName); void Throw_IncorrectAttrValue(const std::string& pAttrName);
/// \fn void Throw_MoreThanOnceDefined(const std::string& pNode, const std::string& pDescription)
/// Call that function when some type of nodes are defined twice or more when must be used only once and exception must be raised. /// Call that function when some type of nodes are defined twice or more when must be used only once and exception must be raised.
/// E.g.: /// E.g.:
/// <object> /// <object>
@ -348,204 +274,158 @@ private:
/// \param [in] pDescription - message about error. E.g. what the node defined while exception raised. /// \param [in] pDescription - message about error. E.g. what the node defined while exception raised.
void Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription); void Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription);
/// \fn void Throw_ID_NotFound(const std::string& pID) const
/// Call that function when referenced element ID are not found in graph and exception must be raised. /// Call that function when referenced element ID are not found in graph and exception must be raised.
/// \param [in] pID - ID of of element which not found. /// \param [in] pID - ID of of element which not found.
/// \throw DeadlyImportError. /// \throw DeadlyImportError.
void Throw_ID_NotFound(const std::string& pID) const; void Throw_ID_NotFound(const std::string& pID) const;
/***********************************************/
/************** Functions: LOG set *************/
/***********************************************/
/***********************************************/
/************** Functions: XML set *************/
/***********************************************/
/// \fn void XML_CheckNode_MustHaveChildren()
/// Check if current node have children: <node>...</node>. If not then exception will throwed. /// Check if current node have children: <node>...</node>. If not then exception will throwed.
void XML_CheckNode_MustHaveChildren(); void XML_CheckNode_MustHaveChildren();
/// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName)
/// Check if current node name is equal to pNodeName. /// Check if current node name is equal to pNodeName.
/// \param [in] pNodeName - name for checking. /// \param [in] pNodeName - name for checking.
/// return true if current node name is equal to pNodeName, else - false. /// return true if current node name is equal to pNodeName, else - false.
bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; } bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
/// \fn void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
/// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node. /// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node.
/// \param [in] pParentNodeName - parent node name. Used for reporting. /// \param [in] pParentNodeName - parent node name. Used for reporting.
void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName); void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName);
/// \fn bool XML_SearchNode(const std::string& pNodeName)
/// Search for specified node in file. XML file read pointer(mReader) will point to found node or file end after search is end. /// Search for specified node in file. XML file read pointer(mReader) will point to found node or file end after search is end.
/// \param [in] pNodeName - requested node name. /// \param [in] pNodeName - requested node name.
/// return true - if node is found, else - false. /// return true - if node is found, else - false.
bool XML_SearchNode(const std::string& pNodeName); bool XML_SearchNode(const std::string& pNodeName);
/// \fn bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
/// Read attribute value. /// Read attribute value.
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
/// \return read data. /// \return read data.
bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx); bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx);
/// \fn float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
/// Read attribute value. /// Read attribute value.
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
/// \return read data. /// \return read data.
float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx); float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx);
/// \fn uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx)
/// Read attribute value. /// Read attribute value.
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
/// \return read data. /// \return read data.
uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx); uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx);
/// \fn float XML_ReadNode_GetVal_AsFloat()
/// Read node value. /// Read node value.
/// \return read data. /// \return read data.
float XML_ReadNode_GetVal_AsFloat(); float XML_ReadNode_GetVal_AsFloat();
/// \fn uint32_t XML_ReadNode_GetVal_AsU32()
/// Read node value. /// Read node value.
/// \return read data. /// \return read data.
uint32_t XML_ReadNode_GetVal_AsU32(); uint32_t XML_ReadNode_GetVal_AsU32();
/// \fn void XML_ReadNode_GetVal_AsString(std::string& pValue)
/// Read node value. /// Read node value.
/// \return read data. /// \return read data.
void XML_ReadNode_GetVal_AsString(std::string& pValue); void XML_ReadNode_GetVal_AsString(std::string& pValue);
/***********************************************/
/******** Functions: parse set private *********/
/***********************************************/
/// \fn void ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode)
/// Make pNode as current and enter deeper for parsing child nodes. At end \ref ParseHelper_Node_Exit must be called. /// Make pNode as current and enter deeper for parsing child nodes. At end \ref ParseHelper_Node_Exit must be called.
/// \param [in] pNode - new current node. /// \param [in] pNode - new current node.
void ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode); void ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode);
/// \fn void ParseHelper_Group_End()
/// This function must be called when exiting from grouping node. \ref ParseHelper_Group_Begin. /// This function must be called when exiting from grouping node. \ref ParseHelper_Group_Begin.
void ParseHelper_Node_Exit(); void ParseHelper_Node_Exit();
/// \fn void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
/// Attribute values of floating point types can take form ".x"(without leading zero). irrXMLReader can not read this form of values and it /// Attribute values of floating point types can take form ".x"(without leading zero). irrXMLReader can not read this form of values and it
/// must be converted to right form - "0.xxx". /// must be converted to right form - "0.xxx".
/// \param [in] pInStr - pointer to input string which can contain incorrect form of values. /// \param [in] pInStr - pointer to input string which can contain incorrect form of values.
/// \param [out[ pOutString - output string with right form of values. /// \param [out[ pOutString - output string with right form of values.
void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString); void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString);
/// \fn void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const
/// Decode Base64-encoded data. /// Decode Base64-encoded data.
/// \param [in] pInputBase64 - reference to input Base64-encoded string. /// \param [in] pInputBase64 - reference to input Base64-encoded string.
/// \param [out] pOutputData - reference to output array for decoded data. /// \param [out] pOutputData - reference to output array for decoded data.
void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const; void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const;
/// \fn void ParseNode_Root()
/// Parse <AMF> node of the file. /// Parse <AMF> node of the file.
void ParseNode_Root(); void ParseNode_Root();
/******** Functions: top nodes *********/
/// \fn void ParseNode_Constellation()
/// Parse <constellation> node of the file. /// Parse <constellation> node of the file.
void ParseNode_Constellation(); void ParseNode_Constellation();
/// \fn void ParseNode_Constellation()
/// Parse <instance> node of the file. /// Parse <instance> node of the file.
void ParseNode_Instance(); void ParseNode_Instance();
/// \fn void ParseNode_Material()
/// Parse <material> node of the file. /// Parse <material> node of the file.
void ParseNode_Material(); void ParseNode_Material();
/// \fn void ParseNode_Metadata()
/// Parse <metadata> node. /// Parse <metadata> node.
void ParseNode_Metadata(); void ParseNode_Metadata();
/// \fn void ParseNode_Object()
/// Parse <object> node of the file. /// Parse <object> node of the file.
void ParseNode_Object(); void ParseNode_Object();
/// \fn void ParseNode_Texture()
/// Parse <texture> node of the file. /// Parse <texture> node of the file.
void ParseNode_Texture(); void ParseNode_Texture();
/******** Functions: geometry nodes *********/
/// \fn void ParseNode_Coordinates()
/// Parse <coordinates> node of the file. /// Parse <coordinates> node of the file.
void ParseNode_Coordinates(); void ParseNode_Coordinates();
/// \fn void ParseNode_Edge()
/// Parse <edge> node of the file. /// Parse <edge> node of the file.
void ParseNode_Edge(); void ParseNode_Edge();
/// \fn void ParseNode_Mesh()
/// Parse <mesh> node of the file. /// Parse <mesh> node of the file.
void ParseNode_Mesh(); void ParseNode_Mesh();
/// \fn void ParseNode_Triangle()
/// Parse <triangle> node of the file. /// Parse <triangle> node of the file.
void ParseNode_Triangle(); void ParseNode_Triangle();
/// \fn void ParseNode_Vertex()
/// Parse <vertex> node of the file. /// Parse <vertex> node of the file.
void ParseNode_Vertex(); void ParseNode_Vertex();
/// \fn void ParseNode_Vertices()
/// Parse <vertices> node of the file. /// Parse <vertices> node of the file.
void ParseNode_Vertices(); void ParseNode_Vertices();
/// \fn void ParseNode_Volume()
/// Parse <volume> node of the file. /// Parse <volume> node of the file.
void ParseNode_Volume(); void ParseNode_Volume();
/******** Functions: material nodes *********/
/// \fn void ParseNode_Color()
/// Parse <color> node of the file. /// Parse <color> node of the file.
void ParseNode_Color(); void ParseNode_Color();
/// \fn void ParseNode_TexMap(const bool pUseOldName = false)
/// Parse <texmap> of <map> node of the file. /// Parse <texmap> of <map> node of the file.
/// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>. /// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>.
void ParseNode_TexMap(const bool pUseOldName = false); void ParseNode_TexMap(const bool pUseOldName = false);
public: public:
/// \fn AMFImporter()
/// Default constructor. /// Default constructor.
AMFImporter() AMFImporter() AI_NO_EXCEPT
: mNodeElement_Cur(nullptr), mReader(nullptr) : mNodeElement_Cur(nullptr)
{} , mReader(nullptr) {
// empty
}
/// \fn ~AMFImporter()
/// Default destructor. /// Default destructor.
~AMFImporter(); ~AMFImporter();
/***********************************************/
/******** Functions: parse set, public *********/
/***********************************************/
/// \fn void ParseFile(const std::string& pFile, IOSystem* pIOHandler)
/// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph. /// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
/// Also exception can be throwed if trouble will found. /// Also exception can be thrown if trouble will found.
/// \param [in] pFile - name of file to be parsed. /// \param [in] pFile - name of file to be parsed.
/// \param [in] pIOHandler - pointer to IO helper object. /// \param [in] pIOHandler - pointer to IO helper object.
void ParseFile(const std::string& pFile, IOSystem* pIOHandler); void ParseFile(const std::string& pFile, IOSystem* pIOHandler);
/***********************************************/
/********* Functions: BaseImporter set *********/
/***********************************************/
bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const; bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const;
void GetExtensionList(std::set<std::string>& pExtensionList); void GetExtensionList(std::set<std::string>& pExtensionList);
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
const aiImporterDesc* GetInfo ()const; const aiImporterDesc* GetInfo ()const;
};// class AMFImporter AMFImporter(const AMFImporter& pScene) = delete;
AMFImporter& operator=(const AMFImporter& pScene) = delete;
private:
static const aiImporterDesc Description;
CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element.
std::list<CAMFImporter_NodeElement*> mNodeElement_List;///< All elements of scene graph.
irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
std::string mUnit;
std::list<SPP_Material> mMaterial_Converted;///< List of converted materials for postprocessing step.
std::list<SPP_Texture> mTexture_Converted;///< List of converted textures for postprocessing step.
};
}// namespace Assimp }// namespace Assimp

View File

@ -68,10 +68,9 @@ namespace Assimp
// Multi elements - No. // Multi elements - No.
// Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The // Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The
// values can be specified as constants, or as a formula depending on the coordinates. // values can be specified as constants, or as a formula depending on the coordinates.
void AMFImporter::ParseNode_Color() void AMFImporter::ParseNode_Color() {
{ std::string profile;
std::string profile; CAMFImporter_NodeElement* ne;
CAMFImporter_NodeElement* ne;
// Read attributes for node <color>. // Read attributes for node <color>.
MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_LOOPBEG;
@ -98,15 +97,19 @@ CAMFImporter_NodeElement* ne;
MACRO_NODECHECK_LOOPEND("color"); MACRO_NODECHECK_LOOPEND("color");
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
// check that all components was defined // check that all components was defined
if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined."); if (!(read_flag[0] && read_flag[1] && read_flag[2])) {
// check if <a> is absent. Then manually add "a == 1". throw DeadlyImportError("Not all color components are defined.");
if(!read_flag[3]) als.Color.a = 1; }
}// if(!mReader->isEmptyElement()) // check if <a> is absent. Then manually add "a == 1".
if (!read_flag[3]) {
als.Color.a = 1;
}
}
else else
{ {
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else }
als.Composed = false; als.Composed = false;
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
@ -119,10 +122,9 @@ CAMFImporter_NodeElement* ne;
// An available material. // An available material.
// Multi elements - Yes. // Multi elements - Yes.
// Parent element - <amf>. // Parent element - <amf>.
void AMFImporter::ParseNode_Material() void AMFImporter::ParseNode_Material() {
{ std::string id;
std::string id; CAMFImporter_NodeElement* ne;
CAMFImporter_NodeElement* ne;
// Read attributes for node <color>. // Read attributes for node <color>.
MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_LOOPBEG;
@ -131,8 +133,10 @@ CAMFImporter_NodeElement* ne;
// create new object. // create new object.
ne = new CAMFImporter_NodeElement_Material(mNodeElement_Cur); ne = new CAMFImporter_NodeElement_Material(mNodeElement_Cur);
// and assign read data // and assign read data
((CAMFImporter_NodeElement_Material*)ne)->ID = id; ((CAMFImporter_NodeElement_Material*)ne)->ID = id;
// Check for child nodes // Check for child nodes
if(!mReader->isEmptyElement()) if(!mReader->isEmptyElement())
{ {
@ -154,11 +158,11 @@ CAMFImporter_NodeElement* ne;
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("material"); MACRO_NODECHECK_LOOPEND("material");
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement()) }
else else
{ {
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else }
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
} }
@ -181,14 +185,13 @@ CAMFImporter_NodeElement* ne;
// Parent element - <amf>. // Parent element - <amf>.
void AMFImporter::ParseNode_Texture() void AMFImporter::ParseNode_Texture()
{ {
std::string id; std::string id;
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
uint32_t depth = 1; uint32_t depth = 1;
std::string type; std::string type;
bool tiled = false; bool tiled = false;
std::string enc64_data; std::string enc64_data;
CAMFImporter_NodeElement* ne;
// Read attributes for node <color>. // Read attributes for node <color>.
MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_LOOPBEG;
@ -201,20 +204,34 @@ CAMFImporter_NodeElement* ne;
MACRO_ATTRREAD_LOOPEND; MACRO_ATTRREAD_LOOPEND;
// create new texture object. // create new texture object.
ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur); CAMFImporter_NodeElement *ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur);
CAMFImporter_NodeElement_Texture& als = *((CAMFImporter_NodeElement_Texture*)ne);// alias for convenience CAMFImporter_NodeElement_Texture& als = *((CAMFImporter_NodeElement_Texture*)ne);// alias for convenience
// Check for child nodes // Check for child nodes
if(!mReader->isEmptyElement()) XML_ReadNode_GetVal_AsString(enc64_data); if (!mReader->isEmptyElement()) {
XML_ReadNode_GetVal_AsString(enc64_data);
}
// check that all components was defined // check that all components was defined
if(id.empty()) throw DeadlyImportError("ID for texture must be defined."); if (id.empty()) {
if(width < 1) Throw_IncorrectAttrValue("width"); throw DeadlyImportError("ID for texture must be defined.");
if(height < 1) Throw_IncorrectAttrValue("height"); }
if(depth < 1) Throw_IncorrectAttrValue("depth"); if (width < 1) {
if(type != "grayscale") Throw_IncorrectAttrValue("type"); Throw_IncorrectAttrValue("width");
if(enc64_data.empty()) throw DeadlyImportError("Texture data not defined."); }
if (height < 1) {
Throw_IncorrectAttrValue("height");
}
if (depth < 1) {
Throw_IncorrectAttrValue("depth");
}
if (type != "grayscale") {
Throw_IncorrectAttrValue("type");
}
if (enc64_data.empty()) {
throw DeadlyImportError("Texture data not defined.");
}
// copy data // copy data
als.ID = id; als.ID = id;
als.Width = width; als.Width = width;
@ -222,8 +239,11 @@ CAMFImporter_NodeElement* ne;
als.Depth = depth; als.Depth = depth;
als.Tiled = tiled; als.Tiled = tiled;
ParseHelper_Decode_Base64(enc64_data, als.Data); ParseHelper_Decode_Base64(enc64_data, als.Data);
// check data size // check data size
if((width * height * depth) != als.Data.size()) throw DeadlyImportError("Texture has incorrect data size."); if ((width * height * depth) != als.Data.size()) {
throw DeadlyImportError("Texture has incorrect data size.");
}
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
@ -243,10 +263,8 @@ CAMFImporter_NodeElement* ne;
// <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>. Old name: <u1>, <u2>, <u3>, <v1>, <v2>, <v3>. // <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>. Old name: <u1>, <u2>, <u3>, <v1>, <v2>, <v3>.
// Multi elements - No. // Multi elements - No.
// Texture coordinates for every vertex of triangle. // Texture coordinates for every vertex of triangle.
void AMFImporter::ParseNode_TexMap(const bool pUseOldName) void AMFImporter::ParseNode_TexMap(const bool pUseOldName) {
{ std::string rtexid, gtexid, btexid, atexid;
std::string rtexid, gtexid, btexid, atexid;
CAMFImporter_NodeElement* ne;
// Read attributes for node <color>. // Read attributes for node <color>.
MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_LOOPBEG;
@ -257,7 +275,7 @@ CAMFImporter_NodeElement* ne;
MACRO_ATTRREAD_LOOPEND; MACRO_ATTRREAD_LOOPEND;
// create new texture coordinates object. // create new texture coordinates object.
ne = new CAMFImporter_NodeElement_TexMap(mNodeElement_Cur); CAMFImporter_NodeElement *ne = new CAMFImporter_NodeElement_TexMap(mNodeElement_Cur);
CAMFImporter_NodeElement_TexMap& als = *((CAMFImporter_NodeElement_TexMap*)ne);// alias for convenience CAMFImporter_NodeElement_TexMap& als = *((CAMFImporter_NodeElement_TexMap*)ne);// alias for convenience
// check data // check data

View File

@ -62,7 +62,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// \class CAMFImporter_NodeElement /// \class CAMFImporter_NodeElement
/// Base class for elements of nodes. /// Base class for elements of nodes.
class CAMFImporter_NodeElement { class CAMFImporter_NodeElement {
public: public:
/// Define what data type contain node element. /// Define what data type contain node element.
enum EType { enum EType {
@ -96,15 +95,11 @@ public: /// Destructor, virtual..
// empty // empty
} }
private: /// Disabled copy constructor and co.
/// Disabled copy constructor. CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement) = delete;
CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement); CAMFImporter_NodeElement(CAMFImporter_NodeElement&&) = delete;
CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement) = delete;
/// Disabled assign operator. CAMFImporter_NodeElement() = delete;
CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement);
/// Disabled default constructor.
CAMFImporter_NodeElement();
protected: protected:
/// In constructor inheritor must set element type. /// In constructor inheritor must set element type.
@ -121,9 +116,7 @@ protected:
/// \struct CAMFImporter_NodeElement_Constellation /// \struct CAMFImporter_NodeElement_Constellation
/// A collection of objects or constellations with specific relative locations. /// A collection of objects or constellations with specific relative locations.
struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement {
{
/// \fn CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent)
@ -134,9 +127,7 @@ struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement
/// \struct CAMFImporter_NodeElement_Instance /// \struct CAMFImporter_NodeElement_Instance
/// Part of constellation. /// Part of constellation.
struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement {
{
/****************** Variables ******************/
std::string ObjectID;///< ID of object for instantiation. std::string ObjectID;///< ID of object for instantiation.
/// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to /// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to
@ -147,237 +138,185 @@ struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement
/// instance of the object in the current constellation. Rotations shall be executed in order of x first, then y, then z. /// instance of the object in the current constellation. Rotations shall be executed in order of x first, then y, then z.
aiVector3D Rotation; aiVector3D Rotation;
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Instance, pParent) : CAMFImporter_NodeElement(ENET_Instance, pParent)
{} {}
};
};// struct CAMFImporter_NodeElement_Instance
/// \struct CAMFImporter_NodeElement_Metadata /// \struct CAMFImporter_NodeElement_Metadata
/// Structure that define metadata node. /// Structure that define metadata node.
struct CAMFImporter_NodeElement_Metadata : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Metadata : public CAMFImporter_NodeElement {
{
/****************** Variables ******************/
std::string Type;///< Type of "Value". std::string Type;///< Type of "Value".
std::string Value;///< Value. std::string Value;///< Value.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Metadata, pParent) : CAMFImporter_NodeElement(ENET_Metadata, pParent)
{} {}
};
};// struct CAMFImporter_NodeElement_Metadata
/// \struct CAMFImporter_NodeElement_Root /// \struct CAMFImporter_NodeElement_Root
/// Structure that define root node. /// Structure that define root node.
struct CAMFImporter_NodeElement_Root : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Root : public CAMFImporter_NodeElement {
{
/****************** Variables ******************/
std::string Unit;///< The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron". std::string Unit;///< The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
std::string Version;///< Version of format. std::string Version;///< Version of format.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Root, pParent) : CAMFImporter_NodeElement(ENET_Root, pParent)
{} {}
};
};// struct CAMFImporter_NodeElement_Root
/// \struct CAMFImporter_NodeElement_Color /// \struct CAMFImporter_NodeElement_Color
/// Structure that define object node. /// Structure that define object node.
struct CAMFImporter_NodeElement_Color : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Color : public CAMFImporter_NodeElement {
{ bool Composed; ///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color.
/****************** Variables ******************/ std::string Color_Composed[4]; ///< By components formulas of composed color. [0..3] - RGBA.
aiColor4D Color; ///< Constant color.
std::string Profile; ///< The ICC color space used to interpret the three color channels r, g and b..
bool Composed;///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color. /// @brief Constructor.
std::string Color_Composed[4];///< By components formulas of composed color. [0..3] => RGBA. /// @param [in] pParent - pointer to parent node.
aiColor4D Color;///< Constant color.
std::string Profile;///< The ICC color space used to interpret the three color channels <r>, <g> and <b>..
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Color, pParent) : CAMFImporter_NodeElement(ENET_Color, pParent)
{} , Composed( false )
, Color()
};// struct CAMFImporter_NodeElement_Color , Profile() {
// empty
}
};
/// \struct CAMFImporter_NodeElement_Material /// \struct CAMFImporter_NodeElement_Material
/// Structure that define material node. /// Structure that define material node.
struct CAMFImporter_NodeElement_Material : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Material : public CAMFImporter_NodeElement {
{
/// \fn CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Material, pParent) : CAMFImporter_NodeElement(ENET_Material, pParent)
{} {}
};// struct CAMFImporter_NodeElement_Material };
/// \struct CAMFImporter_NodeElement_Object /// \struct CAMFImporter_NodeElement_Object
/// Structure that define object node. /// Structure that define object node.
struct CAMFImporter_NodeElement_Object : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Object : public CAMFImporter_NodeElement {
{
/// \fn CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Object, pParent) : CAMFImporter_NodeElement(ENET_Object, pParent)
{} {}
};
};// struct CAMFImporter_NodeElement_Object
/// \struct CAMFImporter_NodeElement_Mesh /// \struct CAMFImporter_NodeElement_Mesh
/// Structure that define mesh node. /// Structure that define mesh node.
struct CAMFImporter_NodeElement_Mesh : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Mesh : public CAMFImporter_NodeElement {
{
/// \fn CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Mesh, pParent) : CAMFImporter_NodeElement(ENET_Mesh, pParent)
{} {}
};
};// struct CAMFImporter_NodeElement_Mesh
/// \struct CAMFImporter_NodeElement_Vertex /// \struct CAMFImporter_NodeElement_Vertex
/// Structure that define vertex node. /// Structure that define vertex node.
struct CAMFImporter_NodeElement_Vertex : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Vertex : public CAMFImporter_NodeElement {
{
/// \fn CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Vertex, pParent) : CAMFImporter_NodeElement(ENET_Vertex, pParent)
{} {}
};
};// struct CAMFImporter_NodeElement_Vertex
/// \struct CAMFImporter_NodeElement_Edge /// \struct CAMFImporter_NodeElement_Edge
/// Structure that define edge node. /// Structure that define edge node.
struct CAMFImporter_NodeElement_Edge : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Edge : public CAMFImporter_NodeElement {
{
/// \fn CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Edge, pParent) : CAMFImporter_NodeElement(ENET_Edge, pParent)
{} {}
};// struct CAMFImporter_NodeElement_Vertex };
/// \struct CAMFImporter_NodeElement_Vertices /// \struct CAMFImporter_NodeElement_Vertices
/// Structure that define vertices node. /// Structure that define vertices node.
struct CAMFImporter_NodeElement_Vertices : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Vertices : public CAMFImporter_NodeElement {
{
/// \fn CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Vertices, pParent) : CAMFImporter_NodeElement(ENET_Vertices, pParent)
{} {}
};
};// struct CAMFImporter_NodeElement_Vertices
/// \struct CAMFImporter_NodeElement_Volume /// \struct CAMFImporter_NodeElement_Volume
/// Structure that define volume node. /// Structure that define volume node.
struct CAMFImporter_NodeElement_Volume : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Volume : public CAMFImporter_NodeElement {
{
/****************** Variables ******************/
std::string MaterialID;///< Which material to use. std::string MaterialID;///< Which material to use.
std::string Type;///< What this volume describes can be “region” or “support”. If none specified, “object” is assumed. std::string Type;///< What this volume describes can be “region” or “support”. If none specified, “object” is assumed.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Volume, pParent) : CAMFImporter_NodeElement(ENET_Volume, pParent)
{} {}
};
};// struct CAMFImporter_NodeElement_Volume
/// \struct CAMFImporter_NodeElement_Coordinates /// \struct CAMFImporter_NodeElement_Coordinates
/// Structure that define coordinates node. /// Structure that define coordinates node.
struct CAMFImporter_NodeElement_Coordinates : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Coordinates : public CAMFImporter_NodeElement
{ {
/****************** Variables ******************/
aiVector3D Coordinate;///< Coordinate. aiVector3D Coordinate;///< Coordinate.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Coordinates, pParent) : CAMFImporter_NodeElement(ENET_Coordinates, pParent)
{} {}
};// struct CAMFImporter_NodeElement_Coordinates };
/// \struct CAMFImporter_NodeElement_TexMap /// \struct CAMFImporter_NodeElement_TexMap
/// Structure that define texture coordinates node. /// Structure that define texture coordinates node.
struct CAMFImporter_NodeElement_TexMap : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_TexMap : public CAMFImporter_NodeElement {
{
/****************** Variables ******************/
aiVector3D TextureCoordinate[3];///< Texture coordinates. aiVector3D TextureCoordinate[3];///< Texture coordinates.
std::string TextureID_R;///< Texture ID for red color component. std::string TextureID_R;///< Texture ID for red color component.
std::string TextureID_G;///< Texture ID for green color component. std::string TextureID_G;///< Texture ID for green color component.
std::string TextureID_B;///< Texture ID for blue color component. std::string TextureID_B;///< Texture ID for blue color component.
std::string TextureID_A;///< Texture ID for alpha color component. std::string TextureID_A;///< Texture ID for alpha color component.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_TexMap, pParent) : CAMFImporter_NodeElement(ENET_TexMap, pParent)
{} , TextureCoordinate{}
, TextureID_R()
};// struct CAMFImporter_NodeElement_TexMap , TextureID_G()
, TextureID_B()
, TextureID_A() {
// empty
}
};
/// \struct CAMFImporter_NodeElement_Triangle /// \struct CAMFImporter_NodeElement_Triangle
/// Structure that define triangle node. /// Structure that define triangle node.
struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement {
{
/****************** Variables ******************/
size_t V[3];///< Triangle vertices. size_t V[3];///< Triangle vertices.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent)
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent) CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Triangle, pParent) : CAMFImporter_NodeElement(ENET_Triangle, pParent) {
{} // empty
}
};// struct CAMFImporter_NodeElement_Triangle };
/// Structure that define texture node. /// Structure that define texture node.
struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement { struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement {
@ -396,6 +335,6 @@ struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement {
, Tiled( false ){ , Tiled( false ){
// empty // empty
} }
};// struct CAMFImporter_NodeElement_Texture };
#endif // INCLUDED_AI_AMF_IMPORTER_NODE_H #endif // INCLUDED_AI_AMF_IMPORTER_NODE_H

View File

@ -71,21 +71,20 @@ struct Material : public D3DS::Material
//! Default constructor has been deleted //! Default constructor has been deleted
Material() = delete; Material() = delete;
//! Constructor with explicit name //! Constructor with explicit name
explicit Material(const std::string &name) explicit Material(const std::string &name)
: D3DS::Material(name) : D3DS::Material(name)
, pcInstance(NULL) , pcInstance(NULL)
, bNeed (false) , bNeed (false) {
{} // empty
}
Material(const Material &other) = default; Material(const Material &other) = default;
Material &operator=(const Material &other) = default; Material &operator=(const Material &other) = default;
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
Material(Material &&other) Material(Material &&other) AI_NO_EXCEPT
: D3DS::Material(std::move(other)) : D3DS::Material(std::move(other))
, avSubMaterials(std::move(other.avSubMaterials)) , avSubMaterials(std::move(other.avSubMaterials))
, pcInstance(std::move(other.pcInstance)) , pcInstance(std::move(other.pcInstance))
@ -95,7 +94,7 @@ struct Material : public D3DS::Material
} }
Material &operator=(Material &&other) { Material &operator=(Material &&other) AI_NO_EXCEPT {
if (this == &other) { if (this == &other) {
return *this; return *this;
} }
@ -127,19 +126,12 @@ struct Material : public D3DS::Material
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file face */ /** Helper structure to represent an ASE file face */
struct Face : public FaceWithSmoothingGroup struct Face : public FaceWithSmoothingGroup {
{
//! Default constructor. Initializes everything with 0 //! Default constructor. Initializes everything with 0
Face() Face() AI_NO_EXCEPT
{ : iMaterial(DEFAULT_MATINDEX)
mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0; , iFace(0) {
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) // empty
{
amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0;
}
iMaterial = DEFAULT_MATINDEX;
iFace = 0;
} }
//! special value to indicate that no material index has //! special value to indicate that no material index has
@ -147,8 +139,6 @@ struct Face : public FaceWithSmoothingGroup
//! will replace this value later. //! will replace this value later.
static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF; static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF;
//! Indices into each list of texture coordinates //! Indices into each list of texture coordinates
unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3]; unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3];
@ -166,15 +156,15 @@ struct Face : public FaceWithSmoothingGroup
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file bone */ /** Helper structure to represent an ASE file bone */
struct Bone struct Bone {
{
//! Constructor //! Constructor
Bone() = delete; Bone() = delete;
//! Construction from an existing name //! Construction from an existing name
explicit Bone( const std::string& name) explicit Bone( const std::string& name)
: mName (name) : mName(name) {
{} // empty
}
//! Name of the bone //! Name of the bone
std::string mName; std::string mName;
@ -182,29 +172,22 @@ struct Bone
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file bone vertex */ /** Helper structure to represent an ASE file bone vertex */
struct BoneVertex struct BoneVertex {
{
//! Bone and corresponding vertex weight. //! Bone and corresponding vertex weight.
//! -1 for unrequired bones .... //! -1 for unrequired bones ....
std::vector<std::pair<int,float> > mBoneWeights; std::vector<std::pair<int,float> > mBoneWeights;
//! Position of the bone vertex.
//! MUST be identical to the vertex position
//aiVector3D mPosition;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file animation */ /** Helper structure to represent an ASE file animation */
struct Animation struct Animation {
{ enum Type {
enum Type
{
TRACK = 0x0, TRACK = 0x0,
BEZIER = 0x1, BEZIER = 0x1,
TCB = 0x2 TCB = 0x2
} mRotationType, mScalingType, mPositionType; } mRotationType, mScalingType, mPositionType;
Animation() Animation() AI_NO_EXCEPT
: mRotationType (TRACK) : mRotationType (TRACK)
, mScalingType (TRACK) , mScalingType (TRACK)
, mPositionType (TRACK) , mPositionType (TRACK)
@ -218,20 +201,17 @@ struct Animation
//! List of track scaling keyframes //! List of track scaling keyframes
std::vector< aiVectorKey > akeyScaling; std::vector< aiVectorKey > akeyScaling;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent the inheritance information of an ASE node */ /** Helper structure to represent the inheritance information of an ASE node */
struct InheritanceInfo struct InheritanceInfo {
{
//! Default constructor //! Default constructor
InheritanceInfo() InheritanceInfo() AI_NO_EXCEPT {
{ for ( size_t i=0; i<3; ++i ) {
// set the inheritance flag for all axes by default to true
for (unsigned int i = 0; i < 3;++i)
abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true; abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
} }
}
//! Inherit the parent's position?, axis order is x,y,z //! Inherit the parent's position?, axis order is x,y,z
bool abInheritPosition[3]; bool abInheritPosition[3];
@ -245,17 +225,19 @@ struct InheritanceInfo
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Represents an ASE file node. Base class for mesh, light and cameras */ /** Represents an ASE file node. Base class for mesh, light and cameras */
struct BaseNode struct BaseNode {
{ enum Type {
enum Type {Light, Camera, Mesh, Dummy} mType; Light,
Camera,
Mesh,
Dummy
} mType;
//! Construction from an existing name //! Construction from an existing name
BaseNode(Type _mType, const std::string &name) BaseNode(Type _mType, const std::string &name)
: mType (_mType) : mType (_mType)
, mName (name) , mName (name)
, mProcessed (false) , mProcessed (false) {
{
// Set mTargetPosition to qnan // Set mTargetPosition to qnan
const ai_real qnan = get_qnan(); const ai_real qnan = get_qnan();
mTargetPosition.x = qnan; mTargetPosition.x = qnan;
@ -291,23 +273,22 @@ struct BaseNode
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file mesh */ /** Helper structure to represent an ASE file mesh */
struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode {
{
//! Default constructor has been deleted //! Default constructor has been deleted
Mesh() = delete; Mesh() = delete;
//! Construction from an existing name //! Construction from an existing name
explicit Mesh(const std::string &name) explicit Mesh(const std::string &name)
: BaseNode (BaseNode::Mesh, name) : BaseNode( BaseNode::Mesh, name )
, mVertexColors()
, mBoneVertices()
, mBones()
, iMaterialIndex(Face::DEFAULT_MATINDEX) , iMaterialIndex(Face::DEFAULT_MATINDEX)
, bSkip (false) , bSkip (false) {
{ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
// use 2 texture vertex components by default
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
this->mNumUVComponents[c] = 2; this->mNumUVComponents[c] = 2;
} }
}
//! List of all texture coordinate sets //! List of all texture coordinate sets
std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
@ -396,12 +377,11 @@ struct Camera : public BaseNode
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE helper object (dummy) */ /** Helper structure to represent an ASE helper object (dummy) */
struct Dummy : public BaseNode struct Dummy : public BaseNode {
{
//! Constructor //! Constructor
Dummy() Dummy() AI_NO_EXCEPT
: BaseNode (BaseNode::Dummy, "DUMMY") : BaseNode (BaseNode::Dummy, "DUMMY") {
{ // empty
} }
}; };
@ -416,12 +396,11 @@ struct Dummy : public BaseNode
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** \brief Class to parse ASE files /** \brief Class to parse ASE files
*/ */
class Parser class Parser {
{
private: private:
Parser() AI_NO_EXCEPT {
Parser() {} // empty
}
public: public:

View File

@ -62,33 +62,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <time.h> #include <time.h>
using namespace Assimp;
namespace Assimp { namespace Assimp {
template <typename T> template <typename T>
size_t Write(IOStream * stream, const T& v) size_t Write(IOStream * stream, const T& v) {
{
return stream->Write( &v, sizeof(T), 1 ); return stream->Write( &v, sizeof(T), 1 );
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize an aiString // Serialize an aiString
template <> template <>
inline size_t Write<aiString>(IOStream * stream, const aiString& s) inline
{ size_t Write<aiString>(IOStream * stream, const aiString& s) {
const size_t s2 = (uint32_t)s.length; const size_t s2 = (uint32_t)s.length;
stream->Write(&s,4,1); stream->Write(&s,4,1);
stream->Write(s.data,s2,1); stream->Write(s.data,s2,1);
return s2+4; return s2+4;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize an unsigned int as uint32_t // Serialize an unsigned int as uint32_t
template <> template <>
inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w) inline
{ size_t Write<unsigned int>(IOStream * stream, const unsigned int& w) {
const uint32_t t = (uint32_t)w; const uint32_t t = (uint32_t)w;
if (w > t) { if (w > t) {
// this shouldn't happen, integers in Assimp data structures never exceed 2^32 // this shouldn't happen, integers in Assimp data structures never exceed 2^32
@ -96,114 +93,123 @@ inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w)
} }
stream->Write(&t,4,1); stream->Write(&t,4,1);
return 4; return 4;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize an unsigned int as uint16_t // Serialize an unsigned int as uint16_t
template <> template <>
inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w) inline
{ size_t Write<uint16_t>(IOStream * stream, const uint16_t& w) {
static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2"); static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2");
stream->Write(&w,2,1); stream->Write(&w,2,1);
return 2; return 2;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a float // Serialize a float
template <> template <>
inline size_t Write<float>(IOStream * stream, const float& f) inline
{ size_t Write<float>(IOStream * stream, const float& f) {
static_assert(sizeof(float)==4, "sizeof(float)==4"); static_assert(sizeof(float)==4, "sizeof(float)==4");
stream->Write(&f,4,1); stream->Write(&f,4,1);
return 4; return 4;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a double // Serialize a double
template <> template <>
inline size_t Write<double>(IOStream * stream, const double& f) inline
{ size_t Write<double>(IOStream * stream, const double& f) {
static_assert(sizeof(double)==8, "sizeof(double)==8"); static_assert(sizeof(double)==8, "sizeof(double)==8");
stream->Write(&f,8,1); stream->Write(&f,8,1);
return 8; return 8;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a vec3 // Serialize a vec3
template <> template <>
inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v) inline
{ size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v) {
size_t t = Write<float>(stream,v.x); size_t t = Write<float>(stream,v.x);
t += Write<float>(stream,v.y); t += Write<float>(stream,v.y);
t += Write<float>(stream,v.z); t += Write<float>(stream,v.z);
return t; return t;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a color value // Serialize a color value
template <> template <>
inline size_t Write<aiColor3D>(IOStream * stream, const aiColor3D& v) inline
{ size_t Write<aiColor3D>(IOStream * stream, const aiColor3D& v) {
size_t t = Write<float>(stream,v.r); size_t t = Write<float>(stream,v.r);
t += Write<float>(stream,v.g); t += Write<float>(stream,v.g);
t += Write<float>(stream,v.b); t += Write<float>(stream,v.b);
return t; return t;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a color value // Serialize a color value
template <> template <>
inline size_t Write<aiColor4D>(IOStream * stream, const aiColor4D& v) inline
{ size_t Write<aiColor4D>(IOStream * stream, const aiColor4D& v) {
size_t t = Write<float>(stream,v.r); size_t t = Write<float>(stream,v.r);
t += Write<float>(stream,v.g); t += Write<float>(stream,v.g);
t += Write<float>(stream,v.b); t += Write<float>(stream,v.b);
t += Write<float>(stream,v.a); t += Write<float>(stream,v.a);
return t; return t;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a quaternion // Serialize a quaternion
template <> template <>
inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v) inline
{ size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v) {
size_t t = Write<float>(stream,v.w); size_t t = Write<float>(stream,v.w);
t += Write<float>(stream,v.x); t += Write<float>(stream,v.x);
t += Write<float>(stream,v.y); t += Write<float>(stream,v.y);
t += Write<float>(stream,v.z); t += Write<float>(stream,v.z);
ai_assert(t == 16); ai_assert(t == 16);
return 16; return 16;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a vertex weight // Serialize a vertex weight
template <> template <>
inline size_t Write<aiVertexWeight>(IOStream * stream, const aiVertexWeight& v) inline
{ size_t Write<aiVertexWeight>(IOStream * stream, const aiVertexWeight& v) {
size_t t = Write<unsigned int>(stream,v.mVertexId); size_t t = Write<unsigned int>(stream,v.mVertexId);
return t+Write<float>(stream,v.mWeight); return t+Write<float>(stream,v.mWeight);
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a mat4x4 // Serialize a mat4x4
template <> template <>
inline size_t Write<aiMatrix4x4>(IOStream * stream, const aiMatrix4x4& m) inline
{ size_t Write<aiMatrix4x4>(IOStream * stream, const aiMatrix4x4& m) {
for (unsigned int i = 0; i < 4;++i) { for (unsigned int i = 0; i < 4;++i) {
for (unsigned int i2 = 0; i2 < 4;++i2) { for (unsigned int i2 = 0; i2 < 4;++i2) {
Write<float>(stream,m[i][i2]); Write<float>(stream,m[i][i2]);
} }
} }
return 64; return 64;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize an aiVectorKey // Serialize an aiVectorKey
template <> template <>
inline size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v) inline
{ size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v) {
const size_t t = Write<double>(stream,v.mTime); const size_t t = Write<double>(stream,v.mTime);
return t + Write<aiVector3D>(stream,v.mValue); return t + Write<aiVector3D>(stream,v.mValue);
} }
@ -211,16 +217,16 @@ inline size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v)
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize an aiQuatKey // Serialize an aiQuatKey
template <> template <>
inline size_t Write<aiQuatKey>(IOStream * stream, const aiQuatKey& v) inline
{ size_t Write<aiQuatKey>(IOStream * stream, const aiQuatKey& v) {
const size_t t = Write<double>(stream,v.mTime); const size_t t = Write<double>(stream,v.mTime);
return t + Write<aiQuaternion>(stream,v.mValue); return t + Write<aiQuaternion>(stream,v.mValue);
} }
template <typename T> template <typename T>
inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size) inline
{ size_t WriteBounds(IOStream * stream, const T* in, unsigned int size) {
T minc,maxc; T minc, maxc;
ArrayBounds(in,size,minc,maxc); ArrayBounds(in,size,minc,maxc);
const size_t t = Write<T>(stream,minc); const size_t t = Write<T>(stream,minc);
@ -230,15 +236,16 @@ inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size)
// We use this to write out non-byte arrays so that we write using the specializations. // 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. // This way we avoid writing out extra bytes that potentially come from struct alignment.
template <typename T> template <typename T>
inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size) inline
{ size_t WriteArray(IOStream * stream, const T* in, unsigned int size) {
size_t n = 0; size_t n = 0;
for (unsigned int i=0; i<size; i++) n += Write<T>(stream,in[i]); for (unsigned int i=0; i<size; i++) n += Write<T>(stream,in[i]);
return n; return n;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
/** @class AssbinChunkWriter /** @class AssbinChunkWriter
* @brief Chunk writer mechanism for the .assbin file structure * @brief Chunk writer mechanism for the .assbin file structure
* *
* This is a standard in-memory IOStream (most of the code is based on BlobIOStream), * This is a standard in-memory IOStream (most of the code is based on BlobIOStream),
@ -247,16 +254,16 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
* and the chunk contents to the container stream. This allows relatively easy chunk * and the chunk contents to the container stream. This allows relatively easy chunk
* chunk construction, even recursively. * chunk construction, even recursively.
*/ */
class AssbinChunkWriter : public IOStream class AssbinChunkWriter : public IOStream
{ {
private: private:
uint8_t* buffer; uint8_t* buffer;
uint32_t magic; uint32_t magic;
IOStream * container; IOStream * container;
size_t cur_size, cursor, initial; size_t cur_size, cursor, initial;
private: private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void Grow(size_t need = 0) void Grow(size_t need = 0)
{ {
@ -273,7 +280,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
cur_size = new_size; cur_size = new_size;
} }
public: public:
AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096) AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096)
: buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial) : buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial)
@ -293,19 +300,25 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
void * GetBufferPointer() { return buffer; } void * GetBufferPointer() { return buffer; }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; } virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) {
virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; } return 0;
virtual size_t Tell() const { return cursor; } }
virtual void Flush() { } virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) {
return aiReturn_FAILURE;
}
virtual size_t Tell() const {
return cursor;
}
virtual void Flush() {
// not implemented
}
virtual size_t FileSize() const virtual size_t FileSize() const {
{
return cursor; return cursor;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) {
{
pSize *= pCount; pSize *= pCount;
if (cursor + pSize > cur_size) { if (cursor + pSize > cur_size) {
Grow(cursor + pSize); Grow(cursor + pSize);
@ -317,22 +330,21 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
return pCount; return pCount;
} }
}; };
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
/** @class AssbinExport /** @class AssbinExport
* @brief Assbin exporter class * @brief Assbin exporter class
* *
* This class performs the .assbin exporting, and is responsible for the file layout. * This class performs the .assbin exporting, and is responsible for the file layout.
*/ */
class AssbinExport class AssbinExport
{ {
private: private:
bool shortened; bool shortened;
bool compressed; bool compressed;
protected: protected:
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void WriteBinaryNode( IOStream * container, const aiNode* node) void WriteBinaryNode( IOStream * container, const aiNode* node)
{ {
@ -734,7 +746,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
} }
public: public:
AssbinExport() AssbinExport()
: shortened(false), compressed(false) // temporary settings until properties are introduced for exporters : shortened(false), compressed(false) // temporary settings until properties are introduced for exporters
{ {
@ -810,10 +822,9 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
pIOSystem->Close( out ); pIOSystem->Close( out );
} }
}; };
void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) {
{
AssbinExport exporter; AssbinExport exporter;
exporter.WriteBinaryDump( pFile, pIOSystem, pScene ); exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
} }

View File

@ -46,6 +46,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_ASSBINEXPORTER_H_INC #ifndef AI_ASSBINEXPORTER_H_INC
#define AI_ASSBINEXPORTER_H_INC #define AI_ASSBINEXPORTER_H_INC
// nothing really needed here - reserved for future use like properties #include <assimp/defs.h>
#endif // nothing really needed here - reserved for future use like properties
namespace Assimp {
void ASSIMP_API ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/);
}
#endif // AI_ASSBINEXPORTER_H_INC

View File

@ -79,16 +79,17 @@ static const aiImporterDesc desc = {
"assbin" "assbin"
}; };
const aiImporterDesc* AssbinImporter::GetInfo() const // -----------------------------------------------------------------------------------
{ const aiImporterDesc* AssbinImporter::GetInfo() const {
return &desc; return &desc;
} }
bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const // -----------------------------------------------------------------------------------
{ bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const {
IOStream * in = pIOHandler->Open(pFile); IOStream * in = pIOHandler->Open(pFile);
if (!in) if (nullptr == in) {
return false; return false;
}
char s[32]; char s[32];
in->Read( s, sizeof(char), 32 ); in->Read( s, sizeof(char), 32 );
@ -98,17 +99,17 @@ bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bo
return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0; return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0;
} }
// -----------------------------------------------------------------------------------
template <typename T> template <typename T>
T Read(IOStream * stream) T Read(IOStream * stream) {
{
T t; T t;
stream->Read( &t, sizeof(T), 1 ); stream->Read( &t, sizeof(T), 1 );
return t; return t;
} }
// -----------------------------------------------------------------------------------
template <> template <>
aiVector3D Read<aiVector3D>(IOStream * stream) aiVector3D Read<aiVector3D>(IOStream * stream) {
{
aiVector3D v; aiVector3D v;
v.x = Read<float>(stream); v.x = Read<float>(stream);
v.y = Read<float>(stream); v.y = Read<float>(stream);
@ -116,9 +117,9 @@ aiVector3D Read<aiVector3D>(IOStream * stream)
return v; return v;
} }
// -----------------------------------------------------------------------------------
template <> template <>
aiColor4D Read<aiColor4D>(IOStream * stream) aiColor4D Read<aiColor4D>(IOStream * stream) {
{
aiColor4D c; aiColor4D c;
c.r = Read<float>(stream); c.r = Read<float>(stream);
c.g = Read<float>(stream); c.g = Read<float>(stream);
@ -127,9 +128,9 @@ aiColor4D Read<aiColor4D>(IOStream * stream)
return c; return c;
} }
// -----------------------------------------------------------------------------------
template <> template <>
aiQuaternion Read<aiQuaternion>(IOStream * stream) aiQuaternion Read<aiQuaternion>(IOStream * stream) {
{
aiQuaternion v; aiQuaternion v;
v.w = Read<float>(stream); v.w = Read<float>(stream);
v.x = Read<float>(stream); v.x = Read<float>(stream);
@ -138,9 +139,9 @@ aiQuaternion Read<aiQuaternion>(IOStream * stream)
return v; return v;
} }
// -----------------------------------------------------------------------------------
template <> template <>
aiString Read<aiString>(IOStream * stream) aiString Read<aiString>(IOStream * stream) {
{
aiString s; aiString s;
stream->Read(&s.length,4,1); stream->Read(&s.length,4,1);
stream->Read(s.data,s.length,1); stream->Read(s.data,s.length,1);
@ -148,18 +149,18 @@ aiString Read<aiString>(IOStream * stream)
return s; return s;
} }
// -----------------------------------------------------------------------------------
template <> template <>
aiVertexWeight Read<aiVertexWeight>(IOStream * stream) aiVertexWeight Read<aiVertexWeight>(IOStream * stream) {
{
aiVertexWeight w; aiVertexWeight w;
w.mVertexId = Read<unsigned int>(stream); w.mVertexId = Read<unsigned int>(stream);
w.mWeight = Read<float>(stream); w.mWeight = Read<float>(stream);
return w; return w;
} }
// -----------------------------------------------------------------------------------
template <> template <>
aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream) aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream) {
{
aiMatrix4x4 m; aiMatrix4x4 m;
for (unsigned int i = 0; i < 4;++i) { for (unsigned int i = 0; i < 4;++i) {
for (unsigned int i2 = 0; i2 < 4;++i2) { for (unsigned int i2 = 0; i2 < 4;++i2) {
@ -169,36 +170,43 @@ aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream)
return m; return m;
} }
// -----------------------------------------------------------------------------------
template <> template <>
aiVectorKey Read<aiVectorKey>(IOStream * stream) aiVectorKey Read<aiVectorKey>(IOStream * stream) {
{
aiVectorKey v; aiVectorKey v;
v.mTime = Read<double>(stream); v.mTime = Read<double>(stream);
v.mValue = Read<aiVector3D>(stream); v.mValue = Read<aiVector3D>(stream);
return v; return v;
} }
// -----------------------------------------------------------------------------------
template <> template <>
aiQuatKey Read<aiQuatKey>(IOStream * stream) aiQuatKey Read<aiQuatKey>(IOStream * stream) {
{
aiQuatKey v; aiQuatKey v;
v.mTime = Read<double>(stream); v.mTime = Read<double>(stream);
v.mValue = Read<aiQuaternion>(stream); v.mValue = Read<aiQuaternion>(stream);
return v; return v;
} }
// -----------------------------------------------------------------------------------
template <typename T> template <typename T>
void ReadArray(IOStream * stream, T * out, unsigned int size) void ReadArray( IOStream *stream, T * out, unsigned int size) {
{ ai_assert( nullptr != stream );
for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream); ai_assert( nullptr != out );
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 ) // -----------------------------------------------------------------------------------
{ template <typename T>
void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n ) {
// not sure what to do here, the data isn't really useful. // not sure what to do here, the data isn't really useful.
stream->Seek( sizeof(T) * n, aiOrigin_CUR ); stream->Seek( sizeof(T) * n, aiOrigin_CUR );
} }
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) { void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) {
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
@ -273,8 +281,7 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* p
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) {
{
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIBONE); ai_assert(chunkID == ASSBIN_CHUNK_AIBONE);
@ -286,20 +293,22 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
// for the moment we write dumb min/max values for the bones, too. // for the moment we write dumb min/max values for the bones, too.
// maybe I'll add a better, hash-like solution later // maybe I'll add a better, hash-like solution later
if (shortened) if (shortened) {
{
ReadBounds(stream,b->mWeights,b->mNumWeights); ReadBounds(stream,b->mWeights,b->mNumWeights);
} // else write as usual } else {
else // else write as usual
{
b->mWeights = new aiVertexWeight[b->mNumWeights]; b->mWeights = new aiVertexWeight[b->mNumWeights];
ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights); ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights);
} }
} }
// -----------------------------------------------------------------------------------
static bool fitsIntoUI16(unsigned int mNumVertices) {
return ( mNumVertices < (1u<<16) );
}
void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) // -----------------------------------------------------------------------------------
{ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIMESH); ai_assert(chunkID == ASSBIN_CHUNK_AIMESH);
@ -314,70 +323,61 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
// first of all, write bits for all existent vertex components // first of all, write bits for all existent vertex components
unsigned int c = Read<unsigned int>(stream); unsigned int c = Read<unsigned int>(stream);
if (c & ASSBIN_MESH_HAS_POSITIONS) if (c & ASSBIN_MESH_HAS_POSITIONS) {
{
if (shortened) { if (shortened) {
ReadBounds(stream,mesh->mVertices,mesh->mNumVertices); ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
} // else write as usual } else {
else // else write as usual
{
mesh->mVertices = new aiVector3D[mesh->mNumVertices]; mesh->mVertices = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices); ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices);
} }
} }
if (c & ASSBIN_MESH_HAS_NORMALS) if (c & ASSBIN_MESH_HAS_NORMALS) {
{
if (shortened) { if (shortened) {
ReadBounds(stream,mesh->mNormals,mesh->mNumVertices); ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
} // else write as usual } else {
else // else write as usual
{
mesh->mNormals = new aiVector3D[mesh->mNumVertices]; mesh->mNormals = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices); ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices);
} }
} }
if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) {
{
if (shortened) { if (shortened) {
ReadBounds(stream,mesh->mTangents,mesh->mNumVertices); ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices); ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
} // else write as usual } else {
else // else write as usual
{
mesh->mTangents = new aiVector3D[mesh->mNumVertices]; mesh->mTangents = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices); ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices);
mesh->mBitangents = new aiVector3D[mesh->mNumVertices]; mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices); ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices);
} }
} }
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
{ if (!(c & ASSBIN_MESH_HAS_COLOR(n))) {
if (!(c & ASSBIN_MESH_HAS_COLOR(n)))
break; break;
}
if (shortened) if (shortened) {
{
ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices); ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
} // else write as usual } else {
else // else write as usual
{
mesh->mColors[n] = new aiColor4D[mesh->mNumVertices]; mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices); ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices);
} }
} }
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
{ if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n))) {
if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n)))
break; break;
}
// write number of UV components // write number of UV components
mesh->mNumUVComponents[n] = Read<unsigned int>(stream); mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
if (shortened) { if (shortened) {
ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices); ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
} // else write as usual } else {
else // else write as usual
{
mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices]; mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mTextureCoords[n],mesh->mNumVertices); ReadArray<aiVector3D>(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
} }
@ -389,9 +389,8 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
// using Assimp's standard hashing function. // using Assimp's standard hashing function.
if (shortened) { if (shortened) {
Read<unsigned int>(stream); Read<unsigned int>(stream);
} } else {
else // else write as usual // else write as usual
{
// if there are less than 2^16 vertices, we can simply use 16 bit integers ... // if there are less than 2^16 vertices, we can simply use 16 bit integers ...
mesh->mFaces = new aiFace[mesh->mNumFaces]; mesh->mFaces = new aiFace[mesh->mNumFaces];
for (unsigned int i = 0; i < mesh->mNumFaces;++i) { for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
@ -402,12 +401,10 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
f.mIndices = new unsigned int[f.mNumIndices]; f.mIndices = new unsigned int[f.mNumIndices];
for (unsigned int a = 0; a < f.mNumIndices;++a) { for (unsigned int a = 0; a < f.mNumIndices;++a) {
if (mesh->mNumVertices < (1u<<16)) // Check if unsigned short ( 16 bit ) are big enought for the indices
{ if ( fitsIntoUI16( mesh->mNumVertices ) ) {
f.mIndices[a] = Read<uint16_t>(stream); f.mIndices[a] = Read<uint16_t>(stream);
} } else {
else
{
f.mIndices[a] = Read<unsigned int>(stream); f.mIndices[a] = Read<unsigned int>(stream);
} }
} }
@ -424,8 +421,8 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
} }
} }
void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) // -----------------------------------------------------------------------------------
{ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) {
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY); ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY);
@ -442,8 +439,7 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) {
{
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL); ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL);
@ -465,8 +461,7 @@ void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) {
{
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM); ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM);
@ -493,9 +488,8 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
if (shortened) { if (shortened) {
ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys); ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
} // else write as usual } else {
else // else write as usual
{
nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys]; nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys); ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys);
} }
@ -504,19 +498,16 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
if (shortened) { if (shortened) {
ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys); ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
} // else write as usual } else {
else // else write as usual
{
nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys]; nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys); ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys);
} }
} }
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) {
{
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION); ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION);
@ -527,8 +518,7 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
anim->mTicksPerSecond = Read<double> (stream); anim->mTicksPerSecond = Read<double> (stream);
anim->mNumChannels = Read<unsigned int>(stream); anim->mNumChannels = Read<unsigned int>(stream);
if (anim->mNumChannels) if (anim->mNumChannels) {
{
anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ]; anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ];
for (unsigned int a = 0; a < anim->mNumChannels;++a) { for (unsigned int a = 0; a < anim->mNumChannels;++a) {
anim->mChannels[a] = new aiNodeAnim(); anim->mChannels[a] = new aiNodeAnim();
@ -537,8 +527,8 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
} }
} }
void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) // -----------------------------------------------------------------------------------
{ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) {
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE); ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE);
@ -552,18 +542,15 @@ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
if (!tex->mHeight) { if (!tex->mHeight) {
tex->pcData = new aiTexel[ tex->mWidth ]; tex->pcData = new aiTexel[ tex->mWidth ];
stream->Read(tex->pcData,1,tex->mWidth); stream->Read(tex->pcData,1,tex->mWidth);
} } else {
else {
tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ]; tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ];
stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4); stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4);
} }
} }
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) {
{
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT); ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT);
@ -586,12 +573,10 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
l->mAngleInnerCone = Read<float>(stream); l->mAngleInnerCone = Read<float>(stream);
l->mAngleOuterCone = Read<float>(stream); l->mAngleOuterCone = Read<float>(stream);
} }
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) {
{
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA); ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA);
@ -607,8 +592,8 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
cam->mAspect = Read<float>(stream); cam->mAspect = Read<float>(stream);
} }
void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) // -----------------------------------------------------------------------------------
{ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
uint32_t chunkID = Read<uint32_t>(stream); uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID); (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AISCENE); ai_assert(chunkID == ASSBIN_CHUNK_AISCENE);
@ -623,12 +608,11 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
scene->mNumCameras = Read<unsigned int>(stream); scene->mNumCameras = Read<unsigned int>(stream);
// Read node graph // Read node graph
scene->mRootNode = new aiNode[1]; //scene->mRootNode = new aiNode[1];
ReadBinaryNode( stream, &scene->mRootNode, (aiNode*)NULL ); ReadBinaryNode( stream, &scene->mRootNode, (aiNode*)NULL );
// Read all meshes // Read all meshes
if (scene->mNumMeshes) if (scene->mNumMeshes) {
{
scene->mMeshes = new aiMesh*[scene->mNumMeshes]; scene->mMeshes = new aiMesh*[scene->mNumMeshes];
for (unsigned int i = 0; i < scene->mNumMeshes;++i) { for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
scene->mMeshes[i] = new aiMesh(); scene->mMeshes[i] = new aiMesh();
@ -637,8 +621,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
} }
// Read materials // Read materials
if (scene->mNumMaterials) if (scene->mNumMaterials) {
{
scene->mMaterials = new aiMaterial*[scene->mNumMaterials]; scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
scene->mMaterials[i] = new aiMaterial(); scene->mMaterials[i] = new aiMaterial();
@ -647,8 +630,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
} }
// Read all animations // Read all animations
if (scene->mNumAnimations) if (scene->mNumAnimations) {
{
scene->mAnimations = new aiAnimation*[scene->mNumAnimations]; scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
for (unsigned int i = 0; i < scene->mNumAnimations;++i) { for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
scene->mAnimations[i] = new aiAnimation(); scene->mAnimations[i] = new aiAnimation();
@ -657,8 +639,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
} }
// Read all textures // Read all textures
if (scene->mNumTextures) if (scene->mNumTextures) {
{
scene->mTextures = new aiTexture*[scene->mNumTextures]; scene->mTextures = new aiTexture*[scene->mNumTextures];
for (unsigned int i = 0; i < scene->mNumTextures;++i) { for (unsigned int i = 0; i < scene->mNumTextures;++i) {
scene->mTextures[i] = new aiTexture(); scene->mTextures[i] = new aiTexture();
@ -667,8 +648,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
} }
// Read lights // Read lights
if (scene->mNumLights) if (scene->mNumLights) {
{
scene->mLights = new aiLight*[scene->mNumLights]; scene->mLights = new aiLight*[scene->mNumLights];
for (unsigned int i = 0; i < scene->mNumLights;++i) { for (unsigned int i = 0; i < scene->mNumLights;++i) {
scene->mLights[i] = new aiLight(); scene->mLights[i] = new aiLight();
@ -677,8 +657,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
} }
// Read cameras // Read cameras
if (scene->mNumCameras) if (scene->mNumCameras) {
{
scene->mCameras = new aiCamera*[scene->mNumCameras]; scene->mCameras = new aiCamera*[scene->mNumCameras];
for (unsigned int i = 0; i < scene->mNumCameras;++i) { for (unsigned int i = 0; i < scene->mNumCameras;++i) {
scene->mCameras[i] = new aiCamera(); scene->mCameras[i] = new aiCamera();
@ -688,16 +667,22 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
} }
void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) // -----------------------------------------------------------------------------------
{ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) {
IOStream * stream = pIOHandler->Open(pFile,"rb"); IOStream * stream = pIOHandler->Open(pFile,"rb");
if (!stream) if (nullptr == stream) {
return; return;
}
stream->Seek( 44, aiOrigin_CUR ); // signature // signature
stream->Seek( 44, aiOrigin_CUR );
unsigned int versionMajor = Read<unsigned int>(stream);
unsigned int versionMinor = Read<unsigned int>(stream);
if (versionMinor != ASSBIN_VERSION_MINOR || versionMajor != ASSBIN_VERSION_MAJOR) {
throw DeadlyImportError( "Invalid version, data format not compatible!" );
}
/*unsigned int versionMajor =*/ Read<unsigned int>(stream);
/*unsigned int versionMinor =*/ Read<unsigned int>(stream);
/*unsigned int versionRevision =*/ Read<unsigned int>(stream); /*unsigned int versionRevision =*/ Read<unsigned int>(stream);
/*unsigned int compileFlags =*/ Read<unsigned int>(stream); /*unsigned int compileFlags =*/ Read<unsigned int>(stream);
@ -711,8 +696,7 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
stream->Seek( 128, aiOrigin_CUR ); // options stream->Seek( 128, aiOrigin_CUR ); // options
stream->Seek( 64, aiOrigin_CUR ); // padding stream->Seek( 64, aiOrigin_CUR ); // padding
if (compressed) if (compressed) {
{
uLongf uncompressedSize = Read<uint32_t>(stream); uLongf uncompressedSize = Read<uint32_t>(stream);
uLongf compressedSize = static_cast<uLongf>(stream->FileSize() - stream->Tell()); uLongf compressedSize = static_cast<uLongf>(stream->FileSize() - stream->Tell());
@ -729,9 +713,7 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
delete[] uncompressedData; delete[] uncompressedData;
delete[] compressedData; delete[] compressedData;
} } else {
else
{
ReadBinaryScene(stream,pScene); ReadBinaryScene(stream,pScene);
} }

View File

@ -85,6 +85,7 @@ public:
aiScene* pScene, aiScene* pScene,
IOSystem* pIOHandler IOSystem* pIOHandler
); );
void ReadHeader();
void ReadBinaryScene( IOStream * stream, aiScene* pScene ); void ReadBinaryScene( IOStream * stream, aiScene* pScene );
void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent ); void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent );
void ReadBinaryMesh( IOStream * stream, aiMesh* mesh ); void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );

View File

@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <map>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
@ -461,6 +462,13 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
aiNodeAnim* nodeAnim = new aiNodeAnim; aiNodeAnim* nodeAnim = new aiNodeAnim;
anim->mChannels[a] = nodeAnim; anim->mChannels[a] = nodeAnim;
nodeAnim->mNodeName.Set( nodeName); nodeAnim->mNodeName.Set( nodeName);
std::map<BVHLoader::ChannelType, int> channelMap;
//Build map of channels
for (unsigned int channel = 0; channel < node.mChannels.size(); ++channel)
{
channelMap[node.mChannels[channel]] = channel;
}
// translational part, if given // translational part, if given
if( node.mChannels.size() == 6) if( node.mChannels.size() == 6)
@ -472,15 +480,31 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
{ {
poskey->mTime = double( fr); poskey->mTime = double( fr);
// Now compute all translations in the right order // Now compute all translations
for( unsigned int channel = 0; channel < 3; ++channel) for(BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel +1))
{ {
switch( node.mChannels[channel]) //Find channel in node
{ std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break; if (mapIter == channelMap.end())
case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break; throw DeadlyImportError("Missing position channel in node " + nodeName);
default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); else {
int channelIdx = mapIter->second;
switch (channel) {
case Channel_PositionX:
poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channelIdx];
break;
case Channel_PositionY:
poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channelIdx];
break;
case Channel_PositionZ:
poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channelIdx];
break;
default:
break;
}
} }
} }
++poskey; ++poskey;
@ -497,12 +521,6 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
// rotation part. Always present. First find value offsets // rotation part. Always present. First find value offsets
{ {
unsigned int rotOffset = 0;
if( node.mChannels.size() == 6)
{
// Offset all further calculations
rotOffset = 3;
}
// Then create the number of rotation keys // Then create the number of rotation keys
nodeAnim->mNumRotationKeys = mAnimNumFrames; nodeAnim->mNumRotationKeys = mAnimNumFrames;
@ -512,19 +530,32 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
{ {
aiMatrix4x4 temp; aiMatrix4x4 temp;
aiMatrix3x3 rotMatrix; aiMatrix3x3 rotMatrix;
for (BVHLoader::ChannelType channel = Channel_RotationX; channel <= Channel_RotationZ; channel = (BVHLoader::ChannelType)(channel + 1))
for( unsigned int channel = 0; channel < 3; ++channel)
{ {
//Find channel in node
std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
if (mapIter == channelMap.end())
throw DeadlyImportError("Missing rotation channel in node " + nodeName);
else {
int channelIdx = mapIter->second;
// translate ZXY euler angels into a quaternion // translate ZXY euler angels into a quaternion
const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f; const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
// Compute rotation transformations in the right order // Compute rotation transformations in the right order
switch (node.mChannels[rotOffset+channel]) switch (channel)
{ {
case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; case Channel_RotationX:
case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; aiMatrix4x4::RotationX(angle, temp); rotMatrix *= aiMatrix3x3(temp);
case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; break;
default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); case Channel_RotationY:
aiMatrix4x4::RotationY(angle, temp); rotMatrix *= aiMatrix3x3(temp);
break;
case Channel_RotationZ: aiMatrix4x4::RotationZ(angle, temp); rotMatrix *= aiMatrix3x3(temp);
break;
default:
break;
}
} }
} }

View File

@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/ParsingUtils.h>
#include "FileSystemFilter.h" #include "FileSystemFilter.h"
#include "Importer.h" #include "Importer.h"
#include <assimp/ByteSwapper.h> #include <assimp/ByteSwapper.h>
@ -53,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <assimp/postprocess.h> #include <assimp/postprocess.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <ios> #include <ios>
#include <list> #include <list>
#include <memory> #include <memory>
@ -63,7 +65,7 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BaseImporter::BaseImporter() BaseImporter::BaseImporter() AI_NO_EXCEPT
: m_progress() { : m_progress() {
// nothing to do here // nothing to do here
} }
@ -143,7 +145,8 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
const char** tokens, const char** tokens,
unsigned int numTokens, unsigned int numTokens,
unsigned int searchBytes /* = 200 */, unsigned int searchBytes /* = 200 */,
bool tokensSol /* false */) bool tokensSol /* false */,
bool noAlphaBeforeTokens /* false */)
{ {
ai_assert( nullptr != tokens ); ai_assert( nullptr != tokens );
ai_assert( 0 != numTokens ); ai_assert( 0 != numTokens );
@ -157,15 +160,14 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
if (pStream.get() ) { if (pStream.get() ) {
// read 200 characters from the file // read 200 characters from the file
std::unique_ptr<char[]> _buffer (new char[searchBytes+1 /* for the '\0' */]); std::unique_ptr<char[]> _buffer (new char[searchBytes+1 /* for the '\0' */]);
char* buffer = _buffer.get(); char *buffer( _buffer.get() );
const size_t read( pStream->Read(buffer,1,searchBytes) );
const size_t read = pStream->Read(buffer,1,searchBytes); if( 0 == read ) {
if( !read ) {
return false; return false;
} }
for( size_t i = 0; i < read; ++i ) { for( size_t i = 0; i < read; ++i ) {
buffer[ i ] = ::tolower( buffer[ i ] ); buffer[ i ] = static_cast<char>( ::tolower( buffer[ i ] ) );
} }
// It is not a proper handling of unicode files here ... // It is not a proper handling of unicode files here ...
@ -186,13 +188,18 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
token.clear(); token.clear();
const char *ptr( tokens[ i ] ); const char *ptr( tokens[ i ] );
for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) { for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) {
token.push_back( tolower( *ptr ) ); token.push_back( static_cast<char>( tolower( *ptr ) ) );
++ptr; ++ptr;
} }
const char* r = strstr( buffer, token.c_str() ); const char* r = strstr( buffer, token.c_str() );
if( !r ) { if( !r ) {
continue; continue;
} }
// We need to make sure that we didn't accidentially identify the end of another token as our token,
// e.g. in a previous version the "gltf " present in some gltf files was detected as "f "
if (noAlphaBeforeTokens && (r != buffer && isalpha(r[-1]))) {
continue;
}
// We got a match, either we don't care where it is, or it happens to // We got a match, either we don't care where it is, or it happens to
// be in the beginning of the file / line // be in the beginning of the file / line
if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') { if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
@ -234,16 +241,19 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get file extension from path // Get file extension from path
/*static*/ std::string BaseImporter::GetExtension (const std::string& pFile) std::string BaseImporter::GetExtension( const std::string& file ) {
{ std::string::size_type pos = file.find_last_of('.');
std::string::size_type pos = pFile.find_last_of('.');
// no file extension at all // no file extension at all
if( pos == std::string::npos) if (pos == std::string::npos) {
return ""; return "";
}
// thanks to Andy Maloney for the hint
std::string ret = file.substr( pos + 1 );
std::transform( ret.begin(), ret.end(), ret.begin(), ToLower<char>);
std::string ret = pFile.substr(pos+1);
std::transform(ret.begin(),ret.end(),ret.begin(),::tolower); // thanks to Andy Maloney for the hint
return ret; return ret;
} }

View File

@ -53,7 +53,7 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BaseProcess::BaseProcess() BaseProcess::BaseProcess() AI_NO_EXCEPT
: shared() : shared()
, progress() , progress()
{ {

View File

@ -211,20 +211,16 @@ private:
* should be executed. If the function returns true, the class' Execute() * should be executed. If the function returns true, the class' Execute()
* function is called subsequently. * function is called subsequently.
*/ */
class ASSIMP_API_WINONLY BaseProcess class ASSIMP_API_WINONLY BaseProcess {
{
friend class Importer; friend class Importer;
public: public:
/** Constructor to be privately used by Importer */ /** Constructor to be privately used by Importer */
BaseProcess(); BaseProcess() AI_NO_EXCEPT;
/** Destructor, private as well */ /** Destructor, private as well */
virtual ~BaseProcess(); virtual ~BaseProcess();
public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag. /** Returns whether the processing step is present in the given flag.
* @param pFlags The processing flags the importer was called with. A * @param pFlags The processing flags the importer was called with. A

View File

@ -0,0 +1,185 @@
#include "BlenderCustomData.h"
#include "BlenderDNA.h"
#include <array>
#include <functional>
namespace Assimp {
namespace Blender {
/**
* @brief read/convert of Structure array to memory
*/
template<typename T>
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
for (size_t i = 0; i < cnt; ++i) {
T read;
s.Convert(read, db);
*p = read;
p++;
}
return true;
}
/**
* @brief pointer to function read memory for n CustomData types
*/
typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
typedef ElemBase * (*PCreate)(const size_t cnt);
typedef void(*PDestroy)(ElemBase *);
#define IMPL_STRUCT_READ(ty) \
bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
return read<ty>(db.dna[#ty], dynamic_cast<ty *>(v), cnt, db); \
}
#define IMPL_STRUCT_CREATE(ty) \
ElemBase *create##ty(const size_t cnt) { \
return new ty[cnt]; \
}
#define IMPL_STRUCT_DESTROY(ty) \
void destroy##ty(ElemBase *pE) { \
ty *p = dynamic_cast<ty *>(pE); \
delete[]p; \
}
/**
* @brief helper macro to define Structure functions
*/
#define IMPL_STRUCT(ty) \
IMPL_STRUCT_READ(ty) \
IMPL_STRUCT_CREATE(ty) \
IMPL_STRUCT_DESTROY(ty)
// supported structures for CustomData
IMPL_STRUCT(MVert)
IMPL_STRUCT(MEdge)
IMPL_STRUCT(MFace)
IMPL_STRUCT(MTFace)
IMPL_STRUCT(MTexPoly)
IMPL_STRUCT(MLoopUV)
IMPL_STRUCT(MLoopCol)
IMPL_STRUCT(MPoly)
IMPL_STRUCT(MLoop)
/**
* @brief describes the size of data and the read function to be used for single CustomerData.type
*/
struct CustomDataTypeDescription {
PRead Read; ///< function to read one CustomData type element
PCreate Create; ///< function to allocate n type elements
PDestroy Destroy;
CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy)
: Read(read)
, Create(create)
, Destroy(destroy)
{}
};
/**
* @brief helper macro to define Structure type specific CustomDataTypeDescription
* @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
*/
#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
CustomDataTypeDescription{&read##ty, &create##ty, &destroy##ty}
/**
* @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type
*/
#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
CustomDataTypeDescription{nullptr, nullptr, nullptr}
/**
* @brief descriptors for data pointed to from CustomDataLayer.data
* @note some of the CustomData uses already well defined Structures
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
* use a special readfunction for that cases
*/
std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
}};
bool isValidCustomDataType(const int cdtype) {
return cdtype >= 0 && cdtype < CD_NUMTYPES;
}
bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
if (!isValidCustomDataType(cdtype)) {
throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index"));
}
const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
// allocate cnt elements and parse them from file
out.reset(cdtd.Create(cnt), cdtd.Destroy);
return cdtd.Read(out.get(), cnt, db);
}
return false;
}
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
if (it->get()->type == cdtype && name == it->get()->name) {
return *it;
}
}
return nullptr;
}
const ElemBase * getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name)
{
const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
if (pLayer && pLayer->data) {
return pLayer->data.get();
}
return nullptr;
}
}
}

View File

@ -0,0 +1,89 @@
#pragma once
#include "BlenderDNA.h"
#include "BlenderScene.h"
#include <memory>
namespace Assimp {
namespace Blender {
/* CustomData.type from Blender (2.79b) */
enum CustomDataType {
CD_AUTO_FROM_NAME = -1,
CD_MVERT = 0,
#ifdef DNA_DEPRECATED
CD_MSTICKY = 1, /* DEPRECATED */
#endif
CD_MDEFORMVERT = 2,
CD_MEDGE = 3,
CD_MFACE = 4,
CD_MTFACE = 5,
CD_MCOL = 6,
CD_ORIGINDEX = 7,
CD_NORMAL = 8,
/* CD_POLYINDEX = 9, */
CD_PROP_FLT = 10,
CD_PROP_INT = 11,
CD_PROP_STR = 12,
CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
CD_ORCO = 14,
CD_MTEXPOLY = 15,
CD_MLOOPUV = 16,
CD_MLOOPCOL = 17,
CD_TANGENT = 18,
CD_MDISPS = 19,
CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */
/* CD_ID_MCOL = 21, */
CD_TEXTURE_MLOOPCOL = 22,
CD_CLOTH_ORCO = 23,
CD_RECAST = 24,
/* BMESH ONLY START */
CD_MPOLY = 25,
CD_MLOOP = 26,
CD_SHAPE_KEYINDEX = 27,
CD_SHAPEKEY = 28,
CD_BWEIGHT = 29,
CD_CREASE = 30,
CD_ORIGSPACE_MLOOP = 31,
CD_PREVIEW_MLOOPCOL = 32,
CD_BM_ELEM_PYPTR = 33,
/* BMESH ONLY END */
CD_PAINT_MASK = 34,
CD_GRID_PAINT_MASK = 35,
CD_MVERT_SKIN = 36,
CD_FREESTYLE_EDGE = 37,
CD_FREESTYLE_FACE = 38,
CD_MLOOPTANGENT = 39,
CD_TESSLOOPNORMAL = 40,
CD_CUSTOMLOOPNORMAL = 41,
CD_NUMTYPES = 42
};
/**
* @brief check if given cdtype is valid (ie >= 0 and < CD_NUMTYPES)
* @param[in] cdtype to check
* @return true when valid
*/
bool isValidCustomDataType(const int cdtype);
/**
* @brief returns CustomDataLayer ptr for given cdtype and name
* @param[in] customdata CustomData to search for wanted layer
* @param[in] cdtype to search for
* @param[in] name to search for
* @return CustomDataLayer * or nullptr if not found
*/
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
/**
* @brief returns CustomDataLayer data ptr for given cdtype and name
* @param[in] customdata CustomData to search for wanted layer
* @param[in] cdtype to search for
* @param[in] name to search for
* @return * to struct data or nullptr if not found
*/
const ElemBase * getCustomDataLayerData(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
}
}

View File

@ -309,6 +309,28 @@ public:
void ReadField(T& out, const char* name, void ReadField(T& out, const char* name,
const FileDatabase& db) const; const FileDatabase& db) const;
// --------------------------------------------------------
/**
* @brief field parsing for dynamic vectors
* @param[in] out vector of struct to be filled
* @param[in] name of field
* @param[in] db to access the file, dna, ...
* @return true when read was successful
*/
template <int error_policy, template <typename> class TOUT, typename T>
bool ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const;
/**
* @brief parses raw customdata
* @param[in] out shared_ptr to be filled
* @param[in] cdtype customdata type to read
* @param[in] name of field ptr
* @param[in] db to access the file, dna, ...
* @return true when read was successful
*/
template <int error_policy>
bool ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const;
private: private:
// -------------------------------------------------------- // --------------------------------------------------------
@ -803,6 +825,17 @@ private:
FileDatabase& db; FileDatabase& db;
}; };
/**
* @brief read CustomData's data to ptr to mem
* @param[out] out memory ptr to set
* @param[in] cdtype to read
* @param[in] cnt cnt of elements to read
* @param[in] db to read elements from
* @return true when ok
*/
bool readCustomData(std::shared_ptr<ElemBase> &out, int cdtype, size_t cnt, const FileDatabase &db);
} // end Blend } // end Blend
} // end Assimp } // end Assimp

View File

@ -307,6 +307,108 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
} }
//--------------------------------------------------------------------------------
// field parsing for raw untyped data (like CustomDataLayer.data)
template <int error_policy>
bool Structure::ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const {
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
Pointer ptrval;
const Field* f;
try {
f = &(*this)[name];
// sanity check, should never happen if the genblenddna script is right
if (!(f->flags & FieldFlag_Pointer)) {
throw Error((Formatter::format(), "Field `", name, "` of structure `",
this->name, "` ought to be a pointer"));
}
db.reader->IncPtr(f->offset);
Convert(ptrval, db);
// actually it is meaningless on which Structure the Convert is called
// because the `Pointer` argument triggers a special implementation.
}
catch (const Error& e) {
_defaultInitializer<error_policy>()(out, e.what());
out.reset();
}
bool readOk = true;
if (ptrval.val) {
// get block for ptr
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
// read block->num instances of given type to out
readOk = readCustomData(out, cdtype, block->num, db);
}
// and recover the previous stream position
db.reader->SetCurrentPos(old);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
++db.stats().fields_read;
#endif
return readOk;
}
//--------------------------------------------------------------------------------
template <int error_policy, template <typename> class TOUT, typename T>
bool Structure::ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const {
out.clear();
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
Pointer ptrval;
const Field* f;
try {
f = &(*this)[name];
// sanity check, should never happen if the genblenddna script is right
if (!(f->flags & FieldFlag_Pointer)) {
throw Error((Formatter::format(), "Field `", name, "` of structure `",
this->name, "` ought to be a pointer"));
}
db.reader->IncPtr(f->offset);
Convert(ptrval, db);
// actually it is meaningless on which Structure the Convert is called
// because the `Pointer` argument triggers a special implementation.
}
catch (const Error& e) {
_defaultInitializer<error_policy>()(out, e.what());
out.clear();
return false;
}
if (ptrval.val) {
// find the file block the pointer is pointing to
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
// I really ought to improve StreamReader to work with 64 bit indices exclusively.
const Structure& s = db.dna[f->type];
for (size_t i = 0; i < block->num; ++i) {
TOUT<T> p(new T);
s.Convert(*p, db);
out.push_back(p);
}
}
db.reader->SetCurrentPos(old);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
++db.stats().fields_read;
#endif
return false;
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <template <typename> class TOUT, typename T> template <template <typename> class TOUT, typename T>
bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db, bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,

View File

@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderIntermediate.h" #include "BlenderIntermediate.h"
#include "BlenderModifier.h" #include "BlenderModifier.h"
#include "BlenderBMesh.h" #include "BlenderBMesh.h"
#include "BlenderCustomData.h"
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
@ -1021,6 +1022,34 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
} }
} }
// TODO should we create the TextureUVMapping map in Convert<Material> to prevent redundant processing?
// create texture <-> uvname mapping for all materials
// key is texture number, value is data *
typedef std::map<uint32_t, const MLoopUV *> TextureUVMapping;
// key is material number, value is the TextureUVMapping for the material
typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
MaterialTextureUVMappings matTexUvMappings;
const uint32_t maxMat = static_cast<const uint32_t>(mesh->mat.size());
for (uint32_t m = 0; m < maxMat; ++m) {
// get material by index
const std::shared_ptr<Material> pMat = mesh->mat[m];
TextureUVMapping texuv;
const uint32_t maxTex = sizeof(pMat->mtex) / sizeof(pMat->mtex[0]);
for (uint32_t t = 0; t < maxTex; ++t) {
if (pMat->mtex[t] && pMat->mtex[t]->uvname[0]) {
// get the CustomData layer for given uvname and correct type
const ElemBase *pLoop = getCustomDataLayerData(mesh->ldata, CD_MLOOPUV, pMat->mtex[t]->uvname);
if (pLoop) {
texuv.insert(std::make_pair(t, dynamic_cast<const MLoopUV *>(pLoop)));
}
}
}
if (texuv.size()) {
matTexUvMappings.insert(std::make_pair(m, texuv));
}
}
// collect texture coordinates, they're stored in a separate per-face buffer // collect texture coordinates, they're stored in a separate per-face buffer
if (mesh->mtface || mesh->mloopuv) { if (mesh->mtface || mesh->mloopuv) {
if (mesh->totface > static_cast<int> ( mesh->mtface.size())) { if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
@ -1028,8 +1057,17 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
} }
for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) { for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
ai_assert((*it)->mNumVertices && (*it)->mNumFaces); ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
if (itMatTexUvMapping == matTexUvMappings.end()) {
// default behaviour like before
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices]; (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
}
else {
// create texture coords for every mapped tex
for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) {
(*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices];
}
}
(*it)->mNumFaces = (*it)->mNumVertices = 0; (*it)->mNumFaces = (*it)->mNumVertices = 0;
} }
@ -1051,13 +1089,34 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ]; aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
const aiFace& f = out->mFaces[out->mNumFaces++]; const aiFace& f = out->mFaces[out->mNumFaces++];
const auto itMatTexUvMapping = matTexUvMappings.find(v.mat_nr);
if (itMatTexUvMapping == matTexUvMappings.end()) {
// old behavior
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices]; aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) { for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) {
const MLoopUV& uv = mesh->mloopuv[v.loopstart + j]; const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
vo->x = uv.uv[0]; vo->x = uv.uv[0];
vo->y = uv.uv[1]; vo->y = uv.uv[1];
} }
}
else {
// create textureCoords for every mapped tex
for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) {
const MLoopUV *tm = itMatTexUvMapping->second[m];
aiVector3D* vo = &out->mTextureCoords[m][out->mNumVertices];
uint32_t j = 0;
for (; j < f.mNumIndices; ++j, ++vo) {
const MLoopUV& uv = tm[v.loopstart + j];
vo->x = uv.uv[0];
vo->y = uv.uv[1];
}
// only update written mNumVertices in last loop
// TODO why must the numVertices be incremented here?
if (m == itMatTexUvMapping->second.size() - 1) {
out->mNumVertices += j;
}
}
}
} }
} }

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderScene.h" #include "BlenderScene.h"
#include "BlenderSceneGen.h" #include "BlenderSceneGen.h"
#include "BlenderDNA.h" #include "BlenderDNA.h"
#include "BlenderCustomData.h"
using namespace Assimp; using namespace Assimp;
using namespace Assimp::Blender; using namespace Assimp::Blender;
@ -481,6 +482,12 @@ template <> void Structure :: Convert<Mesh> (
ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db); ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
ReadField<ErrorPolicy_Igno>(dest.vdata, "vdata", db);
ReadField<ErrorPolicy_Igno>(dest.edata, "edata", db);
ReadField<ErrorPolicy_Igno>(dest.fdata, "fdata", db);
ReadField<ErrorPolicy_Igno>(dest.pdata, "pdata", db);
ReadField<ErrorPolicy_Warn>(dest.ldata, "ldata", db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
@ -786,6 +793,41 @@ template <> void Structure :: Convert<Image> (
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//--------------------------------------------------------------------------------
template <> void Structure::Convert<CustomData>(
CustomData& dest,
const FileDatabase& db
) const
{
ReadFieldArray<ErrorPolicy_Warn>(dest.typemap, "typemap", db);
ReadField<ErrorPolicy_Warn>(dest.totlayer, "totlayer", db);
ReadField<ErrorPolicy_Warn>(dest.maxlayer, "maxlayer", db);
ReadField<ErrorPolicy_Warn>(dest.totsize, "totsize", db);
ReadFieldPtrVector<ErrorPolicy_Warn>(dest.layers, "*layers", db);
db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
template <> void Structure::Convert<CustomDataLayer>(
CustomDataLayer& dest,
const FileDatabase& db
) const
{
ReadField<ErrorPolicy_Fail>(dest.type, "type", db);
ReadField<ErrorPolicy_Fail>(dest.offset, "offset", db);
ReadField<ErrorPolicy_Fail>(dest.flag, "flag", db);
ReadField<ErrorPolicy_Fail>(dest.active, "active", db);
ReadField<ErrorPolicy_Fail>(dest.active_rnd, "active_rnd", db);
ReadField<ErrorPolicy_Fail>(dest.active_clone, "active_clone", db);
ReadField<ErrorPolicy_Fail>(dest.active_mask, "active_mask", db);
ReadField<ErrorPolicy_Fail>(dest.uid, "uid", db);
ReadFieldArray<ErrorPolicy_Warn>(dest.name, "name", db);
ReadCustomDataPtr<ErrorPolicy_Fail>(dest.data, dest.type, "*data", db);
db.reader->IncPtr(size);
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
void DNA::RegisterConverters() { void DNA::RegisterConverters() {
@ -822,6 +864,8 @@ void DNA::RegisterConverters() {
converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> ); converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> ); converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> ); converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
converters["CustomData"] = DNA::FactoryPair(&Structure::Allocate<CustomData>, &Structure::Convert<CustomData>);
converters["CustomDataLayer"] = DNA::FactoryPair(&Structure::Allocate<CustomDataLayer>, &Structure::Convert<CustomDataLayer>);
} }
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -157,10 +157,16 @@ struct World : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MVert : ElemBase { struct MVert : ElemBase {
float co[3] FAIL; float co[3] FAIL;
float no[3] FAIL; float no[3] FAIL; // readed as short and divided through / 32767.f
char flag; char flag;
int mat_nr WARN; int mat_nr WARN;
int bweight; int bweight;
MVert() : ElemBase()
, flag(0)
, mat_nr(0)
, bweight(0)
{}
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -369,6 +375,72 @@ struct Material : ElemBase {
std::shared_ptr<MTex> mtex[18]; std::shared_ptr<MTex> mtex[18];
}; };
/*
CustomDataLayer 104
int type 0 4
int offset 4 4
int flag 8 4
int active 12 4
int active_rnd 16 4
int active_clone 20 4
int active_mask 24 4
int uid 28 4
char name 32 64
void *data 96 8
*/
struct CustomDataLayer : ElemBase {
int type;
int offset;
int flag;
int active;
int active_rnd;
int active_clone;
int active_mask;
int uid;
char name[64];
std::shared_ptr<ElemBase> data; // must be converted to real type according type member
CustomDataLayer()
: ElemBase()
, type(0)
, offset(0)
, flag(0)
, active(0)
, active_rnd(0)
, active_clone(0)
, active_mask(0)
, uid(0)
, data(nullptr)
{
memset(name, 0, sizeof name);
}
};
/*
CustomData 208
CustomDataLayer *layers 0 8
int typemap 8 168
int pad_i1 176 4
int totlayer 180 4
int maxlayer 184 4
int totsize 188 4
BLI_mempool *pool 192 8
CustomDataExternal *external 200 8
*/
struct CustomData : ElemBase {
vector<std::shared_ptr<struct CustomDataLayer> > layers;
int typemap[42]; // CD_NUMTYPES
int totlayer;
int maxlayer;
int totsize;
/*
std::shared_ptr<BLI_mempool> pool;
std::shared_ptr<CustomDataExternal> external;
*/
};
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Mesh : ElemBase { struct Mesh : ElemBase {
ID id FAIL; ID id FAIL;
@ -398,6 +470,12 @@ struct Mesh : ElemBase {
vector<MCol> mcol; vector<MCol> mcol;
vector< std::shared_ptr<Material> > mat FAIL; vector< std::shared_ptr<Material> > mat FAIL;
struct CustomData vdata;
struct CustomData edata;
struct CustomData fdata;
struct CustomData pdata;
struct CustomData ldata;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------

View File

@ -248,6 +248,17 @@ template <> void Structure :: Convert<Image> (
) const ) const
; ;
template <> void Structure::Convert<CustomData>(
CustomData& dest,
const FileDatabase& db
) const
;
template <> void Structure::Convert<CustomDataLayer>(
CustomDataLayer& dest,
const FileDatabase& db
) const
;
} }
} }

View File

@ -469,6 +469,8 @@ ADD_ASSIMP_IMPORTER( BLEND
BlenderBMesh.cpp BlenderBMesh.cpp
BlenderTessellator.h BlenderTessellator.h
BlenderTessellator.cpp BlenderTessellator.cpp
BlenderCustomData.h
BlenderCustomData.cpp
) )
ADD_ASSIMP_IMPORTER( IFC ADD_ASSIMP_IMPORTER( IFC
@ -909,6 +911,12 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_LIBRARY( assimp ${assimp_src} ) ADD_LIBRARY( assimp ${assimp_src} )
TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>
)
TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} ) TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} )
if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM) if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)

View File

@ -137,9 +137,7 @@ void COBImporter::SetupProperties(const Importer* /*pImp*/)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void COBImporter::InternReadFile( const std::string& pFile, void COBImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
aiScene* pScene, IOSystem* pIOHandler)
{
COB::Scene scene; COB::Scene scene;
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE( pIOHandler->Open(pFile,"rb")) ); std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE( pIOHandler->Open(pFile,"rb")) );

View File

@ -272,12 +272,13 @@ struct Node
/** Node instances at this node */ /** Node instances at this node */
std::vector<NodeInstance> mNodeInstances; std::vector<NodeInstance> mNodeInstances;
/** Rootnodes: Name of primary camera, if any */ /** Root-nodes: Name of primary camera, if any */
std::string mPrimaryCamera; std::string mPrimaryCamera;
//! Constructor. Begin with a zero parent //! Constructor. Begin with a zero parent
Node() { Node()
mParent = NULL; : mParent( nullptr ){
// empty
} }
//! Destructor: delete all children subsequently //! Destructor: delete all children subsequently

View File

@ -201,6 +201,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
0, -1, 0, 0, 0, -1, 0, 0,
0, 0, 0, 1); 0, 0, 0, 1);
} }
// store all meshes // store all meshes
StoreSceneMeshes( pScene); StoreSceneMeshes( pScene);
@ -740,10 +741,6 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// create bones if given // create bones if given
if( pSrcController && pSrcController->mType == Collada::Skin) if( pSrcController && pSrcController->mType == Collada::Skin)
{ {
// refuse if the vertex count does not match
// if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
// throw DeadlyImportError( "Joint Controller vertex count does not match mesh vertex count");
// resolve references - joint names // resolve references - joint names
const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource); const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource); const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource);
@ -971,7 +968,8 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
for( size_t b = a+1; b < mAnims.size(); ++b) for( size_t b = a+1; b < mAnims.size(); ++b)
{ {
aiAnimation* other = mAnims[b]; aiAnimation* other = mAnims[b];
if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && other->mTicksPerSecond == templateAnim->mTicksPerSecond ) if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration &&
other->mTicksPerSecond == templateAnim->mTicksPerSecond )
collectedAnimIndices.push_back( b); collectedAnimIndices.push_back( b);
} }

View File

@ -68,7 +68,7 @@ using namespace Assimp::Formatter;
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile) ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
: mFileName( pFile ) : mFileName( pFile )
, mReader( NULL ) , mReader( nullptr )
, mDataLibrary() , mDataLibrary()
, mAccessorLibrary() , mAccessorLibrary()
, mMeshLibrary() , mMeshLibrary()
@ -79,20 +79,20 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
, mLightLibrary() , mLightLibrary()
, mCameraLibrary() , mCameraLibrary()
, mControllerLibrary() , mControllerLibrary()
, mRootNode( NULL ) , mRootNode( nullptr )
, mAnims() , mAnims()
, mUnitSize( 1.0f ) , mUnitSize( 1.0f )
, mUpDirection( UP_Y ) , mUpDirection( UP_Y )
, mFormat(FV_1_5_n ) // We assume the newest file format by default , mFormat(FV_1_5_n ) // We assume the newest file format by default
{ {
// validate io-handler instance // validate io-handler instance
if ( NULL == pIOHandler ) { if (nullptr == pIOHandler ) {
throw DeadlyImportError("IOSystem is NULL." ); throw DeadlyImportError("IOSystem is NULL." );
} }
// open the file // open the file
std::unique_ptr<IOStream> file( pIOHandler->Open(pFile ) ); std::unique_ptr<IOStream> file( pIOHandler->Open(pFile ) );
if (file.get() == NULL) { if (file.get() == nullptr) {
throw DeadlyImportError( "Failed to open file " + pFile + "." ); throw DeadlyImportError( "Failed to open file " + pFile + "." );
} }
@ -363,9 +363,9 @@ void ColladaParser::ReadAnimationClipLibrary()
void ColladaParser::PostProcessControllers() void ColladaParser::PostProcessControllers()
{ {
for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it) std::string meshId;
{ for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it) {
std::string meshId = it->second.mMeshId; meshId = it->second.mMeshId;
ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId); ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId);
while(findItr != mControllerLibrary.end()) { while(findItr != mControllerLibrary.end()) {
meshId = findItr->second.mMeshId; meshId = findItr->second.mMeshId;

View File

@ -59,6 +59,25 @@ using namespace Assimp;
#ifndef ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS #ifndef ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
namespace {
template <typename aiMeshType>
void flipUVs(aiMeshType* pMesh) {
if (pMesh == nullptr) { return; }
// mirror texture y coordinate
for (unsigned int tcIdx = 0; tcIdx < AI_MAX_NUMBER_OF_TEXTURECOORDS; tcIdx++) {
if (!pMesh->HasTextureCoords(tcIdx)) {
break;
}
for (unsigned int vIdx = 0; vIdx < pMesh->mNumVertices; vIdx++) {
pMesh->mTextureCoords[tcIdx][vIdx].y = 1.0f - pMesh->mTextureCoords[tcIdx][vIdx].y;
}
}
}
} // namespace
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
MakeLeftHandedProcess::MakeLeftHandedProcess() MakeLeftHandedProcess::MakeLeftHandedProcess()
@ -282,15 +301,9 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
// Converts a single mesh // Converts a single mesh
void FlipUVsProcess::ProcessMesh( aiMesh* pMesh) void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
{ {
// mirror texture y coordinate flipUVs(pMesh);
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) { for (unsigned int idx = 0; idx < pMesh->mNumAnimMeshes; idx++) {
if( !pMesh->HasTextureCoords( a ) ) { flipUVs(pMesh->mAnimMeshes[idx]);
break;
}
for( unsigned int b = 0; b < pMesh->mNumVertices; b++ ) {
pMesh->mTextureCoords[ a ][ b ].y = 1.0f - pMesh->mTextureCoords[ a ][ b ].y;
}
} }
} }

View File

@ -222,7 +222,7 @@ void D3MFExporter::writeMetaData() {
return; return;
} }
const aiString *key; const aiString *key = nullptr;
const aiMetadataEntry *entry(nullptr); const aiMetadataEntry *entry(nullptr);
for ( size_t i = 0; i < numMetaEntries; ++i ) { for ( size_t i = 0; i < numMetaEntries; ++i ) {
mScene->mMetaData->Get( i, key, entry ); mScene->mMetaData->Get( i, key, entry );

View File

@ -297,8 +297,9 @@ private:
return false; return false;
} }
//format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
const size_t len( strlen( color ) ); const size_t len( strlen( color ) );
if ( 9 != len ) { if ( 9 != len && 7 != len) {
return false; return false;
} }
@ -313,26 +314,28 @@ private:
++buf; ++buf;
comp[ 1 ] = *buf; comp[ 1 ] = *buf;
++buf; ++buf;
diffuse.r = static_cast<ai_real>( strtol( comp, NULL, 16 ) ); diffuse.r = static_cast<ai_real>( strtol( comp, NULL, 16 ) ) / 255.0;
comp[ 0 ] = *buf; comp[ 0 ] = *buf;
++buf; ++buf;
comp[ 1 ] = *buf; comp[ 1 ] = *buf;
++buf; ++buf;
diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / 255.0;
comp[ 0 ] = *buf; comp[ 0 ] = *buf;
++buf; ++buf;
comp[ 1 ] = *buf; comp[ 1 ] = *buf;
++buf; ++buf;
diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / 255.0;
if(7 == len)
return true;
comp[ 0 ] = *buf; comp[ 0 ] = *buf;
++buf; ++buf;
comp[ 1 ] = *buf; comp[ 1 ] = *buf;
++buf; ++buf;
diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / 255.0;
return true; return true;
} }

View File

@ -119,7 +119,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
} }
} }
aiTexel* imageContent = new aiTexel[1u + imageSize / sizeof(aiTexel)]; aiTexel* imageContent = new aiTexel[ 1ul + static_cast<unsigned long>( imageSize ) / sizeof(aiTexel)];
file.seekg(0, std::ios::beg); file.seekg(0, std::ios::beg);
file.read(reinterpret_cast<char*>(imageContent), imageSize); file.read(reinterpret_cast<char*>(imageContent), imageSize);

View File

@ -150,14 +150,14 @@ Exporter::ExportFormatEntry gExporters[] =
#endif #endif
#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2, Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2, Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
#endif #endif
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER

View File

@ -73,11 +73,7 @@ using namespace Util;
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
// XXX vc9's debugger won't step into anonymous namespaces FBXConverter::FBXConverter( aiScene* out, const Document& doc )
//namespace {
Converter::Converter( aiScene* out, const Document& doc )
: defaultMaterialIndex() : defaultMaterialIndex()
, out( out ) , out( out )
, doc( doc ) { , doc( doc ) {
@ -118,7 +114,7 @@ Converter::Converter( aiScene* out, const Document& doc )
} }
Converter::~Converter() { FBXConverter::~FBXConverter() {
std::for_each( meshes.begin(), meshes.end(), Util::delete_fun<aiMesh>() ); std::for_each( meshes.begin(), meshes.end(), Util::delete_fun<aiMesh>() );
std::for_each( materials.begin(), materials.end(), Util::delete_fun<aiMaterial>() ); std::for_each( materials.begin(), materials.end(), Util::delete_fun<aiMaterial>() );
std::for_each( animations.begin(), animations.end(), Util::delete_fun<aiAnimation>() ); std::for_each( animations.begin(), animations.end(), Util::delete_fun<aiAnimation>() );
@ -127,7 +123,7 @@ Converter::~Converter() {
std::for_each( textures.begin(), textures.end(), Util::delete_fun<aiTexture>() ); std::for_each( textures.begin(), textures.end(), Util::delete_fun<aiTexture>() );
} }
void Converter::ConvertRootNode() { void FBXConverter::ConvertRootNode() {
out->mRootNode = new aiNode(); out->mRootNode = new aiNode();
out->mRootNode->mName.Set( "RootNode" ); out->mRootNode->mName.Set( "RootNode" );
@ -135,7 +131,7 @@ void Converter::ConvertRootNode() {
ConvertNodes( 0L, *out->mRootNode ); ConvertNodes( 0L, *out->mRootNode );
} }
void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform ) { void FBXConverter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform ) {
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" ); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" );
std::vector<aiNode*> nodes; std::vector<aiNode*> nodes;
@ -189,12 +185,8 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
} }
if ( !name_carrier ) { if ( !name_carrier ) {
NodeNameCache::const_iterator it( std::find( mNodeNames.begin(), mNodeNames.end(), original_name ) ); std::string old_original_name = original_name;
if ( it != mNodeNames.end() ) { GetUniqueName(old_original_name, original_name);
original_name = original_name + std::string( "001" );
}
mNodeNames.push_back( original_name );
nodes_chain.push_back( new aiNode( original_name ) ); nodes_chain.push_back( new aiNode( original_name ) );
} else { } else {
original_name = nodes_chain.back()->mName.C_Str(); original_name = nodes_chain.back()->mName.C_Str();
@ -286,7 +278,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
} }
void Converter::ConvertLights( const Model& model, const std::string &orig_name ) { void FBXConverter::ConvertLights( const Model& model, const std::string &orig_name ) {
const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes(); const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
for( const NodeAttribute* attr : node_attrs ) { for( const NodeAttribute* attr : node_attrs ) {
const Light* const light = dynamic_cast<const Light*>( attr ); const Light* const light = dynamic_cast<const Light*>( attr );
@ -296,7 +288,7 @@ void Converter::ConvertLights( const Model& model, const std::string &orig_name
} }
} }
void Converter::ConvertCameras( const Model& model, const std::string &orig_name ) { void FBXConverter::ConvertCameras( const Model& model, const std::string &orig_name ) {
const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes(); const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
for( const NodeAttribute* attr : node_attrs ) { for( const NodeAttribute* attr : node_attrs ) {
const Camera* const cam = dynamic_cast<const Camera*>( attr ); const Camera* const cam = dynamic_cast<const Camera*>( attr );
@ -306,7 +298,7 @@ void Converter::ConvertCameras( const Model& model, const std::string &orig_name
} }
} }
void Converter::ConvertLight( const Light& light, const std::string &orig_name ) { void FBXConverter::ConvertLight( const Light& light, const std::string &orig_name ) {
lights.push_back( new aiLight() ); lights.push_back( new aiLight() );
aiLight* const out_light = lights.back(); aiLight* const out_light = lights.back();
@ -383,7 +375,7 @@ void Converter::ConvertLight( const Light& light, const std::string &orig_name )
} }
} }
void Converter::ConvertCamera( const Camera& cam, const std::string &orig_name ) void FBXConverter::ConvertCamera( const Camera& cam, const std::string &orig_name )
{ {
cameras.push_back( new aiCamera() ); cameras.push_back( new aiCamera() );
aiCamera* const out_camera = cameras.back(); aiCamera* const out_camera = cameras.back();
@ -402,36 +394,23 @@ void Converter::ConvertCamera( const Camera& cam, const std::string &orig_name )
out_camera->mClipPlaneFar = cam.FarPlane(); out_camera->mClipPlaneFar = cam.FarPlane();
} }
static bool HasName( NodeNameCache &cache, const std::string &name ) { void FBXConverter::GetUniqueName( const std::string &name, std::string &uniqueName )
NodeNameCache::const_iterator it( std::find( cache.begin(), cache.end(), name ) );
return it != cache.end();
}
void Converter::GetUniqueName( const std::string &name, std::string uniqueName ) {
if ( !HasName( mNodeNames, name ) ) {
uniqueName = name;
return;
}
int i( 0 );
std::string newName;
while ( HasName( mNodeNames, newName ) ) {
++i;
newName.clear();
newName += name;
std::stringstream ext;
ext << std::setfill( '0' ) << std::setw( 3 ) << i;
newName += ext.str();
}
uniqueName = newName;
mNodeNames.push_back( uniqueName );
}
const char* Converter::NameTransformationComp( TransformationComp comp )
{ {
switch ( comp ) int i = 0;
uniqueName = name;
while (mNodeNames.find(uniqueName) != mNodeNames.end())
{ {
++i;
std::stringstream ext;
ext << name << std::setfill('0') << std::setw(3) << i;
uniqueName = ext.str();
}
mNodeNames.insert(uniqueName);
}
const char* FBXConverter::NameTransformationComp( TransformationComp comp ) {
switch ( comp ) {
case TransformationComp_Translation: case TransformationComp_Translation:
return "Translation"; return "Translation";
case TransformationComp_RotationOffset: case TransformationComp_RotationOffset:
@ -472,13 +451,12 @@ const char* Converter::NameTransformationComp( TransformationComp comp )
} }
ai_assert( false ); ai_assert( false );
return NULL;
return nullptr;
} }
const char* Converter::NameTransformationCompProperty( TransformationComp comp ) const char* FBXConverter::NameTransformationCompProperty( TransformationComp comp ) {
{ switch ( comp ) {
switch ( comp )
{
case TransformationComp_Translation: case TransformationComp_Translation:
return "Lcl Translation"; return "Lcl Translation";
case TransformationComp_RotationOffset: case TransformationComp_RotationOffset:
@ -518,17 +496,18 @@ const char* Converter::NameTransformationCompProperty( TransformationComp comp )
} }
ai_assert( false ); ai_assert( false );
return NULL;
return nullptr;
} }
aiVector3D Converter::TransformationCompDefaultValue( TransformationComp comp ) aiVector3D FBXConverter::TransformationCompDefaultValue( TransformationComp comp )
{ {
// XXX a neat way to solve the never-ending special cases for scaling // XXX a neat way to solve the never-ending special cases for scaling
// would be to do everything in log space! // would be to do everything in log space!
return comp == TransformationComp_Scaling ? aiVector3D( 1.f, 1.f, 1.f ) : aiVector3D(); return comp == TransformationComp_Scaling ? aiVector3D( 1.f, 1.f, 1.f ) : aiVector3D();
} }
void Converter::GetRotationMatrix( Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out ) void FBXConverter::GetRotationMatrix( Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out )
{ {
if ( mode == Model::RotOrder_SphericXYZ ) { if ( mode == Model::RotOrder_SphericXYZ ) {
FBXImporter::LogError( "Unsupported RotationMode: SphericXYZ" ); FBXImporter::LogError( "Unsupported RotationMode: SphericXYZ" );
@ -599,11 +578,15 @@ void Converter::GetRotationMatrix( Model::RotOrder mode, const aiVector3D& rotat
default: default:
ai_assert( false ); ai_assert( false );
break;
} }
ai_assert( ( order[ 0 ] >= 0 ) && ( order[ 0 ] <= 2 ) ); ai_assert( order[ 0 ] >= 0 );
ai_assert( ( order[ 1 ] >= 0 ) && ( order[ 1 ] <= 2 ) ); ai_assert( order[ 0 ] <= 2 );
ai_assert( ( order[ 2 ] >= 0 ) && ( order[ 2 ] <= 2 ) ); ai_assert( order[ 1 ] >= 0 );
ai_assert( order[ 1 ] <= 2 );
ai_assert( order[ 2 ] >= 0 );
ai_assert( order[ 2 ] <= 2 );
if ( !is_id[ order[ 0 ] ] ) { if ( !is_id[ order[ 0 ] ] ) {
out = temp[ order[ 0 ] ]; out = temp[ order[ 0 ] ];
@ -618,7 +601,7 @@ void Converter::GetRotationMatrix( Model::RotOrder mode, const aiVector3D& rotat
} }
} }
bool Converter::NeedsComplexTransformationChain( const Model& model ) bool FBXConverter::NeedsComplexTransformationChain( const Model& model )
{ {
const PropertyTable& props = model.Props(); const PropertyTable& props = model.Props();
bool ok; bool ok;
@ -649,13 +632,13 @@ bool Converter::NeedsComplexTransformationChain( const Model& model )
return false; return false;
} }
std::string Converter::NameTransformationChainNode( const std::string& name, TransformationComp comp ) std::string FBXConverter::NameTransformationChainNode( const std::string& name, TransformationComp comp )
{ {
return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp ); return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp );
} }
void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes ) void FBXConverter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes,
{ std::vector<aiNode*>& post_output_nodes ) {
const PropertyTable& props = model.Props(); const PropertyTable& props = model.Props();
const Model::RotOrder rot = model.RotationOrder(); const Model::RotOrder rot = model.RotationOrder();
@ -826,7 +809,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
} }
} }
void Converter::SetupNodeMetadata( const Model& model, aiNode& nd ) void FBXConverter::SetupNodeMetadata( const Model& model, aiNode& nd )
{ {
const PropertyTable& props = model.Props(); const PropertyTable& props = model.Props();
DirectPropertyMap unparsedProperties = props.GetUnparsedProperties(); DirectPropertyMap unparsedProperties = props.GetUnparsedProperties();
@ -863,7 +846,7 @@ void Converter::SetupNodeMetadata( const Model& model, aiNode& nd )
} }
} }
void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform ) void FBXConverter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform )
{ {
const std::vector<const Geometry*>& geos = model.GetGeometry(); const std::vector<const Geometry*>& geos = model.GetGeometry();
@ -890,7 +873,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
} }
} }
std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model, std::vector<unsigned int> FBXConverter::ConvertMesh( const MeshGeometry& mesh, const Model& model,
const aiMatrix4x4& node_global_transform, aiNode& nd) const aiMatrix4x4& node_global_transform, aiNode& nd)
{ {
std::vector<unsigned int> temp; std::vector<unsigned int> temp;
@ -925,7 +908,7 @@ std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, cons
return temp; return temp;
} }
aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd) aiMesh* FBXConverter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd)
{ {
aiMesh* const out_mesh = new aiMesh(); aiMesh* const out_mesh = new aiMesh();
meshes.push_back( out_mesh ); meshes.push_back( out_mesh );
@ -948,7 +931,7 @@ aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd)
return out_mesh; return out_mesh;
} }
unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model, unsigned int FBXConverter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model,
const aiMatrix4x4& node_global_transform, aiNode& nd) const aiMatrix4x4& node_global_transform, aiNode& nd)
{ {
const MatIndexArray& mindices = mesh.GetMaterialIndices(); const MatIndexArray& mindices = mesh.GetMaterialIndices();
@ -1075,7 +1058,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con
return static_cast<unsigned int>( meshes.size() - 1 ); return static_cast<unsigned int>( meshes.size() - 1 );
} }
std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, std::vector<unsigned int> FBXConverter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
const aiMatrix4x4& node_global_transform, aiNode& nd) const aiMatrix4x4& node_global_transform, aiNode& nd)
{ {
const MatIndexArray& mindices = mesh.GetMaterialIndices(); const MatIndexArray& mindices = mesh.GetMaterialIndices();
@ -1095,7 +1078,7 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
return indices; return indices;
} }
unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, unsigned int FBXConverter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
MatIndexArray::value_type index, MatIndexArray::value_type index,
const aiMatrix4x4& node_global_transform, const aiMatrix4x4& node_global_transform,
aiNode& nd) aiNode& nd)
@ -1271,7 +1254,7 @@ unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, cons
return static_cast<unsigned int>( meshes.size() - 1 ); return static_cast<unsigned int>( meshes.size() - 1 );
} }
void Converter::ConvertWeights( aiMesh* out, const Model& model, const MeshGeometry& geo, void FBXConverter::ConvertWeights( aiMesh* out, const Model& model, const MeshGeometry& geo,
const aiMatrix4x4& node_global_transform , const aiMatrix4x4& node_global_transform ,
unsigned int materialIndex, unsigned int materialIndex,
std::vector<unsigned int>* outputVertStartIndices ) std::vector<unsigned int>* outputVertStartIndices )
@ -1376,7 +1359,7 @@ void Converter::ConvertWeights( aiMesh* out, const Model& model, const MeshGeome
std::swap_ranges( bones.begin(), bones.end(), out->mBones ); std::swap_ranges( bones.begin(), bones.end(), out->mBones );
} }
void Converter::ConvertCluster( std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl, void FBXConverter::ConvertCluster( std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
std::vector<size_t>& out_indices, std::vector<size_t>& out_indices,
std::vector<size_t>& index_out_indices, std::vector<size_t>& index_out_indices,
std::vector<size_t>& count_out_indices, std::vector<size_t>& count_out_indices,
@ -1417,7 +1400,7 @@ void Converter::ConvertCluster( std::vector<aiBone*>& bones, const Model& /*mode
} }
} }
void Converter::ConvertMaterialForMesh( aiMesh* out, const Model& model, const MeshGeometry& geo, void FBXConverter::ConvertMaterialForMesh( aiMesh* out, const Model& model, const MeshGeometry& geo,
MatIndexArray::value_type materialIndex ) MatIndexArray::value_type materialIndex )
{ {
// locate source materials for this mesh // locate source materials for this mesh
@ -1439,7 +1422,7 @@ void Converter::ConvertMaterialForMesh( aiMesh* out, const Model& model, const M
materials_converted[ mat ] = out->mMaterialIndex; materials_converted[ mat ] = out->mMaterialIndex;
} }
unsigned int Converter::GetDefaultMaterial() unsigned int FBXConverter::GetDefaultMaterial()
{ {
if ( defaultMaterialIndex ) { if ( defaultMaterialIndex ) {
return defaultMaterialIndex - 1; return defaultMaterialIndex - 1;
@ -1461,7 +1444,7 @@ unsigned int Converter::GetDefaultMaterial()
} }
unsigned int Converter::ConvertMaterial( const Material& material, const MeshGeometry* const mesh ) unsigned int FBXConverter::ConvertMaterial( const Material& material, const MeshGeometry* const mesh )
{ {
const PropertyTable& props = material.Props(); const PropertyTable& props = material.Props();
@ -1496,7 +1479,7 @@ unsigned int Converter::ConvertMaterial( const Material& material, const MeshGeo
return static_cast<unsigned int>( materials.size() - 1 ); return static_cast<unsigned int>( materials.size() - 1 );
} }
unsigned int Converter::ConvertVideo( const Video& video ) unsigned int FBXConverter::ConvertVideo( const Video& video )
{ {
// generate empty output texture // generate empty output texture
aiTexture* out_tex = new aiTexture(); aiTexture* out_tex = new aiTexture();
@ -1526,23 +1509,13 @@ unsigned int Converter::ConvertVideo( const Video& video )
return static_cast<unsigned int>( textures.size() - 1 ); return static_cast<unsigned int>( textures.size() - 1 );
} }
void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, aiString FBXConverter::GetTexturePath(const Texture* tex)
const std::string& propName,
aiTextureType target, const MeshGeometry* const mesh )
{ {
TextureMap::const_iterator it = textures.find( propName );
if ( it == textures.end() ) {
return;
}
const Texture* const tex = ( *it ).second;
if ( tex != 0 )
{
aiString path; aiString path;
path.Set( tex->RelativeFilename() ); path.Set(tex->RelativeFilename());
const Video* media = tex->Media(); const Video* media = tex->Media();
if (media != 0) { if (media != nullptr) {
bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found) bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
unsigned int index; unsigned int index;
@ -1573,6 +1546,22 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
} }
} }
return path;
}
void FBXConverter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& textures,
const std::string& propName,
aiTextureType target, const MeshGeometry* const mesh )
{
TextureMap::const_iterator it = textures.find( propName );
if ( it == textures.end() ) {
return;
}
const Texture* const tex = ( *it ).second;
if ( tex != 0 )
{
aiString path = GetTexturePath(tex);
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 ); out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
aiUVTransform uvTrafo; aiUVTransform uvTrafo;
@ -1678,7 +1667,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
} }
} }
void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, void FBXConverter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
const std::string& propName, const std::string& propName,
aiTextureType target, const MeshGeometry* const mesh ) { aiTextureType target, const MeshGeometry* const mesh ) {
LayeredTextureMap::const_iterator it = layeredTextures.find( propName ); LayeredTextureMap::const_iterator it = layeredTextures.find( propName );
@ -1696,9 +1685,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu
const Texture* const tex = ( *it ).second->getTexture(texIndex); const Texture* const tex = ( *it ).second->getTexture(texIndex);
aiString path; aiString path = GetTexturePath(tex);
path.Set( tex->RelativeFilename() );
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex ); out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex );
aiUVTransform uvTrafo; aiUVTransform uvTrafo;
@ -1803,7 +1790,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu
} }
} }
void Converter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh ) void FBXConverter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh )
{ {
TrySetTextureProperties( out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh ); TrySetTextureProperties( out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh );
TrySetTextureProperties( out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh ); TrySetTextureProperties( out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh );
@ -1818,7 +1805,7 @@ void Converter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& tex
TrySetTextureProperties( out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh ); TrySetTextureProperties( out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh );
} }
void Converter::SetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh ) void FBXConverter::SetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh )
{ {
TrySetTextureProperties( out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh );
@ -1833,7 +1820,7 @@ void Converter::SetTextureProperties( aiMaterial* out_mat, const LayeredTextureM
TrySetTextureProperties( out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh );
} }
aiColor3D Converter::GetColorPropertyFactored( const PropertyTable& props, const std::string& colorName, aiColor3D FBXConverter::GetColorPropertyFactored( const PropertyTable& props, const std::string& colorName,
const std::string& factorName, bool& result, bool useTemplate ) const std::string& factorName, bool& result, bool useTemplate )
{ {
result = true; result = true;
@ -1858,13 +1845,13 @@ aiColor3D Converter::GetColorPropertyFactored( const PropertyTable& props, const
return aiColor3D( BaseColor.x, BaseColor.y, BaseColor.z ); return aiColor3D( BaseColor.x, BaseColor.y, BaseColor.z );
} }
aiColor3D Converter::GetColorPropertyFromMaterial( const PropertyTable& props, const std::string& baseName, aiColor3D FBXConverter::GetColorPropertyFromMaterial( const PropertyTable& props, const std::string& baseName,
bool& result ) bool& result )
{ {
return GetColorPropertyFactored( props, baseName + "Color", baseName + "Factor", result, true ); return GetColorPropertyFactored( props, baseName + "Color", baseName + "Factor", result, true );
} }
aiColor3D Converter::GetColorProperty( const PropertyTable& props, const std::string& colorName, aiColor3D FBXConverter::GetColorProperty( const PropertyTable& props, const std::string& colorName,
bool& result, bool useTemplate ) bool& result, bool useTemplate )
{ {
result = true; result = true;
@ -1877,7 +1864,7 @@ aiColor3D Converter::GetColorProperty( const PropertyTable& props, const std::st
return aiColor3D( ColorVec.x, ColorVec.y, ColorVec.z ); return aiColor3D( ColorVec.x, ColorVec.y, ColorVec.z );
} }
void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyTable& props ) void FBXConverter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyTable& props )
{ {
// Set shading properties. // Set shading properties.
// Modern FBX Files have two separate systems for defining these, // Modern FBX Files have two separate systems for defining these,
@ -1976,8 +1963,7 @@ void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyT
} }
double Converter::FrameRateToDouble( FileGlobalSettings::FrameRate fp, double customFPSVal ) double FBXConverter::FrameRateToDouble( FileGlobalSettings::FrameRate fp, double customFPSVal ) {
{
switch ( fp ) { switch ( fp ) {
case FileGlobalSettings::FrameRate_DEFAULT: case FileGlobalSettings::FrameRate_DEFAULT:
return 1.0; return 1.0;
@ -2025,11 +2011,12 @@ double Converter::FrameRateToDouble( FileGlobalSettings::FrameRate fp, double cu
} }
ai_assert( false ); ai_assert( false );
return -1.0f; return -1.0f;
} }
void Converter::ConvertAnimations() void FBXConverter::ConvertAnimations()
{ {
// first of all determine framerate // first of all determine framerate
const FileGlobalSettings::FrameRate fps = doc.GlobalSettings().TimeMode(); const FileGlobalSettings::FrameRate fps = doc.GlobalSettings().TimeMode();
@ -2042,7 +2029,7 @@ void Converter::ConvertAnimations()
} }
} }
std::string Converter::FixNodeName( const std::string& name ) { std::string FBXConverter::FixNodeName( const std::string& name ) {
// strip Model:: prefix, avoiding ambiguities (i.e. don't strip if // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if
// this causes ambiguities, well possible between empty identifiers, // this causes ambiguities, well possible between empty identifiers,
// such as "Model::" and ""). Make sure the behaviour is consistent // such as "Model::" and ""). Make sure the behaviour is consistent
@ -2055,7 +2042,7 @@ std::string Converter::FixNodeName( const std::string& name ) {
return name; return name;
} }
void Converter::ConvertAnimationStack( const AnimationStack& st ) void FBXConverter::ConvertAnimationStack( const AnimationStack& st )
{ {
const AnimationLayerList& layers = st.Layers(); const AnimationLayerList& layers = st.Layers();
if ( layers.empty() ) { if ( layers.empty() ) {
@ -2197,7 +2184,7 @@ static void validateAnimCurveNodes( const std::vector<const AnimationCurveNode*>
#endif // ASSIMP_BUILD_DEBUG #endif // ASSIMP_BUILD_DEBUG
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Converter::GenerateNodeAnimations( std::vector<aiNodeAnim*>& node_anims, void FBXConverter::GenerateNodeAnimations( std::vector<aiNodeAnim*>& node_anims,
const std::string& fixed_name, const std::string& fixed_name,
const std::vector<const AnimationCurveNode*>& curves, const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map, const LayerMap& layer_map,
@ -2431,10 +2418,9 @@ void Converter::GenerateNodeAnimations( std::vector<aiNodeAnim*>& node_anims,
node_anim_chain_bits[ fixed_name ] = flags; node_anim_chain_bits[ fixed_name ] = flags;
} }
bool Converter::IsRedundantAnimationData( const Model& target, bool FBXConverter::IsRedundantAnimationData( const Model& target,
TransformationComp comp, TransformationComp comp,
const std::vector<const AnimationCurveNode*>& curves ) const std::vector<const AnimationCurveNode*>& curves ) {
{
ai_assert( curves.size() ); ai_assert( curves.size() );
// look for animation nodes with // look for animation nodes with
@ -2477,7 +2463,7 @@ bool Converter::IsRedundantAnimationData( const Model& target,
} }
aiNodeAnim* Converter::GenerateRotationNodeAnim( const std::string& name, aiNodeAnim* FBXConverter::GenerateRotationNodeAnim( const std::string& name,
const Model& target, const Model& target,
const std::vector<const AnimationCurveNode*>& curves, const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map, const LayerMap& layer_map,
@ -2507,7 +2493,7 @@ aiNodeAnim* Converter::GenerateRotationNodeAnim( const std::string& name,
return na.release(); return na.release();
} }
aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name, aiNodeAnim* FBXConverter::GenerateScalingNodeAnim( const std::string& name,
const Model& /*target*/, const Model& /*target*/,
const std::vector<const AnimationCurveNode*>& curves, const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map, const LayerMap& layer_map,
@ -2537,16 +2523,14 @@ aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name,
return na.release(); return na.release();
} }
aiNodeAnim* FBXConverter::GenerateTranslationNodeAnim( const std::string& name,
aiNodeAnim* Converter::GenerateTranslationNodeAnim( const std::string& name,
const Model& /*target*/, const Model& /*target*/,
const std::vector<const AnimationCurveNode*>& curves, const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map, const LayerMap& layer_map,
int64_t start, int64_t stop, int64_t start, int64_t stop,
double& max_time, double& max_time,
double& min_time, double& min_time,
bool inverse ) bool inverse ) {
{
std::unique_ptr<aiNodeAnim> na( new aiNodeAnim() ); std::unique_ptr<aiNodeAnim> na( new aiNodeAnim() );
na->mNodeName.Set( name ); na->mNodeName.Set( name );
@ -2575,7 +2559,7 @@ aiNodeAnim* Converter::GenerateTranslationNodeAnim( const std::string& name,
return na.release(); return na.release();
} }
aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name, aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim( const std::string& name,
const Model& target, const Model& target,
NodeMap::const_iterator chain[ TransformationComp_MAXIMUM ], NodeMap::const_iterator chain[ TransformationComp_MAXIMUM ],
NodeMap::const_iterator iter_end, NodeMap::const_iterator iter_end,
@ -2711,7 +2695,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name,
return na.release(); return na.release();
} }
Converter::KeyFrameListList Converter::GetKeyframeList( const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop ) FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList( const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop )
{ {
KeyFrameListList inputs; KeyFrameListList inputs;
inputs.reserve( nodes.size() * 3 ); inputs.reserve( nodes.size() * 3 );
@ -2767,12 +2751,11 @@ Converter::KeyFrameListList Converter::GetKeyframeList( const std::vector<const
} }
KeyTimeList Converter::GetKeyTimeList( const KeyFrameListList& inputs ) KeyTimeList FBXConverter::GetKeyTimeList( const KeyFrameListList& inputs ) {
{ ai_assert( !inputs.empty() );
ai_assert( inputs.size() );
// reserve some space upfront - it is likely that the keyframe lists // reserve some space upfront - it is likely that the key-frame lists
// have matching time values, so max(of all keyframe lists) should // have matching time values, so max(of all key-frame lists) should
// be a good estimate. // be a good estimate.
KeyTimeList keys; KeyTimeList keys;
@ -2816,17 +2799,15 @@ KeyTimeList Converter::GetKeyTimeList( const KeyFrameListList& inputs )
return keys; return keys;
} }
void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, void FBXConverter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
const aiVector3D& def_value, const aiVector3D& def_value,
double& max_time, double& max_time,
double& min_time ) double& min_time ) {
ai_assert( !keys.empty() );
{ ai_assert( nullptr != valOut );
ai_assert( keys.size() );
ai_assert( valOut );
std::vector<unsigned int> next_pos; std::vector<unsigned int> next_pos;
const size_t count = inputs.size(); const size_t count( inputs.size() );
next_pos.resize( inputs.size(), 0 ); next_pos.resize( inputs.size(), 0 );
@ -2837,6 +2818,9 @@ void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, c
const KeyFrameList& kfl = inputs[ i ]; const KeyFrameList& kfl = inputs[ i ];
const size_t ksize = std::get<0>(kfl)->size(); const size_t ksize = std::get<0>(kfl)->size();
if (ksize == 0) {
continue;
}
if ( ksize > next_pos[ i ] && std::get<0>(kfl)->at( next_pos[ i ] ) == time ) { if ( ksize > next_pos[ i ] && std::get<0>(kfl)->at( next_pos[ i ] ) == time ) {
++next_pos[ i ]; ++next_pos[ i ];
} }
@ -2871,14 +2855,14 @@ void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, c
} }
} }
void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, void FBXConverter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
const aiVector3D& def_value, const aiVector3D& def_value,
double& maxTime, double& maxTime,
double& minTime, double& minTime,
Model::RotOrder order ) Model::RotOrder order )
{ {
ai_assert( keys.size() ); ai_assert( !keys.empty() );
ai_assert( valOut ); ai_assert( nullptr != valOut );
std::unique_ptr<aiVectorKey[]> temp( new aiVectorKey[ keys.size() ] ); std::unique_ptr<aiVectorKey[]> temp( new aiVectorKey[ keys.size() ] );
InterpolateKeys( temp.get(), keys, inputs, def_value, maxTime, minTime ); InterpolateKeys( temp.get(), keys, inputs, def_value, maxTime, minTime );
@ -2909,7 +2893,7 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con
} }
} }
void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale, void FBXConverter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale,
aiVectorKey* out_translation, aiVectorKey* out_translation,
const KeyFrameListList& scaling, const KeyFrameListList& scaling,
const KeyFrameListList& translation, const KeyFrameListList& translation,
@ -2967,7 +2951,7 @@ void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey
} }
} }
aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order ) aiQuaternion FBXConverter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order )
{ {
aiMatrix4x4 m; aiMatrix4x4 m;
GetRotationMatrix( order, rot, m ); GetRotationMatrix( order, rot, m );
@ -2975,7 +2959,7 @@ aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrde
return aiQuaternion( aiMatrix3x3( m ) ); return aiQuaternion( aiMatrix3x3( m ) );
} }
void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/, void FBXConverter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
int64_t start, int64_t stop, int64_t start, int64_t stop,
double& maxTime, double& maxTime,
double& minTime ) double& minTime )
@ -2995,7 +2979,7 @@ void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const Animat
InterpolateKeys( na->mScalingKeys, keys, inputs, aiVector3D( 1.0f, 1.0f, 1.0f ), maxTime, minTime ); InterpolateKeys( na->mScalingKeys, keys, inputs, aiVector3D( 1.0f, 1.0f, 1.0f ), maxTime, minTime );
} }
void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, void FBXConverter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& /*layers*/, const LayerMap& /*layers*/,
int64_t start, int64_t stop, int64_t start, int64_t stop,
double& maxTime, double& maxTime,
@ -3013,7 +2997,7 @@ void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const
InterpolateKeys( na->mPositionKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime ); InterpolateKeys( na->mPositionKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime );
} }
void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, void FBXConverter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& /*layers*/, const LayerMap& /*layers*/,
int64_t start, int64_t stop, int64_t start, int64_t stop,
double& maxTime, double& maxTime,
@ -3033,7 +3017,7 @@ void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const Ani
} }
} }
void Converter::ConvertGlobalSettings() { void FBXConverter::ConvertGlobalSettings() {
if (nullptr == out) { if (nullptr == out) {
return; return;
} }
@ -3044,7 +3028,7 @@ void Converter::ConvertGlobalSettings() {
out->mMetaData->Set(index, "UnitScaleFactor", unitScalFactor); out->mMetaData->Set(index, "UnitScaleFactor", unitScalFactor);
} }
void Converter::TransferDataToScene() void FBXConverter::TransferDataToScene()
{ {
ai_assert( !out->mMeshes ); ai_assert( !out->mMeshes );
ai_assert( !out->mNumMeshes ); ai_assert( !out->mNumMeshes );
@ -3096,12 +3080,10 @@ void Converter::TransferDataToScene()
} }
} }
//} // !anon
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertToAssimpScene(aiScene* out, const Document& doc) void ConvertToAssimpScene(aiScene* out, const Document& doc)
{ {
Converter converter(out,doc); FBXConverter converter(out,doc);
} }
} // !FBX } // !FBX

View File

@ -68,7 +68,7 @@ namespace FBX {
class Document; class Document;
using NodeNameCache = std::vector<std::string>; using NodeNameCache = std::set<std::string>;
/** /**
* Convert a FBX #Document to #aiScene * Convert a FBX #Document to #aiScene
@ -78,7 +78,7 @@ using NodeNameCache = std::vector<std::string>;
void ConvertToAssimpScene(aiScene* out, const Document& doc); void ConvertToAssimpScene(aiScene* out, const Document& doc);
/** Dummy class to encapsulate the conversion process */ /** Dummy class to encapsulate the conversion process */
class Converter { class FBXConverter {
public: public:
/** /**
* The different parts that make up the final local transformation of a fbx-node * The different parts that make up the final local transformation of a fbx-node
@ -106,8 +106,8 @@ public:
}; };
public: public:
Converter(aiScene* out, const Document& doc); FBXConverter(aiScene* out, const Document& doc);
~Converter(); ~FBXConverter();
private: private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -131,7 +131,7 @@ private:
void ConvertCamera( const Camera& cam, const std::string &orig_name ); void ConvertCamera( const Camera& cam, const std::string &orig_name );
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void GetUniqueName( const std::string &name, std::string uniqueName ); void GetUniqueName( const std::string &name, std::string& uniqueName );
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// this returns unified names usable within assimp identifiers (i.e. no space characters - // this returns unified names usable within assimp identifiers (i.e. no space characters -
@ -228,6 +228,10 @@ private:
// Video -> aiTexture // Video -> aiTexture
unsigned int ConvertVideo(const Video& video); unsigned int ConvertVideo(const Video& video);
// ------------------------------------------------------------------------------------------------
// convert embedded texture if necessary and return actual texture path
aiString GetTexturePath(const Texture* tex);
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
const std::string& propName, const std::string& propName,

View File

@ -115,7 +115,7 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
} }
} }
if(!Properties70) { if(!Properties70 || !Properties70->Compound()) {
if(!no_warn) { if(!no_warn) {
DOMWarning("property table (Properties70) not found",&element); DOMWarning("property table (Properties70) not found",&element);
} }

View File

@ -985,6 +985,10 @@ int64_t to_ktime(double ticks, const aiAnimation* anim) {
return (static_cast<int64_t>(ticks) / static_cast<int64_t>(anim->mTicksPerSecond)) * FBX::SECOND; return (static_cast<int64_t>(ticks) / static_cast<int64_t>(anim->mTicksPerSecond)) * FBX::SECOND;
} }
int64_t to_ktime(double time) {
return (static_cast<int64_t>(time * FBX::SECOND));
}
void FBXExporter::WriteObjects () void FBXExporter::WriteObjects ()
{ {
if (!binary) { if (!binary) {
@ -2089,7 +2093,7 @@ void FBXExporter::WriteObjects ()
// position/translation // position/translation
for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) { for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) {
const aiVectorKey& k = na->mPositionKeys[ki]; const aiVectorKey& k = na->mPositionKeys[ki];
times.push_back(to_ktime(k.mTime, anim)); times.push_back(to_ktime(k.mTime));
xval.push_back(k.mValue.x); xval.push_back(k.mValue.x);
yval.push_back(k.mValue.y); yval.push_back(k.mValue.y);
zval.push_back(k.mValue.z); zval.push_back(k.mValue.z);
@ -2103,7 +2107,7 @@ void FBXExporter::WriteObjects ()
times.clear(); xval.clear(); yval.clear(); zval.clear(); times.clear(); xval.clear(); yval.clear(); zval.clear();
for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) { for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) {
const aiQuatKey& k = na->mRotationKeys[ki]; const aiQuatKey& k = na->mRotationKeys[ki];
times.push_back(to_ktime(k.mTime, anim)); times.push_back(to_ktime(k.mTime));
// TODO: aiQuaternion method to convert to Euler... // TODO: aiQuaternion method to convert to Euler...
aiMatrix4x4 m(k.mValue.GetMatrix()); aiMatrix4x4 m(k.mValue.GetMatrix());
aiVector3D qs, qr, qt; aiVector3D qs, qr, qt;
@ -2121,7 +2125,7 @@ void FBXExporter::WriteObjects ()
times.clear(); xval.clear(); yval.clear(); zval.clear(); times.clear(); xval.clear(); yval.clear(); zval.clear();
for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) { for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) {
const aiVectorKey& k = na->mScalingKeys[ki]; const aiVectorKey& k = na->mScalingKeys[ki];
times.push_back(to_ktime(k.mTime, anim)); times.push_back(to_ktime(k.mTime));
xval.push_back(k.mValue.x); xval.push_back(k.mValue.x);
yval.push_back(k.mValue.y); yval.push_back(k.mValue.y);
zval.push_back(k.mValue.z); zval.push_back(k.mValue.z);

View File

@ -437,6 +437,9 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
// deal with this more elegantly and with less redundancy, but right // deal with this more elegantly and with less redundancy, but right
// now it seems unavoidable. // now it seems unavoidable.
if (MappingInformationType == "ByVertice" && isDirect) { if (MappingInformationType == "ByVertice" && isDirect) {
if (!HasElement(source, dataElementName)) {
return;
}
std::vector<T> tempData; std::vector<T> tempData;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));

View File

@ -67,7 +67,7 @@ public:
FileSystemFilter(const std::string& file, IOSystem* old) FileSystemFilter(const std::string& file, IOSystem* old)
: mWrapped (old) : mWrapped (old)
, mSrc_file(file) , mSrc_file(file)
, sep(mWrapped->getOsSeparator()) { , mSep(mWrapped->getOsSeparator()) {
ai_assert(nullptr != mWrapped); ai_assert(nullptr != mWrapped);
// Determine base directory // Determine base directory
@ -116,7 +116,7 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the directory separator. */ /** Returns the directory separator. */
char getOsSeparator() const { char getOsSeparator() const {
return sep; return mSep;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -256,7 +256,7 @@ private:
while(true) { while(true) {
tmp = mBase; tmp = mBase;
tmp += sep; tmp += mSep;
std::string::size_type dirsep = in.rfind('/', last_dirsep); std::string::size_type dirsep = in.rfind('/', last_dirsep);
if (std::string::npos == dirsep) { if (std::string::npos == dirsep) {
@ -298,7 +298,7 @@ private:
in.erase(in.begin(),it+1); in.erase(in.begin(),it+1);
} }
const char sep = getOsSeparator(); const char separator = getOsSeparator();
for (it = in.begin(); it != in.end(); ++it) { for (it = in.begin(); it != in.end(); ++it) {
// Exclude :// and \\, which remain untouched. // Exclude :// and \\, which remain untouched.
// https://sourceforge.net/tracker/?func=detail&aid=3031725&group_id=226462&atid=1067632 // https://sourceforge.net/tracker/?func=detail&aid=3031725&group_id=226462&atid=1067632
@ -313,7 +313,7 @@ private:
// Cleanup path delimiters // Cleanup path delimiters
if (*it == '/' || (*it) == '\\') { if (*it == '/' || (*it) == '\\') {
*it = sep; *it = separator;
// And we're removing double delimiters, frequent issue with // And we're removing double delimiters, frequent issue with
// incorrectly composited paths ... // incorrectly composited paths ...
@ -337,7 +337,7 @@ private:
private: private:
IOSystem *mWrapped; IOSystem *mWrapped;
std::string mSrc_file, mBase; std::string mSrc_file, mBase;
char sep; char mSep;
}; };
} //!ns Assimp } //!ns Assimp

View File

@ -73,6 +73,7 @@ GenFaceNormalsProcess::~GenFaceNormalsProcess()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const { bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const {
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
return (pFlags & aiProcess_GenNormals) != 0; return (pFlags & aiProcess_GenNormals) != 0;
} }
@ -105,7 +106,8 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene) {
bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
{ {
if (NULL != pMesh->mNormals) { if (NULL != pMesh->mNormals) {
return false; if (force_) delete[] pMesh->mNormals;
else return false;
} }
// If the mesh consists of lines and/or points but not of // If the mesh consists of lines and/or points but not of
@ -134,7 +136,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize(); const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
for (unsigned int i = 0;i < face.mNumIndices;++i) { for (unsigned int i = 0;i < face.mNumIndices;++i) {
pMesh->mNormals[face.mIndices[i]] = vNor; pMesh->mNormals[face.mIndices[i]] = vNor;

View File

@ -78,7 +78,8 @@ public:
private: private:
bool GenMeshFaceNormals (aiMesh* pcMesh); bool GenMeshFaceNormals(aiMesh* pcMesh);
mutable bool force_ = false;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -72,6 +72,7 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() {
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
{ {
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
return (pFlags & aiProcess_GenSmoothNormals) != 0; return (pFlags & aiProcess_GenSmoothNormals) != 0;
} }
@ -113,8 +114,10 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex) bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
{ {
if (NULL != pMesh->mNormals) if (NULL != pMesh->mNormals) {
return false; if (force_) delete[] pMesh->mNormals;
else return false;
}
// If the mesh consists of lines and/or points but not of // If the mesh consists of lines and/or points but not of
// triangles or higher-order polygons the normal vectors // triangles or higher-order polygons the normal vectors
@ -146,7 +149,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)); const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
for (unsigned int i = 0;i < face.mNumIndices;++i) { for (unsigned int i = 0;i < face.mNumIndices;++i) {
pMesh->mNormals[face.mIndices[i]] = vNor; pMesh->mNormals[face.mIndices[i]] = vNor;
@ -214,17 +217,15 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound); vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
aiVector3D vr = pMesh->mNormals[i]; aiVector3D vr = pMesh->mNormals[i];
ai_real vrlen = vr.Length();
aiVector3D pcNor; aiVector3D pcNor;
for (unsigned int a = 0; a < verticesFound.size(); ++a) { for (unsigned int a = 0; a < verticesFound.size(); ++a) {
aiVector3D v = pMesh->mNormals[verticesFound[a]]; aiVector3D v = pMesh->mNormals[verticesFound[a]];
// check whether the angle between the two normals is not too large // Check whether the angle between the two normals is not too large.
// HACK: if v.x is qnan the dot product will become qnan, too // Skip the angle check on our own normal to avoid false negatives
// therefore the comparison against fLimit should be false // (v*v is not guaranteed to be 1.0 for all unit vectors v)
// in every case. if (is_not_qnan(v.x) && (verticesFound[a] == i || (v * vr >= fLimit)))
if (v * vr >= fLimit * vrlen * v.Length())
pcNor += v; pcNor += v;
} }
pcNew[i] = pcNor.NormalizeSafe(); pcNew[i] = pcNor.NormalizeSafe();

View File

@ -107,6 +107,7 @@ private:
/** Configuration option: maximum smoothing angle, in radians*/ /** Configuration option: maximum smoothing angle, in radians*/
ai_real configMaxAngle; ai_real configMaxAngle;
mutable bool force_ = false;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -383,6 +383,7 @@ bool _ValidateFlags(unsigned int pFlags)
void Importer::FreeScene( ) void Importer::FreeScene( )
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
delete pimpl->mScene; delete pimpl->mScene;
pimpl->mScene = NULL; pimpl->mScene = NULL;
@ -490,9 +491,9 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength)); SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength));
// read the file and recover the previous IOSystem // read the file and recover the previous IOSystem
static const size_t BufferSize(Importer::MaxLenHint + 28); static const size_t BufSize(Importer::MaxLenHint + 28);
char fbuff[ BufferSize ]; char fbuff[BufSize];
ai_snprintf(fbuff, BufferSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint); ai_snprintf(fbuff, BufSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
ReadFile(fbuff,pFlags); ReadFile(fbuff,pFlags);
SetIOHandler(io); SetIOHandler(io);
@ -930,20 +931,19 @@ BaseImporter* Importer::GetImporter (const char* szExtension) const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Find a loader plugin for a given file extension // Find a loader plugin for a given file extension
size_t Importer::GetImporterIndex (const char* szExtension) const size_t Importer::GetImporterIndex (const char* szExtension) const {
{ ai_assert(nullptr != szExtension);
ai_assert(szExtension);
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// skip over wildcard and dot characters at string head -- // skip over wildcard and dot characters at string head --
for(;*szExtension == '*' || *szExtension == '.'; ++szExtension); for ( ; *szExtension == '*' || *szExtension == '.'; ++szExtension );
std::string ext(szExtension); std::string ext(szExtension);
if (ext.empty()) { if (ext.empty()) {
return static_cast<size_t>(-1); return static_cast<size_t>(-1);
} }
std::transform(ext.begin(),ext.end(), ext.begin(), tolower); std::transform( ext.begin(), ext.end(), ext.begin(), ToLower<char> );
std::set<std::string> str; std::set<std::string> str;
for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) { for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
@ -970,6 +970,8 @@ void Importer::GetExtensionList(aiString& szOut) const
(*i)->GetExtensionList(str); (*i)->GetExtensionList(str);
} }
// List can be empty
if( !str.empty() ) {
for (std::set<std::string>::const_iterator it = str.begin();; ) { for (std::set<std::string>::const_iterator it = str.begin();; ) {
szOut.Append("*."); szOut.Append("*.");
szOut.Append((*it).c_str()); szOut.Append((*it).c_str());
@ -979,6 +981,7 @@ void Importer::GetExtensionList(aiString& szOut) const
} }
szOut.Append(";"); szOut.Append(";");
} }
}
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }

View File

@ -120,11 +120,11 @@ public:
SharedPostProcessInfo* mPPShared; SharedPostProcessInfo* mPPShared;
/// The default class constructor. /// The default class constructor.
ImporterPimpl(); ImporterPimpl() AI_NO_EXCEPT;
}; };
inline inline
ImporterPimpl::ImporterPimpl() ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT
: mIOHandler( nullptr ) : mIOHandler( nullptr )
, mIsDefaultHandler( false ) , mIsDefaultHandler( false )
, mProgressHandler( nullptr ) , mProgressHandler( nullptr )

View File

@ -317,7 +317,7 @@ void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, Tem
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid solid, TempMesh& result, ConversionData& conv) void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh& result, ConversionData& conv)
{ {
const Curve* const curve = Curve::Convert(*solid.Directrix, conv); const Curve* const curve = Curve::Convert(*solid.Directrix, conv);
if(!curve) { if(!curve) {

View File

@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Vertex.h> #include <assimp/Vertex.h>
#include <assimp/TinyFormatter.h> #include <assimp/TinyFormatter.h>
#include <stdio.h> #include <stdio.h>
#include <unordered_set>
using namespace Assimp; using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -239,6 +240,19 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
return 0; return 0;
} }
// We should care only about used vertices, not all of them
// (this can happen due to original file vertices buffer being used by
// multiple meshes)
std::unordered_set<unsigned int> usedVertexIndices;
usedVertexIndices.reserve(pMesh->mNumVertices);
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
aiFace& face = pMesh->mFaces[a];
for( unsigned int b = 0; b < face.mNumIndices; b++) {
usedVertexIndices.insert(face.mIndices[b]);
}
}
// We'll never have more vertices afterwards. // We'll never have more vertices afterwards.
std::vector<Vertex> uniqueVertices; std::vector<Vertex> uniqueVertices;
uniqueVertices.reserve( pMesh->mNumVertices); uniqueVertices.reserve( pMesh->mNumVertices);
@ -292,6 +306,10 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// Now check each vertex if it brings something new to the table // Now check each vertex if it brings something new to the table
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
if (usedVertexIndices.find(a) == usedVertexIndices.end()) {
continue;
}
// collect the vertex data // collect the vertex data
Vertex v(pMesh,a); Vertex v(pMesh,a);

View File

@ -113,14 +113,14 @@ enum PrePostBehaviour
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a LWO animation keyframe /** \brief Data structure for a LWO animation keyframe
*/ */
struct Key struct Key {
{ Key() AI_NO_EXCEPT
Key() : time()
: time(), , value()
value(), , inter(IT_LINE)
inter (IT_LINE), , params() {
params() // empty
{} }
//! Current time //! Current time
double time; double time;
@ -144,17 +144,16 @@ struct Key
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a LWO animation envelope /** \brief Data structure for a LWO animation envelope
*/ */
struct Envelope struct Envelope {
{ Envelope() AI_NO_EXCEPT
Envelope()
: index() : index()
, type (EnvelopeType_Unknown) , type(EnvelopeType_Unknown)
, pre (PrePostBehaviour_Constant) , pre(PrePostBehaviour_Constant)
, post (PrePostBehaviour_Constant) , post(PrePostBehaviour_Constant)
, old_first(0)
, old_first (0) , old_last(0) {
, old_last (0) // empty
{} }
//! Index of this envelope //! Index of this envelope
unsigned int index; unsigned int index;
@ -162,7 +161,7 @@ struct Envelope
//! Type of envelope //! Type of envelope
EnvelopeType type; EnvelopeType type;
//! Pre and post-behaviour //! Pre- and post-behavior
PrePostBehaviour pre,post; PrePostBehaviour pre,post;
//! Keyframes for this envelope //! Keyframes for this envelope

View File

@ -261,14 +261,14 @@ namespace LWO {
* \note We can't use the code in SmoothingGroups.inl here - the mesh * \note We can't use the code in SmoothingGroups.inl here - the mesh
* structures of 3DS/ASE and LWO are too different. * structures of 3DS/ASE and LWO are too different.
*/ */
struct Face : public aiFace struct Face : public aiFace {
{
//! Default construction //! Default construction
Face() Face() AI_NO_EXCEPT
: surfaceIndex (0) : surfaceIndex( 0 )
, smoothGroup (0) , smoothGroup( 0 )
, type (AI_LWO_FACE) , type( AI_LWO_FACE ) {
{} // empty
}
//! Construction from given type //! Construction from given type
explicit Face(uint32_t _type) explicit Face(uint32_t _type)

View File

@ -253,7 +253,8 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur)); pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
// setup the mapping mode // setup the mapping mode
pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur)); int mapping_ = static_cast<int>(mapping);
pcMat->AddProperty<int>(&mapping_, 1, AI_MATKEY_MAPPING(type, cur));
// add the u-wrapping // add the u-wrapping
temp = (unsigned int)GetMapMode(texture.wrapModeWidth); temp = (unsigned int)GetMapMode(texture.wrapModeWidth);
@ -365,7 +366,8 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
} }
if (surf.mMaximumSmoothAngle <= 0.0) if (surf.mMaximumSmoothAngle <= 0.0)
m = aiShadingMode_Flat; m = aiShadingMode_Flat;
pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL); int m_ = static_cast<int>(m);
pcMat->AddProperty(&m_, 1, AI_MATKEY_SHADING_MODEL);
// (the diffuse value is just a scaling factor) // (the diffuse value is just a scaling factor)
// If a diffuse texture is set, we set this value to 1.0 // If a diffuse texture is set, we set this value to 1.0

View File

@ -120,7 +120,7 @@ public:
{ {
unsigned int mBone; ///< Index of the bone unsigned int mBone; ///< Index of the bone
float mWeight; ///< Weight of that bone on this vertex float mWeight; ///< Weight of that bone on this vertex
Weight() Weight() AI_NO_EXCEPT
: mBone(0) : mBone(0)
, mWeight(0.0f) , mWeight(0.0f)
{ } { }

View File

@ -125,7 +125,7 @@ enum AlphaTestFunc
*/ */
struct ShaderMapBlock struct ShaderMapBlock
{ {
ShaderMapBlock() ShaderMapBlock() AI_NO_EXCEPT
: blend_src (BLEND_NONE) : blend_src (BLEND_NONE)
, blend_dest (BLEND_NONE) , blend_dest (BLEND_NONE)
, alpha_test (AT_NONE) , alpha_test (AT_NONE)
@ -150,7 +150,7 @@ struct ShaderMapBlock
*/ */
struct ShaderDataBlock struct ShaderDataBlock
{ {
ShaderDataBlock() ShaderDataBlock() AI_NO_EXCEPT
: cull (CULL_CW) : cull (CULL_CW)
{} {}

View File

@ -192,14 +192,14 @@ typedef std::vector< FrameDesc > FrameList;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Represents a vertex descriptor in a MD5 file /** Represents a vertex descriptor in a MD5 file
*/ */
struct VertexDesc struct VertexDesc {
{ VertexDesc() AI_NO_EXCEPT
VertexDesc() : mFirstWeight(0)
: mFirstWeight (0) , mNumWeights(0) {
, mNumWeights (0) // empty
{} }
//! UV cordinate of the vertex //! UV coordinate of the vertex
aiVector2D mUV; aiVector2D mUV;
//! Index of the first weight of the vertex in //! Index of the first weight of the vertex in

View File

@ -61,7 +61,6 @@ http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf
namespace Assimp { namespace Assimp {
namespace MDC { namespace MDC {
// to make it easier for us, we test the magic word against both "endianesses" // to make it easier for us, we test the magic word against both "endianesses"
#define AI_MDC_MAGIC_NUMBER_BE AI_MAKE_MAGIC("CPDI") #define AI_MDC_MAGIC_NUMBER_BE AI_MAKE_MAGIC("CPDI")
#define AI_MDC_MAGIC_NUMBER_LE AI_MAKE_MAGIC("IDPC") #define AI_MDC_MAGIC_NUMBER_LE AI_MAKE_MAGIC("IDPC")
@ -79,8 +78,7 @@ namespace MDC {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MDC file's main header /** \brief Data structure for a MDC file's main header
*/ */
struct Header struct Header {
{
uint32_t ulIdent ; uint32_t ulIdent ;
uint32_t ulVersion ; uint32_t ulVersion ;
char ucName [ AI_MDC_MAXQPATH ] ; char ucName [ AI_MDC_MAXQPATH ] ;
@ -100,8 +98,7 @@ struct Header
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MDC file's surface header /** \brief Data structure for a MDC file's surface header
*/ */
struct Surface struct Surface {
{
uint32_t ulIdent ; uint32_t ulIdent ;
char ucName [ AI_MDC_MAXQPATH ] ; char ucName [ AI_MDC_MAXQPATH ] ;
uint32_t ulFlags ; uint32_t ulFlags ;
@ -118,23 +115,22 @@ struct Surface
uint32_t ulOffsetFrameBaseFrames ; uint32_t ulOffsetFrameBaseFrames ;
uint32_t ulOffsetFrameCompFrames ; uint32_t ulOffsetFrameCompFrames ;
uint32_t ulOffsetEnd; uint32_t ulOffsetEnd;
Surface() Surface() AI_NO_EXCEPT
: ulIdent(), : ulIdent()
ulFlags(), , ulFlags()
ulNumCompFrames(), , ulNumCompFrames()
ulNumBaseFrames(), , ulNumBaseFrames()
ulNumShaders(), , ulNumShaders()
ulNumVertices(), , ulNumVertices()
ulNumTriangles(), , ulNumTriangles()
ulOffsetTriangles(), , ulOffsetTriangles()
ulOffsetShaders(), , ulOffsetShaders()
ulOffsetTexCoords(), , ulOffsetTexCoords()
ulOffsetBaseVerts(), , ulOffsetBaseVerts()
ulOffsetCompVerts(), , ulOffsetCompVerts()
ulOffsetFrameBaseFrames(), , ulOffsetFrameBaseFrames()
ulOffsetFrameCompFrames(), , ulOffsetFrameCompFrames()
ulOffsetEnd() , ulOffsetEnd() {
{
ucName[AI_MDC_MAXQPATH-1] = '\0'; ucName[AI_MDC_MAXQPATH-1] = '\0';
} }
} PACK_STRUCT; } PACK_STRUCT;
@ -142,8 +138,7 @@ struct Surface
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MDC frame /** \brief Data structure for a MDC frame
*/ */
struct Frame struct Frame {
{
//! bounding box minimum coords //! bounding box minimum coords
aiVector3D bboxMin ; aiVector3D bboxMin ;
@ -163,24 +158,21 @@ struct Frame
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MDC triangle /** \brief Data structure for a MDC triangle
*/ */
struct Triangle struct Triangle {
{
uint32_t aiIndices[3]; uint32_t aiIndices[3];
} PACK_STRUCT; } PACK_STRUCT;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MDC texture coordinate /** \brief Data structure for a MDC texture coordinate
*/ */
struct TexturCoord struct TexturCoord {
{
float u,v; float u,v;
} PACK_STRUCT; } PACK_STRUCT;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MDC base vertex /** \brief Data structure for a MDC base vertex
*/ */
struct BaseVertex struct BaseVertex {
{
int16_t x,y,z; int16_t x,y,z;
uint16_t normal; uint16_t normal;
} PACK_STRUCT; } PACK_STRUCT;
@ -188,25 +180,20 @@ struct BaseVertex
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MDC compressed vertex /** \brief Data structure for a MDC compressed vertex
*/ */
struct CompressedVertex struct CompressedVertex {
{
uint8_t xd,yd,zd,nd; uint8_t xd,yd,zd,nd;
} PACK_STRUCT; } PACK_STRUCT;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MDC shader /** \brief Data structure for a MDC shader
*/ */
struct Shader struct Shader {
{
char ucName [ AI_MDC_MAXQPATH ] ; char ucName [ AI_MDC_MAXQPATH ] ;
uint32_t ulPath; uint32_t ulPath;
} PACK_STRUCT; } PACK_STRUCT;
#include <assimp/Compiler/poppack1.h> #include <assimp/Compiler/poppack1.h>
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Build a floating point vertex from the compressed data in MDC files /** Build a floating point vertex from the compressed data in MDC files
*/ */
@ -215,6 +202,7 @@ void BuildVertex(const Frame& frame,
const CompressedVertex& cvert, const CompressedVertex& cvert,
aiVector3D& vXYZOut, aiVector3D& vXYZOut,
aiVector3D& vNorOut); aiVector3D& vNorOut);
}} }
}
#endif // !! AI_MDCFILEHELPER_H_INC #endif // !! AI_MDCFILEHELPER_H_INC

View File

@ -434,11 +434,13 @@ void MDCImporter::InternReadFile(
else if (1 == pScene->mNumMeshes) else if (1 == pScene->mNumMeshes)
{ {
pScene->mRootNode = new aiNode(); pScene->mRootNode = new aiNode();
if ( nullptr != pScene->mMeshes[0] ) {
pScene->mRootNode->mName = pScene->mMeshes[0]->mName; pScene->mRootNode->mName = pScene->mMeshes[0]->mName;
pScene->mRootNode->mNumMeshes = 1; pScene->mRootNode->mNumMeshes = 1;
pScene->mRootNode->mMeshes = new unsigned int[1]; pScene->mRootNode->mMeshes = new unsigned int[1];
pScene->mRootNode->mMeshes[0] = 0; pScene->mRootNode->mMeshes[0] = 0;
} }
}
else else
{ {
pScene->mRootNode = new aiNode(); pScene->mRootNode = new aiNode();

View File

@ -717,11 +717,9 @@ struct GroupFrame
*/ */
struct IntFace_MDL7 { struct IntFace_MDL7 {
// provide a constructor for our own convenience // provide a constructor for our own convenience
IntFace_MDL7() IntFace_MDL7() AI_NO_EXCEPT {
{ ::memset( mIndices, 0, sizeof(uint32_t) *3);
// set everything to zero ::memset( iMatIndex, 0, sizeof( unsigned int) *2);
mIndices[0] = mIndices[1] = mIndices[2] = 0;
iMatIndex[0] = iMatIndex[1] = 0;
} }
//! Vertex indices //! Vertex indices
@ -737,13 +735,11 @@ struct IntFace_MDL7 {
* which has been created from two single materials along with the * which has been created from two single materials along with the
* original material indices. * original material indices.
*/ */
struct IntMaterial_MDL7 struct IntMaterial_MDL7 {
{
// provide a constructor for our own convenience // provide a constructor for our own convenience
IntMaterial_MDL7() IntMaterial_MDL7() AI_NO_EXCEPT
{ : pcMat( nullptr ) {
pcMat = NULL; ::memset( iOldMatIndices, 0, sizeof(unsigned int) *2);
iOldMatIndices[0] = iOldMatIndices[1] = 0;
} }
//! Material instance //! Material instance
@ -761,7 +757,7 @@ struct IntMaterial_MDL7
struct IntBone_MDL7 : aiBone struct IntBone_MDL7 : aiBone
{ {
//! Default constructor //! Default constructor
IntBone_MDL7() : iParent (0xffff) IntBone_MDL7() AI_NO_EXCEPT : iParent (0xffff)
{ {
pkeyPositions.reserve(30); pkeyPositions.reserve(30);
pkeyScalings.reserve(30); pkeyScalings.reserve(30);
@ -806,12 +802,12 @@ struct IntFrameInfo_MDL7
struct IntGroupInfo_MDL7 struct IntGroupInfo_MDL7
{ {
//! Default constructor //! Default constructor
IntGroupInfo_MDL7() IntGroupInfo_MDL7() AI_NO_EXCEPT
: iIndex(0) : iIndex(0)
, pcGroup(NULL) , pcGroup(nullptr)
, pcGroupUVs(NULL) , pcGroupUVs(nullptr)
, pcGroupTris(NULL) , pcGroupTris(nullptr)
, pcGroupVerts(NULL) , pcGroupVerts(nullptr)
{} {}
//! Construction from an existing group header //! Construction from an existing group header
@ -843,7 +839,7 @@ struct IntGroupInfo_MDL7
//! Holds the data that belongs to a MDL7 mesh group //! Holds the data that belongs to a MDL7 mesh group
struct IntGroupData_MDL7 struct IntGroupData_MDL7
{ {
IntGroupData_MDL7() IntGroupData_MDL7() AI_NO_EXCEPT
: bNeed2UV(false) : bNeed2UV(false)
{} {}
@ -872,10 +868,9 @@ struct IntGroupData_MDL7
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
//! Holds data from an MDL7 file that is shared by all mesh groups //! Holds data from an MDL7 file that is shared by all mesh groups
struct IntSharedData_MDL7 struct IntSharedData_MDL7 {
{
//! Default constructor //! Default constructor
IntSharedData_MDL7() IntSharedData_MDL7() AI_NO_EXCEPT
: apcOutBones(), : apcOutBones(),
iNum() iNum()
{ {

View File

@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <utility> #include <utility>
#include "MMDPmxParser.h" #include "MMDPmxParser.h"
#include <assimp/StringUtils.h>
#include "../contrib/utf8cpp/source/utf8.h" #include "../contrib/utf8cpp/source/utf8.h"
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
@ -118,7 +119,7 @@ namespace pmx
stream->read((char*) &count, sizeof(uint8_t)); stream->read((char*) &count, sizeof(uint8_t));
if (count < 8) if (count < 8)
{ {
throw; throw DeadlyImportError("MMD: invalid size");
} }
stream->read((char*) &encoding, sizeof(uint8_t)); stream->read((char*) &encoding, sizeof(uint8_t));
stream->read((char*) &uv, sizeof(uint8_t)); stream->read((char*) &uv, sizeof(uint8_t));
@ -395,7 +396,7 @@ namespace pmx
} }
break; break;
default: default:
throw; throw DeadlyImportError("MMD: unknown morth type");
} }
} }
@ -476,7 +477,7 @@ namespace pmx
{ {
// 未実装 // 未実装
std::cerr << "Not Implemented Exception" << std::endl; std::cerr << "Not Implemented Exception" << std::endl;
throw; throw DeadlyImportError("MMD: Not Implemented Exception");
} }
void PmxModel::Init() void PmxModel::Init()
@ -516,14 +517,14 @@ namespace pmx
if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20) if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20)
{ {
std::cerr << "invalid magic number." << std::endl; std::cerr << "invalid magic number." << std::endl;
throw; throw DeadlyImportError("MMD: invalid magic number.");
} }
// バージョン // バージョン
stream->read((char*) &version, sizeof(float)); stream->read((char*) &version, sizeof(float));
if (version != 2.0f && version != 2.1f) if (version != 2.0f && version != 2.1f)
{ {
std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl; std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl;
throw; throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but " + to_string(version));
} }
// ファイル設定 // ファイル設定
this->setting.Read(stream); this->setting.Read(stream);
@ -605,34 +606,5 @@ namespace pmx
{ {
this->joints[i].Read(stream, &setting); this->joints[i].Read(stream, &setting);
} }
//if (this->version == 2.1f)
//{
// stream->read((char*) &this->soft_body_count, sizeof(int));
// this->soft_bodies = mmd::make_unique<PmxSoftBody []>(this->soft_body_count);
// for (int i = 0; i < this->soft_body_count; i++)
// {
// this->soft_bodies[i].Read(stream, &setting);
// }
//}
} }
//std::unique_ptr<PmxModel> ReadFromFile(const char *filename)
//{
// auto stream = std::ifstream(filename, std::ios_base::binary);
// auto pmx = PmxModel::ReadFromStream(&stream);
// if (!stream.eof())
// {
// std::cerr << "don't reach the end of file." << std::endl;
// }
// stream.close();
// return pmx;
//}
//std::unique_ptr<PmxModel> ReadFromStream(std::istream *stream)
//{
// auto pmx = mmd::make_unique<PmxModel>();
// pmx->Read(stream);
// return pmx;
//}
} }

View File

@ -63,9 +63,9 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
unsigned int index, unsigned int index,
const aiMaterialProperty** pPropOut) const aiMaterialProperty** pPropOut)
{ {
ai_assert (pMat != NULL); ai_assert( pMat != NULL );
ai_assert (pKey != NULL); ai_assert( pKey != NULL );
ai_assert (pPropOut != NULL); ai_assert( pPropOut != NULL );
/* Just search for a property with exactly this name .. /* Just search for a property with exactly this name ..
* could be improved by hashing, but it's possibly * could be improved by hashing, but it's possibly
@ -76,7 +76,7 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
if (prop /* just for safety ... */ if (prop /* just for safety ... */
&& 0 == strcmp( prop->mKey.data, pKey ) && 0 == strcmp( prop->mKey.data, pKey )
&& (UINT_MAX == type || prop->mSemantic == type) /* UINT_MAX is a wildcard, but this is undocumented :-) */ && (UINT_MAX == type || prop->mSemantic == type) /* UINT_MAX is a wild-card, but this is undocumented :-) */
&& (UINT_MAX == index || prop->mIndex == index)) && (UINT_MAX == index || prop->mIndex == index))
{ {
*pPropOut = pMat->mProperties[i]; *pPropOut = pMat->mProperties[i];
@ -96,8 +96,8 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
ai_real* pOut, ai_real* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
ai_assert (pOut != NULL); ai_assert( pOut != NULL );
ai_assert (pMat != NULL); ai_assert( pMat != NULL );
const aiMaterialProperty* prop; const aiMaterialProperty* prop;
aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop); aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop);
@ -182,8 +182,8 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
int* pOut, int* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
ai_assert (pOut != NULL); ai_assert( pOut != NULL );
ai_assert (pMat != NULL); ai_assert( pMat != NULL );
const aiMaterialProperty* prop; const aiMaterialProperty* prop;
aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop); aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop);
@ -314,7 +314,7 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get the number of textures on a particular texture stack // Get the number of textures on a particular texture stack
ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat, unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat,
C_ENUM aiTextureType type) C_ENUM aiTextureType type)
{ {
ai_assert (pMat != NULL); ai_assert (pMat != NULL);
@ -347,15 +347,18 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
unsigned int* flags /*= NULL*/ unsigned int* flags /*= NULL*/
) )
{ {
ai_assert(NULL != mat && NULL != path); ai_assert( NULL != mat );
ai_assert( NULL != path );
// Get the path to the texture // Get the path to the texture
if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path)) { if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path)) {
return AI_FAILURE; return AI_FAILURE;
} }
// Determine mapping type // Determine mapping type
aiTextureMapping mapping = aiTextureMapping_UV; int mapping_ = static_cast<int>(aiTextureMapping_UV);
aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping); aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index), &mapping_);
aiTextureMapping mapping = static_cast<aiTextureMapping>(mapping_);
if (_mapping) if (_mapping)
*_mapping = mapping; *_mapping = mapping;
@ -380,15 +383,17 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
if (flags){ if (flags){
aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags); aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags);
} }
return AI_SUCCESS; return AI_SUCCESS;
} }
static const unsigned int DefaultNumAllocated = 5; static const unsigned int DefaultNumAllocated = 5;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Construction. Actually the one and only way to get an aiMaterial instance // Construction. Actually the one and only way to get an aiMaterial instance
aiMaterial::aiMaterial() aiMaterial::aiMaterial()
: mProperties( NULL ) : mProperties( nullptr )
, mNumProperties( 0 ) , mNumProperties( 0 )
, mNumAllocated( DefaultNumAllocated ) { , mNumAllocated( DefaultNumAllocated ) {
// Allocate 5 entries by default // Allocate 5 entries by default
@ -403,12 +408,20 @@ aiMaterial::~aiMaterial()
delete[] mProperties; delete[] mProperties;
} }
// ------------------------------------------------------------------------------------------------
aiString aiMaterial::GetName() {
aiString name;
Get(AI_MATKEY_NAME, name);
return name;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void aiMaterial::Clear() void aiMaterial::Clear()
{ {
for (unsigned int i = 0; i < mNumProperties;++i) { for ( unsigned int i = 0; i < mNumProperties; ++i ) {
// delete this entry // delete this entry
delete mProperties[i]; delete mProperties[ i ];
AI_DEBUG_INVALIDATE_PTR(mProperties[i]); AI_DEBUG_INVALIDATE_PTR(mProperties[i]);
} }
mNumProperties = 0; mNumProperties = 0;
@ -417,11 +430,9 @@ void aiMaterial::Clear()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn aiMaterial::RemoveProperty (const char* pKey,unsigned int type, aiReturn aiMaterial::RemoveProperty ( const char* pKey,unsigned int type, unsigned int index )
unsigned int index
)
{ {
ai_assert(NULL != pKey); ai_assert( nullptr != pKey );
for (unsigned int i = 0; i < mNumProperties;++i) { for (unsigned int i = 0; i < mNumProperties;++i) {
aiMaterialProperty* prop = mProperties[i]; aiMaterialProperty* prop = mProperties[i];
@ -453,17 +464,18 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
aiPropertyTypeInfo pType aiPropertyTypeInfo pType
) )
{ {
ai_assert (pInput != NULL); ai_assert( pInput != NULL );
ai_assert (pKey != NULL); ai_assert( pKey != NULL );
ai_assert (0 != pSizeInBytes); ai_assert( 0 != pSizeInBytes );
if ( 0 == pSizeInBytes ) { if ( 0 == pSizeInBytes ) {
} }
// first search the list whether there is already an entry with this key // first search the list whether there is already an entry with this key
unsigned int iOutIndex = UINT_MAX; unsigned int iOutIndex( UINT_MAX );
for (unsigned int i = 0; i < mNumProperties;++i) { for ( unsigned int i = 0; i < mNumProperties; ++i ) {
aiMaterialProperty* prop = mProperties[i]; aiMaterialProperty *prop( mProperties[ i ] );
if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) && if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) &&
prop->mSemantic == type && prop->mIndex == index){ prop->mSemantic == type && prop->mIndex == index){
@ -515,6 +527,7 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
} }
// push back ... // push back ...
mProperties[mNumProperties++] = pcNew; mProperties[mNumProperties++] = pcNew;
return AI_SUCCESS; return AI_SUCCESS;
} }

View File

@ -76,41 +76,36 @@ using namespace std;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Default constructor // Default constructor
ObjFileImporter::ObjFileImporter() : ObjFileImporter::ObjFileImporter()
m_Buffer(), : m_Buffer()
m_pRootObject( NULL ), , m_pRootObject( nullptr )
m_strAbsPath( "" ) , m_strAbsPath( "" ) {
{
DefaultIOSystem io; DefaultIOSystem io;
m_strAbsPath = io.getOsSeparator(); m_strAbsPath = io.getOsSeparator();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor. // Destructor.
ObjFileImporter::~ObjFileImporter() ObjFileImporter::~ObjFileImporter() {
{
delete m_pRootObject; delete m_pRootObject;
m_pRootObject = NULL; m_pRootObject = nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns true, if file is an obj file. // Returns true, if file is an obj file.
bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const {
{ if(!checkSig) {
if(!checkSig) //Check File Extension //Check File Extension
{
return SimpleExtensionCheck(pFile,"obj"); return SimpleExtensionCheck(pFile,"obj");
} } else {
else //Check file Header // Check file Header
{
static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " }; static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 ); return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9, 200, false, true );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiImporterDesc* ObjFileImporter::GetInfo () const const aiImporterDesc* ObjFileImporter::GetInfo () const {
{
return &desc; return &desc;
} }
@ -215,22 +210,80 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
ai_assert(false); ai_assert(false);
} }
if (pModel->m_Objects.size() > 0) {
unsigned int meshCount = 0;
unsigned int childCount = 0;
for(size_t index = 0; index < pModel->m_Objects.size(); ++index) {
if(pModel->m_Objects[index]) {
++childCount;
meshCount += (unsigned int)pModel->m_Objects[index]->m_Meshes.size();
}
}
// Allocate space for the child nodes on the root node
pScene->mRootNode->mChildren = new aiNode*[ childCount ];
// Create nodes for the whole scene // Create nodes for the whole scene
std::vector<aiMesh*> MeshArray; std::vector<aiMesh*> MeshArray;
for (size_t index = 0; index < pModel->m_Objects.size(); ++index ) { MeshArray.reserve(meshCount);
createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray); for (size_t index = 0; index < pModel->m_Objects.size(); ++index) {
createNodes(pModel, pModel->m_Objects[index], pScene->mRootNode, pScene, MeshArray);
} }
ai_assert(pScene->mRootNode->mNumChildren == childCount);
// Create mesh pointer buffer for this scene // Create mesh pointer buffer for this scene
if (pScene->mNumMeshes > 0) { if (pScene->mNumMeshes > 0) {
pScene->mMeshes = new aiMesh*[ MeshArray.size() ]; pScene->mMeshes = new aiMesh*[MeshArray.size()];
for (size_t index =0; index < MeshArray.size(); ++index ) { for (size_t index = 0; index < MeshArray.size(); ++index) {
pScene->mMeshes[ index ] = MeshArray[ index ]; pScene->mMeshes[index] = MeshArray[index];
} }
} }
// Create all materials // Create all materials
createMaterials( pModel, pScene ); createMaterials(pModel, pScene);
}else {
if (pModel->m_Vertices.empty()){
return;
}
std::unique_ptr<aiMesh> mesh( new aiMesh );
mesh->mPrimitiveTypes = aiPrimitiveType_POINT;
unsigned int n = pModel->m_Vertices.size();
mesh->mNumVertices = n;
mesh->mVertices = new aiVector3D[n];
memcpy(mesh->mVertices, pModel->m_Vertices.data(), n*sizeof(aiVector3D) );
if ( !pModel->m_Normals.empty() ) {
mesh->mNormals = new aiVector3D[n];
if (pModel->m_Normals.size() < n) {
throw DeadlyImportError("OBJ: vertex normal index out of range");
}
memcpy(mesh->mNormals, pModel->m_Normals.data(), n*sizeof(aiVector3D));
}
if ( !pModel->m_VertexColors.empty() ){
mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
for (unsigned int i = 0; i < n; ++i) {
if (i < pModel->m_VertexColors.size() ) {
const aiVector3D& color = pModel->m_VertexColors[i];
mesh->mColors[0][i] = aiColor4D(color.x, color.y, color.z, 1.0);
}else {
throw DeadlyImportError("OBJ: vertex color index out of range");
}
}
}
pScene->mRootNode->mNumMeshes = 1;
pScene->mRootNode->mMeshes = new unsigned int[1];
pScene->mRootNode->mMeshes[0] = 0;
pScene->mMeshes = new aiMesh*[1];
pScene->mNumMeshes = 1;
pScene->mMeshes[0] = mesh.release();
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -251,9 +304,8 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
pNode->mName = pObject->m_strObjName; pNode->mName = pObject->m_strObjName;
// If we have a parent node, store it // If we have a parent node, store it
if( pParent != NULL ) { ai_assert( NULL != pParent );
appendChildToParentNode( pParent, pNode ); appendChildToParentNode( pParent, pNode );
}
for ( size_t i=0; i< pObject->m_Meshes.size(); ++i ) { for ( size_t i=0; i< pObject->m_Meshes.size(); ++i ) {
unsigned int meshId = pObject->m_Meshes[ i ]; unsigned int meshId = pObject->m_Meshes[ i ];
@ -406,8 +458,8 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
pMesh->mNumVertices = numIndices; pMesh->mNumVertices = numIndices;
if (pMesh->mNumVertices == 0) { if (pMesh->mNumVertices == 0) {
throw DeadlyImportError( "OBJ: no vertices" ); throw DeadlyImportError( "OBJ: no vertices" );
} else if (pMesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) { } else if (pMesh->mNumVertices > AI_MAX_VERTICES) {
throw DeadlyImportError( "OBJ: Too many vertices, would run out of memory" ); throw DeadlyImportError( "OBJ: Too many vertices" );
} }
pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ]; pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
@ -457,7 +509,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
// Copy all vertex colors // Copy all vertex colors
if ( !pModel->m_VertexColors.empty()) if ( !pModel->m_VertexColors.empty())
{ {
const aiVector3D color = pModel->m_VertexColors[ vertex ]; const aiVector3D& color = pModel->m_VertexColors[ vertex ];
pMesh->mColors[0][ newIndex ] = aiColor4D(color.x, color.y, color.z, 1.0); pMesh->mColors[0][ newIndex ] = aiColor4D(color.x, color.y, color.z, 1.0);
} }
@ -734,25 +786,8 @@ void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
// Assign parent to child // Assign parent to child
pChild->mParent = pParent; pChild->mParent = pParent;
// If already children was assigned to the parent node, store them in a
std::vector<aiNode*> temp;
if (pParent->mChildren != NULL)
{
ai_assert( 0 != pParent->mNumChildren );
for (size_t index = 0; index < pParent->mNumChildren; index++)
{
temp.push_back(pParent->mChildren [ index ] );
}
delete [] pParent->mChildren;
}
// Copy node instances into parent node // Copy node instances into parent node
pParent->mNumChildren++; pParent->mNumChildren++;
pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
for (size_t index = 0; index < pParent->mNumChildren-1; index++)
{
pParent->mChildren[ index ] = temp [ index ];
}
pParent->mChildren[ pParent->mNumChildren-1 ] = pChild; pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
} }

View File

@ -84,8 +84,6 @@ static const std::string BumpOption = "-bm";
static const std::string ChannelOption = "-imfchan"; static const std::string ChannelOption = "-imfchan";
static const std::string TypeOption = "-type"; static const std::string TypeOption = "-type";
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Constructor // Constructor
ObjFileMtlImporter::ObjFileMtlImporter( std::vector<char> &buffer, ObjFileMtlImporter::ObjFileMtlImporter( std::vector<char> &buffer,
@ -334,6 +332,11 @@ void ObjFileMtlImporter::getTexture() {
// Specular texture // Specular texture
out = & m_pModel->m_pCurrentMaterial->textureSpecular; out = & m_pModel->m_pCurrentMaterial->textureSpecular;
clampIndex = ObjFile::Material::TextureSpecularType; clampIndex = ObjFile::Material::TextureSpecularType;
} else if ( !ASSIMP_strincmp( pPtr, DisplacementTexture1.c_str(), static_cast<unsigned int>(DisplacementTexture1.size()) ) ||
!ASSIMP_strincmp( pPtr, DisplacementTexture2.c_str(), static_cast<unsigned int>(DisplacementTexture2.size()) ) ) {
// Displacement texture
out = &m_pModel->m_pCurrentMaterial->textureDisp;
clampIndex = ObjFile::Material::TextureDispType;
} else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), static_cast<unsigned int>(OpacityTexture.size()) ) ) { } else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), static_cast<unsigned int>(OpacityTexture.size()) ) ) {
// Opacity texture // Opacity texture
out = & m_pModel->m_pCurrentMaterial->textureOpacity; out = & m_pModel->m_pCurrentMaterial->textureOpacity;
@ -356,11 +359,6 @@ void ObjFileMtlImporter::getTexture() {
// Reflection texture(s) // Reflection texture(s)
//Do nothing here //Do nothing here
return; return;
} else if ( !ASSIMP_strincmp( pPtr, DisplacementTexture1.c_str(), static_cast<unsigned int>(DisplacementTexture1.size()) ) ||
!ASSIMP_strincmp( pPtr, DisplacementTexture2.c_str(), static_cast<unsigned int>(DisplacementTexture2.size()) ) ) {
// Displacement texture
out = &m_pModel->m_pCurrentMaterial->textureDisp;
clampIndex = ObjFile::Material::TextureDispType;
} else if ( !ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(), static_cast<unsigned int>(SpecularityTexture.size()) ) ) { } else if ( !ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(), static_cast<unsigned int>(SpecularityTexture.size()) ) ) {
// Specularity scaling (glossiness) // Specularity scaling (glossiness)
out = & m_pModel->m_pCurrentMaterial->textureSpecularity; out = & m_pModel->m_pCurrentMaterial->textureSpecularity;

View File

@ -67,20 +67,22 @@ namespace Assimp {
class OptimizeMeshesProcess : public BaseProcess class OptimizeMeshesProcess : public BaseProcess
{ {
public: public:
/// @brief The class constructor.
OptimizeMeshesProcess(); OptimizeMeshesProcess();
/// @brief The class destcructor,
~OptimizeMeshesProcess(); ~OptimizeMeshesProcess();
/** @brief Internal utility to store additional mesh info /** @brief Internal utility to store additional mesh info
*/ */
struct MeshInfo struct MeshInfo {
{ MeshInfo() AI_NO_EXCEPT
MeshInfo() : instance_cnt(0)
: instance_cnt (0) , vertex_format(0)
, vertex_format (0) , output_id(0xffffffff) {
, output_id (0xffffffff) // empty
{} }
//! Number of times this mesh is referenced //! Number of times this mesh is referenced
unsigned int instance_cnt; unsigned int instance_cnt;

View File

@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
using namespace Assimp; using namespace ::Assimp;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"Stanford Polygon Library (PLY) Importer", "Stanford Polygon Library (PLY) Importer",
@ -73,13 +73,12 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Internal stuff // Internal stuff
namespace namespace {
{
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Checks that property index is within range // Checks that property index is within range
template <class T> template <class T>
const T &GetProperty(const std::vector<T> &props, int idx) inline
{ const T &GetProperty(const std::vector<T> &props, int idx) {
if (static_cast<size_t>(idx) >= props.size()) { if (static_cast<size_t>(idx) >= props.size()) {
throw DeadlyImportError("Invalid .ply file: Property index is out of range."); throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
} }
@ -88,7 +87,6 @@ namespace
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
PLYImporter::PLYImporter() PLYImporter::PLYImporter()
@ -129,7 +127,7 @@ const aiImporterDesc* PLYImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static bool isBigEndian(const char* szMe) { static bool isBigEndian(const char* szMe) {
ai_assert(NULL != szMe); ai_assert(nullptr != szMe);
// binary_little_endian // binary_little_endian
// binary_big_endian // binary_big_endian
@ -150,7 +148,7 @@ static bool isBigEndian(const char* szMe) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
static const std::string mode = "rb"; const std::string mode = "rb";
std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode)); std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode));
if (!fileStream.get()) { if (!fileStream.get()) {
throw DeadlyImportError("Failed to open file " + pFile + "."); throw DeadlyImportError("Failed to open file " + pFile + ".");
@ -184,7 +182,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
char* szMe = (char*)&this->mBuffer[0]; char* szMe = (char*)&this->mBuffer[0];
SkipSpacesAndLineEnd(szMe, (const char**)&szMe); SkipSpacesAndLineEnd(szMe, (const char**)&szMe);
// determine the format of the file data and construct the aimesh // determine the format of the file data and construct the aiMesh
PLY::DOM sPlyDom; PLY::DOM sPlyDom;
this->pcDOM = &sPlyDom; this->pcDOM = &sPlyDom;
@ -192,7 +190,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
if (TokenMatch(szMe, "ascii", 5)) { if (TokenMatch(szMe, "ascii", 5)) {
SkipLine(szMe, (const char**)&szMe); SkipLine(szMe, (const char**)&szMe);
if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) { if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) {
if (mGeneratedMesh != NULL) { if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh); delete(mGeneratedMesh);
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
} }
@ -206,7 +204,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
// skip the line, parse the rest of the header and build the DOM // skip the line, parse the rest of the header and build the DOM
if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) { if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) {
if (mGeneratedMesh != NULL) { if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh); delete(mGeneratedMesh);
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
} }
@ -215,7 +213,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)"); throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)");
} }
} else { } else {
if (mGeneratedMesh != NULL) { if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh); delete(mGeneratedMesh);
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
} }
@ -225,7 +223,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
} }
} else { } else {
AI_DEBUG_INVALIDATE_PTR(this->mBuffer); AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
if (mGeneratedMesh != NULL) { if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh); delete(mGeneratedMesh);
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
} }
@ -237,13 +235,13 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
//free the file buffer //free the file buffer
streamedBuffer.close(); streamedBuffer.close();
if (mGeneratedMesh == NULL) { if (mGeneratedMesh == nullptr) {
throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data "); throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data ");
} }
// if no face list is existing we assume that the vertex // if no face list is existing we assume that the vertex
// list is containing a list of points // list is containing a list of points
bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false; bool pointsOnly = mGeneratedMesh->mFaces == nullptr ? true : false;
if (pointsOnly) { if (pointsOnly) {
mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT; mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT;
} }
@ -277,8 +275,8 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
} }
void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) { void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) {
ai_assert(NULL != pcElement); ai_assert(nullptr != pcElement);
ai_assert(NULL != instElement); ai_assert(nullptr != instElement);
ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char }; PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
@ -416,7 +414,7 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
haveColor = true; haveColor = true;
} }
// assume 1.0 for the alpha channel ifit is not set // assume 1.0 for the alpha channel if it is not set
if (0xFFFFFFFF == aiColors[3]) { if (0xFFFFFFFF == aiColors[3]) {
cOut.a = 1.0; cOut.a = 1.0;
} else { } else {
@ -481,13 +479,11 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert a color component to [0...1] // Convert a color component to [0...1]
ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType) { ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType) {
switch (eType) switch (eType) {
{
case EDT_Float: case EDT_Float:
return val.fFloat; return val.fFloat;
case EDT_Double: case EDT_Double:
return (ai_real)val.fDouble; return (ai_real)val.fDouble;
case EDT_UChar: case EDT_UChar:
return (ai_real)val.iUInt / (ai_real)0xFF; return (ai_real)val.iUInt / (ai_real)0xFF;
case EDT_Char: case EDT_Char:
@ -500,20 +496,23 @@ ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val,
return (ai_real)val.iUInt / (ai_real)0xFFFF; return (ai_real)val.iUInt / (ai_real)0xFFFF;
case EDT_Int: case EDT_Int:
return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f; return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
default:; default:
}; break;
}
return 0.0f; return 0.0f;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Try to extract proper faces from the PLY DOM // Try to extract proper faces from the PLY DOM
void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement,
{ unsigned int pos) {
ai_assert(NULL != pcElement); ai_assert(nullptr != pcElement);
ai_assert(NULL != instElement); ai_assert(nullptr != instElement);
if (mGeneratedMesh == NULL) if (mGeneratedMesh == nullptr) {
throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces"); throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces");
}
bool bOne = false; bool bOne = false;
@ -531,35 +530,24 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
PLY::EDataType eType3 = EDT_Char; PLY::EDataType eType3 = EDT_Char;
// face = unique number of vertex indices // face = unique number of vertex indices
if (PLY::EEST_Face == pcElement->eSemantic) if (PLY::EEST_Face == pcElement->eSemantic) {
{
unsigned int _a = 0; unsigned int _a = 0;
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin(); for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
a != pcElement->alProperties.end(); ++a, ++_a) a != pcElement->alProperties.end(); ++a, ++_a) {
{ if (PLY::EST_VertexIndex == (*a).Semantic) {
if (PLY::EST_VertexIndex == (*a).Semantic)
{
// must be a dynamic list! // must be a dynamic list!
if (!(*a).bIsList) if (!(*a).bIsList) {
continue; continue;
}
iProperty = _a; iProperty = _a;
bOne = true; bOne = true;
eType = (*a).eType; eType = (*a).eType;
} } else if (PLY::EST_TextureCoordinates == (*a).Semantic) {
/*else if (PLY::EST_MaterialIndex == (*a).Semantic)
{
if ((*a).bIsList)
continue;
iMaterialIndex = _a;
bOne = true;
eType2 = (*a).eType;
}*/
else if (PLY::EST_TextureCoordinates == (*a).Semantic)
{
// must be a dynamic list! // must be a dynamic list!
if (!(*a).bIsList) if (!(*a).bIsList) {
continue; continue;
}
iTextureCoord = _a; iTextureCoord = _a;
bOne = true; bOne = true;
eType3 = (*a).eType; eType3 = (*a).eType;
@ -568,15 +556,14 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
} }
// triangle strip // triangle strip
// TODO: triangle strip and material index support??? // TODO: triangle strip and material index support???
else if (PLY::EEST_TriStrip == pcElement->eSemantic) else if (PLY::EEST_TriStrip == pcElement->eSemantic) {
{
unsigned int _a = 0; unsigned int _a = 0;
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin(); for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
a != pcElement->alProperties.end(); ++a, ++_a) a != pcElement->alProperties.end(); ++a, ++_a) {
{
// must be a dynamic list! // must be a dynamic list!
if (!(*a).bIsList) if (!(*a).bIsList) {
continue; continue;
}
iProperty = _a; iProperty = _a;
bOne = true; bOne = true;
bIsTriStrip = true; bIsTriStrip = true;
@ -586,19 +573,15 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
} }
// check whether we have at least one per-face information set // check whether we have at least one per-face information set
if (bOne) if (bOne) {
{ if (mGeneratedMesh->mFaces == nullptr) {
if (mGeneratedMesh->mFaces == NULL)
{
mGeneratedMesh->mNumFaces = pcElement->NumOccur; mGeneratedMesh->mNumFaces = pcElement->NumOccur;
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
} }
if (!bIsTriStrip) if (!bIsTriStrip) {
{
// parse the list of vertex indices // parse the list of vertex indices
if (0xFFFFFFFF != iProperty) if (0xFFFFFFFF != iProperty) {
{
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size(); const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size();
mGeneratedMesh->mFaces[pos].mNumIndices = iNum; mGeneratedMesh->mFaces[pos].mNumIndices = iNum;
mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum]; mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
@ -606,8 +589,7 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p = std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
GetProperty(instElement->alProperties, iProperty).avList.begin(); GetProperty(instElement->alProperties, iProperty).avList.begin();
for (unsigned int a = 0; a < iNum; ++a, ++p) for (unsigned int a = 0; a < iNum; ++a, ++p) {
{
mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType); mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType);
} }
} }
@ -620,8 +602,7 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2); GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
}*/ }*/
if (0xFFFFFFFF != iTextureCoord) if (0xFFFFFFFF != iTextureCoord) {
{
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size(); const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
//should be 6 coords //should be 6 coords
@ -630,30 +611,26 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
if ((iNum / 3) == 2) // X Y coord if ((iNum / 3) == 2) // X Y coord
{ {
for (unsigned int a = 0; a < iNum; ++a, ++p) for (unsigned int a = 0; a < iNum; ++a, ++p) {
{
unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2]; unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2];
if (vindex < mGeneratedMesh->mNumVertices) if (vindex < mGeneratedMesh->mNumVertices) {
{ if (mGeneratedMesh->mTextureCoords[0] == nullptr ) {
if (mGeneratedMesh->mTextureCoords[0] == NULL)
{
mGeneratedMesh->mNumUVComponents[0] = 2; mGeneratedMesh->mNumUVComponents[0] = 2;
mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices]; mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
} }
if (a % 2 == 0) if (a % 2 == 0) {
mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3); mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
else } else {
mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3); mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
}
mGeneratedMesh->mTextureCoords[0][vindex].z = 0; mGeneratedMesh->mTextureCoords[0][vindex].z = 0;
} }
} }
} }
} }
} } else { // triangle strips
else // triangle strips
{
// normally we have only one triangle strip instance where // normally we have only one triangle strip instance where
// a value of -1 indicates a restart of the strip // a value of -1 indicates a restart of the strip
bool flip = false; bool flip = false;
@ -679,8 +656,7 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
continue; continue;
} }
if (mGeneratedMesh->mFaces == NULL) if (mGeneratedMesh->mFaces == nullptr) {
{
mGeneratedMesh->mNumFaces = pcElement->NumOccur; mGeneratedMesh->mNumFaces = pcElement->NumOccur;
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
} }
@ -691,7 +667,9 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1]; mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1];
mGeneratedMesh->mFaces[pos].mIndices[2] = p; mGeneratedMesh->mFaces[pos].mIndices[2] = p;
if ((flip = !flip)) { // every second pass swap the indices.
flip = !flip;
if ( flip ) {
std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]); std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]);
} }

View File

@ -209,7 +209,7 @@ enum EElementSemantic {
class Property { class Property {
public: public:
//! Default constructor //! Default constructor
Property() Property() AI_NO_EXCEPT
: eType (EDT_Int) : eType (EDT_Int)
, Semantic() , Semantic()
, bIsList(false) , bIsList(false)
@ -257,7 +257,7 @@ public:
class Element { class Element {
public: public:
//! Default constructor //! Default constructor
Element() Element() AI_NO_EXCEPT
: eSemantic (EEST_INVALID) : eSemantic (EEST_INVALID)
, NumOccur(0) { , NumOccur(0) {
// empty // empty
@ -297,8 +297,9 @@ class PropertyInstance
public: public:
//! Default constructor //! Default constructor
PropertyInstance () PropertyInstance() AI_NO_EXCEPT {
{} // empty
}
union ValueUnion union ValueUnion
{ {
@ -356,13 +357,13 @@ public:
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
/** \brief Class for an element instance in a PLY file /** \brief Class for an element instance in a PLY file
*/ */
class ElementInstance class ElementInstance {
{
public: public:
//! Default constructor //! Default constructor
ElementInstance () ElementInstance() AI_NO_EXCEPT
{} : alProperties() {
// empty
}
//! List of all parsed properties //! List of all parsed properties
std::vector< PropertyInstance > alProperties; std::vector< PropertyInstance > alProperties;
@ -386,8 +387,10 @@ class ElementInstanceList
public: public:
//! Default constructor //! Default constructor
ElementInstanceList () ElementInstanceList() AI_NO_EXCEPT
{} : alInstances() {
// empty
}
//! List of all element instances //! List of all element instances
std::vector< ElementInstance > alInstances; std::vector< ElementInstance > alInstances;
@ -411,8 +414,11 @@ class DOM
public: public:
//! Default constructor //! Default constructor
DOM() DOM() AI_NO_EXCEPT
{} : alElements()
, alElementData() {
}
//! Contains all elements of the file format //! Contains all elements of the file format

View File

@ -164,9 +164,6 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
#if (!defined ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS) #if (!defined ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
out.push_back( new OptimizeGraphProcess()); out.push_back( new OptimizeGraphProcess());
#endif #endif
#if (!defined ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS)
out.push_back( new FindDegeneratesProcess());
#endif
#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS #ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
out.push_back( new ComputeUVMappingProcess()); out.push_back( new ComputeUVMappingProcess());
#endif #endif
@ -179,6 +176,12 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
#if (!defined ASSIMP_BUILD_NO_TRIANGULATE_PROCESS) #if (!defined ASSIMP_BUILD_NO_TRIANGULATE_PROCESS)
out.push_back( new TriangulateProcess()); out.push_back( new TriangulateProcess());
#endif #endif
#if (!defined ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS)
//find degenerates should run after triangulation (to sort out small
//generated triangles) but before sort by p types (in case there are lines
//and points generated and inserted into a mesh)
out.push_back( new FindDegeneratesProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS) #if (!defined ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS)
out.push_back( new SortByPTypeProcess()); out.push_back( new SortByPTypeProcess());
#endif #endif

View File

@ -63,16 +63,16 @@ struct aiNode;
#include <vector> #include <vector>
namespace Assimp { namespace Assimp {
namespace SMD { namespace SMD {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Data structure for a vertex in a SMD file /** Data structure for a vertex in a SMD file
*/ */
struct Vertex struct Vertex {
{ Vertex() AI_NO_EXCEPT
Vertex() : iParentNode(UINT_MAX) : iParentNode(UINT_MAX) {
{} // empty
}
//! Vertex position, normal and texture coordinate //! Vertex position, normal and texture coordinate
aiVector3D pos,nor,uv; aiVector3D pos,nor,uv;
@ -90,10 +90,12 @@ struct Vertex
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Data structure for a face in a SMD file /** Data structure for a face in a SMD file
*/ */
struct Face struct Face {
{ Face() AI_NO_EXCEPT
Face() : iTexture(0x0) : iTexture(0x0)
{} , avVertices{} {
// empty
}
//! Texture index for the face //! Texture index for the face
unsigned int iTexture; unsigned int iTexture;
@ -105,11 +107,12 @@ struct Face
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Data structure for a bone in a SMD file /** Data structure for a bone in a SMD file
*/ */
struct Bone struct Bone {
{
//! Default constructor //! Default constructor
Bone() : iParent(UINT_MAX), bIsUsed(false) Bone() AI_NO_EXCEPT
{ : iParent(UINT_MAX)
, bIsUsed(false) {
// empty
} }
//! Destructor //! Destructor
@ -124,12 +127,10 @@ struct Bone
uint32_t iParent; uint32_t iParent;
//! Animation of the bone //! Animation of the bone
struct Animation struct Animation {
{
//! Public default constructor //! Public default constructor
Animation() Animation() AI_NO_EXCEPT
: iFirstTimeKey() : iFirstTimeKey() {
{
asKeys.reserve(20); asKeys.reserve(20);
} }

View File

@ -90,6 +90,9 @@ static bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
return expectedBinaryFileSize == fileSize; return expectedBinaryFileSize == fileSize;
} }
static const size_t BufferSize = 500;
static const char UnicodeBoundary = 127;
// An ascii STL buffer will begin with "solid NAME", where NAME is optional. // An ascii STL buffer will begin with "solid NAME", where NAME is optional.
// Note: The "solid NAME" check is necessary, but not sufficient, to determine // Note: The "solid NAME" check is necessary, but not sufficient, to determine
// if the buffer is ASCII; a binary header could also begin with "solid NAME". // if the buffer is ASCII; a binary header could also begin with "solid NAME".
@ -108,10 +111,10 @@ static bool IsAsciiSTL(const char* buffer, unsigned int fileSize) {
bool isASCII( strncmp( buffer, "solid", 5 ) == 0 ); bool isASCII( strncmp( buffer, "solid", 5 ) == 0 );
if( isASCII ) { if( isASCII ) {
// A lot of importers are write solid even if the file is binary. So we have to check for ASCII-characters. // A lot of importers are write solid even if the file is binary. So we have to check for ASCII-characters.
if( fileSize >= 500 ) { if( fileSize >= BufferSize) {
isASCII = true; isASCII = true;
for( unsigned int i = 0; i < 500; i++ ) { for( unsigned int i = 0; i < BufferSize; i++ ) {
if( buffer[ i ] > 127 ) { if( buffer[ i ] > UnicodeBoundary) {
isASCII = false; isASCII = false;
break; break;
} }
@ -352,7 +355,7 @@ void STLImporter::LoadASCIIFile( aiNode *root ) {
if (positionBuffer.empty()) { if (positionBuffer.empty()) {
pMesh->mNumFaces = 0; pMesh->mNumFaces = 0;
throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded"); ASSIMP_LOG_WARN("STL: mesh is empty or invalid; no data loaded");
} }
if (positionBuffer.size() % 3 != 0) { if (positionBuffer.size() % 3 != 0) {
pMesh->mNumFaces = 0; pMesh->mNumFaces = 0;
@ -362,14 +365,23 @@ void STLImporter::LoadASCIIFile( aiNode *root ) {
pMesh->mNumFaces = 0; pMesh->mNumFaces = 0;
throw DeadlyImportError("Normal buffer size does not match position buffer size"); throw DeadlyImportError("Normal buffer size does not match position buffer size");
} }
// only process positionbuffer when filled, else exception when accessing with index operator
// see line 353: only warning is triggered
// see line 373(now): access to empty positionbuffer with index operator forced exception
if (!positionBuffer.empty()) {
pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3); pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3);
pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size()); pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size());
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
positionBuffer.clear(); positionBuffer.clear();
}
// also only process normalBuffer when filled, else exception when accessing with index operator
if (!normalBuffer.empty()) {
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
normalBuffer.clear(); normalBuffer.clear();
}
// now copy faces // now copy faces
addFacesToMesh(pMesh); addFacesToMesh(pMesh);
@ -526,11 +538,21 @@ bool STLImporter::LoadBinaryFile()
// now copy faces // now copy faces
addFacesToMesh(pMesh); addFacesToMesh(pMesh);
aiNode* root = pScene->mRootNode;
// allocate one node
aiNode* node = new aiNode();
node->mParent = root;
root->mNumChildren = 1u;
root->mChildren = new aiNode*[root->mNumChildren];
root->mChildren[0] = node;
// add all created meshes to the single node // add all created meshes to the single node
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; node->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; node->mMeshes = new unsigned int[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes; i++) for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
pScene->mRootNode->mMeshes[i] = i; node->mMeshes[i] = i;
if (bIsMaterialise && !pMesh->mColors[0]) if (bIsMaterialise && !pMesh->mColors[0])
{ {

View File

@ -707,30 +707,30 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator
// we work with hashes to make the comparisons MUCH faster, // we work with hashes to make the comparisons MUCH faster,
// at least if we have many bones. // at least if we have many bones.
std::list<BoneWithHash> asBones; std::list<BoneWithHash> asBones;
BuildUniqueBoneList(asBones, it,end); BuildUniqueBoneList( asBones, it, end );
// now create the output bones // now create the output bones
out->mNumBones = 0; out->mNumBones = 0;
out->mBones = new aiBone*[asBones.size()]; out->mBones = new aiBone*[asBones.size()];
for (std::list<BoneWithHash>::const_iterator it = asBones.begin(),end = asBones.end(); it != end;++it) { for (std::list<BoneWithHash>::const_iterator boneIt = asBones.begin(),boneEnd = asBones.end(); boneIt != boneEnd; ++boneIt ) {
// Allocate a bone and setup it's name // Allocate a bone and setup it's name
aiBone* pc = out->mBones[out->mNumBones++] = new aiBone(); aiBone* pc = out->mBones[out->mNumBones++] = new aiBone();
pc->mName = aiString( *((*it).second )); pc->mName = aiString( *( boneIt->second ));
std::vector< BoneSrcIndex >::const_iterator wend = (*it).pSrcBones.end(); std::vector< BoneSrcIndex >::const_iterator wend = boneIt->pSrcBones.end();
// Loop through all bones to be joined for this bone // Loop through all bones to be joined for this bone
for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).pSrcBones.begin(); wmit != wend; ++wmit) { for (std::vector< BoneSrcIndex >::const_iterator wmit = boneIt->pSrcBones.begin(); wmit != wend; ++wmit) {
pc->mNumWeights += (*wmit).first->mNumWeights; pc->mNumWeights += (*wmit).first->mNumWeights;
// NOTE: different offset matrices for bones with equal names // NOTE: different offset matrices for bones with equal names
// are - at the moment - not handled correctly. // are - at the moment - not handled correctly.
if (wmit != (*it).pSrcBones.begin() && pc->mOffsetMatrix != (*wmit).first->mOffsetMatrix) { if (wmit != boneIt->pSrcBones.begin() && pc->mOffsetMatrix != wmit->first->mOffsetMatrix) {
ASSIMP_LOG_WARN("Bones with equal names but different offset matrices can't be joined at the moment"); ASSIMP_LOG_WARN("Bones with equal names but different offset matrices can't be joined at the moment");
continue; continue;
} }
pc->mOffsetMatrix = (*wmit).first->mOffsetMatrix; pc->mOffsetMatrix = wmit->first->mOffsetMatrix;
} }
// Allocate the vertex weight array // Allocate the vertex weight array
@ -738,7 +738,7 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator
// And copy the final weights - adjust the vertex IDs by the // And copy the final weights - adjust the vertex IDs by the
// face index offset of the corresponding mesh. // face index offset of the corresponding mesh.
for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).pSrcBones.begin(); wmit != wend; ++wmit) { for (std::vector< BoneSrcIndex >::const_iterator wmit = (*boneIt).pSrcBones.begin(); wmit != wend; ++wmit) {
aiBone* pip = (*wmit).first; aiBone* pip = (*wmit).first;
for (unsigned int mp = 0; mp < pip->mNumWeights;++mp,++avw) { for (unsigned int mp = 0; mp < pip->mNumWeights;++mp,++avw) {
const aiVertexWeight& vfi = pip->mWeights[mp]; const aiVertexWeight& vfi = pip->mWeights[mp];
@ -849,14 +849,14 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
// copy vertex colors // copy vertex colors
n = 0; n = 0;
while ((**begin).HasVertexColors(n)) { while ((**begin).HasVertexColors(n)) {
aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices]; aiColor4D *pVec2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { for ( std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it ) {
if ((*it)->mColors[n]) { if ((*it)->mColors[n]) {
::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D)); ::memcpy( pVec2, (*it)->mColors[ n ], (*it)->mNumVertices * sizeof( aiColor4D ) ) ;
} else { } else {
ASSIMP_LOG_WARN( "JoinMeshes: VCs expected but input mesh contains no VCs" ); ASSIMP_LOG_WARN( "JoinMeshes: VCs expected but input mesh contains no VCs" );
} }
pv2 += (*it)->mNumVertices; pVec2 += (*it)->mNumVertices;
} }
++n; ++n;
} }

View File

@ -55,12 +55,8 @@ namespace Assimp {
class Importer; class Importer;
struct ScenePrivateData { struct ScenePrivateData {
ScenePrivateData() // The struct constructor.
: mOrigImporter( nullptr ) ScenePrivateData() AI_NO_EXCEPT;
, mPPStepsApplied( 0 )
, mIsCopy( false ) {
// empty
}
// Importer that originally loaded the scene though the C-API // Importer that originally loaded the scene though the C-API
// If set, this object is owned by this private data instance. // If set, this object is owned by this private data instance.
@ -77,6 +73,14 @@ struct ScenePrivateData {
bool mIsCopy; bool mIsCopy;
}; };
inline
ScenePrivateData::ScenePrivateData() AI_NO_EXCEPT
: mOrigImporter( nullptr )
, mPPStepsApplied( 0 )
, mIsCopy( false ) {
// empty
}
// Access private data stored in the scene // Access private data stored in the scene
inline inline
ScenePrivateData* ScenePriv(aiScene* in) { ScenePrivateData* ScenePriv(aiScene* in) {

View File

@ -223,7 +223,7 @@ namespace {
if( (-42 == (~42 + 1)) && (binValue & 0x80000000)) if( (-42 == (~42 + 1)) && (binValue & 0x80000000))
return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue; return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
// One's complement? // One's complement?
else if( (-42 == ~42) && (binValue & 0x80000000)) else if ( (-42 == ~42) && (binValue & 0x80000000))
return BinFloat(-0) - binValue; return BinFloat(-0) - binValue;
// Sign-magnitude? // Sign-magnitude?
else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary

View File

@ -393,7 +393,7 @@ void SplitByBoneCountProcess::UpdateNode( aiNode* pNode) const
newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end()); newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end());
} }
delete pNode->mMeshes; delete [] pNode->mMeshes;
pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size()); pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());
pNode->mMeshes = new unsigned int[pNode->mNumMeshes]; pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes); std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);

View File

@ -65,14 +65,14 @@ namespace Assimp {
/** Small helper structure representing a shortcut into the material list /** Small helper structure representing a shortcut into the material list
* to be able to update some values quickly. * to be able to update some values quickly.
*/ */
struct TTUpdateInfo struct TTUpdateInfo {
{ TTUpdateInfo() AI_NO_EXCEPT
TTUpdateInfo() : : directShortcut(nullptr)
directShortcut (NULL) , mat(nullptr)
, mat (NULL) , semantic(0)
, semantic (0) , index(0) {
, index (0) // empty
{} }
//! Direct shortcut, if available //! Direct shortcut, if available
unsigned int* directShortcut; unsigned int* directShortcut;
@ -88,15 +88,14 @@ struct TTUpdateInfo
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper class representing texture coordinate transformations /** Helper class representing texture coordinate transformations
*/ */
struct STransformVecInfo : public aiUVTransform struct STransformVecInfo : public aiUVTransform {
{ STransformVecInfo() AI_NO_EXCEPT
: uvIndex(0)
STransformVecInfo() , mapU(aiTextureMapMode_Wrap)
: uvIndex (0) , mapV(aiTextureMapMode_Wrap)
, mapU (aiTextureMapMode_Wrap) , lockedPos(AI_TT_UV_IDX_LOCK_NONE) {
, mapV (aiTextureMapMode_Wrap) // empty
, lockedPos (AI_TT_UV_IDX_LOCK_NONE) }
{}
//! Source texture coordinate index //! Source texture coordinate index
unsigned int uvIndex; unsigned int uvIndex;

View File

@ -105,10 +105,12 @@ void TriangulateProcess::Execute( aiScene* pScene)
bool bHas = false; bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
{ {
if (pScene->mMeshes[ a ]) {
if ( TriangulateMesh( pScene->mMeshes[ a ] ) ) { if ( TriangulateMesh( pScene->mMeshes[ a ] ) ) {
bHas = true; bHas = true;
} }
} }
}
if ( bHas ) { if ( bHas ) {
ASSIMP_LOG_INFO( "TriangulateProcess finished. All polygons have been triangulated." ); ASSIMP_LOG_INFO( "TriangulateProcess finished. All polygons have been triangulated." );
} else { } else {
@ -485,21 +487,22 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
for(aiFace* f = last_face; f != curOut; ) { for(aiFace* f = last_face; f != curOut; ) {
unsigned int* i = f->mIndices; unsigned int* i = f->mIndices;
// drop dumb 0-area triangles // drop dumb 0-area triangles - deactivated for now:
if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) { //FindDegenerates post processing step can do the same thing
ASSIMP_LOG_DEBUG("Dropping triangle with area 0"); //if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
--curOut; // ASSIMP_LOG_DEBUG("Dropping triangle with area 0");
// --curOut;
delete[] f->mIndices; // delete[] f->mIndices;
f->mIndices = NULL; // f->mIndices = nullptr;
for(aiFace* ff = f; ff != curOut; ++ff) { // for(aiFace* ff = f; ff != curOut; ++ff) {
ff->mNumIndices = (ff+1)->mNumIndices; // ff->mNumIndices = (ff+1)->mNumIndices;
ff->mIndices = (ff+1)->mIndices; // ff->mIndices = (ff+1)->mIndices;
(ff+1)->mIndices = NULL; // (ff+1)->mIndices = nullptr;
} // }
continue; // continue;
} //}
i[0] = idx[i[0]]; i[0] = idx[i[0]];
i[1] = idx[i[1]]; i[1] = idx[i[1]];

View File

@ -369,7 +369,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
// positions must always be there ... // positions must always be there ...
if (!pMesh->mNumVertices || (!pMesh->mVertices && !mScene->mFlags)) { if (!pMesh->mNumVertices || (!pMesh->mVertices && !mScene->mFlags)) {
ReportError("The mesh contains no vertices"); ReportError("The mesh %s contains no vertices", pMesh->mName.C_Str());
} }
if (pMesh->mNumVertices > AI_MAX_VERTICES) { if (pMesh->mNumVertices > AI_MAX_VERTICES) {
@ -386,7 +386,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
// faces, too // faces, too
if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) { if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) {
ReportError("Mesh contains no faces"); ReportError("Mesh %s contains no faces", pMesh->mName.C_Str());
} }
// now check whether the face indexing layout is correct: // now check whether the face indexing layout is correct:

View File

@ -150,9 +150,11 @@ ASSIMP_API aiScene::~aiScene() {
delete mMeshes[a]; delete mMeshes[a];
delete [] mMeshes; delete [] mMeshes;
if (mNumMaterials && mMaterials) if (mNumMaterials && mMaterials) {
for( unsigned int a = 0; a < mNumMaterials; a++) for (unsigned int a = 0; a < mNumMaterials; ++a ) {
delete mMaterials[a]; delete mMaterials[ a ];
}
}
delete [] mMaterials; delete [] mMaterials;
if (mNumAnimations && mAnimations) if (mNumAnimations && mAnimations)

View File

@ -55,32 +55,33 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/anim.h> #include <assimp/anim.h>
#include <assimp/Defines.h> #include <assimp/Defines.h>
namespace Assimp namespace Assimp {
{ namespace XFile {
namespace XFile
{
/** Helper structure representing a XFile mesh face */ /** Helper structure representing a XFile mesh face */
struct Face struct Face {
{
std::vector<unsigned int> mIndices; std::vector<unsigned int> mIndices;
}; };
/** Helper structure representing a texture filename inside a material and its potential source */ /** Helper structure representing a texture filename inside a material and its potential source */
struct TexEntry struct TexEntry {
{
std::string mName; std::string mName;
bool mIsNormalMap; // true if the texname was specified in a NormalmapFilename tag bool mIsNormalMap; // true if the texname was specified in a NormalmapFilename tag
TexEntry() { mIsNormalMap = false; } TexEntry() AI_NO_EXCEPT
TexEntry( const std::string& pName, bool pIsNormalMap = false) : mName()
: mName( pName), mIsNormalMap( pIsNormalMap) , mIsNormalMap(false) {
{ /* done */ } // empty
}
TexEntry(const std::string& pName, bool pIsNormalMap = false)
: mName(pName)
, mIsNormalMap(pIsNormalMap) {
// empty
}
}; };
/** Helper structure representing a XFile material */ /** Helper structure representing a XFile material */
struct Material struct Material {
{
std::string mName; std::string mName;
bool mIsReference; // if true, mName holds a name by which the actual material can be found in the material list bool mIsReference; // if true, mName holds a name by which the actual material can be found in the material list
aiColor4D mDiffuse; aiColor4D mDiffuse;
@ -88,19 +89,18 @@ struct Material
aiColor3D mSpecular; aiColor3D mSpecular;
aiColor3D mEmissive; aiColor3D mEmissive;
std::vector<TexEntry> mTextures; std::vector<TexEntry> mTextures;
size_t sceneIndex; ///< the index under which it was stored in the scene's material list size_t sceneIndex; ///< the index under which it was stored in the scene's material list
Material() Material() AI_NO_EXCEPT
: mIsReference(false), : mIsReference(false)
mSpecularExponent(), , mSpecularExponent()
sceneIndex(SIZE_MAX) , sceneIndex(SIZE_MAX) {
{} // empty
}
}; };
/** Helper structure to represent a bone weight */ /** Helper structure to represent a bone weight */
struct BoneWeight struct BoneWeight {
{
unsigned int mVertex; unsigned int mVertex;
ai_real mWeight; ai_real mWeight;
}; };
@ -114,8 +114,7 @@ struct Bone
}; };
/** Helper structure to represent an XFile mesh */ /** Helper structure to represent an XFile mesh */
struct Mesh struct Mesh {
{
std::string mName; std::string mName;
std::vector<aiVector3D> mPositions; std::vector<aiVector3D> mPositions;
std::vector<Face> mPosFaces; std::vector<Face> mPosFaces;
@ -131,38 +130,65 @@ struct Mesh
std::vector<Bone> mBones; std::vector<Bone> mBones;
explicit Mesh(const std::string &pName = "") { mName = pName; mNumTextures = 0; mNumColorSets = 0; } explicit Mesh(const std::string &pName = "") AI_NO_EXCEPT
: mName( pName )
, mPositions()
, mPosFaces()
, mNormals()
, mNormFaces()
, mNumTextures(0)
, mTexCoords{}
, mNumColorSets(0)
, mColors{}
, mFaceMaterials()
, mMaterials()
, mBones() {
// empty
}
}; };
/** Helper structure to represent a XFile frame */ /** Helper structure to represent a XFile frame */
struct Node struct Node {
{
std::string mName; std::string mName;
aiMatrix4x4 mTrafoMatrix; aiMatrix4x4 mTrafoMatrix;
Node* mParent; Node* mParent;
std::vector<Node*> mChildren; std::vector<Node*> mChildren;
std::vector<Mesh*> mMeshes; std::vector<Mesh*> mMeshes;
Node() { mParent = NULL; } Node() AI_NO_EXCEPT
explicit Node( Node* pParent) { mParent = pParent; } : mName()
~Node() , mTrafoMatrix()
{ , mParent(nullptr)
for( unsigned int a = 0; a < mChildren.size(); a++) , mChildren()
, mMeshes() {
// empty
}
explicit Node( Node* pParent)
: mName()
, mTrafoMatrix()
, mParent(pParent)
, mChildren()
, mMeshes() {
// empty
}
~Node() {
for (unsigned int a = 0; a < mChildren.size(); ++a ) {
delete mChildren[a]; delete mChildren[a];
for( unsigned int a = 0; a < mMeshes.size(); a++) }
for (unsigned int a = 0; a < mMeshes.size(); ++a) {
delete mMeshes[a]; delete mMeshes[a];
} }
}
}; };
struct MatrixKey struct MatrixKey {
{
double mTime; double mTime;
aiMatrix4x4 mMatrix; aiMatrix4x4 mMatrix;
}; };
/** Helper structure representing a single animated bone in a XFile */ /** Helper structure representing a single animated bone in a XFile */
struct AnimBone struct AnimBone {
{
std::string mBoneName; std::string mBoneName;
std::vector<aiVectorKey> mPosKeys; // either three separate key sequences for position, rotation, scaling std::vector<aiVectorKey> mPosKeys; // either three separate key sequences for position, rotation, scaling
std::vector<aiQuatKey> mRotKeys; std::vector<aiQuatKey> mRotKeys;
@ -194,15 +220,23 @@ struct Scene
std::vector<Animation*> mAnims; std::vector<Animation*> mAnims;
unsigned int mAnimTicksPerSecond; unsigned int mAnimTicksPerSecond;
Scene() { mRootNode = NULL; mAnimTicksPerSecond = 0; } Scene() AI_NO_EXCEPT
~Scene() : mRootNode(nullptr)
{ , mGlobalMeshes()
, mGlobalMaterials()
, mAnimTicksPerSecond(0) {
// empty
}
~Scene() {
delete mRootNode; delete mRootNode;
for( unsigned int a = 0; a < mGlobalMeshes.size(); a++) mRootNode = nullptr;
for (unsigned int a = 0; a < mGlobalMeshes.size(); ++a ) {
delete mGlobalMeshes[a]; delete mGlobalMeshes[a];
for( unsigned int a = 0; a < mAnims.size(); a++) }
for (unsigned int a = 0; a < mAnims.size(); ++a ) {
delete mAnims[a]; delete mAnims[a];
} }
}
}; };
} // end of namespace XFile } // end of namespace XFile

View File

@ -332,6 +332,11 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
// collect vertex data for indices of this face // collect vertex data for indices of this face
for( unsigned int d = 0; d < df.mNumIndices; ++d ) { for( unsigned int d = 0; d < df.mNumIndices; ++d ) {
df.mIndices[d] = newIndex; df.mIndices[d] = newIndex;
const unsigned int newIdx( pf.mIndices[ d ] );
if ( newIdx > sourceMesh->mPositions.size() ) {
continue;
}
orgPoints[newIndex] = pf.mIndices[d]; orgPoints[newIndex] = pf.mIndices[d];
// Position // Position
@ -459,7 +464,7 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
nbone->mNodeName.Set( bone->mBoneName); nbone->mNodeName.Set( bone->mBoneName);
nanim->mChannels[b] = nbone; nanim->mChannels[b] = nbone;
// keyframes are given as combined transformation matrix keys // key-frames are given as combined transformation matrix keys
if( !bone->mTrafoKeys.empty() ) if( !bone->mTrafoKeys.empty() )
{ {
nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size(); nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size();

View File

@ -471,7 +471,10 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh)
unsigned int numIndices = ReadInt(); unsigned int numIndices = ReadInt();
Face& face = pMesh->mPosFaces[a]; Face& face = pMesh->mPosFaces[a];
for (unsigned int b = 0; b < numIndices; ++b) { for (unsigned int b = 0; b < numIndices; ++b) {
face.mIndices.push_back( ReadInt() ); const int idx( ReadInt() );
if ( static_cast<unsigned int>( idx ) <= numVertices ) {
face.mIndices.push_back( idx );
}
} }
TestForSeparator(); TestForSeparator();
} }
@ -1305,7 +1308,8 @@ unsigned int XFileParser::ReadInt()
} }
--mBinaryNumCount; --mBinaryNumCount;
if ( mEnd - mP >= 4) { const size_t len( mEnd - mP );
if ( len >= 4) {
return ReadBinDWord(); return ReadBinDWord();
} else { } else {
mP = mEnd; mP = mEnd;
@ -1340,6 +1344,7 @@ unsigned int XFileParser::ReadInt()
} }
CheckForSeparator(); CheckForSeparator();
return isNegative ? ((unsigned int) -int( number)) : number; return isNegative ? ((unsigned int) -int( number)) : number;
} }
} }

View File

@ -766,10 +766,17 @@ namespace glTF2
Ref<Accessor> indices; Ref<Accessor> indices;
Ref<Material> material; Ref<Material> material;
struct Target {
AccessorList position, normal, tangent;
};
std::vector<Target> targets;
}; };
std::vector<Primitive> primitives; std::vector<Primitive> primitives;
std::vector<float> weights;
Mesh() {} Mesh() {}
/// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root) /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)

View File

@ -931,6 +931,21 @@ namespace {
else return false; else return false;
return true; return true;
} }
inline bool GetAttribTargetVector(Mesh::Primitive& p, const int targetIndex, const char* attr, Mesh::AccessorList*& v, int& pos)
{
if ((pos = Compare(attr, "POSITION"))) {
v = &(p.targets[targetIndex].position);
}
else if ((pos = Compare(attr, "NORMAL"))) {
v = &(p.targets[targetIndex].normal);
}
else if ((pos = Compare(attr, "TANGENT"))) {
v = &(p.targets[targetIndex].tangent);
}
else return false;
return true;
}
} }
inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
@ -965,6 +980,26 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
} }
} }
if (Value* targetsArray = FindArray(primitive, "targets")) {
prim.targets.resize(targetsArray->Size());
for (unsigned int i = 0; i < targetsArray->Size(); ++i) {
Value& target = (*targetsArray)[i];
if (!target.IsObject()) continue;
for (Value::MemberIterator it = target.MemberBegin(); it != target.MemberEnd(); ++it) {
if (!it->value.IsUint()) continue;
const char* attr = it->name.GetString();
// Valid attribute semantics include POSITION, NORMAL, TANGENT
int undPos = 0;
Mesh::AccessorList* vec = 0;
if (GetAttribTargetVector(prim, i, attr, vec, undPos)) {
size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
if ((*vec).size() <= idx) (*vec).resize(idx + 1);
(*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint());
}
}
}
}
if (Value* indices = FindUInt(primitive, "indices")) { if (Value* indices = FindUInt(primitive, "indices")) {
prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint()); prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint());
} }
@ -974,6 +1009,16 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
} }
} }
} }
if (Value* weights = FindArray(pJSON_Object, "weights")) {
this->weights.resize(weights->Size());
for (unsigned int i = 0; i < weights->Size(); ++i) {
Value& weightValue = (*weights)[i];
if (weightValue.IsNumber()) {
this->weights[i] = weightValue.GetFloat();
}
}
}
} }
inline void Camera::Read(Value& obj, Asset& /*r*/) inline void Camera::Read(Value& obj, Asset& /*r*/)
@ -1216,12 +1261,15 @@ inline void Asset::Load(const std::string& pFile, bool isBinary)
// Read the "scene" property, which specifies which scene to load // Read the "scene" property, which specifies which scene to load
// and recursively load everything referenced by it // and recursively load everything referenced by it
unsigned int sceneIndex = 0;
if (Value* scene = FindUInt(doc, "scene")) { if (Value* scene = FindUInt(doc, "scene")) {
unsigned int sceneIndex = scene->GetUint(); sceneIndex = scene->GetUint();
}
Ref<Scene> s = scenes.Retrieve(sceneIndex); if (Value* scenesArray = FindArray(doc, "scenes")) {
if (sceneIndex < scenesArray->Size()) {
this->scene = s; this->scene = scenes.Retrieve(sceneIndex);
}
} }
// Clean up // Clean up

View File

@ -94,19 +94,7 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
, mIOSystem(pIOSystem) , mIOSystem(pIOSystem)
, mProperties(pProperties) , mProperties(pProperties)
{ {
aiScene* sceneCopy_tmp; mScene = pScene;
SceneCombiner::CopyScene(&sceneCopy_tmp, pScene);
std::unique_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());
mScene = sceneCopy.get();
mAsset.reset( new Asset( pIOSystem ) ); mAsset.reset( new Asset( pIOSystem ) );
@ -516,7 +504,7 @@ void glTF2Exporter::ExportMaterials()
if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) { if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) {
float shininess; float shininess;
if (mat->Get(AI_MATKEY_SHININESS, shininess)) { if (mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
pbrSG.glossinessFactor = shininess / 1000; pbrSG.glossinessFactor = shininess / 1000;
} }
} }
@ -682,12 +670,7 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buf
void glTF2Exporter::ExportMeshes() void glTF2Exporter::ExportMeshes()
{ {
// Not for typedef decltype(aiFace::mNumIndices) IndicesType;
// using IndicesType = decltype(aiFace::mNumIndices);
// But yes for
// using IndicesType = unsigned short;
// because "ComponentType_UNSIGNED_SHORT" used for indices. And it's a maximal type according to glTF specification.
typedef unsigned short IndicesType;
std::string fname = std::string(mFilename); std::string fname = std::string(mFilename);
std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf")); std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf"));
@ -779,11 +762,11 @@ void glTF2Exporter::ExportMeshes()
indices.resize(aim->mNumFaces * nIndicesPerFace); indices.resize(aim->mNumFaces * nIndicesPerFace);
for (size_t i = 0; i < aim->mNumFaces; ++i) { for (size_t i = 0; i < aim->mNumFaces; ++i) {
for (size_t j = 0; j < nIndicesPerFace; ++j) { for (size_t j = 0; j < nIndicesPerFace; ++j) {
indices[i*nIndicesPerFace + j] = uint16_t(aim->mFaces[i].mIndices[j]); indices[i*nIndicesPerFace + j] = IndicesType(aim->mFaces[i].mIndices[j]);
} }
} }
p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, true); p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, true);
} }
switch (aim->mPrimitiveTypes) { switch (aim->mPrimitiveTypes) {

194
code/glTF2Importer.cpp 100644 → 100755
View File

@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/CreateAnimMesh.h>
#include <memory> #include <memory>
@ -65,6 +66,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
using namespace glTF2; using namespace glTF2;
namespace {
// generate bitangents from normals and tangents according to spec
struct Tangent {
aiVector3D xyz;
ai_real w;
};
} // namespace
// //
// glTF2Importer // glTF2Importer
@ -109,18 +117,29 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool
if (pIOHandler) { if (pIOHandler) {
glTF2::Asset asset(pIOHandler); glTF2::Asset asset(pIOHandler);
try {
asset.Load(pFile, extension == "glb"); asset.Load(pFile, extension == "glb");
std::string version = asset.asset.version; std::string version = asset.asset.version;
return !version.empty() && version[0] == '2'; return !version.empty() && version[0] == '2';
} catch (...) {
return false;
}
} }
return false; return false;
} }
static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode)
{
switch (gltfWrapMode) {
case SamplerWrap::Mirrored_Repeat:
return aiTextureMapMode_Mirror;
case SamplerWrap::Clamp_To_Edge:
return aiTextureMapMode_Clamp;
case SamplerWrap::UNSET:
case SamplerWrap::Repeat:
default:
return aiTextureMapMode_Wrap;
}
}
//static void CopyValue(const glTF2::vec3& v, aiColor3D& out) //static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
//{ //{
@ -198,8 +217,10 @@ inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset&
mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot)); mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot));
mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot)); mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot));
mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); aiTextureMapMode wrapS = ConvertWrappingMode(sampler->wrapS);
mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); aiTextureMapMode wrapT = ConvertWrappingMode(sampler->wrapT);
mat->AddProperty(&wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
mat->AddProperty(&wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
if (sampler->magFilter != SamplerMagFilter::UNSET) { if (sampler->magFilter != SamplerMagFilter::UNSET) {
mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot)); mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot));
@ -399,10 +420,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
// only extract tangents if normals are present // only extract tangents if normals are present
if (attr.tangent.size() > 0 && attr.tangent[0]) { if (attr.tangent.size() > 0 && attr.tangent[0]) {
// generate bitangents from normals and tangents according to spec // generate bitangents from normals and tangents according to spec
struct Tangent { Tangent *tangents = nullptr;
aiVector3D xyz;
ai_real w;
} *tangents = nullptr;
attr.tangent[0]->ExtractData(tangents); attr.tangent[0]->ExtractData(tangents);
@ -419,6 +437,12 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
} }
for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
if (attr.texcoord[tc]->count != aim->mNumVertices) {
DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name +
"\" does not match the vertex count");
continue;
}
attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]);
aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
@ -428,11 +452,57 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
} }
} }
std::vector<Mesh::Primitive::Target>& targets = prim.targets;
if (targets.size() > 0) {
aim->mNumAnimMeshes = targets.size();
aim->mAnimMeshes = new aiAnimMesh*[aim->mNumAnimMeshes];
for (size_t i = 0; i < targets.size(); i++) {
aim->mAnimMeshes[i] = aiCreateAnimMesh(aim);
aiAnimMesh& aiAnimMesh = *(aim->mAnimMeshes[i]);
Mesh::Primitive::Target& target = targets[i];
if (target.position.size() > 0) {
aiVector3D *positionDiff = nullptr;
target.position[0]->ExtractData(positionDiff);
for(unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId];
}
delete [] positionDiff;
}
if (target.normal.size() > 0) {
aiVector3D *normalDiff = nullptr;
target.normal[0]->ExtractData(normalDiff);
for(unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId];
}
delete [] normalDiff;
}
if (target.tangent.size() > 0) {
Tangent *tangent = nullptr;
attr.tangent[0]->ExtractData(tangent);
aiVector3D *tangentDiff = nullptr;
target.tangent[0]->ExtractData(tangentDiff);
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) {
tangent[vertexId].xyz += tangentDiff[vertexId];
aiAnimMesh.mTangents[vertexId] = tangent[vertexId].xyz;
aiAnimMesh.mBitangents[vertexId] = (aiAnimMesh.mNormals[vertexId] ^ tangent[vertexId].xyz) * tangent[vertexId].w;
}
delete [] tangent;
delete [] tangentDiff;
}
if (mesh.weights.size() > i) {
aiAnimMesh.mWeight = mesh.weights[i];
}
}
}
if (prim.indices) {
aiFace* faces = 0; aiFace* faces = 0;
unsigned int nFaces = 0; unsigned int nFaces = 0;
if (prim.indices) {
unsigned int count = prim.indices->count; unsigned int count = prim.indices->count;
Accessor::Indexer data = prim.indices->GetIndexer(); Accessor::Indexer data = prim.indices->GetIndexer();
@ -482,9 +552,18 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
case PrimitiveMode_TRIANGLE_STRIP: { case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2; nFaces = count - 2;
faces = new aiFace[nFaces]; faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); for (unsigned int i = 0; i < nFaces; ++i) {
for (unsigned int i = 3; i < count; ++i) { //The ordering is to ensure that the triangles are all drawn with the same orientation
SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); if ((i + 1) % 2 == 0)
{
//For even n, vertices n + 1, n, and n + 2 define triangle n
SetFace(faces[i], data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2));
}
else
{
//For odd n, vertices n, n+1, and n+2 define triangle n
SetFace(faces[i], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
} }
break; break;
} }
@ -492,19 +571,92 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
nFaces = count - 2; nFaces = count - 2;
faces = new aiFace[nFaces]; faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 3; i < count; ++i) { for (unsigned int i = 1; i < nFaces; ++i) {
SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2));
} }
break; break;
} }
}
else { // no indices provided so directly generate from counts
// use the already determined count as it includes checks
unsigned int count = aim->mNumVertices;
switch (prim.mode) {
case PrimitiveMode_POINTS: {
nFaces = count;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; ++i) {
SetFace(faces[i], i);
}
break;
}
case PrimitiveMode_LINES: {
nFaces = count / 2;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFace(faces[i / 2], i, i + 1);
}
break;
}
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
faces = new aiFace[nFaces];
SetFace(faces[0], 0, 1);
for (unsigned int i = 2; i < count; ++i) {
SetFace(faces[i - 1], faces[i - 2].mIndices[1], i);
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]);
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
SetFace(faces[i / 3], i, i + 1, i + 2);
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < nFaces; ++i) {
//The ordering is to ensure that the triangles are all drawn with the same orientation
if ((i+1) % 2 == 0)
{
//For even n, vertices n + 1, n, and n + 2 define triangle n
SetFace(faces[i], i+1, i, i+2);
}
else
{
//For odd n, vertices n, n+1, and n+2 define triangle n
SetFace(faces[i], i, i+1, i+2);
}
}
break;
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], 0, 1, 2);
for (unsigned int i = 1; i < nFaces; ++i) {
SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], i + 2);
}
break;
}
}
if (faces) { if (faces) {
aim->mFaces = faces; aim->mFaces = faces;
aim->mNumFaces = nFaces; aim->mNumFaces = nFaces;
ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices)); ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices));
} }
}
if (prim.material) { if (prim.material) {
aim->mMaterialIndex = prim.material.GetIndex(); aim->mMaterialIndex = prim.material.GetIndex();
@ -716,12 +868,6 @@ void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IO
ImportNodes(asset); ImportNodes(asset);
// TODO: it does not split the loaded vertices, should it?
//pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
MakeVerboseFormatProcess process;
process.Execute(pScene);
if (pScene->mNumMeshes == 0) { if (pScene->mNumMeshes == 0) {
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
} }

75
code/glTFImporter.cpp 100644 → 100755
View File

@ -351,10 +351,10 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
} }
if (prim.indices) {
aiFace* faces = 0; aiFace* faces = 0;
unsigned int nFaces = 0; unsigned int nFaces = 0;
if (prim.indices) {
unsigned int count = prim.indices->count; unsigned int count = prim.indices->count;
Accessor::Indexer data = prim.indices->GetIndexer(); Accessor::Indexer data = prim.indices->GetIndexer();
@ -419,14 +419,78 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
} }
break; break;
} }
}
else { // no indices provided so directly generate from counts
// use the already determined count as it includes checks
unsigned int count = aim->mNumVertices;
switch (prim.mode) {
case PrimitiveMode_POINTS: {
nFaces = count;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; ++i) {
SetFace(faces[i], i);
}
break;
}
case PrimitiveMode_LINES: {
nFaces = count / 2;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFace(faces[i / 2], i, i + 1);
}
break;
}
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
faces = new aiFace[nFaces];
SetFace(faces[0], 0, 1);
for (unsigned int i = 2; i < count; ++i) {
SetFace(faces[i - 1], faces[i - 2].mIndices[1], i);
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]);
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
SetFace(faces[i / 3], i, i + 1, i + 2);
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], 0, 1, 2);
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], i);
}
break;
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], 0, 1, 2);
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], i);
}
break;
}
}
if (faces) { if (faces) {
aim->mFaces = faces; aim->mFaces = faces;
aim->mNumFaces = nFaces; aim->mNumFaces = nFaces;
ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices)); ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices));
} }
}
if (prim.material) { if (prim.material) {
aim->mMaterialIndex = prim.material.GetIndex(); aim->mMaterialIndex = prim.material.GetIndex();
@ -676,11 +740,6 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS
ImportNodes(asset); ImportNodes(asset);
// TODO: it does not split the loaded vertices, should it?
//pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
MakeVerboseFormatProcess process;
process.Execute(pScene);
if (pScene->mNumMeshes == 0) { if (pScene->mNumMeshes == 0) {
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;

View File

@ -21,7 +21,6 @@ class array
{ {
public: public:
array() array()
: data(0), allocated(0), used(0), : data(0), allocated(0), used(0),
free_when_destroyed(true), is_sorted(true) free_when_destroyed(true), is_sorted(true)

View File

@ -100,10 +100,16 @@ static bool isUnsignedIntegerType( Value::ValueType integerType ) {
} }
static DDLNode *createDDLNode( Text *id, OpenDDLParser *parser ) { static DDLNode *createDDLNode( Text *id, OpenDDLParser *parser ) {
// Basic checks
if( ddl_nullptr == id || ddl_nullptr == parser ) { if( ddl_nullptr == id || ddl_nullptr == parser ) {
return ddl_nullptr; return ddl_nullptr;
} }
// If the buffer is empty ( an empty node ) return nullptr
if ( ddl_nullptr == id->m_buffer ) {
return ddl_nullptr;
}
const std::string type( id->m_buffer ); const std::string type( id->m_buffer );
DDLNode *parent( parser->top() ); DDLNode *parent( parser->top() );
DDLNode *node = DDLNode::create( type, "", parent ); DDLNode *node = DDLNode::create( type, "", parent );

View File

@ -77,19 +77,17 @@ class IOStream;
* imports the given file. ReadFile is not overridable, it just calls * imports the given file. ReadFile is not overridable, it just calls
* InternReadFile() and catches any ImportErrorException that might occur. * InternReadFile() and catches any ImportErrorException that might occur.
*/ */
class ASSIMP_API BaseImporter class ASSIMP_API BaseImporter {
{
friend class Importer; friend class Importer;
public: public:
/** Constructor to be privately used by #Importer */ /** Constructor to be privately used by #Importer */
BaseImporter(); BaseImporter() AI_NO_EXCEPT;
/** Destructor, private as well */ /** Destructor, private as well */
virtual ~BaseImporter(); virtual ~BaseImporter();
public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* *
@ -244,7 +242,8 @@ public: // static utilities
const char** tokens, const char** tokens,
unsigned int numTokens, unsigned int numTokens,
unsigned int searchBytes = 200, unsigned int searchBytes = 200,
bool tokensSol = false); bool tokensSol = false,
bool noAlphaBeforeTokens = false);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Check whether a file has a specific file extension /** @brief Check whether a file has a specific file extension

View File

@ -60,9 +60,8 @@ namespace Assimp {
* This is required to read big-endian model formats on little-endian machines, * This is required to read big-endian model formats on little-endian machines,
* and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */ * and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
class ByteSwap class ByteSwap {
{ ByteSwap() AI_NO_EXCEPT {}
ByteSwap() {}
public: public:

View File

@ -69,7 +69,7 @@ class ASSIMP_API DefaultIOStream : public IOStream
#endif // __ANDROID__ #endif // __ANDROID__
protected: protected:
DefaultIOStream(); DefaultIOStream() AI_NO_EXCEPT;
DefaultIOStream(FILE* pFile, const std::string &strFilename); DefaultIOStream(FILE* pFile, const std::string &strFilename);
public: public:
@ -111,27 +111,25 @@ private:
FILE* mFile; FILE* mFile;
// Filename // Filename
std::string mFilename; std::string mFilename;
// Cached file size // Cached file size
mutable size_t mCachedSize; mutable size_t mCachedSize;
}; };
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
inline DefaultIOStream::DefaultIOStream () : inline
mFile (NULL), DefaultIOStream::DefaultIOStream() AI_NO_EXCEPT
mFilename (""), : mFile(nullptr)
mCachedSize(SIZE_MAX) , mFilename("")
{ , mCachedSize(SIZE_MAX) {
// empty // empty
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
inline DefaultIOStream::DefaultIOStream (FILE* pFile, inline
const std::string &strFilename) : DefaultIOStream::DefaultIOStream (FILE* pFile, const std::string &strFilename)
mFile(pFile), : mFile(pFile)
mFilename(strFilename), , mFilename(strFilename)
mCachedSize(SIZE_MAX) , mCachedSize(SIZE_MAX) {
{
// empty // empty
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------

View File

@ -50,8 +50,7 @@ namespace Assimp {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Default implementation of IOSystem using the standard C file functions */ /** Default implementation of IOSystem using the standard C file functions */
class ASSIMP_API DefaultIOSystem : public IOSystem class ASSIMP_API DefaultIOSystem : public IOSystem {
{
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Tests for the existence of a file at the given path. */ /** Tests for the existence of a file at the given path. */

View File

@ -71,7 +71,7 @@ class ASSIMP_API IOStream
{ {
protected: protected:
/** Constructor protected, use IOSystem::Open() to create an instance. */ /** Constructor protected, use IOSystem::Open() to create an instance. */
IOStream(); IOStream() AI_NO_EXCEPT;
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -126,7 +126,7 @@ public:
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
inline inline
IOStream::IOStream() { IOStream::IOStream() AI_NO_EXCEPT {
// empty // empty
} }

View File

@ -95,7 +95,7 @@ public:
* Create an instance of your derived class and assign it to an * Create an instance of your derived class and assign it to an
* #Assimp::Importer instance by calling Importer::SetIOHandler(). * #Assimp::Importer instance by calling Importer::SetIOHandler().
*/ */
IOSystem(); IOSystem() AI_NO_EXCEPT;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Virtual destructor. /** @brief Virtual destructor.
@ -105,9 +105,6 @@ public:
*/ */
virtual ~IOSystem(); virtual ~IOSystem();
public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief For backward compatibility /** @brief For backward compatibility
* @see Exists(const char*) * @see Exists(const char*)
@ -233,7 +230,7 @@ private:
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AI_FORCE_INLINE AI_FORCE_INLINE
IOSystem::IOSystem() IOSystem::IOSystem() AI_NO_EXCEPT
: m_pathStack() { : m_pathStack() {
// empty // empty
} }

View File

@ -44,11 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief LineSplitter, a helper class to iterate through all lines * @brief LineSplitter, a helper class to iterate through all lines
* of a file easily. Works with StreamReader. * of a file easily. Works with StreamReader.
*/ */
#pragma once
#ifndef INCLUDED_LINE_SPLITTER_H #ifndef INCLUDED_LINE_SPLITTER_H
#define INCLUDED_LINE_SPLITTER_H #define INCLUDED_LINE_SPLITTER_H
#include <stdexcept> #include <stdexcept>
#include "StreamReader.h" #include "StreamReader.h"
#include "ParsingUtils.h" #include "ParsingUtils.h"
@ -81,164 +81,205 @@ public:
/** construct from existing stream reader /** construct from existing stream reader
note: trim is *always* assumed true if skyp_empty_lines==true note: trim is *always* assumed true if skyp_empty_lines==true
*/ */
LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true) LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true);
: idx( 0 )
, stream(stream)
, swallow()
, skip_empty_lines(skip_empty_lines)
, trim(trim) {
cur.reserve(1024);
operator++();
idx = 0; ~LineSplitter();
}
~LineSplitter() {
// empty
}
public:
// ----------------------------------------- // -----------------------------------------
/** pseudo-iterator increment */ /** pseudo-iterator increment */
LineSplitter& operator++() { LineSplitter& operator++();
if(swallow) {
swallow = false; // -----------------------------------------
LineSplitter& operator++(int);
// -----------------------------------------
/** get a pointer to the beginning of a particular token */
const char* operator[] (size_t idx) const;
// -----------------------------------------
/** extract the start positions of N tokens from the current line*/
template <size_t N>
void get_tokens(const char* (&tokens)[N]) const;
// -----------------------------------------
/** member access */
const std::string* operator -> () const;
std::string operator* () const;
// -----------------------------------------
/** boolean context */
operator bool() const;
// -----------------------------------------
/** line indices are zero-based, empty lines are included */
operator line_idx() const;
line_idx get_index() const;
// -----------------------------------------
/** access the underlying stream object */
StreamReaderLE& get_stream();
// -----------------------------------------
/** !strcmp((*this)->substr(0,strlen(check)),check) */
bool match_start(const char* check);
// -----------------------------------------
/** swallow the next call to ++, return the previous value. */
void swallow_next_increment();
LineSplitter( const LineSplitter & ) = delete;
LineSplitter(LineSplitter &&) = delete;
LineSplitter &operator = ( const LineSplitter & ) = delete;
private:
line_idx mIdx;
std::string mCur;
StreamReaderLE& mStream;
bool mSwallow, mSkip_empty_lines, mTrim;
};
inline
LineSplitter::LineSplitter(StreamReaderLE& stream, bool skip_empty_lines, bool trim )
: mIdx(0)
, mCur()
, mStream(stream)
, mSwallow()
, mSkip_empty_lines(skip_empty_lines)
, mTrim(trim) {
mCur.reserve(1024);
operator++();
mIdx = 0;
}
inline
LineSplitter::~LineSplitter() {
// empty
}
inline
LineSplitter& LineSplitter::operator++() {
if (mSwallow) {
mSwallow = false;
return *this; return *this;
} }
if (!*this) { if (!*this) {
throw std::logic_error("End of file, no more lines to be retrieved."); throw std::logic_error("End of file, no more lines to be retrieved.");
} }
char s; char s;
cur.clear(); mCur.clear();
while(stream.GetRemainingSize() && (s = stream.GetI1(),1)) { while (mStream.GetRemainingSize() && (s = mStream.GetI1(), 1)) {
if (s == '\n' || s == '\r') { if (s == '\n' || s == '\r') {
if (skip_empty_lines) { if (mSkip_empty_lines) {
while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n')); while (mStream.GetRemainingSize() && ((s = mStream.GetI1()) == ' ' || s == '\r' || s == '\n'));
if (stream.GetRemainingSize()) { if (mStream.GetRemainingSize()) {
stream.IncPtr(-1); mStream.IncPtr(-1);
} }
} } else {
else {
// skip both potential line terminators but don't read past this line. // skip both potential line terminators but don't read past this line.
if (stream.GetRemainingSize() && (s == '\r' && stream.GetI1() != '\n')) { if (mStream.GetRemainingSize() && (s == '\r' && mStream.GetI1() != '\n')) {
stream.IncPtr(-1); mStream.IncPtr(-1);
} }
if (trim) { if (mTrim) {
while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\t')); while (mStream.GetRemainingSize() && ((s = mStream.GetI1()) == ' ' || s == '\t'));
if (stream.GetRemainingSize()) { if (mStream.GetRemainingSize()) {
stream.IncPtr(-1); mStream.IncPtr(-1);
} }
} }
} }
break; break;
} }
cur += s; mCur += s;
} }
++idx; ++mIdx;
return *this; return *this;
} }
// ----------------------------------------- inline
LineSplitter& operator++(int) { LineSplitter &LineSplitter::operator++(int) {
return ++(*this); return ++(*this);
} }
// ----------------------------------------- inline
/** get a pointer to the beginning of a particular token */ const char *LineSplitter::operator[] (size_t idx) const {
const char* operator[] (size_t idx) const {
const char* s = operator->()->c_str(); const char* s = operator->()->c_str();
SkipSpaces(&s); SkipSpaces(&s);
for(size_t i = 0; i < idx; ++i) { for (size_t i = 0; i < idx; ++i) {
for(;!IsSpace(*s); ++s) { for (; !IsSpace(*s); ++s) {
if(IsLineEnd(*s)) { if (IsLineEnd(*s)) {
throw std::range_error("Token index out of range, EOL reached"); throw std::range_error("Token index out of range, EOL reached");
} }
} }
SkipSpaces(&s); SkipSpaces(&s);
} }
return s; return s;
} }
// ----------------------------------------- template <size_t N>
/** extract the start positions of N tokens from the current line*/ inline
template <size_t N> void LineSplitter::get_tokens(const char* (&tokens)[N]) const {
void get_tokens(const char* (&tokens)[N]) const {
const char* s = operator->()->c_str(); const char* s = operator->()->c_str();
SkipSpaces(&s); SkipSpaces(&s);
for(size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
if(IsLineEnd(*s)) { if (IsLineEnd(*s)) {
throw std::range_error("Token count out of range, EOL reached"); throw std::range_error("Token count out of range, EOL reached");
} }
tokens[i] = s; tokens[i] = s;
for(;*s && !IsSpace(*s); ++s); for (; *s && !IsSpace(*s); ++s);
SkipSpaces(&s); SkipSpaces(&s);
} }
}
// -----------------------------------------
/** member access */
const std::string* operator -> () const {
return &cur;
}
std::string operator* () const {
return cur;
}
// -----------------------------------------
/** boolean context */
operator bool() const {
return stream.GetRemainingSize()>0;
}
// -----------------------------------------
/** line indices are zero-based, empty lines are included */
operator line_idx() const {
return idx;
}
line_idx get_index() const {
return idx;
}
// -----------------------------------------
/** access the underlying stream object */
StreamReaderLE& get_stream() {
return stream;
}
// -----------------------------------------
/** !strcmp((*this)->substr(0,strlen(check)),check) */
bool match_start(const char* check) {
const size_t len = strlen(check);
return len <= cur.length() && std::equal(check,check+len,cur.begin());
}
// -----------------------------------------
/** swallow the next call to ++, return the previous value. */
void swallow_next_increment() {
swallow = true;
}
private:
LineSplitter( const LineSplitter & );
LineSplitter &operator = ( const LineSplitter & );
private:
line_idx idx;
std::string cur;
StreamReaderLE& stream;
bool swallow, skip_empty_lines, trim;
};
} }
inline
const std::string* LineSplitter::operator -> () const {
return &mCur;
}
inline
std::string LineSplitter::operator* () const {
return mCur;
}
inline
LineSplitter::operator bool() const {
return mStream.GetRemainingSize() > 0;
}
inline
LineSplitter::operator line_idx() const {
return mIdx;
}
inline
LineSplitter::line_idx LineSplitter::get_index() const {
return mIdx;
}
inline
StreamReaderLE &LineSplitter::get_stream() {
return mStream;
}
inline
bool LineSplitter::match_start(const char* check) {
const size_t len = ::strlen(check);
return len <= mCur.length() && std::equal(check, check + len, mCur.begin());
}
inline
void LineSplitter::swallow_next_increment() {
mSwallow = true;
}
} // Namespace Assimp
#endif // INCLUDED_LINE_SPLITTER_H #endif // INCLUDED_LINE_SPLITTER_H

View File

@ -65,7 +65,7 @@ class ASSIMP_API LogStream
{ {
protected: protected:
/** @brief Default constructor */ /** @brief Default constructor */
LogStream(); LogStream() AI_NO_EXCEPT;
public: public:
/** @brief Virtual destructor */ /** @brief Virtual destructor */
@ -91,12 +91,12 @@ public:
* @return New LogStream instance. */ * @return New LogStream instance. */
static LogStream* createDefaultStream(aiDefaultLogStream stream, static LogStream* createDefaultStream(aiDefaultLogStream stream,
const char* name = "AssimpLog.txt", const char* name = "AssimpLog.txt",
IOSystem* io = NULL); IOSystem* io = nullptr );
}; // !class LogStream }; // !class LogStream
inline inline
LogStream::LogStream() { LogStream::LogStream() AI_NO_EXCEPT {
// empty // empty
} }

View File

@ -161,7 +161,7 @@ protected:
/** /**
* Default constructor * Default constructor
*/ */
Logger(); Logger() AI_NO_EXCEPT;
/** /**
* Construction with a given log severity * Construction with a given log severity
@ -215,8 +215,9 @@ protected:
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Default constructor // Default constructor
inline inline
Logger::Logger() { Logger::Logger() AI_NO_EXCEPT
setLogSeverity(NORMAL); : m_Severity(NORMAL) {
// empty
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
@ -229,8 +230,9 @@ Logger::~Logger() {
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Construction with given logging severity // Construction with given logging severity
inline inline
Logger::Logger(LogSeverity severity) { Logger::Logger(LogSeverity severity)
setLogSeverity(severity); : m_Severity(severity) {
// empty
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------

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