Merge branch 'master' into fix_gltf2_export_componentType_error
commit
cc0b3e1249
|
@ -12,6 +12,8 @@ build
|
|||
bin/
|
||||
lib/
|
||||
|
||||
# QtCreator
|
||||
CMakeLists.txt.user
|
||||
|
||||
# Generated
|
||||
assimp.pc
|
||||
|
@ -19,6 +21,7 @@ revision.h
|
|||
contrib/zlib/zconf.h
|
||||
contrib/zlib/zlib.pc
|
||||
include/assimp/config.h
|
||||
unit.vcxproj.user
|
||||
|
||||
# CMake
|
||||
CMakeCache.txt
|
||||
|
@ -85,3 +88,9 @@ lib64/assimp-vc120-mt.exp
|
|||
xcuserdata
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
|
@ -39,10 +39,12 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
|
|||
PROJECT( Assimp )
|
||||
|
||||
# All supported options ###############################################
|
||||
|
||||
OPTION( BUILD_SHARED_LIBS
|
||||
"Build package with shared libraries."
|
||||
ON
|
||||
)
|
||||
|
||||
OPTION( BUILD_FRAMEWORK
|
||||
"Build package as Mac OS X Framework bundle."
|
||||
OFF
|
||||
|
@ -103,6 +105,16 @@ OPTION ( BUILD_DOCS
|
|||
"Build documentation using Doxygen."
|
||||
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
|
||||
if (WIN32)
|
||||
|
@ -152,7 +164,7 @@ EXECUTE_PROCESS(
|
|||
|
||||
# Get the latest abbreviated commit hash of the working branch
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND git log -1 --format=%h
|
||||
COMMAND git log -1 --format=%h --no-show-signature
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
|
@ -198,13 +210,13 @@ ENDIF( UNIX )
|
|||
# Grouped compiler settings
|
||||
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
|
||||
# hide all not-exported symbols
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -std=c++0x")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fPIC -fno-strict-aliasing -Wall -std=c++0x ${CMAKE_CXX_FLAGS}")
|
||||
SET(CMAKE_C_FLAGS "-fPIC -fno-strict-aliasing ${CMAKE_C_FLAGS}")
|
||||
SET(LIBSTDC++_LIBRARIES -lstdc++)
|
||||
ELSEIF(MSVC)
|
||||
# enable multi-core compilation with MSVC
|
||||
ADD_COMPILE_OPTIONS(/MP)
|
||||
IF("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
ADD_COMPILE_OPTIONS( /bigobj )
|
||||
ENDIF()
|
||||
# disable "elements of array '' will be default initialized" warning on MSVC2013
|
||||
|
@ -212,19 +224,26 @@ ELSEIF(MSVC)
|
|||
ADD_COMPILE_OPTIONS(/wd4351)
|
||||
ENDIF()
|
||||
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" )
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
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 "-fPIC -fno-strict-aliasing ${CMAKE_C_FLAGS}")
|
||||
ELSEIF( CMAKE_COMPILER_IS_MINGW )
|
||||
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -std=c++11" )
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
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 "-fPIC -fno-strict-aliasing ${CMAKE_C_FLAGS} ")
|
||||
ADD_DEFINITIONS( -U__STRICT_ANSI__ )
|
||||
ENDIF()
|
||||
|
||||
IF (IOS)
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
|
||||
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_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
|
||||
ENDIF()
|
||||
|
||||
ENDIF( IOS )
|
||||
|
||||
IF (ASSIMP_COVERALLS)
|
||||
MESSAGE(STATUS "Coveralls enabled")
|
||||
INCLUDE(Coveralls)
|
||||
|
@ -320,6 +339,8 @@ IF( NOT ZLIB_FOUND )
|
|||
SET(ZLIB_FOUND 1)
|
||||
SET(ZLIB_LIBRARIES zlibstatic)
|
||||
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)
|
||||
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
|
||||
SET(ZLIB_LIBRARIES_LINKED -lz)
|
||||
|
@ -327,7 +348,17 @@ ENDIF(NOT ZLIB_FOUND)
|
|||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
|
||||
|
||||
# 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 )
|
||||
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
|
||||
|
@ -412,32 +443,9 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
|
|||
ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
|
||||
|
||||
ADD_SUBDIRECTORY( tools/assimp_cmd/ )
|
||||
|
||||
# Check dependencies for assimp_qt_viewer.
|
||||
# Why here? Maybe user do not want Qt viewer and have no Qt.
|
||||
# Why assimp_qt_viewer/CMakeLists.txt still contain similar check?
|
||||
# Because viewer can be build independently of Assimp.
|
||||
FIND_PACKAGE(Qt5Widgets QUIET)
|
||||
FIND_PACKAGE(DevIL QUIET)
|
||||
FIND_PACKAGE(OpenGL QUIET)
|
||||
IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
|
||||
ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
|
||||
ELSE()
|
||||
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
|
||||
IF (NOT Qt5_FOUND)
|
||||
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5")
|
||||
ENDIF (NOT Qt5_FOUND)
|
||||
|
||||
IF (NOT IL_FOUND)
|
||||
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL")
|
||||
ENDIF (NOT IL_FOUND)
|
||||
|
||||
IF (NOT OPENGL_FOUND)
|
||||
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL")
|
||||
ENDIF (NOT OPENGL_FOUND)
|
||||
|
||||
MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}")
|
||||
ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
|
||||
IF (NOT IOS)
|
||||
ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
|
||||
ENDIF (NOT IOS)
|
||||
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
|
||||
|
||||
IF ( ASSIMP_BUILD_SAMPLES)
|
||||
|
|
|
@ -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.
|
||||
|
|
3
INSTALL
3
INSTALL
|
@ -42,3 +42,6 @@ For Windows:
|
|||
1. Open a command prompt
|
||||
2. cmake CMakeLists.txt
|
||||
2. Open your default IDE and build it
|
||||
|
||||
For iOS:
|
||||
Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS
|
||||
|
|
|
@ -30,6 +30,8 @@ One-off donations via PayPal:
|
|||
|
||||
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 ####
|
||||
|
||||
__Importers__:
|
||||
|
|
|
@ -32,6 +32,9 @@ install:
|
|||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
|
||||
- if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
|
||||
- cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%"
|
||||
- set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
|
||||
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe
|
||||
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe
|
||||
|
||||
cache:
|
||||
- code\assimp.dir\%CONFIGURATION%
|
||||
|
@ -50,6 +53,7 @@ build:
|
|||
project: Assimp.sln
|
||||
|
||||
after_build:
|
||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss
|
||||
- 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\*
|
||||
|
||||
test_script:
|
||||
|
|
|
@ -204,8 +204,9 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
|
|||
mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
|
||||
|
||||
// Setup the texture mapping mode
|
||||
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
|
||||
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
|
||||
int mapMode = static_cast<int>(texture.mMapMode);
|
||||
mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
|
||||
mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
|
||||
|
||||
// Mirroring - double the scaling values
|
||||
// FIXME: this is not really correct ...
|
||||
|
@ -313,7 +314,8 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
|
|||
case D3DS::Discreet3DS::Blinn :
|
||||
eShading = aiShadingMode_Blinn; break;
|
||||
}
|
||||
mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
|
||||
int eShading_ = static_cast<int>(eShading);
|
||||
mat.AddProperty<int>(&eShading_, 1, AI_MATKEY_SHADING_MODEL);
|
||||
|
||||
// DIFFUSE texture
|
||||
if( oldMat.sTexDiffuse.mMapName.length() > 0)
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace D3DS {
|
|||
*/
|
||||
class Discreet3DS {
|
||||
private:
|
||||
Discreet3DS() {
|
||||
Discreet3DS() AI_NO_EXCEPT {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -328,19 +328,17 @@ struct Face : public FaceWithSmoothingGroup
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper structure representing a texture */
|
||||
struct Texture
|
||||
{
|
||||
struct Texture {
|
||||
//! Default constructor
|
||||
Texture()
|
||||
: mOffsetU (0.0)
|
||||
, mOffsetV (0.0)
|
||||
, mScaleU (1.0)
|
||||
, mScaleV (1.0)
|
||||
, mRotation (0.0)
|
||||
, mMapMode (aiTextureMapMode_Wrap)
|
||||
, bPrivate()
|
||||
, iUVSrc (0)
|
||||
{
|
||||
Texture() AI_NO_EXCEPT
|
||||
: mOffsetU (0.0)
|
||||
, mOffsetV (0.0)
|
||||
, mScaleU (1.0)
|
||||
, mScaleV (1.0)
|
||||
, mRotation (0.0)
|
||||
, mMapMode (aiTextureMapMode_Wrap)
|
||||
, bPrivate()
|
||||
, iUVSrc (0) {
|
||||
mTextureBlend = get_qnan();
|
||||
}
|
||||
|
||||
|
@ -394,7 +392,7 @@ struct Material
|
|||
|
||||
|
||||
//! 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))
|
||||
, mDiffuse(std::move(other.mDiffuse))
|
||||
, 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) {
|
||||
return *this;
|
||||
}
|
||||
|
@ -447,7 +445,7 @@ struct Material
|
|||
}
|
||||
|
||||
|
||||
~Material() {}
|
||||
virtual ~Material() {}
|
||||
|
||||
|
||||
//! Name of the material
|
||||
|
|
|
@ -71,7 +71,7 @@ static const aiImporterDesc desc = {
|
|||
0,
|
||||
0,
|
||||
0,
|
||||
"3ds prj 3DS PRJ"
|
||||
"3ds prj"
|
||||
};
|
||||
|
||||
|
||||
|
@ -127,7 +127,7 @@ Discreet3DSImporter::~Discreet3DSImporter() {
|
|||
// Returns whether the class can handle the format of the given file.
|
||||
bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
|
||||
std::string extension = GetExtension(pFile);
|
||||
if(extension == "3ds" || extension == "3DS" || extension == "prj"|| extension == "PRJ" ) {
|
||||
if(extension == "3ds" || extension == "prj") {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,8 +63,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// Header files, stdlib.
|
||||
#include <set>
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Assimp {
|
||||
|
||||
/// \class AMFImporter
|
||||
/// Class that holding scene graph which include: geometry, metadata, materials etc.
|
||||
///
|
||||
|
@ -99,100 +99,49 @@ namespace Assimp
|
|||
/// new - <texmap> and children <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>
|
||||
/// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3>
|
||||
///
|
||||
class AMFImporter : public BaseImporter
|
||||
{
|
||||
/***********************************************/
|
||||
/******************** Types ********************/
|
||||
/***********************************************/
|
||||
|
||||
class AMFImporter : public BaseImporter {
|
||||
private:
|
||||
struct SPP_Material;// forward declaration
|
||||
|
||||
struct SPP_Material;// forward declaration
|
||||
/// \struct SPP_Composite
|
||||
/// Data type for post-processing step. More suitable container for part of material's composition.
|
||||
struct SPP_Composite {
|
||||
SPP_Material* Material;///< Pointer to material - part of composition.
|
||||
std::string Formula;///< Formula for calculating ratio of \ref Material.
|
||||
};
|
||||
|
||||
/// \struct SPP_Composite
|
||||
/// Data type for postprocessing step. More suitable container for part of material's composition.
|
||||
struct SPP_Composite
|
||||
{
|
||||
SPP_Material* Material;///< Pointer to material - part of composition.
|
||||
std::string Formula;///< Formula for calculating ratio of \ref Material.
|
||||
};
|
||||
/// \struct SPP_Material
|
||||
/// Data type for post-processing step. More suitable container for material.
|
||||
struct SPP_Material {
|
||||
std::string ID;///< Material ID.
|
||||
std::list<CAMFImporter_NodeElement_Metadata*> Metadata;///< Metadata 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.
|
||||
|
||||
/// \struct SPP_Material
|
||||
/// Data type for postprocessing step. More suitable container for material.
|
||||
struct SPP_Material
|
||||
{
|
||||
std::string ID;///< Material ID.
|
||||
std::list<CAMFImporter_NodeElement_Metadata*> Metadata;///< Metadata 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.
|
||||
/// Return color calculated for specified coordinate.
|
||||
/// \param [in] pX - "x" coordinate.
|
||||
/// \param [in] pY - "y" coordinate.
|
||||
/// \param [in] pZ - "z" coordinate.
|
||||
/// \return calculated color.
|
||||
aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
|
||||
};
|
||||
|
||||
/// \fn aiColor4D GetColor(const float pX, const float pY, const float pZ) const
|
||||
/// Return color calculated for specified coordinate.
|
||||
/// \param [in] pX - "x" coordinate.
|
||||
/// \param [in] pY - "y" coordinate.
|
||||
/// \param [in] pZ - "z" coordinate.
|
||||
/// \return calculated color.
|
||||
aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
|
||||
};
|
||||
/// Data type for post-processing step. More suitable container for texture.
|
||||
struct SPP_Texture {
|
||||
std::string ID;
|
||||
size_t Width, Height, Depth;
|
||||
bool Tiled;
|
||||
char FormatHint[9];// 8 for string + 1 for terminator.
|
||||
uint8_t *Data;
|
||||
};
|
||||
|
||||
/// \struct SPP_Texture
|
||||
/// Data type for post-processing step. More suitable container for texture.
|
||||
struct SPP_Texture
|
||||
{
|
||||
std::string ID;
|
||||
size_t Width, Height, Depth;
|
||||
bool Tiled;
|
||||
char FormatHint[ 9 ];// 8 for string + 1 for terminator.
|
||||
uint8_t *Data;
|
||||
};
|
||||
/// Data type for post-processing step. Contain face data.
|
||||
struct SComplexFace {
|
||||
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_TexMap* TexMap;///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
|
||||
};
|
||||
|
||||
/// \struct SComplexFace
|
||||
/// Data type for post-processing step. Contain face data.
|
||||
struct SComplexFace
|
||||
{
|
||||
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_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.
|
||||
void Clear();
|
||||
|
||||
|
@ -200,7 +149,6 @@ private:
|
|||
/************* 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).
|
||||
/// \param [in] pID - ID(name) of requested node element.
|
||||
/// \param [in] pType - type of node element.
|
||||
|
@ -208,7 +156,6 @@ private:
|
|||
/// \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;
|
||||
|
||||
/// \fn bool Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const
|
||||
/// Find requested aiNode in node list.
|
||||
/// \param [in] pID - ID(name) of requested node.
|
||||
/// \param [in] pNodeList - list of nodes where to find the node.
|
||||
|
@ -216,15 +163,13 @@ private:
|
|||
/// \return true - if the node is found, else - false.
|
||||
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.
|
||||
/// \param [in] pID - material ID.
|
||||
/// \param [out] pConvertedMaterial - pointer to found converted material (\ref SPP_Material).
|
||||
/// \return true - if the material is found, else - false.
|
||||
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_G - ID of source "green" texture.
|
||||
/// \param [in] pID_B - ID of source "blue" 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,
|
||||
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.
|
||||
/// \param [in] pNodeElement - reference to node element which kept <object> data.
|
||||
/// \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,
|
||||
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
|
||||
/// 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.
|
||||
|
@ -260,27 +200,23 @@ private:
|
|||
/// \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);
|
||||
|
||||
/// \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).
|
||||
/// \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.
|
||||
/// \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);
|
||||
|
||||
/// \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.
|
||||
/// \param [in] pMetadataList - reference to list with collected metadata.
|
||||
/// \param [out] pSceneNode - scene node in which metadata will be added.
|
||||
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>.
|
||||
/// \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] pSceneNode - pointer to place where new aiNode will be created.
|
||||
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>.
|
||||
/// \param [in] pNodeElement - reference to node element which kept <mesh> data.
|
||||
/// \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,
|
||||
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.
|
||||
/// \param [in] pMaterial - source CAMFImporter_NodeElement_Material.
|
||||
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>.
|
||||
/// \param [in] pConstellation - reference to <constellation> node.
|
||||
/// \param [out] pNodeList - reference to aiNode's list.
|
||||
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.
|
||||
/// \param [out] pScene - pointer to aiScene where tree will be built.
|
||||
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.
|
||||
/// E.g.:
|
||||
/// <amf>
|
||||
|
@ -324,19 +253,16 @@ private:
|
|||
/// \param [in] pNode - node name in which exception happened.
|
||||
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.
|
||||
/// \param [in] pAttrName - attribute name.
|
||||
/// \throw DeadlyImportError.
|
||||
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.
|
||||
/// \param [in] pAttrName - attribute name.
|
||||
/// \throw DeadlyImportError.
|
||||
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.
|
||||
/// E.g.:
|
||||
/// <object>
|
||||
|
@ -348,204 +274,158 @@ private:
|
|||
/// \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);
|
||||
|
||||
/// \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.
|
||||
/// \param [in] pID - ID of of element which not found.
|
||||
/// \throw DeadlyImportError.
|
||||
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.
|
||||
void XML_CheckNode_MustHaveChildren();
|
||||
|
||||
/// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName)
|
||||
/// Check if current node name is equal to pNodeName.
|
||||
/// \param [in] pNodeName - name for checking.
|
||||
/// return true if current node name is equal to pNodeName, else - false.
|
||||
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.
|
||||
/// \param [in] pParentNodeName - parent node name. Used for reporting.
|
||||
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.
|
||||
/// \param [in] pNodeName - requested node name.
|
||||
/// return true - if node is found, else - false.
|
||||
bool XML_SearchNode(const std::string& pNodeName);
|
||||
|
||||
/// \fn bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \return read data.
|
||||
bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx);
|
||||
|
||||
/// \fn float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \return read data.
|
||||
float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx);
|
||||
|
||||
/// \fn uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \return read data.
|
||||
uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx);
|
||||
|
||||
/// \fn float XML_ReadNode_GetVal_AsFloat()
|
||||
/// Read node value.
|
||||
/// \return read data.
|
||||
float XML_ReadNode_GetVal_AsFloat();
|
||||
|
||||
/// \fn uint32_t XML_ReadNode_GetVal_AsU32()
|
||||
/// Read node value.
|
||||
/// \return read data.
|
||||
uint32_t XML_ReadNode_GetVal_AsU32();
|
||||
|
||||
/// \fn void XML_ReadNode_GetVal_AsString(std::string& pValue)
|
||||
/// Read node value.
|
||||
/// \return read data.
|
||||
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.
|
||||
/// \param [in] pNode - new current node.
|
||||
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.
|
||||
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
|
||||
/// must be converted to right form - "0.xxx".
|
||||
/// \param [in] pInStr - pointer to input string which can contain incorrect form of values.
|
||||
/// \param [out[ pOutString - output string with right form of values.
|
||||
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.
|
||||
/// \param [in] pInputBase64 - reference to input Base64-encoded string.
|
||||
/// \param [out] pOutputData - reference to output array for decoded data.
|
||||
void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const;
|
||||
|
||||
/// \fn void ParseNode_Root()
|
||||
/// Parse <AMF> node of the file.
|
||||
void ParseNode_Root();
|
||||
|
||||
/******** Functions: top nodes *********/
|
||||
|
||||
/// \fn void ParseNode_Constellation()
|
||||
/// Parse <constellation> node of the file.
|
||||
void ParseNode_Constellation();
|
||||
|
||||
/// \fn void ParseNode_Constellation()
|
||||
/// Parse <instance> node of the file.
|
||||
void ParseNode_Instance();
|
||||
|
||||
/// \fn void ParseNode_Material()
|
||||
/// Parse <material> node of the file.
|
||||
void ParseNode_Material();
|
||||
|
||||
/// \fn void ParseNode_Metadata()
|
||||
/// Parse <metadata> node.
|
||||
void ParseNode_Metadata();
|
||||
|
||||
/// \fn void ParseNode_Object()
|
||||
/// Parse <object> node of the file.
|
||||
void ParseNode_Object();
|
||||
|
||||
/// \fn void ParseNode_Texture()
|
||||
/// Parse <texture> node of the file.
|
||||
void ParseNode_Texture();
|
||||
|
||||
/******** Functions: geometry nodes *********/
|
||||
|
||||
/// \fn void ParseNode_Coordinates()
|
||||
/// Parse <coordinates> node of the file.
|
||||
void ParseNode_Coordinates();
|
||||
|
||||
/// \fn void ParseNode_Edge()
|
||||
/// Parse <edge> node of the file.
|
||||
void ParseNode_Edge();
|
||||
|
||||
/// \fn void ParseNode_Mesh()
|
||||
/// Parse <mesh> node of the file.
|
||||
void ParseNode_Mesh();
|
||||
|
||||
/// \fn void ParseNode_Triangle()
|
||||
/// Parse <triangle> node of the file.
|
||||
void ParseNode_Triangle();
|
||||
|
||||
/// \fn void ParseNode_Vertex()
|
||||
/// Parse <vertex> node of the file.
|
||||
void ParseNode_Vertex();
|
||||
|
||||
/// \fn void ParseNode_Vertices()
|
||||
/// Parse <vertices> node of the file.
|
||||
void ParseNode_Vertices();
|
||||
|
||||
/// \fn void ParseNode_Volume()
|
||||
/// Parse <volume> node of the file.
|
||||
void ParseNode_Volume();
|
||||
|
||||
/******** Functions: material nodes *********/
|
||||
|
||||
/// \fn void ParseNode_Color()
|
||||
/// Parse <color> node of the file.
|
||||
void ParseNode_Color();
|
||||
|
||||
/// \fn void ParseNode_TexMap(const bool pUseOldName = false)
|
||||
/// 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>.
|
||||
void ParseNode_TexMap(const bool pUseOldName = false);
|
||||
|
||||
public:
|
||||
|
||||
/// \fn AMFImporter()
|
||||
/// Default constructor.
|
||||
AMFImporter()
|
||||
: mNodeElement_Cur(nullptr), mReader(nullptr)
|
||||
{}
|
||||
AMFImporter() AI_NO_EXCEPT
|
||||
: mNodeElement_Cur(nullptr)
|
||||
, mReader(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
/// \fn ~AMFImporter()
|
||||
/// Default destructor.
|
||||
~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.
|
||||
/// 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] pIOHandler - pointer to IO helper object.
|
||||
void ParseFile(const std::string& pFile, IOSystem* pIOHandler);
|
||||
|
||||
/***********************************************/
|
||||
/********* Functions: BaseImporter set *********/
|
||||
/***********************************************/
|
||||
|
||||
bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const;
|
||||
void GetExtensionList(std::set<std::string>& pExtensionList);
|
||||
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
|
||||
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
|
||||
|
||||
|
|
|
@ -68,10 +68,9 @@ namespace Assimp
|
|||
// Multi elements - No.
|
||||
// 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.
|
||||
void AMFImporter::ParseNode_Color()
|
||||
{
|
||||
std::string profile;
|
||||
CAMFImporter_NodeElement* ne;
|
||||
void AMFImporter::ParseNode_Color() {
|
||||
std::string profile;
|
||||
CAMFImporter_NodeElement* ne;
|
||||
|
||||
// Read attributes for node <color>.
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
|
@ -98,15 +97,19 @@ CAMFImporter_NodeElement* ne;
|
|||
MACRO_NODECHECK_LOOPEND("color");
|
||||
ParseHelper_Node_Exit();
|
||||
// check that all components was defined
|
||||
if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
|
||||
// check if <a> is absent. Then manually add "a == 1".
|
||||
if(!read_flag[3]) als.Color.a = 1;
|
||||
if (!(read_flag[0] && read_flag[1] && read_flag[2])) {
|
||||
throw DeadlyImportError("Not all color components are defined.");
|
||||
}
|
||||
|
||||
}// if(!mReader->isEmptyElement())
|
||||
// check if <a> is absent. Then manually add "a == 1".
|
||||
if (!read_flag[3]) {
|
||||
als.Color.a = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
|
||||
}// if(!mReader->isEmptyElement()) else
|
||||
}
|
||||
|
||||
als.Composed = false;
|
||||
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.
|
||||
// Multi elements - Yes.
|
||||
// Parent element - <amf>.
|
||||
void AMFImporter::ParseNode_Material()
|
||||
{
|
||||
std::string id;
|
||||
CAMFImporter_NodeElement* ne;
|
||||
void AMFImporter::ParseNode_Material() {
|
||||
std::string id;
|
||||
CAMFImporter_NodeElement* ne;
|
||||
|
||||
// Read attributes for node <color>.
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
|
@ -131,9 +133,11 @@ CAMFImporter_NodeElement* ne;
|
|||
|
||||
// create new object.
|
||||
ne = new CAMFImporter_NodeElement_Material(mNodeElement_Cur);
|
||||
// and assign read data
|
||||
|
||||
// and assign read data
|
||||
((CAMFImporter_NodeElement_Material*)ne)->ID = id;
|
||||
// Check for child nodes
|
||||
|
||||
// Check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
bool col_read = false;
|
||||
|
@ -154,11 +158,11 @@ CAMFImporter_NodeElement* ne;
|
|||
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
|
||||
MACRO_NODECHECK_LOOPEND("material");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
}
|
||||
else
|
||||
{
|
||||
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.
|
||||
}
|
||||
|
@ -181,14 +185,13 @@ CAMFImporter_NodeElement* ne;
|
|||
// Parent element - <amf>.
|
||||
void AMFImporter::ParseNode_Texture()
|
||||
{
|
||||
std::string id;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
uint32_t depth = 1;
|
||||
std::string type;
|
||||
bool tiled = false;
|
||||
std::string enc64_data;
|
||||
CAMFImporter_NodeElement* ne;
|
||||
std::string id;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
uint32_t depth = 1;
|
||||
std::string type;
|
||||
bool tiled = false;
|
||||
std::string enc64_data;
|
||||
|
||||
// Read attributes for node <color>.
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
|
@ -201,20 +204,34 @@ CAMFImporter_NodeElement* ne;
|
|||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
if(id.empty()) throw DeadlyImportError("ID for texture must be defined.");
|
||||
if(width < 1) Throw_IncorrectAttrValue("width");
|
||||
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.");
|
||||
if (id.empty()) {
|
||||
throw DeadlyImportError("ID for texture must be defined.");
|
||||
}
|
||||
if (width < 1) {
|
||||
Throw_IncorrectAttrValue("width");
|
||||
}
|
||||
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
|
||||
als.ID = id;
|
||||
als.Width = width;
|
||||
|
@ -222,8 +239,11 @@ CAMFImporter_NodeElement* ne;
|
|||
als.Depth = depth;
|
||||
als.Tiled = tiled;
|
||||
ParseHelper_Decode_Base64(enc64_data, als.Data);
|
||||
// check data size
|
||||
if((width * height * depth) != als.Data.size()) throw DeadlyImportError("Texture has incorrect data size.");
|
||||
|
||||
// check 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_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>.
|
||||
// Multi elements - No.
|
||||
// Texture coordinates for every vertex of triangle.
|
||||
void AMFImporter::ParseNode_TexMap(const bool pUseOldName)
|
||||
{
|
||||
std::string rtexid, gtexid, btexid, atexid;
|
||||
CAMFImporter_NodeElement* ne;
|
||||
void AMFImporter::ParseNode_TexMap(const bool pUseOldName) {
|
||||
std::string rtexid, gtexid, btexid, atexid;
|
||||
|
||||
// Read attributes for node <color>.
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
|
@ -257,7 +275,7 @@ CAMFImporter_NodeElement* ne;
|
|||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// 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
|
||||
// check data
|
||||
|
|
|
@ -62,7 +62,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
/// \class CAMFImporter_NodeElement
|
||||
/// Base class for elements of nodes.
|
||||
class CAMFImporter_NodeElement {
|
||||
|
||||
public:
|
||||
/// Define what data type contain node element.
|
||||
enum EType {
|
||||
|
@ -96,15 +95,11 @@ public: /// Destructor, virtual..
|
|||
// empty
|
||||
}
|
||||
|
||||
private:
|
||||
/// Disabled copy constructor.
|
||||
CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement);
|
||||
|
||||
/// Disabled assign operator.
|
||||
CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement);
|
||||
|
||||
/// Disabled default constructor.
|
||||
CAMFImporter_NodeElement();
|
||||
/// Disabled copy constructor and co.
|
||||
CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement) = delete;
|
||||
CAMFImporter_NodeElement(CAMFImporter_NodeElement&&) = delete;
|
||||
CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement) = delete;
|
||||
CAMFImporter_NodeElement() = delete;
|
||||
|
||||
protected:
|
||||
/// In constructor inheritor must set element type.
|
||||
|
@ -121,9 +116,7 @@ protected:
|
|||
|
||||
/// \struct CAMFImporter_NodeElement_Constellation
|
||||
/// A collection of objects or constellations with specific relative locations.
|
||||
struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement
|
||||
{
|
||||
/// \fn CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent)
|
||||
struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement {
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent)
|
||||
|
@ -134,9 +127,7 @@ struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement
|
|||
|
||||
/// \struct CAMFImporter_NodeElement_Instance
|
||||
/// Part of constellation.
|
||||
struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement
|
||||
{
|
||||
/****************** Variables ******************/
|
||||
struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement {
|
||||
|
||||
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
|
||||
|
@ -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.
|
||||
aiVector3D Rotation;
|
||||
|
||||
/****************** Functions ******************/
|
||||
|
||||
/// \fn CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Instance, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Instance
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Metadata
|
||||
/// Structure that define metadata node.
|
||||
struct CAMFImporter_NodeElement_Metadata : public CAMFImporter_NodeElement
|
||||
{
|
||||
/****************** Variables ******************/
|
||||
struct CAMFImporter_NodeElement_Metadata : public CAMFImporter_NodeElement {
|
||||
|
||||
std::string Type;///< Type of "Value".
|
||||
std::string Type;///< Type of "Value".
|
||||
std::string Value;///< Value.
|
||||
|
||||
/****************** Functions ******************/
|
||||
|
||||
/// \fn CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Metadata, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Metadata
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Root
|
||||
/// Structure that define root node.
|
||||
struct CAMFImporter_NodeElement_Root : public CAMFImporter_NodeElement
|
||||
{
|
||||
/****************** Variables ******************/
|
||||
struct CAMFImporter_NodeElement_Root : public CAMFImporter_NodeElement {
|
||||
|
||||
std::string Unit;///< The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
|
||||
std::string Version;///< Version of format.
|
||||
|
||||
/****************** Functions ******************/
|
||||
|
||||
/// \fn CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Root, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Root
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Color
|
||||
/// Structure that define object node.
|
||||
struct CAMFImporter_NodeElement_Color : public CAMFImporter_NodeElement
|
||||
{
|
||||
/****************** Variables ******************/
|
||||
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.
|
||||
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.
|
||||
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>..
|
||||
|
||||
/****************** Functions ******************/
|
||||
|
||||
/// \fn CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// @brief Constructor.
|
||||
/// @param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Color, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Color
|
||||
: CAMFImporter_NodeElement(ENET_Color, pParent)
|
||||
, Composed( false )
|
||||
, Color()
|
||||
, Profile() {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Material
|
||||
/// Structure that define material node.
|
||||
struct CAMFImporter_NodeElement_Material : public CAMFImporter_NodeElement
|
||||
{
|
||||
/// \fn CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent)
|
||||
struct CAMFImporter_NodeElement_Material : public CAMFImporter_NodeElement {
|
||||
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Material, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Material
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Object
|
||||
/// Structure that define object node.
|
||||
struct CAMFImporter_NodeElement_Object : public CAMFImporter_NodeElement
|
||||
{
|
||||
/// \fn CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
struct CAMFImporter_NodeElement_Object : public CAMFImporter_NodeElement {
|
||||
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Object, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Object
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Mesh
|
||||
/// Structure that define mesh node.
|
||||
struct CAMFImporter_NodeElement_Mesh : public CAMFImporter_NodeElement
|
||||
{
|
||||
/// \fn CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent)
|
||||
struct CAMFImporter_NodeElement_Mesh : public CAMFImporter_NodeElement {
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Mesh, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Mesh
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Vertex
|
||||
/// Structure that define vertex node.
|
||||
struct CAMFImporter_NodeElement_Vertex : public CAMFImporter_NodeElement
|
||||
{
|
||||
/// \fn CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent)
|
||||
struct CAMFImporter_NodeElement_Vertex : public CAMFImporter_NodeElement {
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Vertex, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Vertex
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Edge
|
||||
/// Structure that define edge node.
|
||||
struct CAMFImporter_NodeElement_Edge : public CAMFImporter_NodeElement
|
||||
{
|
||||
/// \fn CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent)
|
||||
struct CAMFImporter_NodeElement_Edge : public CAMFImporter_NodeElement {
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Edge, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Vertex
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Vertices
|
||||
/// Structure that define vertices node.
|
||||
struct CAMFImporter_NodeElement_Vertices : public CAMFImporter_NodeElement
|
||||
{
|
||||
/// \fn CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent)
|
||||
struct CAMFImporter_NodeElement_Vertices : public CAMFImporter_NodeElement {
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Vertices, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Vertices
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Volume
|
||||
/// Structure that define volume node.
|
||||
struct CAMFImporter_NodeElement_Volume : public CAMFImporter_NodeElement
|
||||
{
|
||||
/****************** Variables ******************/
|
||||
|
||||
struct CAMFImporter_NodeElement_Volume : public CAMFImporter_NodeElement {
|
||||
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.
|
||||
|
||||
/****************** Functions ******************/
|
||||
|
||||
/// \fn CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Volume, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Volume
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Coordinates
|
||||
/// Structure that define coordinates node.
|
||||
struct CAMFImporter_NodeElement_Coordinates : public CAMFImporter_NodeElement
|
||||
{
|
||||
/****************** Variables ******************/
|
||||
|
||||
aiVector3D Coordinate;///< Coordinate.
|
||||
|
||||
/****************** Functions ******************/
|
||||
|
||||
/// \fn CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Coordinates, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Coordinates
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_TexMap
|
||||
/// Structure that define texture coordinates node.
|
||||
struct CAMFImporter_NodeElement_TexMap : public CAMFImporter_NodeElement
|
||||
{
|
||||
/****************** Variables ******************/
|
||||
|
||||
struct CAMFImporter_NodeElement_TexMap : public CAMFImporter_NodeElement {
|
||||
aiVector3D TextureCoordinate[3];///< Texture coordinates.
|
||||
std::string TextureID_R;///< Texture ID for red 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_A;///< Texture ID for alpha color component.
|
||||
|
||||
/****************** Functions ******************/
|
||||
|
||||
/// \fn CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_TexMap, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_TexMap
|
||||
: CAMFImporter_NodeElement(ENET_TexMap, pParent)
|
||||
, TextureCoordinate{}
|
||||
, TextureID_R()
|
||||
, TextureID_G()
|
||||
, TextureID_B()
|
||||
, TextureID_A() {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/// \struct CAMFImporter_NodeElement_Triangle
|
||||
/// Structure that define triangle node.
|
||||
struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement
|
||||
{
|
||||
/****************** Variables ******************/
|
||||
|
||||
struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement {
|
||||
size_t V[3];///< Triangle vertices.
|
||||
|
||||
/****************** Functions ******************/
|
||||
|
||||
/// \fn CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent)
|
||||
: CAMFImporter_NodeElement(ENET_Triangle, pParent)
|
||||
{}
|
||||
|
||||
};// struct CAMFImporter_NodeElement_Triangle
|
||||
: CAMFImporter_NodeElement(ENET_Triangle, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/// Structure that define texture node.
|
||||
struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement {
|
||||
|
@ -396,6 +335,6 @@ struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement {
|
|||
, Tiled( false ){
|
||||
// empty
|
||||
}
|
||||
};// struct CAMFImporter_NodeElement_Texture
|
||||
};
|
||||
|
||||
#endif // INCLUDED_AI_AMF_IMPORTER_NODE_H
|
||||
|
|
113
code/ASEParser.h
113
code/ASEParser.h
|
@ -71,21 +71,20 @@ struct Material : public D3DS::Material
|
|||
//! Default constructor has been deleted
|
||||
Material() = delete;
|
||||
|
||||
|
||||
//! Constructor with explicit name
|
||||
explicit Material(const std::string &name)
|
||||
: D3DS::Material(name)
|
||||
, pcInstance(NULL)
|
||||
, bNeed (false)
|
||||
{}
|
||||
|
||||
, bNeed (false) {
|
||||
// empty
|
||||
}
|
||||
|
||||
Material(const Material &other) = default;
|
||||
Material &operator=(const Material &other) = default;
|
||||
|
||||
|
||||
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
|
||||
Material(Material &&other)
|
||||
Material(Material &&other) AI_NO_EXCEPT
|
||||
: D3DS::Material(std::move(other))
|
||||
, avSubMaterials(std::move(other.avSubMaterials))
|
||||
, 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) {
|
||||
return *this;
|
||||
}
|
||||
|
@ -127,19 +126,12 @@ struct Material : public D3DS::Material
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper structure to represent an ASE file face */
|
||||
struct Face : public FaceWithSmoothingGroup
|
||||
{
|
||||
struct Face : public FaceWithSmoothingGroup {
|
||||
//! Default constructor. Initializes everything with 0
|
||||
Face()
|
||||
{
|
||||
mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0;
|
||||
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
{
|
||||
amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0;
|
||||
}
|
||||
|
||||
iMaterial = DEFAULT_MATINDEX;
|
||||
iFace = 0;
|
||||
Face() AI_NO_EXCEPT
|
||||
: iMaterial(DEFAULT_MATINDEX)
|
||||
, iFace(0) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! special value to indicate that no material index has
|
||||
|
@ -147,8 +139,6 @@ struct Face : public FaceWithSmoothingGroup
|
|||
//! will replace this value later.
|
||||
static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF;
|
||||
|
||||
|
||||
|
||||
//! Indices into each list of texture coordinates
|
||||
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 */
|
||||
struct Bone
|
||||
{
|
||||
struct Bone {
|
||||
//! Constructor
|
||||
Bone() = delete;
|
||||
|
||||
//! Construction from an existing name
|
||||
explicit Bone( const std::string& name)
|
||||
: mName (name)
|
||||
{}
|
||||
: mName(name) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Name of the bone
|
||||
std::string mName;
|
||||
|
@ -182,29 +172,22 @@ struct Bone
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper structure to represent an ASE file bone vertex */
|
||||
struct BoneVertex
|
||||
{
|
||||
struct BoneVertex {
|
||||
//! Bone and corresponding vertex weight.
|
||||
//! -1 for unrequired bones ....
|
||||
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 */
|
||||
struct Animation
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
struct Animation {
|
||||
enum Type {
|
||||
TRACK = 0x0,
|
||||
BEZIER = 0x1,
|
||||
TCB = 0x2
|
||||
} mRotationType, mScalingType, mPositionType;
|
||||
|
||||
Animation()
|
||||
Animation() AI_NO_EXCEPT
|
||||
: mRotationType (TRACK)
|
||||
, mScalingType (TRACK)
|
||||
, mPositionType (TRACK)
|
||||
|
@ -218,19 +201,16 @@ struct Animation
|
|||
|
||||
//! List of track scaling keyframes
|
||||
std::vector< aiVectorKey > akeyScaling;
|
||||
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper structure to represent the inheritance information of an ASE node */
|
||||
struct InheritanceInfo
|
||||
{
|
||||
struct InheritanceInfo {
|
||||
//! Default constructor
|
||||
InheritanceInfo()
|
||||
{
|
||||
// set the inheritance flag for all axes by default to true
|
||||
for (unsigned int i = 0; i < 3;++i)
|
||||
InheritanceInfo() AI_NO_EXCEPT {
|
||||
for ( size_t i=0; i<3; ++i ) {
|
||||
abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
//! Inherit the parent's position?, axis order is x,y,z
|
||||
|
@ -245,17 +225,19 @@ struct InheritanceInfo
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Represents an ASE file node. Base class for mesh, light and cameras */
|
||||
struct BaseNode
|
||||
{
|
||||
enum Type {Light, Camera, Mesh, Dummy} mType;
|
||||
|
||||
struct BaseNode {
|
||||
enum Type {
|
||||
Light,
|
||||
Camera,
|
||||
Mesh,
|
||||
Dummy
|
||||
} mType;
|
||||
|
||||
//! Construction from an existing name
|
||||
BaseNode(Type _mType, const std::string &name)
|
||||
: mType (_mType)
|
||||
, mName (name)
|
||||
, mProcessed (false)
|
||||
{
|
||||
, mProcessed (false) {
|
||||
// Set mTargetPosition to qnan
|
||||
const ai_real qnan = get_qnan();
|
||||
mTargetPosition.x = qnan;
|
||||
|
@ -291,24 +273,23 @@ struct BaseNode
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** 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
|
||||
Mesh() = delete;
|
||||
|
||||
|
||||
//! Construction from an existing name
|
||||
explicit Mesh(const std::string &name)
|
||||
: BaseNode (BaseNode::Mesh, name)
|
||||
: BaseNode( BaseNode::Mesh, name )
|
||||
, mVertexColors()
|
||||
, mBoneVertices()
|
||||
, mBones()
|
||||
, iMaterialIndex(Face::DEFAULT_MATINDEX)
|
||||
, bSkip (false)
|
||||
{
|
||||
// use 2 texture vertex components by default
|
||||
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
|
||||
, bSkip (false) {
|
||||
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
|
||||
this->mNumUVComponents[c] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! List of all texture coordinate sets
|
||||
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) */
|
||||
struct Dummy : public BaseNode
|
||||
{
|
||||
struct Dummy : public BaseNode {
|
||||
//! Constructor
|
||||
Dummy()
|
||||
: BaseNode (BaseNode::Dummy, "DUMMY")
|
||||
{
|
||||
Dummy() AI_NO_EXCEPT
|
||||
: BaseNode (BaseNode::Dummy, "DUMMY") {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -416,12 +396,11 @@ struct Dummy : public BaseNode
|
|||
// -------------------------------------------------------------------------------
|
||||
/** \brief Class to parse ASE files
|
||||
*/
|
||||
class Parser
|
||||
{
|
||||
|
||||
class Parser {
|
||||
private:
|
||||
|
||||
Parser() {}
|
||||
Parser() AI_NO_EXCEPT {
|
||||
// empty
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -46,6 +46,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef 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
|
||||
|
|
|
@ -79,16 +79,17 @@ static const aiImporterDesc desc = {
|
|||
"assbin"
|
||||
};
|
||||
|
||||
const aiImporterDesc* AssbinImporter::GetInfo() const
|
||||
{
|
||||
// -----------------------------------------------------------------------------------
|
||||
const aiImporterDesc* AssbinImporter::GetInfo() const {
|
||||
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);
|
||||
if (!in)
|
||||
if (nullptr == in) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char s[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;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
T Read(IOStream * stream)
|
||||
{
|
||||
T Read(IOStream * stream) {
|
||||
T t;
|
||||
stream->Read( &t, sizeof(T), 1 );
|
||||
return t;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <>
|
||||
aiVector3D Read<aiVector3D>(IOStream * stream)
|
||||
{
|
||||
aiVector3D Read<aiVector3D>(IOStream * stream) {
|
||||
aiVector3D v;
|
||||
v.x = Read<float>(stream);
|
||||
v.y = Read<float>(stream);
|
||||
|
@ -116,9 +117,9 @@ aiVector3D Read<aiVector3D>(IOStream * stream)
|
|||
return v;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <>
|
||||
aiColor4D Read<aiColor4D>(IOStream * stream)
|
||||
{
|
||||
aiColor4D Read<aiColor4D>(IOStream * stream) {
|
||||
aiColor4D c;
|
||||
c.r = Read<float>(stream);
|
||||
c.g = Read<float>(stream);
|
||||
|
@ -127,9 +128,9 @@ aiColor4D Read<aiColor4D>(IOStream * stream)
|
|||
return c;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <>
|
||||
aiQuaternion Read<aiQuaternion>(IOStream * stream)
|
||||
{
|
||||
aiQuaternion Read<aiQuaternion>(IOStream * stream) {
|
||||
aiQuaternion v;
|
||||
v.w = Read<float>(stream);
|
||||
v.x = Read<float>(stream);
|
||||
|
@ -138,9 +139,9 @@ aiQuaternion Read<aiQuaternion>(IOStream * stream)
|
|||
return v;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <>
|
||||
aiString Read<aiString>(IOStream * stream)
|
||||
{
|
||||
aiString Read<aiString>(IOStream * stream) {
|
||||
aiString s;
|
||||
stream->Read(&s.length,4,1);
|
||||
stream->Read(s.data,s.length,1);
|
||||
|
@ -148,18 +149,18 @@ aiString Read<aiString>(IOStream * stream)
|
|||
return s;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <>
|
||||
aiVertexWeight Read<aiVertexWeight>(IOStream * stream)
|
||||
{
|
||||
aiVertexWeight Read<aiVertexWeight>(IOStream * stream) {
|
||||
aiVertexWeight w;
|
||||
w.mVertexId = Read<unsigned int>(stream);
|
||||
w.mWeight = Read<float>(stream);
|
||||
return w;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <>
|
||||
aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream)
|
||||
{
|
||||
aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream) {
|
||||
aiMatrix4x4 m;
|
||||
for (unsigned int i = 0; i < 4;++i) {
|
||||
for (unsigned int i2 = 0; i2 < 4;++i2) {
|
||||
|
@ -169,36 +170,43 @@ aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream)
|
|||
return m;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <>
|
||||
aiVectorKey Read<aiVectorKey>(IOStream * stream)
|
||||
{
|
||||
aiVectorKey Read<aiVectorKey>(IOStream * stream) {
|
||||
aiVectorKey v;
|
||||
v.mTime = Read<double>(stream);
|
||||
v.mValue = Read<aiVector3D>(stream);
|
||||
return v;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <>
|
||||
aiQuatKey Read<aiQuatKey>(IOStream * stream)
|
||||
{
|
||||
aiQuatKey Read<aiQuatKey>(IOStream * stream) {
|
||||
aiQuatKey v;
|
||||
v.mTime = Read<double>(stream);
|
||||
v.mValue = Read<aiQuaternion>(stream);
|
||||
return v;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
void ReadArray(IOStream * stream, T * out, unsigned int size)
|
||||
{
|
||||
for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream);
|
||||
void ReadArray( IOStream *stream, T * out, unsigned int size) {
|
||||
ai_assert( nullptr != stream );
|
||||
ai_assert( nullptr != out );
|
||||
|
||||
for (unsigned int i=0; i<size; i++) {
|
||||
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.
|
||||
stream->Seek( sizeof(T) * n, aiOrigin_CUR );
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) {
|
||||
uint32_t chunkID = Read<uint32_t>(stream);
|
||||
(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);
|
||||
(void)(chunkID);
|
||||
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.
|
||||
// maybe I'll add a better, hash-like solution later
|
||||
if (shortened)
|
||||
{
|
||||
if (shortened) {
|
||||
ReadBounds(stream,b->mWeights,b->mNumWeights);
|
||||
} // else write as usual
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// else write as usual
|
||||
b->mWeights = new aiVertexWeight[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);
|
||||
(void)(chunkID);
|
||||
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
|
||||
unsigned int c = Read<unsigned int>(stream);
|
||||
|
||||
if (c & ASSBIN_MESH_HAS_POSITIONS)
|
||||
{
|
||||
if (c & ASSBIN_MESH_HAS_POSITIONS) {
|
||||
if (shortened) {
|
||||
ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
|
||||
} // else write as usual
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// else write as usual
|
||||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||
ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices);
|
||||
}
|
||||
}
|
||||
if (c & ASSBIN_MESH_HAS_NORMALS)
|
||||
{
|
||||
if (c & ASSBIN_MESH_HAS_NORMALS) {
|
||||
if (shortened) {
|
||||
ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
|
||||
} // else write as usual
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// else write as usual
|
||||
mesh->mNormals = new aiVector3D[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) {
|
||||
ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
|
||||
ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
|
||||
} // else write as usual
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// else write as usual
|
||||
mesh->mTangents = new aiVector3D[mesh->mNumVertices];
|
||||
ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices);
|
||||
mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
|
||||
ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices);
|
||||
}
|
||||
}
|
||||
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n)
|
||||
{
|
||||
if (!(c & ASSBIN_MESH_HAS_COLOR(n)))
|
||||
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
|
||||
if (!(c & ASSBIN_MESH_HAS_COLOR(n))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (shortened)
|
||||
{
|
||||
if (shortened) {
|
||||
ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
|
||||
} // else write as usual
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// else write as usual
|
||||
mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
|
||||
ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices);
|
||||
}
|
||||
}
|
||||
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
|
||||
{
|
||||
if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n)))
|
||||
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
|
||||
if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// write number of UV components
|
||||
mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
|
||||
|
||||
if (shortened) {
|
||||
ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
|
||||
} // else write as usual
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// else write as usual
|
||||
mesh->mTextureCoords[n] = new aiVector3D[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.
|
||||
if (shortened) {
|
||||
Read<unsigned int>(stream);
|
||||
}
|
||||
else // else write as usual
|
||||
{
|
||||
} else {
|
||||
// else write as usual
|
||||
// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
|
||||
mesh->mFaces = new aiFace[mesh->mNumFaces];
|
||||
for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
|
||||
|
@ -402,12 +401,10 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
|
|||
f.mIndices = new unsigned int[f.mNumIndices];
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
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);
|
||||
(void)(chunkID);
|
||||
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);
|
||||
(void)(chunkID);
|
||||
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);
|
||||
(void)(chunkID);
|
||||
ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM);
|
||||
|
@ -493,9 +488,8 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
|
|||
if (shortened) {
|
||||
ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
|
||||
|
||||
} // else write as usual
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// else write as usual
|
||||
nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
|
||||
ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys);
|
||||
}
|
||||
|
@ -504,19 +498,16 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
|
|||
if (shortened) {
|
||||
ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
|
||||
|
||||
} // else write as usual
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// else write as usual
|
||||
nd->mScalingKeys = new aiVectorKey[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);
|
||||
(void)(chunkID);
|
||||
ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION);
|
||||
|
@ -527,8 +518,7 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
|
|||
anim->mTicksPerSecond = Read<double> (stream);
|
||||
anim->mNumChannels = Read<unsigned int>(stream);
|
||||
|
||||
if (anim->mNumChannels)
|
||||
{
|
||||
if (anim->mNumChannels) {
|
||||
anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ];
|
||||
for (unsigned int a = 0; a < anim->mNumChannels;++a) {
|
||||
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);
|
||||
(void)(chunkID);
|
||||
ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE);
|
||||
|
@ -552,18 +542,15 @@ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
|
|||
if (!tex->mHeight) {
|
||||
tex->pcData = new aiTexel[ tex->mWidth ];
|
||||
stream->Read(tex->pcData,1,tex->mWidth);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ];
|
||||
stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
|
||||
{
|
||||
void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) {
|
||||
uint32_t chunkID = Read<uint32_t>(stream);
|
||||
(void)(chunkID);
|
||||
ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT);
|
||||
|
@ -586,12 +573,10 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
|
|||
l->mAngleInnerCone = 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);
|
||||
(void)(chunkID);
|
||||
ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA);
|
||||
|
@ -607,8 +592,8 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
|
|||
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);
|
||||
(void)(chunkID);
|
||||
ai_assert(chunkID == ASSBIN_CHUNK_AISCENE);
|
||||
|
@ -623,12 +608,11 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
|
|||
scene->mNumCameras = Read<unsigned int>(stream);
|
||||
|
||||
// Read node graph
|
||||
scene->mRootNode = new aiNode[1];
|
||||
//scene->mRootNode = new aiNode[1];
|
||||
ReadBinaryNode( stream, &scene->mRootNode, (aiNode*)NULL );
|
||||
|
||||
// Read all meshes
|
||||
if (scene->mNumMeshes)
|
||||
{
|
||||
if (scene->mNumMeshes) {
|
||||
scene->mMeshes = new aiMesh*[scene->mNumMeshes];
|
||||
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
|
||||
scene->mMeshes[i] = new aiMesh();
|
||||
|
@ -637,8 +621,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
|
|||
}
|
||||
|
||||
// Read materials
|
||||
if (scene->mNumMaterials)
|
||||
{
|
||||
if (scene->mNumMaterials) {
|
||||
scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
|
||||
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
|
||||
scene->mMaterials[i] = new aiMaterial();
|
||||
|
@ -647,8 +630,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
|
|||
}
|
||||
|
||||
// Read all animations
|
||||
if (scene->mNumAnimations)
|
||||
{
|
||||
if (scene->mNumAnimations) {
|
||||
scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
|
||||
for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
|
||||
scene->mAnimations[i] = new aiAnimation();
|
||||
|
@ -657,8 +639,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
|
|||
}
|
||||
|
||||
// Read all textures
|
||||
if (scene->mNumTextures)
|
||||
{
|
||||
if (scene->mNumTextures) {
|
||||
scene->mTextures = new aiTexture*[scene->mNumTextures];
|
||||
for (unsigned int i = 0; i < scene->mNumTextures;++i) {
|
||||
scene->mTextures[i] = new aiTexture();
|
||||
|
@ -667,8 +648,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
|
|||
}
|
||||
|
||||
// Read lights
|
||||
if (scene->mNumLights)
|
||||
{
|
||||
if (scene->mNumLights) {
|
||||
scene->mLights = new aiLight*[scene->mNumLights];
|
||||
for (unsigned int i = 0; i < scene->mNumLights;++i) {
|
||||
scene->mLights[i] = new aiLight();
|
||||
|
@ -677,8 +657,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
|
|||
}
|
||||
|
||||
// Read cameras
|
||||
if (scene->mNumCameras)
|
||||
{
|
||||
if (scene->mNumCameras) {
|
||||
scene->mCameras = new aiCamera*[scene->mNumCameras];
|
||||
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
|
||||
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");
|
||||
if (!stream)
|
||||
if (nullptr == stream) {
|
||||
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 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( 64, aiOrigin_CUR ); // padding
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
if (compressed) {
|
||||
uLongf uncompressedSize = Read<uint32_t>(stream);
|
||||
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[] compressedData;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ReadBinaryScene(stream,pScene);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,32 +70,33 @@ namespace Assimp {
|
|||
class AssbinImporter : public BaseImporter
|
||||
{
|
||||
private:
|
||||
bool shortened;
|
||||
bool compressed;
|
||||
bool shortened;
|
||||
bool compressed;
|
||||
|
||||
public:
|
||||
virtual bool CanRead(
|
||||
const std::string& pFile,
|
||||
IOSystem* pIOHandler,
|
||||
bool checkSig
|
||||
virtual bool CanRead(
|
||||
const std::string& pFile,
|
||||
IOSystem* pIOHandler,
|
||||
bool checkSig
|
||||
) const;
|
||||
virtual const aiImporterDesc* GetInfo() const;
|
||||
virtual void InternReadFile(
|
||||
virtual const aiImporterDesc* GetInfo() const;
|
||||
virtual void InternReadFile(
|
||||
const std::string& pFile,
|
||||
aiScene* pScene,
|
||||
IOSystem* pIOHandler
|
||||
aiScene* pScene,
|
||||
IOSystem* pIOHandler
|
||||
);
|
||||
void ReadBinaryScene( IOStream * stream, aiScene* pScene );
|
||||
void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent );
|
||||
void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
|
||||
void ReadBinaryBone( IOStream * stream, aiBone* bone );
|
||||
void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);
|
||||
void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop);
|
||||
void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd);
|
||||
void ReadBinaryAnim( IOStream * stream, aiAnimation* anim );
|
||||
void ReadBinaryTexture(IOStream * stream, aiTexture* tex);
|
||||
void ReadBinaryLight( IOStream * stream, aiLight* l );
|
||||
void ReadBinaryCamera( IOStream * stream, aiCamera* cam );
|
||||
void ReadHeader();
|
||||
void ReadBinaryScene( IOStream * stream, aiScene* pScene );
|
||||
void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent );
|
||||
void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
|
||||
void ReadBinaryBone( IOStream * stream, aiBone* bone );
|
||||
void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);
|
||||
void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop);
|
||||
void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd);
|
||||
void ReadBinaryAnim( IOStream * stream, aiAnimation* anim );
|
||||
void ReadBinaryTexture(IOStream * stream, aiTexture* tex);
|
||||
void ReadBinaryLight( IOStream * stream, aiLight* l );
|
||||
void ReadBinaryCamera( IOStream * stream, aiCamera* cam );
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <map>
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Formatter;
|
||||
|
@ -461,6 +462,13 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
|
|||
aiNodeAnim* nodeAnim = new aiNodeAnim;
|
||||
anim->mChannels[a] = nodeAnim;
|
||||
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
|
||||
if( node.mChannels.size() == 6)
|
||||
|
@ -472,16 +480,32 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
|
|||
{
|
||||
poskey->mTime = double( fr);
|
||||
|
||||
// Now compute all translations in the right order
|
||||
for( unsigned int channel = 0; channel < 3; ++channel)
|
||||
// Now compute all translations
|
||||
for(BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel +1))
|
||||
{
|
||||
switch( node.mChannels[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;
|
||||
case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
|
||||
default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
|
||||
}
|
||||
//Find channel in node
|
||||
std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
|
||||
|
||||
if (mapIter == channelMap.end())
|
||||
throw DeadlyImportError("Missing position channel in 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;
|
||||
}
|
||||
|
@ -497,12 +521,6 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
|
|||
|
||||
// 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
|
||||
nodeAnim->mNumRotationKeys = mAnimNumFrames;
|
||||
|
@ -512,20 +530,33 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
|
|||
{
|
||||
aiMatrix4x4 temp;
|
||||
aiMatrix3x3 rotMatrix;
|
||||
for (BVHLoader::ChannelType channel = Channel_RotationX; channel <= Channel_RotationZ; channel = (BVHLoader::ChannelType)(channel + 1))
|
||||
{
|
||||
//Find channel in node
|
||||
std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
|
||||
|
||||
for( unsigned int channel = 0; channel < 3; ++channel)
|
||||
{
|
||||
// translate ZXY euler angels into a quaternion
|
||||
const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f;
|
||||
if (mapIter == channelMap.end())
|
||||
throw DeadlyImportError("Missing rotation channel in node " + nodeName);
|
||||
else {
|
||||
int channelIdx = mapIter->second;
|
||||
// translate ZXY euler angels into a quaternion
|
||||
const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
|
||||
|
||||
// Compute rotation transformations in the right order
|
||||
switch (node.mChannels[rotOffset+channel])
|
||||
{
|
||||
case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
|
||||
case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
|
||||
case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
|
||||
default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
|
||||
}
|
||||
// Compute rotation transformations in the right order
|
||||
switch (channel)
|
||||
{
|
||||
case Channel_RotationX:
|
||||
aiMatrix4x4::RotationX(angle, temp); rotMatrix *= aiMatrix3x3(temp);
|
||||
break;
|
||||
case Channel_RotationY:
|
||||
aiMatrix4x4::RotationY(angle, temp); rotMatrix *= aiMatrix3x3(temp);
|
||||
break;
|
||||
case Channel_RotationZ: aiMatrix4x4::RotationZ(angle, temp); rotMatrix *= aiMatrix3x3(temp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rotkey->mTime = double( fr);
|
||||
|
|
|
@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include "FileSystemFilter.h"
|
||||
#include "Importer.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/postprocess.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
|
||||
#include <ios>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
@ -63,7 +65,7 @@ using namespace Assimp;
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
BaseImporter::BaseImporter()
|
||||
BaseImporter::BaseImporter() AI_NO_EXCEPT
|
||||
: m_progress() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
@ -143,7 +145,8 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
|||
const char** tokens,
|
||||
unsigned int numTokens,
|
||||
unsigned int searchBytes /* = 200 */,
|
||||
bool tokensSol /* false */)
|
||||
bool tokensSol /* false */,
|
||||
bool noAlphaBeforeTokens /* false */)
|
||||
{
|
||||
ai_assert( nullptr != tokens );
|
||||
ai_assert( 0 != numTokens );
|
||||
|
@ -157,15 +160,14 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
|||
if (pStream.get() ) {
|
||||
// read 200 characters from the file
|
||||
std::unique_ptr<char[]> _buffer (new char[searchBytes+1 /* for the '\0' */]);
|
||||
char* buffer = _buffer.get();
|
||||
|
||||
const size_t read = pStream->Read(buffer,1,searchBytes);
|
||||
if( !read ) {
|
||||
char *buffer( _buffer.get() );
|
||||
const size_t read( pStream->Read(buffer,1,searchBytes) );
|
||||
if( 0 == read ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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 ...
|
||||
|
@ -186,13 +188,18 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
|||
token.clear();
|
||||
const char *ptr( tokens[ i ] );
|
||||
for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) {
|
||||
token.push_back( tolower( *ptr ) );
|
||||
token.push_back( static_cast<char>( tolower( *ptr ) ) );
|
||||
++ptr;
|
||||
}
|
||||
const char* r = strstr( buffer, token.c_str() );
|
||||
if( !r ) {
|
||||
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
|
||||
// be in the beginning of the file / line
|
||||
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
|
||||
/*static*/ std::string BaseImporter::GetExtension (const std::string& pFile)
|
||||
{
|
||||
std::string::size_type pos = pFile.find_last_of('.');
|
||||
std::string BaseImporter::GetExtension( const std::string& file ) {
|
||||
std::string::size_type pos = file.find_last_of('.');
|
||||
|
||||
// no file extension at all
|
||||
if( pos == std::string::npos)
|
||||
if (pos == std::string::npos) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ using namespace Assimp;
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
BaseProcess::BaseProcess()
|
||||
BaseProcess::BaseProcess() AI_NO_EXCEPT
|
||||
: shared()
|
||||
, progress()
|
||||
{
|
||||
|
|
|
@ -211,20 +211,16 @@ private:
|
|||
* should be executed. If the function returns true, the class' Execute()
|
||||
* function is called subsequently.
|
||||
*/
|
||||
class ASSIMP_API_WINONLY BaseProcess
|
||||
{
|
||||
class ASSIMP_API_WINONLY BaseProcess {
|
||||
friend class Importer;
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor to be privately used by Importer */
|
||||
BaseProcess();
|
||||
BaseProcess() AI_NO_EXCEPT;
|
||||
|
||||
/** Destructor, private as well */
|
||||
virtual ~BaseProcess();
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the processing step is present in the given flag.
|
||||
* @param pFlags The processing flags the importer was called with. A
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
#include "BlenderCustomData.h"
|
||||
#include "BlenderDNA.h"
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
/**
|
||||
* @brief read/convert of Structure array to memory
|
||||
*/
|
||||
template<typename T>
|
||||
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
|
||||
for (size_t i = 0; i < cnt; ++i) {
|
||||
T read;
|
||||
s.Convert(read, db);
|
||||
*p = read;
|
||||
p++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief pointer to function read memory for n CustomData types
|
||||
*/
|
||||
typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
|
||||
typedef ElemBase * (*PCreate)(const size_t cnt);
|
||||
typedef void(*PDestroy)(ElemBase *);
|
||||
|
||||
#define IMPL_STRUCT_READ(ty) \
|
||||
bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
|
||||
return read<ty>(db.dna[#ty], dynamic_cast<ty *>(v), cnt, db); \
|
||||
}
|
||||
|
||||
#define IMPL_STRUCT_CREATE(ty) \
|
||||
ElemBase *create##ty(const size_t cnt) { \
|
||||
return new ty[cnt]; \
|
||||
}
|
||||
|
||||
#define IMPL_STRUCT_DESTROY(ty) \
|
||||
void destroy##ty(ElemBase *pE) { \
|
||||
ty *p = dynamic_cast<ty *>(pE); \
|
||||
delete[]p; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief helper macro to define Structure functions
|
||||
*/
|
||||
#define IMPL_STRUCT(ty) \
|
||||
IMPL_STRUCT_READ(ty) \
|
||||
IMPL_STRUCT_CREATE(ty) \
|
||||
IMPL_STRUCT_DESTROY(ty)
|
||||
|
||||
// supported structures for CustomData
|
||||
IMPL_STRUCT(MVert)
|
||||
IMPL_STRUCT(MEdge)
|
||||
IMPL_STRUCT(MFace)
|
||||
IMPL_STRUCT(MTFace)
|
||||
IMPL_STRUCT(MTexPoly)
|
||||
IMPL_STRUCT(MLoopUV)
|
||||
IMPL_STRUCT(MLoopCol)
|
||||
IMPL_STRUCT(MPoly)
|
||||
IMPL_STRUCT(MLoop)
|
||||
|
||||
/**
|
||||
* @brief describes the size of data and the read function to be used for single CustomerData.type
|
||||
*/
|
||||
struct CustomDataTypeDescription {
|
||||
PRead Read; ///< function to read one CustomData type element
|
||||
PCreate Create; ///< function to allocate n type elements
|
||||
PDestroy Destroy;
|
||||
|
||||
CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy)
|
||||
: Read(read)
|
||||
, Create(create)
|
||||
, Destroy(destroy)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief helper macro to define Structure type specific CustomDataTypeDescription
|
||||
* @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
|
||||
*/
|
||||
#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
|
||||
CustomDataTypeDescription{&read##ty, &create##ty, &destroy##ty}
|
||||
|
||||
/**
|
||||
* @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type
|
||||
*/
|
||||
#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
|
||||
CustomDataTypeDescription{nullptr, nullptr, nullptr}
|
||||
|
||||
/**
|
||||
* @brief descriptors for data pointed to from CustomDataLayer.data
|
||||
* @note some of the CustomData uses already well defined Structures
|
||||
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
|
||||
* use a special readfunction for that cases
|
||||
*/
|
||||
std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
|
||||
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
|
||||
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
|
||||
}};
|
||||
|
||||
|
||||
bool isValidCustomDataType(const int cdtype) {
|
||||
return cdtype >= 0 && cdtype < CD_NUMTYPES;
|
||||
}
|
||||
|
||||
bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
|
||||
if (!isValidCustomDataType(cdtype)) {
|
||||
throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index"));
|
||||
}
|
||||
|
||||
const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
|
||||
if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
|
||||
// allocate cnt elements and parse them from file
|
||||
out.reset(cdtd.Create(cnt), cdtd.Destroy);
|
||||
return cdtd.Read(out.get(), cnt, db);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
|
||||
for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
|
||||
if (it->get()->type == cdtype && name == it->get()->name) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ElemBase * getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name)
|
||||
{
|
||||
const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
|
||||
if (pLayer && pLayer->data) {
|
||||
return pLayer->data.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderScene.h"
|
||||
#include <memory>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Blender {
|
||||
/* CustomData.type from Blender (2.79b) */
|
||||
enum CustomDataType {
|
||||
CD_AUTO_FROM_NAME = -1,
|
||||
CD_MVERT = 0,
|
||||
#ifdef DNA_DEPRECATED
|
||||
CD_MSTICKY = 1, /* DEPRECATED */
|
||||
#endif
|
||||
CD_MDEFORMVERT = 2,
|
||||
CD_MEDGE = 3,
|
||||
CD_MFACE = 4,
|
||||
CD_MTFACE = 5,
|
||||
CD_MCOL = 6,
|
||||
CD_ORIGINDEX = 7,
|
||||
CD_NORMAL = 8,
|
||||
/* CD_POLYINDEX = 9, */
|
||||
CD_PROP_FLT = 10,
|
||||
CD_PROP_INT = 11,
|
||||
CD_PROP_STR = 12,
|
||||
CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
|
||||
CD_ORCO = 14,
|
||||
CD_MTEXPOLY = 15,
|
||||
CD_MLOOPUV = 16,
|
||||
CD_MLOOPCOL = 17,
|
||||
CD_TANGENT = 18,
|
||||
CD_MDISPS = 19,
|
||||
CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */
|
||||
/* CD_ID_MCOL = 21, */
|
||||
CD_TEXTURE_MLOOPCOL = 22,
|
||||
CD_CLOTH_ORCO = 23,
|
||||
CD_RECAST = 24,
|
||||
|
||||
/* BMESH ONLY START */
|
||||
CD_MPOLY = 25,
|
||||
CD_MLOOP = 26,
|
||||
CD_SHAPE_KEYINDEX = 27,
|
||||
CD_SHAPEKEY = 28,
|
||||
CD_BWEIGHT = 29,
|
||||
CD_CREASE = 30,
|
||||
CD_ORIGSPACE_MLOOP = 31,
|
||||
CD_PREVIEW_MLOOPCOL = 32,
|
||||
CD_BM_ELEM_PYPTR = 33,
|
||||
/* BMESH ONLY END */
|
||||
|
||||
CD_PAINT_MASK = 34,
|
||||
CD_GRID_PAINT_MASK = 35,
|
||||
CD_MVERT_SKIN = 36,
|
||||
CD_FREESTYLE_EDGE = 37,
|
||||
CD_FREESTYLE_FACE = 38,
|
||||
CD_MLOOPTANGENT = 39,
|
||||
CD_TESSLOOPNORMAL = 40,
|
||||
CD_CUSTOMLOOPNORMAL = 41,
|
||||
|
||||
CD_NUMTYPES = 42
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief check if given cdtype is valid (ie >= 0 and < CD_NUMTYPES)
|
||||
* @param[in] cdtype to check
|
||||
* @return true when valid
|
||||
*/
|
||||
bool isValidCustomDataType(const int cdtype);
|
||||
|
||||
/**
|
||||
* @brief returns CustomDataLayer ptr for given cdtype and name
|
||||
* @param[in] customdata CustomData to search for wanted layer
|
||||
* @param[in] cdtype to search for
|
||||
* @param[in] name to search for
|
||||
* @return CustomDataLayer * or nullptr if not found
|
||||
*/
|
||||
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief returns CustomDataLayer data ptr for given cdtype and name
|
||||
* @param[in] customdata CustomData to search for wanted layer
|
||||
* @param[in] cdtype to search for
|
||||
* @param[in] name to search for
|
||||
* @return * to struct data or nullptr if not found
|
||||
*/
|
||||
const ElemBase * getCustomDataLayerData(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
|
||||
}
|
||||
}
|
|
@ -309,6 +309,28 @@ public:
|
|||
void ReadField(T& out, const char* name,
|
||||
const FileDatabase& db) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
/**
|
||||
* @brief field parsing for dynamic vectors
|
||||
* @param[in] out vector of struct to be filled
|
||||
* @param[in] name of field
|
||||
* @param[in] db to access the file, dna, ...
|
||||
* @return true when read was successful
|
||||
*/
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
bool ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const;
|
||||
|
||||
/**
|
||||
* @brief parses raw customdata
|
||||
* @param[in] out shared_ptr to be filled
|
||||
* @param[in] cdtype customdata type to read
|
||||
* @param[in] name of field ptr
|
||||
* @param[in] db to access the file, dna, ...
|
||||
* @return true when read was successful
|
||||
*/
|
||||
template <int error_policy>
|
||||
bool ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const;
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
@ -803,6 +825,17 @@ private:
|
|||
FileDatabase& db;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief read CustomData's data to ptr to mem
|
||||
* @param[out] out memory ptr to set
|
||||
* @param[in] cdtype to read
|
||||
* @param[in] cnt cnt of elements to read
|
||||
* @param[in] db to read elements from
|
||||
* @return true when ok
|
||||
*/
|
||||
bool readCustomData(std::shared_ptr<ElemBase> &out, int cdtype, size_t cnt, const FileDatabase &db);
|
||||
|
||||
|
||||
} // end Blend
|
||||
} // end Assimp
|
||||
|
||||
|
|
|
@ -307,6 +307,108 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
|
|||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// field parsing for raw untyped data (like CustomDataLayer.data)
|
||||
template <int error_policy>
|
||||
bool Structure::ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const {
|
||||
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
|
||||
Pointer ptrval;
|
||||
const Field* f;
|
||||
try {
|
||||
f = &(*this)[name];
|
||||
|
||||
// sanity check, should never happen if the genblenddna script is right
|
||||
if (!(f->flags & FieldFlag_Pointer)) {
|
||||
throw Error((Formatter::format(), "Field `", name, "` of structure `",
|
||||
this->name, "` ought to be a pointer"));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f->offset);
|
||||
Convert(ptrval, db);
|
||||
// actually it is meaningless on which Structure the Convert is called
|
||||
// because the `Pointer` argument triggers a special implementation.
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out, e.what());
|
||||
out.reset();
|
||||
}
|
||||
|
||||
bool readOk = true;
|
||||
if (ptrval.val) {
|
||||
// get block for ptr
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
|
||||
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
|
||||
// read block->num instances of given type to out
|
||||
readOk = readCustomData(out, cdtype, block->num, db);
|
||||
}
|
||||
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
|
||||
return readOk;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
bool Structure::ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const {
|
||||
out.clear();
|
||||
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
|
||||
Pointer ptrval;
|
||||
const Field* f;
|
||||
try {
|
||||
f = &(*this)[name];
|
||||
|
||||
// sanity check, should never happen if the genblenddna script is right
|
||||
if (!(f->flags & FieldFlag_Pointer)) {
|
||||
throw Error((Formatter::format(), "Field `", name, "` of structure `",
|
||||
this->name, "` ought to be a pointer"));
|
||||
}
|
||||
|
||||
db.reader->IncPtr(f->offset);
|
||||
Convert(ptrval, db);
|
||||
// actually it is meaningless on which Structure the Convert is called
|
||||
// because the `Pointer` argument triggers a special implementation.
|
||||
}
|
||||
catch (const Error& e) {
|
||||
_defaultInitializer<error_policy>()(out, e.what());
|
||||
out.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (ptrval.val) {
|
||||
// find the file block the pointer is pointing to
|
||||
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
|
||||
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
|
||||
// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
|
||||
// I really ought to improve StreamReader to work with 64 bit indices exclusively.
|
||||
|
||||
const Structure& s = db.dna[f->type];
|
||||
for (size_t i = 0; i < block->num; ++i) {
|
||||
TOUT<T> p(new T);
|
||||
s.Convert(*p, db);
|
||||
out.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
db.reader->SetCurrentPos(old);
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
|
||||
|
|
|
@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "BlenderIntermediate.h"
|
||||
#include "BlenderModifier.h"
|
||||
#include "BlenderBMesh.h"
|
||||
#include "BlenderCustomData.h"
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
|
@ -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
|
||||
if (mesh->mtface || mesh->mloopuv) {
|
||||
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) {
|
||||
ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
|
||||
|
||||
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
|
||||
const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
|
||||
if (itMatTexUvMapping == matTexUvMappings.end()) {
|
||||
// default behaviour like before
|
||||
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
|
||||
}
|
||||
else {
|
||||
// create texture coords for every mapped tex
|
||||
for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) {
|
||||
(*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices];
|
||||
}
|
||||
}
|
||||
(*it)->mNumFaces = (*it)->mNumVertices = 0;
|
||||
}
|
||||
|
||||
|
@ -1051,13 +1089,34 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
|
||||
const aiFace& f = out->mFaces[out->mNumFaces++];
|
||||
|
||||
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
|
||||
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
|
||||
const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
|
||||
vo->x = uv.uv[0];
|
||||
vo->y = uv.uv[1];
|
||||
const auto itMatTexUvMapping = matTexUvMappings.find(v.mat_nr);
|
||||
if (itMatTexUvMapping == matTexUvMappings.end()) {
|
||||
// old behavior
|
||||
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
|
||||
for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) {
|
||||
const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
|
||||
vo->x = uv.uv[0];
|
||||
vo->y = uv.uv[1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// create textureCoords for every mapped tex
|
||||
for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) {
|
||||
const MLoopUV *tm = itMatTexUvMapping->second[m];
|
||||
aiVector3D* vo = &out->mTextureCoords[m][out->mNumVertices];
|
||||
uint32_t j = 0;
|
||||
for (; j < f.mNumIndices; ++j, ++vo) {
|
||||
const MLoopUV& uv = tm[v.loopstart + j];
|
||||
vo->x = uv.uv[0];
|
||||
vo->y = uv.uv[1];
|
||||
}
|
||||
// only update written mNumVertices in last loop
|
||||
// TODO why must the numVertices be incremented here?
|
||||
if (m == itMatTexUvMapping->second.size() - 1) {
|
||||
out->mNumVertices += j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "BlenderScene.h"
|
||||
#include "BlenderSceneGen.h"
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderCustomData.h"
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
|
@ -481,6 +482,12 @@ template <> void Structure :: Convert<Mesh> (
|
|||
ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
|
||||
ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
|
||||
|
||||
ReadField<ErrorPolicy_Igno>(dest.vdata, "vdata", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.edata, "edata", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.fdata, "fdata", db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.pdata, "pdata", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.ldata, "ldata", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
|
@ -786,6 +793,41 @@ template <> void Structure :: Convert<Image> (
|
|||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure::Convert<CustomData>(
|
||||
CustomData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.typemap, "typemap", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.totlayer, "totlayer", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.maxlayer, "maxlayer", db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.totsize, "totsize", db);
|
||||
ReadFieldPtrVector<ErrorPolicy_Warn>(dest.layers, "*layers", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure::Convert<CustomDataLayer>(
|
||||
CustomDataLayer& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
ReadField<ErrorPolicy_Fail>(dest.type, "type", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.offset, "offset", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.flag, "flag", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active, "active", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active_rnd, "active_rnd", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active_clone, "active_clone", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.active_mask, "active_mask", db);
|
||||
ReadField<ErrorPolicy_Fail>(dest.uid, "uid", db);
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.name, "name", db);
|
||||
ReadCustomDataPtr<ErrorPolicy_Fail>(dest.data, dest.type, "*data", db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
void DNA::RegisterConverters() {
|
||||
|
||||
|
@ -822,6 +864,8 @@ void DNA::RegisterConverters() {
|
|||
converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
|
||||
converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
|
||||
converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
|
||||
converters["CustomData"] = DNA::FactoryPair(&Structure::Allocate<CustomData>, &Structure::Convert<CustomData>);
|
||||
converters["CustomDataLayer"] = DNA::FactoryPair(&Structure::Allocate<CustomDataLayer>, &Structure::Convert<CustomDataLayer>);
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
|
|
@ -157,10 +157,16 @@ struct World : ElemBase {
|
|||
// -------------------------------------------------------------------------------
|
||||
struct MVert : ElemBase {
|
||||
float co[3] FAIL;
|
||||
float no[3] FAIL;
|
||||
float no[3] FAIL; // readed as short and divided through / 32767.f
|
||||
char flag;
|
||||
int mat_nr WARN;
|
||||
int bweight;
|
||||
|
||||
MVert() : ElemBase()
|
||||
, flag(0)
|
||||
, mat_nr(0)
|
||||
, bweight(0)
|
||||
{}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
@ -369,6 +375,72 @@ struct Material : ElemBase {
|
|||
std::shared_ptr<MTex> mtex[18];
|
||||
};
|
||||
|
||||
/*
|
||||
CustomDataLayer 104
|
||||
|
||||
int type 0 4
|
||||
int offset 4 4
|
||||
int flag 8 4
|
||||
int active 12 4
|
||||
int active_rnd 16 4
|
||||
int active_clone 20 4
|
||||
int active_mask 24 4
|
||||
int uid 28 4
|
||||
char name 32 64
|
||||
void *data 96 8
|
||||
*/
|
||||
struct CustomDataLayer : ElemBase {
|
||||
int type;
|
||||
int offset;
|
||||
int flag;
|
||||
int active;
|
||||
int active_rnd;
|
||||
int active_clone;
|
||||
int active_mask;
|
||||
int uid;
|
||||
char name[64];
|
||||
std::shared_ptr<ElemBase> data; // must be converted to real type according type member
|
||||
|
||||
CustomDataLayer()
|
||||
: ElemBase()
|
||||
, type(0)
|
||||
, offset(0)
|
||||
, flag(0)
|
||||
, active(0)
|
||||
, active_rnd(0)
|
||||
, active_clone(0)
|
||||
, active_mask(0)
|
||||
, uid(0)
|
||||
, data(nullptr)
|
||||
{
|
||||
memset(name, 0, sizeof name);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
CustomData 208
|
||||
|
||||
CustomDataLayer *layers 0 8
|
||||
int typemap 8 168
|
||||
int pad_i1 176 4
|
||||
int totlayer 180 4
|
||||
int maxlayer 184 4
|
||||
int totsize 188 4
|
||||
BLI_mempool *pool 192 8
|
||||
CustomDataExternal *external 200 8
|
||||
*/
|
||||
struct CustomData : ElemBase {
|
||||
vector<std::shared_ptr<struct CustomDataLayer> > layers;
|
||||
int typemap[42]; // CD_NUMTYPES
|
||||
int totlayer;
|
||||
int maxlayer;
|
||||
int totsize;
|
||||
/*
|
||||
std::shared_ptr<BLI_mempool> pool;
|
||||
std::shared_ptr<CustomDataExternal> external;
|
||||
*/
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct Mesh : ElemBase {
|
||||
ID id FAIL;
|
||||
|
@ -398,6 +470,12 @@ struct Mesh : ElemBase {
|
|||
vector<MCol> mcol;
|
||||
|
||||
vector< std::shared_ptr<Material> > mat FAIL;
|
||||
|
||||
struct CustomData vdata;
|
||||
struct CustomData edata;
|
||||
struct CustomData fdata;
|
||||
struct CustomData pdata;
|
||||
struct CustomData ldata;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
|
|
@ -248,6 +248,17 @@ template <> void Structure :: Convert<Image> (
|
|||
) const
|
||||
;
|
||||
|
||||
template <> void Structure::Convert<CustomData>(
|
||||
CustomData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure::Convert<CustomDataLayer>(
|
||||
CustomDataLayer& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -469,6 +469,8 @@ ADD_ASSIMP_IMPORTER( BLEND
|
|||
BlenderBMesh.cpp
|
||||
BlenderTessellator.h
|
||||
BlenderTessellator.cpp
|
||||
BlenderCustomData.h
|
||||
BlenderCustomData.cpp
|
||||
)
|
||||
|
||||
ADD_ASSIMP_IMPORTER( IFC
|
||||
|
@ -909,6 +911,12 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
|||
|
||||
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} )
|
||||
|
||||
if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
|
||||
|
|
|
@ -137,9 +137,7 @@ void COBImporter::SetupProperties(const Importer* /*pImp*/)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void COBImporter::InternReadFile( const std::string& pFile,
|
||||
aiScene* pScene, IOSystem* pIOHandler)
|
||||
{
|
||||
void COBImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
|
||||
COB::Scene scene;
|
||||
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE( pIOHandler->Open(pFile,"rb")) );
|
||||
|
||||
|
|
|
@ -272,12 +272,13 @@ struct Node
|
|||
/** Node instances at this node */
|
||||
std::vector<NodeInstance> mNodeInstances;
|
||||
|
||||
/** Rootnodes: Name of primary camera, if any */
|
||||
/** Root-nodes: Name of primary camera, if any */
|
||||
std::string mPrimaryCamera;
|
||||
|
||||
//! Constructor. Begin with a zero parent
|
||||
Node() {
|
||||
mParent = NULL;
|
||||
Node()
|
||||
: mParent( nullptr ){
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Destructor: delete all children subsequently
|
||||
|
|
|
@ -181,26 +181,27 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
|||
// ... then fill the materials with the now adjusted settings
|
||||
FillMaterials(parser, pScene);
|
||||
|
||||
// Apply unitsize scale calculation
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
|
||||
0, parser.mUnitSize, 0, 0,
|
||||
0, 0, parser.mUnitSize, 0,
|
||||
0, 0, 0, 1);
|
||||
if( !ignoreUpDirection ) {
|
||||
// Convert to Y_UP, if different orientation
|
||||
if( parser.mUpDirection == ColladaParser::UP_X)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
0, -1, 0, 0,
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1);
|
||||
else if( parser.mUpDirection == ColladaParser::UP_Z)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
// Apply unitsize scale calculation
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
|
||||
0, parser.mUnitSize, 0, 0,
|
||||
0, 0, parser.mUnitSize, 0,
|
||||
0, 0, 0, 1);
|
||||
if( !ignoreUpDirection ) {
|
||||
// Convert to Y_UP, if different orientation
|
||||
if( parser.mUpDirection == ColladaParser::UP_X)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
0, -1, 0, 0,
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1);
|
||||
else if( parser.mUpDirection == ColladaParser::UP_Z)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
// store all meshes
|
||||
StoreSceneMeshes( pScene);
|
||||
|
||||
|
@ -740,10 +741,6 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|||
// create bones if given
|
||||
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
|
||||
const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ using namespace Assimp::Formatter;
|
|||
// Constructor to be privately used by Importer
|
||||
ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
|
||||
: mFileName( pFile )
|
||||
, mReader( NULL )
|
||||
, mReader( nullptr )
|
||||
, mDataLibrary()
|
||||
, mAccessorLibrary()
|
||||
, mMeshLibrary()
|
||||
|
@ -79,20 +79,20 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
|
|||
, mLightLibrary()
|
||||
, mCameraLibrary()
|
||||
, mControllerLibrary()
|
||||
, mRootNode( NULL )
|
||||
, mRootNode( nullptr )
|
||||
, mAnims()
|
||||
, mUnitSize( 1.0f )
|
||||
, mUpDirection( UP_Y )
|
||||
, mFormat(FV_1_5_n ) // We assume the newest file format by default
|
||||
{
|
||||
// validate io-handler instance
|
||||
if ( NULL == pIOHandler ) {
|
||||
if (nullptr == pIOHandler ) {
|
||||
throw DeadlyImportError("IOSystem is NULL." );
|
||||
}
|
||||
|
||||
// open the file
|
||||
std::unique_ptr<IOStream> file( pIOHandler->Open(pFile ) );
|
||||
if (file.get() == NULL) {
|
||||
if (file.get() == nullptr) {
|
||||
throw DeadlyImportError( "Failed to open file " + pFile + "." );
|
||||
}
|
||||
|
||||
|
@ -363,17 +363,17 @@ void ColladaParser::ReadAnimationClipLibrary()
|
|||
|
||||
void ColladaParser::PostProcessControllers()
|
||||
{
|
||||
for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it)
|
||||
{
|
||||
std::string meshId = it->second.mMeshId;
|
||||
ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId);
|
||||
while(findItr != mControllerLibrary.end()) {
|
||||
meshId = findItr->second.mMeshId;
|
||||
findItr = mControllerLibrary.find(meshId);
|
||||
}
|
||||
std::string meshId;
|
||||
for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it) {
|
||||
meshId = it->second.mMeshId;
|
||||
ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId);
|
||||
while(findItr != mControllerLibrary.end()) {
|
||||
meshId = findItr->second.mMeshId;
|
||||
findItr = mControllerLibrary.find(meshId);
|
||||
}
|
||||
|
||||
it->second.mMeshId = meshId;
|
||||
}
|
||||
it->second.mMeshId = meshId;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -59,6 +59,25 @@ using namespace Assimp;
|
|||
|
||||
#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
|
||||
MakeLeftHandedProcess::MakeLeftHandedProcess()
|
||||
|
@ -282,15 +301,9 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
|
|||
// Converts a single mesh
|
||||
void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
|
||||
{
|
||||
// mirror texture y coordinate
|
||||
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
|
||||
if( !pMesh->HasTextureCoords( a ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
for( unsigned int b = 0; b < pMesh->mNumVertices; b++ ) {
|
||||
pMesh->mTextureCoords[ a ][ b ].y = 1.0f - pMesh->mTextureCoords[ a ][ b ].y;
|
||||
}
|
||||
flipUVs(pMesh);
|
||||
for (unsigned int idx = 0; idx < pMesh->mNumAnimMeshes; idx++) {
|
||||
flipUVs(pMesh->mAnimMeshes[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ void D3MFExporter::writeMetaData() {
|
|||
return;
|
||||
}
|
||||
|
||||
const aiString *key;
|
||||
const aiString *key = nullptr;
|
||||
const aiMetadataEntry *entry(nullptr);
|
||||
for ( size_t i = 0; i < numMetaEntries; ++i ) {
|
||||
mScene->mMetaData->Get( i, key, entry );
|
||||
|
|
|
@ -297,8 +297,9 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
//format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
|
||||
const size_t len( strlen( color ) );
|
||||
if ( 9 != len ) {
|
||||
if ( 9 != len && 7 != len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -313,26 +314,28 @@ private:
|
|||
++buf;
|
||||
comp[ 1 ] = *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;
|
||||
++buf;
|
||||
comp[ 1 ] = *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;
|
||||
++buf;
|
||||
comp[ 1 ] = *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;
|
||||
++buf;
|
||||
comp[ 1 ] = *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;
|
||||
}
|
||||
|
|
|
@ -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.read(reinterpret_cast<char*>(imageContent), imageSize);
|
||||
|
||||
|
|
|
@ -150,14 +150,14 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
#endif
|
||||
|
||||
#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,
|
||||
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
|
||||
Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2,
|
||||
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
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
|
||||
|
|
|
@ -73,11 +73,7 @@ using namespace Util;
|
|||
|
||||
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
|
||||
|
||||
// XXX vc9's debugger won't step into anonymous namespaces
|
||||
//namespace {
|
||||
|
||||
|
||||
Converter::Converter( aiScene* out, const Document& doc )
|
||||
FBXConverter::FBXConverter( aiScene* out, const Document& doc )
|
||||
: defaultMaterialIndex()
|
||||
, out( out )
|
||||
, 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( materials.begin(), materials.end(), Util::delete_fun<aiMaterial>() );
|
||||
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>() );
|
||||
}
|
||||
|
||||
void Converter::ConvertRootNode() {
|
||||
void FBXConverter::ConvertRootNode() {
|
||||
out->mRootNode = new aiNode();
|
||||
out->mRootNode->mName.Set( "RootNode" );
|
||||
|
||||
|
@ -135,7 +131,7 @@ void Converter::ConvertRootNode() {
|
|||
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" );
|
||||
|
||||
std::vector<aiNode*> nodes;
|
||||
|
@ -189,12 +185,8 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
|||
}
|
||||
|
||||
if ( !name_carrier ) {
|
||||
NodeNameCache::const_iterator it( std::find( mNodeNames.begin(), mNodeNames.end(), original_name ) );
|
||||
if ( it != mNodeNames.end() ) {
|
||||
original_name = original_name + std::string( "001" );
|
||||
}
|
||||
|
||||
mNodeNames.push_back( original_name );
|
||||
std::string old_original_name = original_name;
|
||||
GetUniqueName(old_original_name, original_name);
|
||||
nodes_chain.push_back( new aiNode( original_name ) );
|
||||
} else {
|
||||
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();
|
||||
for( const NodeAttribute* attr : node_attrs ) {
|
||||
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();
|
||||
for( const NodeAttribute* attr : node_attrs ) {
|
||||
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() );
|
||||
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() );
|
||||
aiCamera* const out_camera = cameras.back();
|
||||
|
@ -402,133 +394,120 @@ void Converter::ConvertCamera( const Camera& cam, const std::string &orig_name )
|
|||
out_camera->mClipPlaneFar = cam.FarPlane();
|
||||
}
|
||||
|
||||
static bool HasName( NodeNameCache &cache, const std::string &name ) {
|
||||
NodeNameCache::const_iterator it( std::find( cache.begin(), cache.end(), name ) );
|
||||
return it != cache.end();
|
||||
|
||||
}
|
||||
void Converter::GetUniqueName( const std::string &name, std::string uniqueName ) {
|
||||
if ( !HasName( mNodeNames, name ) ) {
|
||||
uniqueName = name;
|
||||
return;
|
||||
}
|
||||
|
||||
int i( 0 );
|
||||
std::string newName;
|
||||
while ( HasName( mNodeNames, newName ) ) {
|
||||
void FBXConverter::GetUniqueName( const std::string &name, std::string &uniqueName )
|
||||
{
|
||||
int i = 0;
|
||||
uniqueName = name;
|
||||
while (mNodeNames.find(uniqueName) != mNodeNames.end())
|
||||
{
|
||||
++i;
|
||||
newName.clear();
|
||||
newName += name;
|
||||
std::stringstream ext;
|
||||
ext << std::setfill( '0' ) << std::setw( 3 ) << i;
|
||||
newName += ext.str();
|
||||
ext << name << std::setfill('0') << std::setw(3) << i;
|
||||
uniqueName = ext.str();
|
||||
}
|
||||
uniqueName = newName;
|
||||
mNodeNames.push_back( uniqueName );
|
||||
mNodeNames.insert(uniqueName);
|
||||
}
|
||||
|
||||
|
||||
const char* Converter::NameTransformationComp( TransformationComp comp )
|
||||
{
|
||||
switch ( comp )
|
||||
{
|
||||
case TransformationComp_Translation:
|
||||
return "Translation";
|
||||
case TransformationComp_RotationOffset:
|
||||
return "RotationOffset";
|
||||
case TransformationComp_RotationPivot:
|
||||
return "RotationPivot";
|
||||
case TransformationComp_PreRotation:
|
||||
return "PreRotation";
|
||||
case TransformationComp_Rotation:
|
||||
return "Rotation";
|
||||
case TransformationComp_PostRotation:
|
||||
return "PostRotation";
|
||||
case TransformationComp_RotationPivotInverse:
|
||||
return "RotationPivotInverse";
|
||||
case TransformationComp_ScalingOffset:
|
||||
return "ScalingOffset";
|
||||
case TransformationComp_ScalingPivot:
|
||||
return "ScalingPivot";
|
||||
case TransformationComp_Scaling:
|
||||
return "Scaling";
|
||||
case TransformationComp_ScalingPivotInverse:
|
||||
return "ScalingPivotInverse";
|
||||
case TransformationComp_GeometricScaling:
|
||||
return "GeometricScaling";
|
||||
case TransformationComp_GeometricRotation:
|
||||
return "GeometricRotation";
|
||||
case TransformationComp_GeometricTranslation:
|
||||
return "GeometricTranslation";
|
||||
case TransformationComp_GeometricScalingInverse:
|
||||
return "GeometricScalingInverse";
|
||||
case TransformationComp_GeometricRotationInverse:
|
||||
return "GeometricRotationInverse";
|
||||
case TransformationComp_GeometricTranslationInverse:
|
||||
return "GeometricTranslationInverse";
|
||||
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
|
||||
default:
|
||||
break;
|
||||
const char* FBXConverter::NameTransformationComp( TransformationComp comp ) {
|
||||
switch ( comp ) {
|
||||
case TransformationComp_Translation:
|
||||
return "Translation";
|
||||
case TransformationComp_RotationOffset:
|
||||
return "RotationOffset";
|
||||
case TransformationComp_RotationPivot:
|
||||
return "RotationPivot";
|
||||
case TransformationComp_PreRotation:
|
||||
return "PreRotation";
|
||||
case TransformationComp_Rotation:
|
||||
return "Rotation";
|
||||
case TransformationComp_PostRotation:
|
||||
return "PostRotation";
|
||||
case TransformationComp_RotationPivotInverse:
|
||||
return "RotationPivotInverse";
|
||||
case TransformationComp_ScalingOffset:
|
||||
return "ScalingOffset";
|
||||
case TransformationComp_ScalingPivot:
|
||||
return "ScalingPivot";
|
||||
case TransformationComp_Scaling:
|
||||
return "Scaling";
|
||||
case TransformationComp_ScalingPivotInverse:
|
||||
return "ScalingPivotInverse";
|
||||
case TransformationComp_GeometricScaling:
|
||||
return "GeometricScaling";
|
||||
case TransformationComp_GeometricRotation:
|
||||
return "GeometricRotation";
|
||||
case TransformationComp_GeometricTranslation:
|
||||
return "GeometricTranslation";
|
||||
case TransformationComp_GeometricScalingInverse:
|
||||
return "GeometricScalingInverse";
|
||||
case TransformationComp_GeometricRotationInverse:
|
||||
return "GeometricRotationInverse";
|
||||
case TransformationComp_GeometricTranslationInverse:
|
||||
return "GeometricTranslationInverse";
|
||||
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ai_assert( false );
|
||||
return NULL;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* Converter::NameTransformationCompProperty( TransformationComp comp )
|
||||
{
|
||||
switch ( comp )
|
||||
{
|
||||
case TransformationComp_Translation:
|
||||
return "Lcl Translation";
|
||||
case TransformationComp_RotationOffset:
|
||||
return "RotationOffset";
|
||||
case TransformationComp_RotationPivot:
|
||||
return "RotationPivot";
|
||||
case TransformationComp_PreRotation:
|
||||
return "PreRotation";
|
||||
case TransformationComp_Rotation:
|
||||
return "Lcl Rotation";
|
||||
case TransformationComp_PostRotation:
|
||||
return "PostRotation";
|
||||
case TransformationComp_RotationPivotInverse:
|
||||
return "RotationPivotInverse";
|
||||
case TransformationComp_ScalingOffset:
|
||||
return "ScalingOffset";
|
||||
case TransformationComp_ScalingPivot:
|
||||
return "ScalingPivot";
|
||||
case TransformationComp_Scaling:
|
||||
return "Lcl Scaling";
|
||||
case TransformationComp_ScalingPivotInverse:
|
||||
return "ScalingPivotInverse";
|
||||
case TransformationComp_GeometricScaling:
|
||||
return "GeometricScaling";
|
||||
case TransformationComp_GeometricRotation:
|
||||
return "GeometricRotation";
|
||||
case TransformationComp_GeometricTranslation:
|
||||
return "GeometricTranslation";
|
||||
case TransformationComp_GeometricScalingInverse:
|
||||
return "GeometricScalingInverse";
|
||||
case TransformationComp_GeometricRotationInverse:
|
||||
return "GeometricRotationInverse";
|
||||
case TransformationComp_GeometricTranslationInverse:
|
||||
return "GeometricTranslationInverse";
|
||||
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
|
||||
break;
|
||||
const char* FBXConverter::NameTransformationCompProperty( TransformationComp comp ) {
|
||||
switch ( comp ) {
|
||||
case TransformationComp_Translation:
|
||||
return "Lcl Translation";
|
||||
case TransformationComp_RotationOffset:
|
||||
return "RotationOffset";
|
||||
case TransformationComp_RotationPivot:
|
||||
return "RotationPivot";
|
||||
case TransformationComp_PreRotation:
|
||||
return "PreRotation";
|
||||
case TransformationComp_Rotation:
|
||||
return "Lcl Rotation";
|
||||
case TransformationComp_PostRotation:
|
||||
return "PostRotation";
|
||||
case TransformationComp_RotationPivotInverse:
|
||||
return "RotationPivotInverse";
|
||||
case TransformationComp_ScalingOffset:
|
||||
return "ScalingOffset";
|
||||
case TransformationComp_ScalingPivot:
|
||||
return "ScalingPivot";
|
||||
case TransformationComp_Scaling:
|
||||
return "Lcl Scaling";
|
||||
case TransformationComp_ScalingPivotInverse:
|
||||
return "ScalingPivotInverse";
|
||||
case TransformationComp_GeometricScaling:
|
||||
return "GeometricScaling";
|
||||
case TransformationComp_GeometricRotation:
|
||||
return "GeometricRotation";
|
||||
case TransformationComp_GeometricTranslation:
|
||||
return "GeometricTranslation";
|
||||
case TransformationComp_GeometricScalingInverse:
|
||||
return "GeometricScalingInverse";
|
||||
case TransformationComp_GeometricRotationInverse:
|
||||
return "GeometricRotationInverse";
|
||||
case TransformationComp_GeometricTranslationInverse:
|
||||
return "GeometricTranslationInverse";
|
||||
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
|
||||
break;
|
||||
}
|
||||
|
||||
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
|
||||
// would be to do everything in log space!
|
||||
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 ) {
|
||||
FBXImporter::LogError( "Unsupported RotationMode: SphericXYZ" );
|
||||
|
@ -599,11 +578,15 @@ void Converter::GetRotationMatrix( Model::RotOrder mode, const aiVector3D& rotat
|
|||
|
||||
default:
|
||||
ai_assert( false );
|
||||
break;
|
||||
}
|
||||
|
||||
ai_assert( ( order[ 0 ] >= 0 ) && ( order[ 0 ] <= 2 ) );
|
||||
ai_assert( ( order[ 1 ] >= 0 ) && ( order[ 1 ] <= 2 ) );
|
||||
ai_assert( ( order[ 2 ] >= 0 ) && ( order[ 2 ] <= 2 ) );
|
||||
ai_assert( order[ 0 ] >= 0 );
|
||||
ai_assert( order[ 0 ] <= 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 ] ] ) {
|
||||
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();
|
||||
bool ok;
|
||||
|
@ -649,13 +632,13 @@ bool Converter::NeedsComplexTransformationChain( const Model& model )
|
|||
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 );
|
||||
}
|
||||
|
||||
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 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();
|
||||
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();
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
std::vector<unsigned int> temp;
|
||||
|
@ -925,7 +908,7 @@ std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, cons
|
|||
return temp;
|
||||
}
|
||||
|
||||
aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd)
|
||||
aiMesh* FBXConverter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd)
|
||||
{
|
||||
aiMesh* const out_mesh = new aiMesh();
|
||||
meshes.push_back( out_mesh );
|
||||
|
@ -948,7 +931,7 @@ aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd)
|
|||
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 MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||
|
@ -1075,7 +1058,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con
|
|||
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 MatIndexArray& mindices = mesh.GetMaterialIndices();
|
||||
|
@ -1095,7 +1078,7 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
|
|||
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,
|
||||
const aiMatrix4x4& node_global_transform,
|
||||
aiNode& nd)
|
||||
|
@ -1271,7 +1254,7 @@ unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, cons
|
|||
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 ,
|
||||
unsigned int materialIndex,
|
||||
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 );
|
||||
}
|
||||
|
||||
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>& index_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 )
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
unsigned int Converter::GetDefaultMaterial()
|
||||
unsigned int FBXConverter::GetDefaultMaterial()
|
||||
{
|
||||
if ( defaultMaterialIndex ) {
|
||||
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();
|
||||
|
||||
|
@ -1496,7 +1479,7 @@ unsigned int Converter::ConvertMaterial( const Material& material, const MeshGeo
|
|||
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
|
||||
aiTexture* out_tex = new aiTexture();
|
||||
|
@ -1526,7 +1509,47 @@ unsigned int Converter::ConvertVideo( const Video& video )
|
|||
return static_cast<unsigned int>( textures.size() - 1 );
|
||||
}
|
||||
|
||||
void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& textures,
|
||||
aiString FBXConverter::GetTexturePath(const Texture* tex)
|
||||
{
|
||||
aiString path;
|
||||
path.Set(tex->RelativeFilename());
|
||||
|
||||
const Video* media = tex->Media();
|
||||
if (media != nullptr) {
|
||||
bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
|
||||
unsigned int index;
|
||||
|
||||
VideoMap::const_iterator it = textures_converted.find(media);
|
||||
if (it != textures_converted.end()) {
|
||||
index = (*it).second;
|
||||
textureReady = true;
|
||||
}
|
||||
else {
|
||||
if (media->ContentLength() > 0) {
|
||||
index = ConvertVideo(*media);
|
||||
textures_converted[media] = index;
|
||||
textureReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
|
||||
if (doc.Settings().useLegacyEmbeddedTextureNaming) {
|
||||
if (textureReady) {
|
||||
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
|
||||
// In FBX files textures are now stored internally by Assimp with their filename included
|
||||
// Now Assimp can lookup through the loaded textures after all data is processed
|
||||
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
|
||||
// This may occur on this case too, it has to be studied
|
||||
path.data[0] = '*';
|
||||
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void FBXConverter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& textures,
|
||||
const std::string& propName,
|
||||
aiTextureType target, const MeshGeometry* const mesh )
|
||||
{
|
||||
|
@ -1538,41 +1561,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
|
|||
const Texture* const tex = ( *it ).second;
|
||||
if ( tex != 0 )
|
||||
{
|
||||
aiString path;
|
||||
path.Set( tex->RelativeFilename() );
|
||||
|
||||
const Video* media = tex->Media();
|
||||
if (media != 0) {
|
||||
bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
|
||||
unsigned int index;
|
||||
|
||||
VideoMap::const_iterator it = textures_converted.find(media);
|
||||
if (it != textures_converted.end()) {
|
||||
index = (*it).second;
|
||||
textureReady = true;
|
||||
}
|
||||
else {
|
||||
if (media->ContentLength() > 0) {
|
||||
index = ConvertVideo(*media);
|
||||
textures_converted[media] = index;
|
||||
textureReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
|
||||
if (doc.Settings().useLegacyEmbeddedTextureNaming) {
|
||||
if (textureReady) {
|
||||
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
|
||||
// In FBX files textures are now stored internally by Assimp with their filename included
|
||||
// Now Assimp can lookup through the loaded textures after all data is processed
|
||||
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
|
||||
// This may occur on this case too, it has to be studied
|
||||
path.data[0] = '*';
|
||||
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiString path = GetTexturePath(tex);
|
||||
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
|
||||
|
||||
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,
|
||||
aiTextureType target, const MeshGeometry* const mesh ) {
|
||||
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);
|
||||
|
||||
aiString path;
|
||||
path.Set( tex->RelativeFilename() );
|
||||
|
||||
aiString path = GetTexturePath(tex);
|
||||
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex );
|
||||
|
||||
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, "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 );
|
||||
}
|
||||
|
||||
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, "AmbientColor", aiTextureType_AMBIENT, mesh );
|
||||
|
@ -1833,7 +1820,7 @@ void Converter::SetTextureProperties( aiMaterial* out_mat, const LayeredTextureM
|
|||
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 )
|
||||
{
|
||||
result = true;
|
||||
|
@ -1858,13 +1845,13 @@ aiColor3D Converter::GetColorPropertyFactored( const PropertyTable& props, const
|
|||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
result = true;
|
||||
|
@ -1877,7 +1864,7 @@ aiColor3D Converter::GetColorProperty( const PropertyTable& props, const std::st
|
|||
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.
|
||||
// Modern FBX Files have two separate systems for defining these,
|
||||
|
@ -1976,60 +1963,60 @@ 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 ) {
|
||||
case FileGlobalSettings::FrameRate_DEFAULT:
|
||||
return 1.0;
|
||||
case FileGlobalSettings::FrameRate_DEFAULT:
|
||||
return 1.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_120:
|
||||
return 120.0;
|
||||
case FileGlobalSettings::FrameRate_120:
|
||||
return 120.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_100:
|
||||
return 100.0;
|
||||
case FileGlobalSettings::FrameRate_100:
|
||||
return 100.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_60:
|
||||
return 60.0;
|
||||
case FileGlobalSettings::FrameRate_60:
|
||||
return 60.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_50:
|
||||
return 50.0;
|
||||
case FileGlobalSettings::FrameRate_50:
|
||||
return 50.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_48:
|
||||
return 48.0;
|
||||
case FileGlobalSettings::FrameRate_48:
|
||||
return 48.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_30:
|
||||
case FileGlobalSettings::FrameRate_30_DROP:
|
||||
return 30.0;
|
||||
case FileGlobalSettings::FrameRate_30:
|
||||
case FileGlobalSettings::FrameRate_30_DROP:
|
||||
return 30.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_NTSC_DROP_FRAME:
|
||||
case FileGlobalSettings::FrameRate_NTSC_FULL_FRAME:
|
||||
return 29.9700262;
|
||||
case FileGlobalSettings::FrameRate_NTSC_DROP_FRAME:
|
||||
case FileGlobalSettings::FrameRate_NTSC_FULL_FRAME:
|
||||
return 29.9700262;
|
||||
|
||||
case FileGlobalSettings::FrameRate_PAL:
|
||||
return 25.0;
|
||||
case FileGlobalSettings::FrameRate_PAL:
|
||||
return 25.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_CINEMA:
|
||||
return 24.0;
|
||||
case FileGlobalSettings::FrameRate_CINEMA:
|
||||
return 24.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_1000:
|
||||
return 1000.0;
|
||||
case FileGlobalSettings::FrameRate_1000:
|
||||
return 1000.0;
|
||||
|
||||
case FileGlobalSettings::FrameRate_CINEMA_ND:
|
||||
return 23.976;
|
||||
case FileGlobalSettings::FrameRate_CINEMA_ND:
|
||||
return 23.976;
|
||||
|
||||
case FileGlobalSettings::FrameRate_CUSTOM:
|
||||
return customFPSVal;
|
||||
case FileGlobalSettings::FrameRate_CUSTOM:
|
||||
return customFPSVal;
|
||||
|
||||
case FileGlobalSettings::FrameRate_MAX: // this is to silence compiler warnings
|
||||
break;
|
||||
case FileGlobalSettings::FrameRate_MAX: // this is to silence compiler warnings
|
||||
break;
|
||||
}
|
||||
|
||||
ai_assert( false );
|
||||
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
|
||||
void Converter::ConvertAnimations()
|
||||
void FBXConverter::ConvertAnimations()
|
||||
{
|
||||
// first of all determine framerate
|
||||
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
|
||||
// this causes ambiguities, well possible between empty identifiers,
|
||||
// such as "Model::" and ""). Make sure the behaviour is consistent
|
||||
|
@ -2055,7 +2042,7 @@ std::string Converter::FixNodeName( const std::string& name ) {
|
|||
return name;
|
||||
}
|
||||
|
||||
void Converter::ConvertAnimationStack( const AnimationStack& st )
|
||||
void FBXConverter::ConvertAnimationStack( const AnimationStack& st )
|
||||
{
|
||||
const AnimationLayerList& layers = st.Layers();
|
||||
if ( layers.empty() ) {
|
||||
|
@ -2197,7 +2184,7 @@ static void validateAnimCurveNodes( const std::vector<const AnimationCurveNode*>
|
|||
#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::vector<const AnimationCurveNode*>& curves,
|
||||
const LayerMap& layer_map,
|
||||
|
@ -2431,10 +2418,9 @@ void Converter::GenerateNodeAnimations( std::vector<aiNodeAnim*>& node_anims,
|
|||
node_anim_chain_bits[ fixed_name ] = flags;
|
||||
}
|
||||
|
||||
bool Converter::IsRedundantAnimationData( const Model& target,
|
||||
TransformationComp comp,
|
||||
const std::vector<const AnimationCurveNode*>& curves )
|
||||
{
|
||||
bool FBXConverter::IsRedundantAnimationData( const Model& target,
|
||||
TransformationComp comp,
|
||||
const std::vector<const AnimationCurveNode*>& curves ) {
|
||||
ai_assert( curves.size() );
|
||||
|
||||
// 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 std::vector<const AnimationCurveNode*>& curves,
|
||||
const LayerMap& layer_map,
|
||||
|
@ -2507,7 +2493,7 @@ aiNodeAnim* Converter::GenerateRotationNodeAnim( const std::string& name,
|
|||
return na.release();
|
||||
}
|
||||
|
||||
aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name,
|
||||
aiNodeAnim* FBXConverter::GenerateScalingNodeAnim( const std::string& name,
|
||||
const Model& /*target*/,
|
||||
const std::vector<const AnimationCurveNode*>& curves,
|
||||
const LayerMap& layer_map,
|
||||
|
@ -2537,16 +2523,14 @@ aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name,
|
|||
return na.release();
|
||||
}
|
||||
|
||||
|
||||
aiNodeAnim* Converter::GenerateTranslationNodeAnim( const std::string& name,
|
||||
const Model& /*target*/,
|
||||
const std::vector<const AnimationCurveNode*>& curves,
|
||||
const LayerMap& layer_map,
|
||||
int64_t start, int64_t stop,
|
||||
double& max_time,
|
||||
double& min_time,
|
||||
bool inverse )
|
||||
{
|
||||
aiNodeAnim* FBXConverter::GenerateTranslationNodeAnim( const std::string& name,
|
||||
const Model& /*target*/,
|
||||
const std::vector<const AnimationCurveNode*>& curves,
|
||||
const LayerMap& layer_map,
|
||||
int64_t start, int64_t stop,
|
||||
double& max_time,
|
||||
double& min_time,
|
||||
bool inverse ) {
|
||||
std::unique_ptr<aiNodeAnim> na( new aiNodeAnim() );
|
||||
na->mNodeName.Set( name );
|
||||
|
||||
|
@ -2575,7 +2559,7 @@ aiNodeAnim* Converter::GenerateTranslationNodeAnim( const std::string& name,
|
|||
return na.release();
|
||||
}
|
||||
|
||||
aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name,
|
||||
aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim( const std::string& name,
|
||||
const Model& target,
|
||||
NodeMap::const_iterator chain[ TransformationComp_MAXIMUM ],
|
||||
NodeMap::const_iterator iter_end,
|
||||
|
@ -2711,7 +2695,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name,
|
|||
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;
|
||||
inputs.reserve( nodes.size() * 3 );
|
||||
|
@ -2767,12 +2751,11 @@ Converter::KeyFrameListList Converter::GetKeyframeList( const std::vector<const
|
|||
}
|
||||
|
||||
|
||||
KeyTimeList Converter::GetKeyTimeList( const KeyFrameListList& inputs )
|
||||
{
|
||||
ai_assert( inputs.size() );
|
||||
KeyTimeList FBXConverter::GetKeyTimeList( const KeyFrameListList& inputs ) {
|
||||
ai_assert( !inputs.empty() );
|
||||
|
||||
// reserve some space upfront - it is likely that the keyframe lists
|
||||
// have matching time values, so max(of all keyframe lists) should
|
||||
// reserve some space upfront - it is likely that the key-frame lists
|
||||
// have matching time values, so max(of all key-frame lists) should
|
||||
// be a good estimate.
|
||||
KeyTimeList keys;
|
||||
|
||||
|
@ -2816,17 +2799,15 @@ KeyTimeList Converter::GetKeyTimeList( const KeyFrameListList& inputs )
|
|||
return keys;
|
||||
}
|
||||
|
||||
void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
|
||||
const aiVector3D& def_value,
|
||||
double& max_time,
|
||||
double& min_time )
|
||||
|
||||
{
|
||||
ai_assert( keys.size() );
|
||||
ai_assert( valOut );
|
||||
void FBXConverter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
|
||||
const aiVector3D& def_value,
|
||||
double& max_time,
|
||||
double& min_time ) {
|
||||
ai_assert( !keys.empty() );
|
||||
ai_assert( nullptr != valOut );
|
||||
|
||||
std::vector<unsigned int> next_pos;
|
||||
const size_t count = inputs.size();
|
||||
const size_t count( inputs.size() );
|
||||
|
||||
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 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 ) {
|
||||
++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,
|
||||
double& maxTime,
|
||||
double& minTime,
|
||||
Model::RotOrder order )
|
||||
{
|
||||
ai_assert( keys.size() );
|
||||
ai_assert( valOut );
|
||||
ai_assert( !keys.empty() );
|
||||
ai_assert( nullptr != valOut );
|
||||
|
||||
std::unique_ptr<aiVectorKey[]> temp( new aiVectorKey[ keys.size() ] );
|
||||
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,
|
||||
const KeyFrameListList& scaling,
|
||||
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;
|
||||
GetRotationMatrix( order, rot, m );
|
||||
|
@ -2975,7 +2959,7 @@ aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrde
|
|||
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,
|
||||
double& maxTime,
|
||||
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 );
|
||||
}
|
||||
|
||||
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*/,
|
||||
int64_t start, int64_t stop,
|
||||
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 );
|
||||
}
|
||||
|
||||
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*/,
|
||||
int64_t start, int64_t stop,
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
@ -3044,7 +3028,7 @@ void Converter::ConvertGlobalSettings() {
|
|||
out->mMetaData->Set(index, "UnitScaleFactor", unitScalFactor);
|
||||
}
|
||||
|
||||
void Converter::TransferDataToScene()
|
||||
void FBXConverter::TransferDataToScene()
|
||||
{
|
||||
ai_assert( !out->mMeshes );
|
||||
ai_assert( !out->mNumMeshes );
|
||||
|
@ -3096,12 +3080,10 @@ void Converter::TransferDataToScene()
|
|||
}
|
||||
}
|
||||
|
||||
//} // !anon
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertToAssimpScene(aiScene* out, const Document& doc)
|
||||
{
|
||||
Converter converter(out,doc);
|
||||
FBXConverter converter(out,doc);
|
||||
}
|
||||
|
||||
} // !FBX
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace FBX {
|
|||
|
||||
class Document;
|
||||
|
||||
using NodeNameCache = std::vector<std::string>;
|
||||
using NodeNameCache = std::set<std::string>;
|
||||
|
||||
/**
|
||||
* Convert a FBX #Document to #aiScene
|
||||
|
@ -78,7 +78,7 @@ using NodeNameCache = std::vector<std::string>;
|
|||
void ConvertToAssimpScene(aiScene* out, const Document& doc);
|
||||
|
||||
/** Dummy class to encapsulate the conversion process */
|
||||
class Converter {
|
||||
class FBXConverter {
|
||||
public:
|
||||
/**
|
||||
* The different parts that make up the final local transformation of a fbx-node
|
||||
|
@ -106,8 +106,8 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
Converter(aiScene* out, const Document& doc);
|
||||
~Converter();
|
||||
FBXConverter(aiScene* out, const Document& doc);
|
||||
~FBXConverter();
|
||||
|
||||
private:
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -131,7 +131,7 @@ private:
|
|||
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 -
|
||||
|
@ -228,6 +228,10 @@ private:
|
|||
// Video -> aiTexture
|
||||
unsigned int ConvertVideo(const Video& video);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// convert embedded texture if necessary and return actual texture path
|
||||
aiString GetTexturePath(const Texture* tex);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
|
||||
const std::string& propName,
|
||||
|
|
|
@ -115,7 +115,7 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
|
|||
}
|
||||
}
|
||||
|
||||
if(!Properties70) {
|
||||
if(!Properties70 || !Properties70->Compound()) {
|
||||
if(!no_warn) {
|
||||
DOMWarning("property table (Properties70) not found",&element);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
int64_t to_ktime(double time) {
|
||||
return (static_cast<int64_t>(time * FBX::SECOND));
|
||||
}
|
||||
|
||||
void FBXExporter::WriteObjects ()
|
||||
{
|
||||
if (!binary) {
|
||||
|
@ -2089,7 +2093,7 @@ void FBXExporter::WriteObjects ()
|
|||
// position/translation
|
||||
for (size_t ki = 0; ki < na->mNumPositionKeys; ++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);
|
||||
yval.push_back(k.mValue.y);
|
||||
zval.push_back(k.mValue.z);
|
||||
|
@ -2103,7 +2107,7 @@ void FBXExporter::WriteObjects ()
|
|||
times.clear(); xval.clear(); yval.clear(); zval.clear();
|
||||
for (size_t ki = 0; ki < na->mNumRotationKeys; ++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...
|
||||
aiMatrix4x4 m(k.mValue.GetMatrix());
|
||||
aiVector3D qs, qr, qt;
|
||||
|
@ -2121,7 +2125,7 @@ void FBXExporter::WriteObjects ()
|
|||
times.clear(); xval.clear(); yval.clear(); zval.clear();
|
||||
for (size_t ki = 0; ki < na->mNumScalingKeys; ++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);
|
||||
yval.push_back(k.mValue.y);
|
||||
zval.push_back(k.mValue.z);
|
||||
|
|
|
@ -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
|
||||
// now it seems unavoidable.
|
||||
if (MappingInformationType == "ByVertice" && isDirect) {
|
||||
if (!HasElement(source, dataElementName)) {
|
||||
return;
|
||||
}
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
FileSystemFilter(const std::string& file, IOSystem* old)
|
||||
: mWrapped (old)
|
||||
, mSrc_file(file)
|
||||
, sep(mWrapped->getOsSeparator()) {
|
||||
, mSep(mWrapped->getOsSeparator()) {
|
||||
ai_assert(nullptr != mWrapped);
|
||||
|
||||
// Determine base directory
|
||||
|
@ -116,7 +116,7 @@ public:
|
|||
// -------------------------------------------------------------------
|
||||
/** Returns the directory separator. */
|
||||
char getOsSeparator() const {
|
||||
return sep;
|
||||
return mSep;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -256,7 +256,7 @@ private:
|
|||
|
||||
while(true) {
|
||||
tmp = mBase;
|
||||
tmp += sep;
|
||||
tmp += mSep;
|
||||
|
||||
std::string::size_type dirsep = in.rfind('/', last_dirsep);
|
||||
if (std::string::npos == dirsep) {
|
||||
|
@ -298,7 +298,7 @@ private:
|
|||
in.erase(in.begin(),it+1);
|
||||
}
|
||||
|
||||
const char sep = getOsSeparator();
|
||||
const char separator = getOsSeparator();
|
||||
for (it = in.begin(); it != in.end(); ++it) {
|
||||
// Exclude :// and \\, which remain untouched.
|
||||
// https://sourceforge.net/tracker/?func=detail&aid=3031725&group_id=226462&atid=1067632
|
||||
|
@ -313,7 +313,7 @@ private:
|
|||
|
||||
// Cleanup path delimiters
|
||||
if (*it == '/' || (*it) == '\\') {
|
||||
*it = sep;
|
||||
*it = separator;
|
||||
|
||||
// And we're removing double delimiters, frequent issue with
|
||||
// incorrectly composited paths ...
|
||||
|
@ -337,7 +337,7 @@ private:
|
|||
private:
|
||||
IOSystem *mWrapped;
|
||||
std::string mSrc_file, mBase;
|
||||
char sep;
|
||||
char mSep;
|
||||
};
|
||||
|
||||
} //!ns Assimp
|
||||
|
|
|
@ -73,6 +73,7 @@ GenFaceNormalsProcess::~GenFaceNormalsProcess()
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const {
|
||||
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
|
||||
return (pFlags & aiProcess_GenNormals) != 0;
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,8 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene) {
|
|||
bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
|
||||
{
|
||||
if (NULL != pMesh->mNormals) {
|
||||
return false;
|
||||
if (force_) delete[] pMesh->mNormals;
|
||||
else return false;
|
||||
}
|
||||
|
||||
// If the mesh consists of lines and/or points but not of
|
||||
|
@ -134,7 +136,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
|
|||
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
|
||||
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i) {
|
||||
pMesh->mNormals[face.mIndices[i]] = vNor;
|
||||
|
|
|
@ -78,7 +78,8 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
bool GenMeshFaceNormals (aiMesh* pcMesh);
|
||||
bool GenMeshFaceNormals(aiMesh* pcMesh);
|
||||
mutable bool force_ = false;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -72,6 +72,7 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() {
|
|||
// Returns whether the processing step is present in the given flag field.
|
||||
bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
|
||||
return (pFlags & aiProcess_GenSmoothNormals) != 0;
|
||||
}
|
||||
|
||||
|
@ -113,8 +114,10 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
|
|||
// Executes the post processing step on the given imported data.
|
||||
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
|
||||
{
|
||||
if (NULL != pMesh->mNormals)
|
||||
return false;
|
||||
if (NULL != pMesh->mNormals) {
|
||||
if (force_) delete[] pMesh->mNormals;
|
||||
else return false;
|
||||
}
|
||||
|
||||
// If the mesh consists of lines and/or points but not of
|
||||
// triangles or higher-order polygons the normal vectors
|
||||
|
@ -146,7 +149,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
|||
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1));
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
|
||||
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i) {
|
||||
pMesh->mNormals[face.mIndices[i]] = vNor;
|
||||
|
@ -214,17 +217,15 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
|||
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
|
||||
|
||||
aiVector3D vr = pMesh->mNormals[i];
|
||||
ai_real vrlen = vr.Length();
|
||||
|
||||
aiVector3D pcNor;
|
||||
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
|
||||
aiVector3D v = pMesh->mNormals[verticesFound[a]];
|
||||
|
||||
// check whether the angle between the two normals is not too large
|
||||
// HACK: if v.x is qnan the dot product will become qnan, too
|
||||
// therefore the comparison against fLimit should be false
|
||||
// in every case.
|
||||
if (v * vr >= fLimit * vrlen * v.Length())
|
||||
// Check whether the angle between the two normals is not too large.
|
||||
// Skip the angle check on our own normal to avoid false negatives
|
||||
// (v*v is not guaranteed to be 1.0 for all unit vectors v)
|
||||
if (is_not_qnan(v.x) && (verticesFound[a] == i || (v * vr >= fLimit)))
|
||||
pcNor += v;
|
||||
}
|
||||
pcNew[i] = pcNor.NormalizeSafe();
|
||||
|
|
|
@ -107,6 +107,7 @@ private:
|
|||
|
||||
/** Configuration option: maximum smoothing angle, in radians*/
|
||||
ai_real configMaxAngle;
|
||||
mutable bool force_ = false;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -383,6 +383,7 @@ bool _ValidateFlags(unsigned int pFlags)
|
|||
void Importer::FreeScene( )
|
||||
{
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
delete pimpl->mScene;
|
||||
pimpl->mScene = NULL;
|
||||
|
||||
|
@ -490,9 +491,9 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
|
|||
SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength));
|
||||
|
||||
// read the file and recover the previous IOSystem
|
||||
static const size_t BufferSize(Importer::MaxLenHint + 28);
|
||||
char fbuff[ BufferSize ];
|
||||
ai_snprintf(fbuff, BufferSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
|
||||
static const size_t BufSize(Importer::MaxLenHint + 28);
|
||||
char fbuff[BufSize];
|
||||
ai_snprintf(fbuff, BufSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
|
||||
|
||||
ReadFile(fbuff,pFlags);
|
||||
SetIOHandler(io);
|
||||
|
@ -930,20 +931,19 @@ BaseImporter* Importer::GetImporter (const char* szExtension) const
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Find a loader plugin for a given file extension
|
||||
size_t Importer::GetImporterIndex (const char* szExtension) const
|
||||
{
|
||||
ai_assert(szExtension);
|
||||
size_t Importer::GetImporterIndex (const char* szExtension) const {
|
||||
ai_assert(nullptr != szExtension);
|
||||
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// skip over wildcard and dot characters at string head --
|
||||
for(;*szExtension == '*' || *szExtension == '.'; ++szExtension);
|
||||
for ( ; *szExtension == '*' || *szExtension == '.'; ++szExtension );
|
||||
|
||||
std::string ext(szExtension);
|
||||
if (ext.empty()) {
|
||||
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;
|
||||
for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
|
||||
|
@ -970,15 +970,18 @@ void Importer::GetExtensionList(aiString& szOut) const
|
|||
(*i)->GetExtensionList(str);
|
||||
}
|
||||
|
||||
for (std::set<std::string>::const_iterator it = str.begin();; ) {
|
||||
szOut.Append("*.");
|
||||
szOut.Append((*it).c_str());
|
||||
// List can be empty
|
||||
if( !str.empty() ) {
|
||||
for (std::set<std::string>::const_iterator it = str.begin();; ) {
|
||||
szOut.Append("*.");
|
||||
szOut.Append((*it).c_str());
|
||||
|
||||
if (++it == str.end()) {
|
||||
break;
|
||||
}
|
||||
szOut.Append(";");
|
||||
}
|
||||
if (++it == str.end()) {
|
||||
break;
|
||||
}
|
||||
szOut.Append(";");
|
||||
}
|
||||
}
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
|
|
|
@ -120,11 +120,11 @@ public:
|
|||
SharedPostProcessInfo* mPPShared;
|
||||
|
||||
/// The default class constructor.
|
||||
ImporterPimpl();
|
||||
ImporterPimpl() AI_NO_EXCEPT;
|
||||
};
|
||||
|
||||
inline
|
||||
ImporterPimpl::ImporterPimpl()
|
||||
ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT
|
||||
: mIOHandler( nullptr )
|
||||
, mIsDefaultHandler( false )
|
||||
, mProgressHandler( nullptr )
|
||||
|
|
|
@ -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);
|
||||
if(!curve) {
|
||||
|
|
|
@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/Vertex.h>
|
||||
#include <assimp/TinyFormatter.h>
|
||||
#include <stdio.h>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace Assimp;
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -239,6 +240,19 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
|||
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.
|
||||
std::vector<Vertex> uniqueVertices;
|
||||
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
|
||||
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
|
||||
if (usedVertexIndices.find(a) == usedVertexIndices.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// collect the vertex data
|
||||
Vertex v(pMesh,a);
|
||||
|
||||
|
|
|
@ -113,14 +113,14 @@ enum PrePostBehaviour
|
|||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO animation keyframe
|
||||
*/
|
||||
struct Key
|
||||
{
|
||||
Key()
|
||||
: time(),
|
||||
value(),
|
||||
inter (IT_LINE),
|
||||
params()
|
||||
{}
|
||||
struct Key {
|
||||
Key() AI_NO_EXCEPT
|
||||
: time()
|
||||
, value()
|
||||
, inter(IT_LINE)
|
||||
, params() {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Current time
|
||||
double time;
|
||||
|
@ -144,17 +144,16 @@ struct Key
|
|||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO animation envelope
|
||||
*/
|
||||
struct Envelope
|
||||
{
|
||||
Envelope()
|
||||
: index()
|
||||
, type (EnvelopeType_Unknown)
|
||||
, pre (PrePostBehaviour_Constant)
|
||||
, post (PrePostBehaviour_Constant)
|
||||
|
||||
, old_first (0)
|
||||
, old_last (0)
|
||||
{}
|
||||
struct Envelope {
|
||||
Envelope() AI_NO_EXCEPT
|
||||
: index()
|
||||
, type(EnvelopeType_Unknown)
|
||||
, pre(PrePostBehaviour_Constant)
|
||||
, post(PrePostBehaviour_Constant)
|
||||
, old_first(0)
|
||||
, old_last(0) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Index of this envelope
|
||||
unsigned int index;
|
||||
|
@ -162,7 +161,7 @@ struct Envelope
|
|||
//! Type of envelope
|
||||
EnvelopeType type;
|
||||
|
||||
//! Pre and post-behaviour
|
||||
//! Pre- and post-behavior
|
||||
PrePostBehaviour pre,post;
|
||||
|
||||
//! Keyframes for this envelope
|
||||
|
|
|
@ -261,14 +261,14 @@ namespace LWO {
|
|||
* \note We can't use the code in SmoothingGroups.inl here - the mesh
|
||||
* structures of 3DS/ASE and LWO are too different.
|
||||
*/
|
||||
struct Face : public aiFace
|
||||
{
|
||||
struct Face : public aiFace {
|
||||
//! Default construction
|
||||
Face()
|
||||
: surfaceIndex (0)
|
||||
, smoothGroup (0)
|
||||
, type (AI_LWO_FACE)
|
||||
{}
|
||||
Face() AI_NO_EXCEPT
|
||||
: surfaceIndex( 0 )
|
||||
, smoothGroup( 0 )
|
||||
, type( AI_LWO_FACE ) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Construction from given type
|
||||
explicit Face(uint32_t _type)
|
||||
|
|
|
@ -253,7 +253,8 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
|
||||
|
||||
// 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
|
||||
temp = (unsigned int)GetMapMode(texture.wrapModeWidth);
|
||||
|
@ -365,7 +366,8 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
|
|||
}
|
||||
if (surf.mMaximumSmoothAngle <= 0.0)
|
||||
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)
|
||||
// If a diffuse texture is set, we set this value to 1.0
|
||||
|
|
|
@ -120,7 +120,7 @@ public:
|
|||
{
|
||||
unsigned int mBone; ///< Index of the bone
|
||||
float mWeight; ///< Weight of that bone on this vertex
|
||||
Weight()
|
||||
Weight() AI_NO_EXCEPT
|
||||
: mBone(0)
|
||||
, mWeight(0.0f)
|
||||
{ }
|
||||
|
|
|
@ -125,7 +125,7 @@ enum AlphaTestFunc
|
|||
*/
|
||||
struct ShaderMapBlock
|
||||
{
|
||||
ShaderMapBlock()
|
||||
ShaderMapBlock() AI_NO_EXCEPT
|
||||
: blend_src (BLEND_NONE)
|
||||
, blend_dest (BLEND_NONE)
|
||||
, alpha_test (AT_NONE)
|
||||
|
@ -150,7 +150,7 @@ struct ShaderMapBlock
|
|||
*/
|
||||
struct ShaderDataBlock
|
||||
{
|
||||
ShaderDataBlock()
|
||||
ShaderDataBlock() AI_NO_EXCEPT
|
||||
: cull (CULL_CW)
|
||||
{}
|
||||
|
||||
|
|
|
@ -192,14 +192,14 @@ typedef std::vector< FrameDesc > FrameList;
|
|||
// ---------------------------------------------------------------------------
|
||||
/** Represents a vertex descriptor in a MD5 file
|
||||
*/
|
||||
struct VertexDesc
|
||||
{
|
||||
VertexDesc()
|
||||
: mFirstWeight (0)
|
||||
, mNumWeights (0)
|
||||
{}
|
||||
struct VertexDesc {
|
||||
VertexDesc() AI_NO_EXCEPT
|
||||
: mFirstWeight(0)
|
||||
, mNumWeights(0) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! UV cordinate of the vertex
|
||||
//! UV coordinate of the vertex
|
||||
aiVector2D mUV;
|
||||
|
||||
//! Index of the first weight of the vertex in
|
||||
|
|
|
@ -61,7 +61,6 @@ http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf
|
|||
namespace Assimp {
|
||||
namespace MDC {
|
||||
|
||||
|
||||
// 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_LE AI_MAKE_MAGIC("IDPC")
|
||||
|
@ -79,8 +78,7 @@ namespace MDC {
|
|||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a MDC file's main header
|
||||
*/
|
||||
struct Header
|
||||
{
|
||||
struct Header {
|
||||
uint32_t ulIdent ;
|
||||
uint32_t ulVersion ;
|
||||
char ucName [ AI_MDC_MAXQPATH ] ;
|
||||
|
@ -100,8 +98,7 @@ struct Header
|
|||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a MDC file's surface header
|
||||
*/
|
||||
struct Surface
|
||||
{
|
||||
struct Surface {
|
||||
uint32_t ulIdent ;
|
||||
char ucName [ AI_MDC_MAXQPATH ] ;
|
||||
uint32_t ulFlags ;
|
||||
|
@ -118,23 +115,22 @@ struct Surface
|
|||
uint32_t ulOffsetFrameBaseFrames ;
|
||||
uint32_t ulOffsetFrameCompFrames ;
|
||||
uint32_t ulOffsetEnd;
|
||||
Surface()
|
||||
: ulIdent(),
|
||||
ulFlags(),
|
||||
ulNumCompFrames(),
|
||||
ulNumBaseFrames(),
|
||||
ulNumShaders(),
|
||||
ulNumVertices(),
|
||||
ulNumTriangles(),
|
||||
ulOffsetTriangles(),
|
||||
ulOffsetShaders(),
|
||||
ulOffsetTexCoords(),
|
||||
ulOffsetBaseVerts(),
|
||||
ulOffsetCompVerts(),
|
||||
ulOffsetFrameBaseFrames(),
|
||||
ulOffsetFrameCompFrames(),
|
||||
ulOffsetEnd()
|
||||
{
|
||||
Surface() AI_NO_EXCEPT
|
||||
: ulIdent()
|
||||
, ulFlags()
|
||||
, ulNumCompFrames()
|
||||
, ulNumBaseFrames()
|
||||
, ulNumShaders()
|
||||
, ulNumVertices()
|
||||
, ulNumTriangles()
|
||||
, ulOffsetTriangles()
|
||||
, ulOffsetShaders()
|
||||
, ulOffsetTexCoords()
|
||||
, ulOffsetBaseVerts()
|
||||
, ulOffsetCompVerts()
|
||||
, ulOffsetFrameBaseFrames()
|
||||
, ulOffsetFrameCompFrames()
|
||||
, ulOffsetEnd() {
|
||||
ucName[AI_MDC_MAXQPATH-1] = '\0';
|
||||
}
|
||||
} PACK_STRUCT;
|
||||
|
@ -142,8 +138,7 @@ struct Surface
|
|||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a MDC frame
|
||||
*/
|
||||
struct Frame
|
||||
{
|
||||
struct Frame {
|
||||
//! bounding box minimum coords
|
||||
aiVector3D bboxMin ;
|
||||
|
||||
|
@ -163,24 +158,21 @@ struct Frame
|
|||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a MDC triangle
|
||||
*/
|
||||
struct Triangle
|
||||
{
|
||||
struct Triangle {
|
||||
uint32_t aiIndices[3];
|
||||
} PACK_STRUCT;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a MDC texture coordinate
|
||||
*/
|
||||
struct TexturCoord
|
||||
{
|
||||
struct TexturCoord {
|
||||
float u,v;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a MDC base vertex
|
||||
*/
|
||||
struct BaseVertex
|
||||
{
|
||||
struct BaseVertex {
|
||||
int16_t x,y,z;
|
||||
uint16_t normal;
|
||||
} PACK_STRUCT;
|
||||
|
@ -188,25 +180,20 @@ struct BaseVertex
|
|||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a MDC compressed vertex
|
||||
*/
|
||||
struct CompressedVertex
|
||||
{
|
||||
struct CompressedVertex {
|
||||
uint8_t xd,yd,zd,nd;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a MDC shader
|
||||
*/
|
||||
struct Shader
|
||||
{
|
||||
struct Shader {
|
||||
char ucName [ AI_MDC_MAXQPATH ] ;
|
||||
uint32_t ulPath;
|
||||
|
||||
} PACK_STRUCT;
|
||||
|
||||
#include <assimp/Compiler/poppack1.h>
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Build a floating point vertex from the compressed data in MDC files
|
||||
*/
|
||||
|
@ -215,6 +202,7 @@ void BuildVertex(const Frame& frame,
|
|||
const CompressedVertex& cvert,
|
||||
aiVector3D& vXYZOut,
|
||||
aiVector3D& vNorOut);
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !! AI_MDCFILEHELPER_H_INC
|
||||
|
|
|
@ -434,10 +434,12 @@ void MDCImporter::InternReadFile(
|
|||
else if (1 == pScene->mNumMeshes)
|
||||
{
|
||||
pScene->mRootNode = new aiNode();
|
||||
pScene->mRootNode->mName = pScene->mMeshes[0]->mName;
|
||||
pScene->mRootNode->mNumMeshes = 1;
|
||||
pScene->mRootNode->mMeshes = new unsigned int[1];
|
||||
pScene->mRootNode->mMeshes[0] = 0;
|
||||
if ( nullptr != pScene->mMeshes[0] ) {
|
||||
pScene->mRootNode->mName = pScene->mMeshes[0]->mName;
|
||||
pScene->mRootNode->mNumMeshes = 1;
|
||||
pScene->mRootNode->mMeshes = new unsigned int[1];
|
||||
pScene->mRootNode->mMeshes[0] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -717,11 +717,9 @@ struct GroupFrame
|
|||
*/
|
||||
struct IntFace_MDL7 {
|
||||
// provide a constructor for our own convenience
|
||||
IntFace_MDL7()
|
||||
{
|
||||
// set everything to zero
|
||||
mIndices[0] = mIndices[1] = mIndices[2] = 0;
|
||||
iMatIndex[0] = iMatIndex[1] = 0;
|
||||
IntFace_MDL7() AI_NO_EXCEPT {
|
||||
::memset( mIndices, 0, sizeof(uint32_t) *3);
|
||||
::memset( iMatIndex, 0, sizeof( unsigned int) *2);
|
||||
}
|
||||
|
||||
//! Vertex indices
|
||||
|
@ -737,13 +735,11 @@ struct IntFace_MDL7 {
|
|||
* which has been created from two single materials along with the
|
||||
* original material indices.
|
||||
*/
|
||||
struct IntMaterial_MDL7
|
||||
{
|
||||
struct IntMaterial_MDL7 {
|
||||
// provide a constructor for our own convenience
|
||||
IntMaterial_MDL7()
|
||||
{
|
||||
pcMat = NULL;
|
||||
iOldMatIndices[0] = iOldMatIndices[1] = 0;
|
||||
IntMaterial_MDL7() AI_NO_EXCEPT
|
||||
: pcMat( nullptr ) {
|
||||
::memset( iOldMatIndices, 0, sizeof(unsigned int) *2);
|
||||
}
|
||||
|
||||
//! Material instance
|
||||
|
@ -761,7 +757,7 @@ struct IntMaterial_MDL7
|
|||
struct IntBone_MDL7 : aiBone
|
||||
{
|
||||
//! Default constructor
|
||||
IntBone_MDL7() : iParent (0xffff)
|
||||
IntBone_MDL7() AI_NO_EXCEPT : iParent (0xffff)
|
||||
{
|
||||
pkeyPositions.reserve(30);
|
||||
pkeyScalings.reserve(30);
|
||||
|
@ -806,12 +802,12 @@ struct IntFrameInfo_MDL7
|
|||
struct IntGroupInfo_MDL7
|
||||
{
|
||||
//! Default constructor
|
||||
IntGroupInfo_MDL7()
|
||||
IntGroupInfo_MDL7() AI_NO_EXCEPT
|
||||
: iIndex(0)
|
||||
, pcGroup(NULL)
|
||||
, pcGroupUVs(NULL)
|
||||
, pcGroupTris(NULL)
|
||||
, pcGroupVerts(NULL)
|
||||
, pcGroup(nullptr)
|
||||
, pcGroupUVs(nullptr)
|
||||
, pcGroupTris(nullptr)
|
||||
, pcGroupVerts(nullptr)
|
||||
{}
|
||||
|
||||
//! Construction from an existing group header
|
||||
|
@ -843,7 +839,7 @@ struct IntGroupInfo_MDL7
|
|||
//! Holds the data that belongs to a MDL7 mesh group
|
||||
struct IntGroupData_MDL7
|
||||
{
|
||||
IntGroupData_MDL7()
|
||||
IntGroupData_MDL7() AI_NO_EXCEPT
|
||||
: bNeed2UV(false)
|
||||
{}
|
||||
|
||||
|
@ -872,10 +868,9 @@ struct IntGroupData_MDL7
|
|||
|
||||
// -------------------------------------------------------------------------------------
|
||||
//! Holds data from an MDL7 file that is shared by all mesh groups
|
||||
struct IntSharedData_MDL7
|
||||
{
|
||||
struct IntSharedData_MDL7 {
|
||||
//! Default constructor
|
||||
IntSharedData_MDL7()
|
||||
IntSharedData_MDL7() AI_NO_EXCEPT
|
||||
: apcOutBones(),
|
||||
iNum()
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
#include <utility>
|
||||
#include "MMDPmxParser.h"
|
||||
#include <assimp/StringUtils.h>
|
||||
#include "../contrib/utf8cpp/source/utf8.h"
|
||||
#include <assimp/Exceptional.h>
|
||||
|
||||
|
@ -118,7 +119,7 @@ namespace pmx
|
|||
stream->read((char*) &count, sizeof(uint8_t));
|
||||
if (count < 8)
|
||||
{
|
||||
throw;
|
||||
throw DeadlyImportError("MMD: invalid size");
|
||||
}
|
||||
stream->read((char*) &encoding, sizeof(uint8_t));
|
||||
stream->read((char*) &uv, sizeof(uint8_t));
|
||||
|
@ -395,7 +396,7 @@ namespace pmx
|
|||
}
|
||||
break;
|
||||
default:
|
||||
throw;
|
||||
throw DeadlyImportError("MMD: unknown morth type");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,8 +477,8 @@ namespace pmx
|
|||
{
|
||||
// 未実装
|
||||
std::cerr << "Not Implemented Exception" << std::endl;
|
||||
throw;
|
||||
}
|
||||
throw DeadlyImportError("MMD: Not Implemented Exception");
|
||||
}
|
||||
|
||||
void PmxModel::Init()
|
||||
{
|
||||
|
@ -516,15 +517,15 @@ namespace pmx
|
|||
if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20)
|
||||
{
|
||||
std::cerr << "invalid magic number." << std::endl;
|
||||
throw;
|
||||
}
|
||||
throw DeadlyImportError("MMD: invalid magic number.");
|
||||
}
|
||||
// バージョン
|
||||
stream->read((char*) &version, sizeof(float));
|
||||
if (version != 2.0f && version != 2.1f)
|
||||
{
|
||||
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);
|
||||
|
||||
|
@ -605,34 +606,5 @@ namespace pmx
|
|||
{
|
||||
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;
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -63,9 +63,9 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
|
|||
unsigned int index,
|
||||
const aiMaterialProperty** pPropOut)
|
||||
{
|
||||
ai_assert (pMat != NULL);
|
||||
ai_assert (pKey != NULL);
|
||||
ai_assert (pPropOut != NULL);
|
||||
ai_assert( pMat != NULL );
|
||||
ai_assert( pKey != NULL );
|
||||
ai_assert( pPropOut != NULL );
|
||||
|
||||
/* Just search for a property with exactly this name ..
|
||||
* could be improved by hashing, but it's possibly
|
||||
|
@ -76,7 +76,7 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
|
|||
|
||||
if (prop /* just for safety ... */
|
||||
&& 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))
|
||||
{
|
||||
*pPropOut = pMat->mProperties[i];
|
||||
|
@ -96,8 +96,8 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
|
|||
ai_real* pOut,
|
||||
unsigned int* pMax)
|
||||
{
|
||||
ai_assert (pOut != NULL);
|
||||
ai_assert (pMat != NULL);
|
||||
ai_assert( pOut != NULL );
|
||||
ai_assert( pMat != NULL );
|
||||
|
||||
const aiMaterialProperty* prop;
|
||||
aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop);
|
||||
|
@ -182,8 +182,8 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
|
|||
int* pOut,
|
||||
unsigned int* pMax)
|
||||
{
|
||||
ai_assert (pOut != NULL);
|
||||
ai_assert (pMat != NULL);
|
||||
ai_assert( pOut != NULL );
|
||||
ai_assert( pMat != NULL );
|
||||
|
||||
const aiMaterialProperty* prop;
|
||||
aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop);
|
||||
|
@ -274,7 +274,7 @@ aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat,
|
|||
aiUVTransform* pOut)
|
||||
{
|
||||
unsigned int iMax = 4;
|
||||
return aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
|
||||
return aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -314,7 +314,7 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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)
|
||||
{
|
||||
ai_assert (pMat != NULL);
|
||||
|
@ -347,15 +347,18 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
|
|||
unsigned int* flags /*= NULL*/
|
||||
)
|
||||
{
|
||||
ai_assert(NULL != mat && NULL != path);
|
||||
ai_assert( NULL != mat );
|
||||
ai_assert( NULL != path );
|
||||
|
||||
// Get the path to the texture
|
||||
if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path)) {
|
||||
return AI_FAILURE;
|
||||
}
|
||||
|
||||
// Determine mapping type
|
||||
aiTextureMapping mapping = aiTextureMapping_UV;
|
||||
aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping);
|
||||
int mapping_ = static_cast<int>(aiTextureMapping_UV);
|
||||
aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index), &mapping_);
|
||||
aiTextureMapping mapping = static_cast<aiTextureMapping>(mapping_);
|
||||
if (_mapping)
|
||||
*_mapping = mapping;
|
||||
|
||||
|
@ -380,15 +383,17 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
|
|||
if (flags){
|
||||
aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags);
|
||||
}
|
||||
|
||||
return AI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static const unsigned int DefaultNumAllocated = 5;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Construction. Actually the one and only way to get an aiMaterial instance
|
||||
aiMaterial::aiMaterial()
|
||||
: mProperties( NULL )
|
||||
: mProperties( nullptr )
|
||||
, mNumProperties( 0 )
|
||||
, mNumAllocated( DefaultNumAllocated ) {
|
||||
// Allocate 5 entries by default
|
||||
|
@ -403,12 +408,20 @@ aiMaterial::~aiMaterial()
|
|||
delete[] mProperties;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiString aiMaterial::GetName() {
|
||||
aiString name;
|
||||
Get(AI_MATKEY_NAME, name);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void aiMaterial::Clear()
|
||||
{
|
||||
for (unsigned int i = 0; i < mNumProperties;++i) {
|
||||
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
|
||||
// delete this entry
|
||||
delete mProperties[i];
|
||||
delete mProperties[ i ];
|
||||
AI_DEBUG_INVALIDATE_PTR(mProperties[i]);
|
||||
}
|
||||
mNumProperties = 0;
|
||||
|
@ -417,11 +430,9 @@ void aiMaterial::Clear()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiReturn aiMaterial::RemoveProperty (const char* pKey,unsigned int type,
|
||||
unsigned int index
|
||||
)
|
||||
aiReturn aiMaterial::RemoveProperty ( const char* pKey,unsigned int type, unsigned int index )
|
||||
{
|
||||
ai_assert(NULL != pKey);
|
||||
ai_assert( nullptr != pKey );
|
||||
|
||||
for (unsigned int i = 0; i < mNumProperties;++i) {
|
||||
aiMaterialProperty* prop = mProperties[i];
|
||||
|
@ -453,17 +464,18 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
|
|||
aiPropertyTypeInfo pType
|
||||
)
|
||||
{
|
||||
ai_assert (pInput != NULL);
|
||||
ai_assert (pKey != NULL);
|
||||
ai_assert (0 != pSizeInBytes);
|
||||
ai_assert( pInput != NULL );
|
||||
ai_assert( pKey != NULL );
|
||||
ai_assert( 0 != pSizeInBytes );
|
||||
|
||||
if ( 0 == pSizeInBytes ) {
|
||||
|
||||
}
|
||||
|
||||
// first search the list whether there is already an entry with this key
|
||||
unsigned int iOutIndex = UINT_MAX;
|
||||
for (unsigned int i = 0; i < mNumProperties;++i) {
|
||||
aiMaterialProperty* prop = mProperties[i];
|
||||
unsigned int iOutIndex( UINT_MAX );
|
||||
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
|
||||
aiMaterialProperty *prop( mProperties[ i ] );
|
||||
|
||||
if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) &&
|
||||
prop->mSemantic == type && prop->mIndex == index){
|
||||
|
@ -515,6 +527,7 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
|
|||
}
|
||||
// push back ...
|
||||
mProperties[mNumProperties++] = pcNew;
|
||||
|
||||
return AI_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,41 +76,36 @@ using namespace std;
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Default constructor
|
||||
ObjFileImporter::ObjFileImporter() :
|
||||
m_Buffer(),
|
||||
m_pRootObject( NULL ),
|
||||
m_strAbsPath( "" )
|
||||
{
|
||||
ObjFileImporter::ObjFileImporter()
|
||||
: m_Buffer()
|
||||
, m_pRootObject( nullptr )
|
||||
, m_strAbsPath( "" ) {
|
||||
DefaultIOSystem io;
|
||||
m_strAbsPath = io.getOsSeparator();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor.
|
||||
ObjFileImporter::~ObjFileImporter()
|
||||
{
|
||||
ObjFileImporter::~ObjFileImporter() {
|
||||
delete m_pRootObject;
|
||||
m_pRootObject = NULL;
|
||||
m_pRootObject = nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns true, if file is an obj file.
|
||||
bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const
|
||||
{
|
||||
if(!checkSig) //Check File Extension
|
||||
{
|
||||
bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const {
|
||||
if(!checkSig) {
|
||||
//Check File Extension
|
||||
return SimpleExtensionCheck(pFile,"obj");
|
||||
}
|
||||
else //Check file Header
|
||||
{
|
||||
} else {
|
||||
// Check file Header
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -215,22 +210,80 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
|
|||
ai_assert(false);
|
||||
}
|
||||
|
||||
// Create nodes for the whole scene
|
||||
std::vector<aiMesh*> MeshArray;
|
||||
for (size_t index = 0; index < pModel->m_Objects.size(); ++index ) {
|
||||
createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
|
||||
}
|
||||
if (pModel->m_Objects.size() > 0) {
|
||||
|
||||
// Create mesh pointer buffer for this scene
|
||||
if (pScene->mNumMeshes > 0) {
|
||||
pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
|
||||
for (size_t index =0; index < MeshArray.size(); ++index ) {
|
||||
pScene->mMeshes[ index ] = MeshArray[ index ];
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create all materials
|
||||
createMaterials( pModel, pScene );
|
||||
// Allocate space for the child nodes on the root node
|
||||
pScene->mRootNode->mChildren = new aiNode*[ childCount ];
|
||||
|
||||
// Create nodes for the whole scene
|
||||
std::vector<aiMesh*> MeshArray;
|
||||
MeshArray.reserve(meshCount);
|
||||
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
|
||||
if (pScene->mNumMeshes > 0) {
|
||||
pScene->mMeshes = new aiMesh*[MeshArray.size()];
|
||||
for (size_t index = 0; index < MeshArray.size(); ++index) {
|
||||
pScene->mMeshes[index] = MeshArray[index];
|
||||
}
|
||||
}
|
||||
|
||||
// Create all materials
|
||||
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;
|
||||
|
||||
// If we have a parent node, store it
|
||||
if( pParent != NULL ) {
|
||||
appendChildToParentNode( pParent, pNode );
|
||||
}
|
||||
ai_assert( NULL != pParent );
|
||||
appendChildToParentNode( pParent, pNode );
|
||||
|
||||
for ( size_t i=0; i< pObject->m_Meshes.size(); ++i ) {
|
||||
unsigned int meshId = pObject->m_Meshes[ i ];
|
||||
|
@ -406,8 +458,8 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
|||
pMesh->mNumVertices = numIndices;
|
||||
if (pMesh->mNumVertices == 0) {
|
||||
throw DeadlyImportError( "OBJ: no vertices" );
|
||||
} else if (pMesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) {
|
||||
throw DeadlyImportError( "OBJ: Too many vertices, would run out of memory" );
|
||||
} else if (pMesh->mNumVertices > AI_MAX_VERTICES) {
|
||||
throw DeadlyImportError( "OBJ: Too many vertices" );
|
||||
}
|
||||
pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
|
||||
|
||||
|
@ -457,7 +509,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
|||
// Copy all vertex colors
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -734,25 +786,8 @@ void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
|
|||
// Assign parent to child
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,8 +84,6 @@ static const std::string BumpOption = "-bm";
|
|||
static const std::string ChannelOption = "-imfchan";
|
||||
static const std::string TypeOption = "-type";
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Constructor
|
||||
ObjFileMtlImporter::ObjFileMtlImporter( std::vector<char> &buffer,
|
||||
|
@ -334,6 +332,11 @@ void ObjFileMtlImporter::getTexture() {
|
|||
// Specular texture
|
||||
out = & m_pModel->m_pCurrentMaterial->textureSpecular;
|
||||
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()) ) ) {
|
||||
// Opacity texture
|
||||
out = & m_pModel->m_pCurrentMaterial->textureOpacity;
|
||||
|
@ -356,11 +359,6 @@ void ObjFileMtlImporter::getTexture() {
|
|||
// Reflection texture(s)
|
||||
//Do nothing here
|
||||
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()) ) ) {
|
||||
// Specularity scaling (glossiness)
|
||||
out = & m_pModel->m_pCurrentMaterial->textureSpecularity;
|
||||
|
|
|
@ -67,20 +67,22 @@ namespace Assimp {
|
|||
class OptimizeMeshesProcess : public BaseProcess
|
||||
{
|
||||
public:
|
||||
|
||||
/// @brief The class constructor.
|
||||
OptimizeMeshesProcess();
|
||||
|
||||
/// @brief The class destcructor,
|
||||
~OptimizeMeshesProcess();
|
||||
|
||||
|
||||
/** @brief Internal utility to store additional mesh info
|
||||
*/
|
||||
struct MeshInfo
|
||||
{
|
||||
MeshInfo()
|
||||
: instance_cnt (0)
|
||||
, vertex_format (0)
|
||||
, output_id (0xffffffff)
|
||||
{}
|
||||
struct MeshInfo {
|
||||
MeshInfo() AI_NO_EXCEPT
|
||||
: instance_cnt(0)
|
||||
, vertex_format(0)
|
||||
, output_id(0xffffffff) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Number of times this mesh is referenced
|
||||
unsigned int instance_cnt;
|
||||
|
|
|
@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/scene.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace ::Assimp;
|
||||
|
||||
static const aiImporterDesc desc = {
|
||||
"Stanford Polygon Library (PLY) Importer",
|
||||
|
@ -73,22 +73,20 @@ static const aiImporterDesc desc = {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Internal stuff
|
||||
namespace
|
||||
{
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Checks that property index is within range
|
||||
template <class T>
|
||||
const T &GetProperty(const std::vector<T> &props, int idx)
|
||||
{
|
||||
if (static_cast<size_t>(idx) >= props.size()) {
|
||||
throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
|
||||
namespace {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Checks that property index is within range
|
||||
template <class T>
|
||||
inline
|
||||
const T &GetProperty(const std::vector<T> &props, int idx) {
|
||||
if (static_cast<size_t>(idx) >= props.size()) {
|
||||
throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
|
||||
}
|
||||
|
||||
return props[idx];
|
||||
}
|
||||
|
||||
return props[idx];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
PLYImporter::PLYImporter()
|
||||
|
@ -129,7 +127,7 @@ const aiImporterDesc* PLYImporter::GetInfo() const {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static bool isBigEndian(const char* szMe) {
|
||||
ai_assert(NULL != szMe);
|
||||
ai_assert(nullptr != szMe);
|
||||
|
||||
// binary_little_endian
|
||||
// binary_big_endian
|
||||
|
@ -150,7 +148,7 @@ static bool isBigEndian(const char* szMe) {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
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));
|
||||
if (!fileStream.get()) {
|
||||
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];
|
||||
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;
|
||||
this->pcDOM = &sPlyDom;
|
||||
|
||||
|
@ -192,7 +190,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
|
|||
if (TokenMatch(szMe, "ascii", 5)) {
|
||||
SkipLine(szMe, (const char**)&szMe);
|
||||
if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) {
|
||||
if (mGeneratedMesh != NULL) {
|
||||
if (mGeneratedMesh != nullptr) {
|
||||
delete(mGeneratedMesh);
|
||||
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
|
||||
if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) {
|
||||
if (mGeneratedMesh != NULL) {
|
||||
if (mGeneratedMesh != nullptr) {
|
||||
delete(mGeneratedMesh);
|
||||
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)");
|
||||
}
|
||||
} else {
|
||||
if (mGeneratedMesh != NULL) {
|
||||
if (mGeneratedMesh != nullptr) {
|
||||
delete(mGeneratedMesh);
|
||||
mGeneratedMesh = nullptr;
|
||||
}
|
||||
|
@ -225,7 +223,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
|
|||
}
|
||||
} else {
|
||||
AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
|
||||
if (mGeneratedMesh != NULL) {
|
||||
if (mGeneratedMesh != nullptr) {
|
||||
delete(mGeneratedMesh);
|
||||
mGeneratedMesh = nullptr;
|
||||
}
|
||||
|
@ -237,13 +235,13 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
|
|||
//free the file buffer
|
||||
streamedBuffer.close();
|
||||
|
||||
if (mGeneratedMesh == NULL) {
|
||||
if (mGeneratedMesh == nullptr) {
|
||||
throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data ");
|
||||
}
|
||||
|
||||
// if no face list is existing we assume that the vertex
|
||||
// list is containing a list of points
|
||||
bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false;
|
||||
bool pointsOnly = mGeneratedMesh->mFaces == nullptr ? true : false;
|
||||
if (pointsOnly) {
|
||||
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) {
|
||||
ai_assert(NULL != pcElement);
|
||||
ai_assert(NULL != instElement);
|
||||
ai_assert(nullptr != pcElement);
|
||||
ai_assert(nullptr != instElement);
|
||||
|
||||
ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
|
||||
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;
|
||||
}
|
||||
|
||||
// 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]) {
|
||||
cOut.a = 1.0;
|
||||
} else {
|
||||
|
@ -481,225 +479,205 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Convert a color component to [0...1]
|
||||
ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType) {
|
||||
switch (eType)
|
||||
{
|
||||
case EDT_Float:
|
||||
return val.fFloat;
|
||||
case EDT_Double:
|
||||
return (ai_real)val.fDouble;
|
||||
switch (eType) {
|
||||
case EDT_Float:
|
||||
return val.fFloat;
|
||||
case EDT_Double:
|
||||
return (ai_real)val.fDouble;
|
||||
case EDT_UChar:
|
||||
return (ai_real)val.iUInt / (ai_real)0xFF;
|
||||
case EDT_Char:
|
||||
return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF;
|
||||
case EDT_UShort:
|
||||
return (ai_real)val.iUInt / (ai_real)0xFFFF;
|
||||
case EDT_Short:
|
||||
return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF;
|
||||
case EDT_UInt:
|
||||
return (ai_real)val.iUInt / (ai_real)0xFFFF;
|
||||
case EDT_Int:
|
||||
return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
case EDT_UChar:
|
||||
return (ai_real)val.iUInt / (ai_real)0xFF;
|
||||
case EDT_Char:
|
||||
return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF;
|
||||
case EDT_UShort:
|
||||
return (ai_real)val.iUInt / (ai_real)0xFFFF;
|
||||
case EDT_Short:
|
||||
return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF;
|
||||
case EDT_UInt:
|
||||
return (ai_real)val.iUInt / (ai_real)0xFFFF;
|
||||
case EDT_Int:
|
||||
return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
|
||||
default:;
|
||||
};
|
||||
return 0.0f;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Try to extract proper faces from the PLY DOM
|
||||
void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos)
|
||||
{
|
||||
ai_assert(NULL != pcElement);
|
||||
ai_assert(NULL != instElement);
|
||||
void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement,
|
||||
unsigned int pos) {
|
||||
ai_assert(nullptr != pcElement);
|
||||
ai_assert(nullptr != instElement);
|
||||
|
||||
if (mGeneratedMesh == NULL)
|
||||
throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces");
|
||||
|
||||
bool bOne = false;
|
||||
|
||||
// index of the vertex index list
|
||||
unsigned int iProperty = 0xFFFFFFFF;
|
||||
PLY::EDataType eType = EDT_Char;
|
||||
bool bIsTriStrip = false;
|
||||
|
||||
// index of the material index property
|
||||
//unsigned int iMaterialIndex = 0xFFFFFFFF;
|
||||
//PLY::EDataType eType2 = EDT_Char;
|
||||
|
||||
// texture coordinates
|
||||
unsigned int iTextureCoord = 0xFFFFFFFF;
|
||||
PLY::EDataType eType3 = EDT_Char;
|
||||
|
||||
// face = unique number of vertex indices
|
||||
if (PLY::EEST_Face == pcElement->eSemantic)
|
||||
{
|
||||
unsigned int _a = 0;
|
||||
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
|
||||
a != pcElement->alProperties.end(); ++a, ++_a)
|
||||
{
|
||||
if (PLY::EST_VertexIndex == (*a).Semantic)
|
||||
{
|
||||
// must be a dynamic list!
|
||||
if (!(*a).bIsList)
|
||||
continue;
|
||||
|
||||
iProperty = _a;
|
||||
bOne = true;
|
||||
eType = (*a).eType;
|
||||
}
|
||||
/*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!
|
||||
if (!(*a).bIsList)
|
||||
continue;
|
||||
iTextureCoord = _a;
|
||||
bOne = true;
|
||||
eType3 = (*a).eType;
|
||||
}
|
||||
}
|
||||
}
|
||||
// triangle strip
|
||||
// TODO: triangle strip and material index support???
|
||||
else if (PLY::EEST_TriStrip == pcElement->eSemantic)
|
||||
{
|
||||
unsigned int _a = 0;
|
||||
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
|
||||
a != pcElement->alProperties.end(); ++a, ++_a)
|
||||
{
|
||||
// must be a dynamic list!
|
||||
if (!(*a).bIsList)
|
||||
continue;
|
||||
iProperty = _a;
|
||||
bOne = true;
|
||||
bIsTriStrip = true;
|
||||
eType = (*a).eType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check whether we have at least one per-face information set
|
||||
if (bOne)
|
||||
{
|
||||
if (mGeneratedMesh->mFaces == NULL)
|
||||
{
|
||||
mGeneratedMesh->mNumFaces = pcElement->NumOccur;
|
||||
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
|
||||
if (mGeneratedMesh == nullptr) {
|
||||
throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces");
|
||||
}
|
||||
|
||||
if (!bIsTriStrip)
|
||||
{
|
||||
// parse the list of vertex indices
|
||||
if (0xFFFFFFFF != iProperty)
|
||||
{
|
||||
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size();
|
||||
mGeneratedMesh->mFaces[pos].mNumIndices = iNum;
|
||||
mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
|
||||
bool bOne = false;
|
||||
|
||||
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
|
||||
GetProperty(instElement->alProperties, iProperty).avList.begin();
|
||||
// index of the vertex index list
|
||||
unsigned int iProperty = 0xFFFFFFFF;
|
||||
PLY::EDataType eType = EDT_Char;
|
||||
bool bIsTriStrip = false;
|
||||
|
||||
for (unsigned int a = 0; a < iNum; ++a, ++p)
|
||||
{
|
||||
mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType);
|
||||
}
|
||||
}
|
||||
// index of the material index property
|
||||
//unsigned int iMaterialIndex = 0xFFFFFFFF;
|
||||
//PLY::EDataType eType2 = EDT_Char;
|
||||
|
||||
// parse the material index
|
||||
// cannot be handled without processing the whole file first
|
||||
/*if (0xFFFFFFFF != iMaterialIndex)
|
||||
{
|
||||
mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo<unsigned int>(
|
||||
GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
|
||||
}*/
|
||||
// texture coordinates
|
||||
unsigned int iTextureCoord = 0xFFFFFFFF;
|
||||
PLY::EDataType eType3 = EDT_Char;
|
||||
|
||||
if (0xFFFFFFFF != iTextureCoord)
|
||||
{
|
||||
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
|
||||
// face = unique number of vertex indices
|
||||
if (PLY::EEST_Face == pcElement->eSemantic) {
|
||||
unsigned int _a = 0;
|
||||
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
|
||||
a != pcElement->alProperties.end(); ++a, ++_a) {
|
||||
if (PLY::EST_VertexIndex == (*a).Semantic) {
|
||||
// must be a dynamic list!
|
||||
if (!(*a).bIsList) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//should be 6 coords
|
||||
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
|
||||
GetProperty(instElement->alProperties, iTextureCoord).avList.begin();
|
||||
|
||||
if ((iNum / 3) == 2) // X Y coord
|
||||
{
|
||||
for (unsigned int a = 0; a < iNum; ++a, ++p)
|
||||
{
|
||||
unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2];
|
||||
if (vindex < mGeneratedMesh->mNumVertices)
|
||||
{
|
||||
if (mGeneratedMesh->mTextureCoords[0] == NULL)
|
||||
{
|
||||
mGeneratedMesh->mNumUVComponents[0] = 2;
|
||||
mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
|
||||
}
|
||||
|
||||
if (a % 2 == 0)
|
||||
mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
|
||||
else
|
||||
mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
|
||||
|
||||
mGeneratedMesh->mTextureCoords[0][vindex].z = 0;
|
||||
iProperty = _a;
|
||||
bOne = true;
|
||||
eType = (*a).eType;
|
||||
} else if (PLY::EST_TextureCoordinates == (*a).Semantic) {
|
||||
// must be a dynamic list!
|
||||
if (!(*a).bIsList) {
|
||||
continue;
|
||||
}
|
||||
iTextureCoord = _a;
|
||||
bOne = true;
|
||||
eType3 = (*a).eType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // triangle strips
|
||||
{
|
||||
// normally we have only one triangle strip instance where
|
||||
// a value of -1 indicates a restart of the strip
|
||||
bool flip = false;
|
||||
const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty(instElement->alProperties, iProperty).avList;
|
||||
//pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption
|
||||
|
||||
int aiTable[2] = { -1, -1 };
|
||||
for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin(); a != quak.end(); ++a) {
|
||||
const int p = PLY::PropertyInstance::ConvertTo<int>(*a, eType);
|
||||
|
||||
if (-1 == p) {
|
||||
// restart the strip ...
|
||||
aiTable[0] = aiTable[1] = -1;
|
||||
flip = false;
|
||||
continue;
|
||||
// triangle strip
|
||||
// TODO: triangle strip and material index support???
|
||||
else if (PLY::EEST_TriStrip == pcElement->eSemantic) {
|
||||
unsigned int _a = 0;
|
||||
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
|
||||
a != pcElement->alProperties.end(); ++a, ++_a) {
|
||||
// must be a dynamic list!
|
||||
if (!(*a).bIsList) {
|
||||
continue;
|
||||
}
|
||||
iProperty = _a;
|
||||
bOne = true;
|
||||
bIsTriStrip = true;
|
||||
eType = (*a).eType;
|
||||
break;
|
||||
}
|
||||
if (-1 == aiTable[0]) {
|
||||
aiTable[0] = p;
|
||||
continue;
|
||||
}
|
||||
if (-1 == aiTable[1]) {
|
||||
aiTable[1] = p;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check whether we have at least one per-face information set
|
||||
if (bOne) {
|
||||
if (mGeneratedMesh->mFaces == nullptr) {
|
||||
mGeneratedMesh->mNumFaces = pcElement->NumOccur;
|
||||
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
|
||||
}
|
||||
|
||||
if (mGeneratedMesh->mFaces == NULL)
|
||||
if (!bIsTriStrip) {
|
||||
// parse the list of vertex indices
|
||||
if (0xFFFFFFFF != iProperty) {
|
||||
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size();
|
||||
mGeneratedMesh->mFaces[pos].mNumIndices = iNum;
|
||||
mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
|
||||
|
||||
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
|
||||
GetProperty(instElement->alProperties, iProperty).avList.begin();
|
||||
|
||||
for (unsigned int a = 0; a < iNum; ++a, ++p) {
|
||||
mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType);
|
||||
}
|
||||
}
|
||||
|
||||
// parse the material index
|
||||
// cannot be handled without processing the whole file first
|
||||
/*if (0xFFFFFFFF != iMaterialIndex)
|
||||
{
|
||||
mGeneratedMesh->mNumFaces = pcElement->NumOccur;
|
||||
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
|
||||
mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo<unsigned int>(
|
||||
GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
|
||||
}*/
|
||||
|
||||
if (0xFFFFFFFF != iTextureCoord) {
|
||||
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
|
||||
|
||||
//should be 6 coords
|
||||
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
|
||||
GetProperty(instElement->alProperties, iTextureCoord).avList.begin();
|
||||
|
||||
if ((iNum / 3) == 2) // X Y coord
|
||||
{
|
||||
for (unsigned int a = 0; a < iNum; ++a, ++p) {
|
||||
unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2];
|
||||
if (vindex < mGeneratedMesh->mNumVertices) {
|
||||
if (mGeneratedMesh->mTextureCoords[0] == nullptr ) {
|
||||
mGeneratedMesh->mNumUVComponents[0] = 2;
|
||||
mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
|
||||
}
|
||||
|
||||
if (a % 2 == 0) {
|
||||
mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
|
||||
} else {
|
||||
mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
|
||||
}
|
||||
|
||||
mGeneratedMesh->mTextureCoords[0][vindex].z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // triangle strips
|
||||
// normally we have only one triangle strip instance where
|
||||
// a value of -1 indicates a restart of the strip
|
||||
bool flip = false;
|
||||
const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty(instElement->alProperties, iProperty).avList;
|
||||
//pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption
|
||||
|
||||
int aiTable[2] = { -1, -1 };
|
||||
for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin(); a != quak.end(); ++a) {
|
||||
const int p = PLY::PropertyInstance::ConvertTo<int>(*a, eType);
|
||||
|
||||
if (-1 == p) {
|
||||
// restart the strip ...
|
||||
aiTable[0] = aiTable[1] = -1;
|
||||
flip = false;
|
||||
continue;
|
||||
}
|
||||
if (-1 == aiTable[0]) {
|
||||
aiTable[0] = p;
|
||||
continue;
|
||||
}
|
||||
if (-1 == aiTable[1]) {
|
||||
aiTable[1] = p;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mGeneratedMesh->mFaces == nullptr) {
|
||||
mGeneratedMesh->mNumFaces = pcElement->NumOccur;
|
||||
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
|
||||
}
|
||||
|
||||
mGeneratedMesh->mFaces[pos].mNumIndices = 3;
|
||||
mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[3];
|
||||
mGeneratedMesh->mFaces[pos].mIndices[0] = aiTable[0];
|
||||
mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1];
|
||||
mGeneratedMesh->mFaces[pos].mIndices[2] = p;
|
||||
|
||||
// every second pass swap the indices.
|
||||
flip = !flip;
|
||||
if ( flip ) {
|
||||
std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]);
|
||||
}
|
||||
|
||||
aiTable[0] = aiTable[1];
|
||||
aiTable[1] = p;
|
||||
}
|
||||
}
|
||||
|
||||
mGeneratedMesh->mFaces[pos].mNumIndices = 3;
|
||||
mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[3];
|
||||
mGeneratedMesh->mFaces[pos].mIndices[0] = aiTable[0];
|
||||
mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1];
|
||||
mGeneratedMesh->mFaces[pos].mIndices[2] = p;
|
||||
|
||||
if ((flip = !flip)) {
|
||||
std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]);
|
||||
}
|
||||
|
||||
aiTable[0] = aiTable[1];
|
||||
aiTable[1] = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -209,7 +209,7 @@ enum EElementSemantic {
|
|||
class Property {
|
||||
public:
|
||||
//! Default constructor
|
||||
Property()
|
||||
Property() AI_NO_EXCEPT
|
||||
: eType (EDT_Int)
|
||||
, Semantic()
|
||||
, bIsList(false)
|
||||
|
@ -257,7 +257,7 @@ public:
|
|||
class Element {
|
||||
public:
|
||||
//! Default constructor
|
||||
Element()
|
||||
Element() AI_NO_EXCEPT
|
||||
: eSemantic (EEST_INVALID)
|
||||
, NumOccur(0) {
|
||||
// empty
|
||||
|
@ -297,8 +297,9 @@ class PropertyInstance
|
|||
public:
|
||||
|
||||
//! Default constructor
|
||||
PropertyInstance ()
|
||||
{}
|
||||
PropertyInstance() AI_NO_EXCEPT {
|
||||
// empty
|
||||
}
|
||||
|
||||
union ValueUnion
|
||||
{
|
||||
|
@ -356,13 +357,13 @@ public:
|
|||
// ---------------------------------------------------------------------------------
|
||||
/** \brief Class for an element instance in a PLY file
|
||||
*/
|
||||
class ElementInstance
|
||||
{
|
||||
class ElementInstance {
|
||||
public:
|
||||
|
||||
//! Default constructor
|
||||
ElementInstance ()
|
||||
{}
|
||||
ElementInstance() AI_NO_EXCEPT
|
||||
: alProperties() {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! List of all parsed properties
|
||||
std::vector< PropertyInstance > alProperties;
|
||||
|
@ -386,8 +387,10 @@ class ElementInstanceList
|
|||
public:
|
||||
|
||||
//! Default constructor
|
||||
ElementInstanceList ()
|
||||
{}
|
||||
ElementInstanceList() AI_NO_EXCEPT
|
||||
: alInstances() {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! List of all element instances
|
||||
std::vector< ElementInstance > alInstances;
|
||||
|
@ -411,8 +414,11 @@ class DOM
|
|||
public:
|
||||
|
||||
//! Default constructor
|
||||
DOM()
|
||||
{}
|
||||
DOM() AI_NO_EXCEPT
|
||||
: alElements()
|
||||
, alElementData() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Contains all elements of the file format
|
||||
|
|
|
@ -164,9 +164,6 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
|
|||
#if (!defined ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
|
||||
out.push_back( new OptimizeGraphProcess());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS)
|
||||
out.push_back( new FindDegeneratesProcess());
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
|
||||
out.push_back( new ComputeUVMappingProcess());
|
||||
#endif
|
||||
|
@ -179,6 +176,12 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
|
|||
#if (!defined ASSIMP_BUILD_NO_TRIANGULATE_PROCESS)
|
||||
out.push_back( new TriangulateProcess());
|
||||
#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)
|
||||
out.push_back( new SortByPTypeProcess());
|
||||
#endif
|
||||
|
|
|
@ -62,17 +62,17 @@ struct aiNode;
|
|||
// STL headers
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
namespace SMD {
|
||||
namespace Assimp {
|
||||
namespace SMD {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Data structure for a vertex in a SMD file
|
||||
*/
|
||||
struct Vertex
|
||||
{
|
||||
Vertex() : iParentNode(UINT_MAX)
|
||||
{}
|
||||
struct Vertex {
|
||||
Vertex() AI_NO_EXCEPT
|
||||
: iParentNode(UINT_MAX) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Vertex position, normal and texture coordinate
|
||||
aiVector3D pos,nor,uv;
|
||||
|
@ -90,10 +90,12 @@ struct Vertex
|
|||
// ---------------------------------------------------------------------------
|
||||
/** Data structure for a face in a SMD file
|
||||
*/
|
||||
struct Face
|
||||
{
|
||||
Face() : iTexture(0x0)
|
||||
{}
|
||||
struct Face {
|
||||
Face() AI_NO_EXCEPT
|
||||
: iTexture(0x0)
|
||||
, avVertices{} {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Texture index for the face
|
||||
unsigned int iTexture;
|
||||
|
@ -105,11 +107,12 @@ struct Face
|
|||
// ---------------------------------------------------------------------------
|
||||
/** Data structure for a bone in a SMD file
|
||||
*/
|
||||
struct Bone
|
||||
{
|
||||
struct Bone {
|
||||
//! Default constructor
|
||||
Bone() : iParent(UINT_MAX), bIsUsed(false)
|
||||
{
|
||||
Bone() AI_NO_EXCEPT
|
||||
: iParent(UINT_MAX)
|
||||
, bIsUsed(false) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
|
@ -124,12 +127,10 @@ struct Bone
|
|||
uint32_t iParent;
|
||||
|
||||
//! Animation of the bone
|
||||
struct Animation
|
||||
{
|
||||
struct Animation {
|
||||
//! Public default constructor
|
||||
Animation()
|
||||
: iFirstTimeKey()
|
||||
{
|
||||
Animation() AI_NO_EXCEPT
|
||||
: iFirstTimeKey() {
|
||||
asKeys.reserve(20);
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,9 @@ static bool IsBinarySTL(const char* buffer, unsigned int 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.
|
||||
// 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".
|
||||
|
@ -108,10 +111,10 @@ static bool IsAsciiSTL(const char* buffer, unsigned int fileSize) {
|
|||
bool isASCII( strncmp( buffer, "solid", 5 ) == 0 );
|
||||
if( isASCII ) {
|
||||
// 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;
|
||||
for( unsigned int i = 0; i < 500; i++ ) {
|
||||
if( buffer[ i ] > 127 ) {
|
||||
for( unsigned int i = 0; i < BufferSize; i++ ) {
|
||||
if( buffer[ i ] > UnicodeBoundary) {
|
||||
isASCII = false;
|
||||
break;
|
||||
}
|
||||
|
@ -352,7 +355,7 @@ void STLImporter::LoadASCIIFile( aiNode *root ) {
|
|||
|
||||
if (positionBuffer.empty()) {
|
||||
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) {
|
||||
pMesh->mNumFaces = 0;
|
||||
|
@ -362,14 +365,23 @@ void STLImporter::LoadASCIIFile( aiNode *root ) {
|
|||
pMesh->mNumFaces = 0;
|
||||
throw DeadlyImportError("Normal buffer size does not match position buffer size");
|
||||
}
|
||||
pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3);
|
||||
pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size());
|
||||
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
|
||||
memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
|
||||
positionBuffer.clear();
|
||||
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
||||
memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
|
||||
normalBuffer.clear();
|
||||
|
||||
// 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->mNumVertices = static_cast<unsigned int>(positionBuffer.size());
|
||||
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
|
||||
memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
|
||||
positionBuffer.clear();
|
||||
}
|
||||
// also only process normalBuffer when filled, else exception when accessing with index operator
|
||||
if (!normalBuffer.empty()) {
|
||||
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
||||
memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
|
||||
normalBuffer.clear();
|
||||
}
|
||||
|
||||
// now copy faces
|
||||
addFacesToMesh(pMesh);
|
||||
|
@ -526,11 +538,21 @@ bool STLImporter::LoadBinaryFile()
|
|||
// now copy faces
|
||||
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
|
||||
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
|
||||
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
|
||||
node->mNumMeshes = pScene->mNumMeshes;
|
||||
node->mMeshes = new unsigned int[pScene->mNumMeshes];
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
|
||||
pScene->mRootNode->mMeshes[i] = i;
|
||||
node->mMeshes[i] = i;
|
||||
|
||||
if (bIsMaterialise && !pMesh->mColors[0])
|
||||
{
|
||||
|
|
|
@ -707,30 +707,30 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator
|
|||
// we work with hashes to make the comparisons MUCH faster,
|
||||
// at least if we have many bones.
|
||||
std::list<BoneWithHash> asBones;
|
||||
BuildUniqueBoneList(asBones, it,end);
|
||||
BuildUniqueBoneList( asBones, it, end );
|
||||
|
||||
// now create the output bones
|
||||
out->mNumBones = 0;
|
||||
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
|
||||
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
|
||||
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;
|
||||
|
||||
// NOTE: different offset matrices for bones with equal names
|
||||
// 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");
|
||||
continue;
|
||||
}
|
||||
pc->mOffsetMatrix = (*wmit).first->mOffsetMatrix;
|
||||
pc->mOffsetMatrix = wmit->first->mOffsetMatrix;
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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;
|
||||
for (unsigned int mp = 0; mp < pip->mNumWeights;++mp,++avw) {
|
||||
const aiVertexWeight& vfi = pip->mWeights[mp];
|
||||
|
@ -849,14 +849,14 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
|
|||
// copy vertex colors
|
||||
n = 0;
|
||||
while ((**begin).HasVertexColors(n)) {
|
||||
aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
|
||||
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
|
||||
aiColor4D *pVec2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
|
||||
for ( std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it ) {
|
||||
if ((*it)->mColors[n]) {
|
||||
::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D));
|
||||
::memcpy( pVec2, (*it)->mColors[ n ], (*it)->mNumVertices * sizeof( aiColor4D ) ) ;
|
||||
} else {
|
||||
ASSIMP_LOG_WARN( "JoinMeshes: VCs expected but input mesh contains no VCs" );
|
||||
}
|
||||
pv2 += (*it)->mNumVertices;
|
||||
pVec2 += (*it)->mNumVertices;
|
||||
}
|
||||
++n;
|
||||
}
|
||||
|
|
|
@ -55,12 +55,8 @@ namespace Assimp {
|
|||
class Importer;
|
||||
|
||||
struct ScenePrivateData {
|
||||
ScenePrivateData()
|
||||
: mOrigImporter( nullptr )
|
||||
, mPPStepsApplied( 0 )
|
||||
, mIsCopy( false ) {
|
||||
// empty
|
||||
}
|
||||
// The struct constructor.
|
||||
ScenePrivateData() AI_NO_EXCEPT;
|
||||
|
||||
// Importer that originally loaded the scene though the C-API
|
||||
// If set, this object is owned by this private data instance.
|
||||
|
@ -77,6 +73,14 @@ struct ScenePrivateData {
|
|||
bool mIsCopy;
|
||||
};
|
||||
|
||||
inline
|
||||
ScenePrivateData::ScenePrivateData() AI_NO_EXCEPT
|
||||
: mOrigImporter( nullptr )
|
||||
, mPPStepsApplied( 0 )
|
||||
, mIsCopy( false ) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// Access private data stored in the scene
|
||||
inline
|
||||
ScenePrivateData* ScenePriv(aiScene* in) {
|
||||
|
|
|
@ -223,7 +223,7 @@ namespace {
|
|||
if( (-42 == (~42 + 1)) && (binValue & 0x80000000))
|
||||
return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
|
||||
// One's complement?
|
||||
else if( (-42 == ~42) && (binValue & 0x80000000))
|
||||
else if ( (-42 == ~42) && (binValue & 0x80000000))
|
||||
return BinFloat(-0) - binValue;
|
||||
// Sign-magnitude?
|
||||
else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary
|
||||
|
|
|
@ -393,7 +393,7 @@ void SplitByBoneCountProcess::UpdateNode( aiNode* pNode) const
|
|||
newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end());
|
||||
}
|
||||
|
||||
delete pNode->mMeshes;
|
||||
delete [] pNode->mMeshes;
|
||||
pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());
|
||||
pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
|
||||
std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
|
||||
|
|
|
@ -65,14 +65,14 @@ namespace Assimp {
|
|||
/** Small helper structure representing a shortcut into the material list
|
||||
* to be able to update some values quickly.
|
||||
*/
|
||||
struct TTUpdateInfo
|
||||
{
|
||||
TTUpdateInfo() :
|
||||
directShortcut (NULL)
|
||||
, mat (NULL)
|
||||
, semantic (0)
|
||||
, index (0)
|
||||
{}
|
||||
struct TTUpdateInfo {
|
||||
TTUpdateInfo() AI_NO_EXCEPT
|
||||
: directShortcut(nullptr)
|
||||
, mat(nullptr)
|
||||
, semantic(0)
|
||||
, index(0) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Direct shortcut, if available
|
||||
unsigned int* directShortcut;
|
||||
|
@ -88,15 +88,14 @@ struct TTUpdateInfo
|
|||
// ---------------------------------------------------------------------------
|
||||
/** Helper class representing texture coordinate transformations
|
||||
*/
|
||||
struct STransformVecInfo : public aiUVTransform
|
||||
{
|
||||
|
||||
STransformVecInfo()
|
||||
: uvIndex (0)
|
||||
, mapU (aiTextureMapMode_Wrap)
|
||||
, mapV (aiTextureMapMode_Wrap)
|
||||
, lockedPos (AI_TT_UV_IDX_LOCK_NONE)
|
||||
{}
|
||||
struct STransformVecInfo : public aiUVTransform {
|
||||
STransformVecInfo() AI_NO_EXCEPT
|
||||
: uvIndex(0)
|
||||
, mapU(aiTextureMapMode_Wrap)
|
||||
, mapV(aiTextureMapMode_Wrap)
|
||||
, lockedPos(AI_TT_UV_IDX_LOCK_NONE) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Source texture coordinate index
|
||||
unsigned int uvIndex;
|
||||
|
|
|
@ -105,8 +105,10 @@ void TriangulateProcess::Execute( aiScene* pScene)
|
|||
bool bHas = false;
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
|
||||
{
|
||||
if ( TriangulateMesh( pScene->mMeshes[ a ] ) ) {
|
||||
bHas = true;
|
||||
if (pScene->mMeshes[ a ]) {
|
||||
if ( TriangulateMesh( pScene->mMeshes[ a ] ) ) {
|
||||
bHas = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bHas ) {
|
||||
|
@ -285,7 +287,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
|||
// We project it onto a plane to get a 2d triangle.
|
||||
|
||||
// Collect all vertices of of the polygon.
|
||||
for (tmp = 0; tmp < max; ++tmp) {
|
||||
for (tmp = 0; tmp < max; ++tmp) {
|
||||
temp_verts3d[tmp] = verts[idx[tmp]];
|
||||
}
|
||||
|
||||
|
@ -485,21 +487,22 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
|||
for(aiFace* f = last_face; f != curOut; ) {
|
||||
unsigned int* i = f->mIndices;
|
||||
|
||||
// drop dumb 0-area triangles
|
||||
if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
|
||||
ASSIMP_LOG_DEBUG("Dropping triangle with area 0");
|
||||
--curOut;
|
||||
// drop dumb 0-area triangles - deactivated for now:
|
||||
//FindDegenerates post processing step can do the same thing
|
||||
//if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
|
||||
// ASSIMP_LOG_DEBUG("Dropping triangle with area 0");
|
||||
// --curOut;
|
||||
|
||||
delete[] f->mIndices;
|
||||
f->mIndices = NULL;
|
||||
// delete[] f->mIndices;
|
||||
// f->mIndices = nullptr;
|
||||
|
||||
for(aiFace* ff = f; ff != curOut; ++ff) {
|
||||
ff->mNumIndices = (ff+1)->mNumIndices;
|
||||
ff->mIndices = (ff+1)->mIndices;
|
||||
(ff+1)->mIndices = NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// for(aiFace* ff = f; ff != curOut; ++ff) {
|
||||
// ff->mNumIndices = (ff+1)->mNumIndices;
|
||||
// ff->mIndices = (ff+1)->mIndices;
|
||||
// (ff+1)->mIndices = nullptr;
|
||||
// }
|
||||
// continue;
|
||||
//}
|
||||
|
||||
i[0] = idx[i[0]];
|
||||
i[1] = idx[i[1]];
|
||||
|
|
|
@ -369,7 +369,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
|||
|
||||
// positions must always be there ...
|
||||
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) {
|
||||
|
@ -386,7 +386,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
|||
|
||||
// faces, too
|
||||
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:
|
||||
|
|
|
@ -150,9 +150,11 @@ ASSIMP_API aiScene::~aiScene() {
|
|||
delete mMeshes[a];
|
||||
delete [] mMeshes;
|
||||
|
||||
if (mNumMaterials && mMaterials)
|
||||
for( unsigned int a = 0; a < mNumMaterials; a++)
|
||||
delete mMaterials[a];
|
||||
if (mNumMaterials && mMaterials) {
|
||||
for (unsigned int a = 0; a < mNumMaterials; ++a ) {
|
||||
delete mMaterials[ a ];
|
||||
}
|
||||
}
|
||||
delete [] mMaterials;
|
||||
|
||||
if (mNumAnimations && mAnimations)
|
||||
|
|
|
@ -55,32 +55,33 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/anim.h>
|
||||
#include <assimp/Defines.h>
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace XFile
|
||||
{
|
||||
namespace Assimp {
|
||||
namespace XFile {
|
||||
|
||||
/** Helper structure representing a XFile mesh face */
|
||||
struct Face
|
||||
{
|
||||
struct Face {
|
||||
std::vector<unsigned int> mIndices;
|
||||
};
|
||||
|
||||
/** Helper structure representing a texture filename inside a material and its potential source */
|
||||
struct TexEntry
|
||||
{
|
||||
struct TexEntry {
|
||||
std::string mName;
|
||||
bool mIsNormalMap; // true if the texname was specified in a NormalmapFilename tag
|
||||
|
||||
TexEntry() { mIsNormalMap = false; }
|
||||
TexEntry( const std::string& pName, bool pIsNormalMap = false)
|
||||
: mName( pName), mIsNormalMap( pIsNormalMap)
|
||||
{ /* done */ }
|
||||
TexEntry() AI_NO_EXCEPT
|
||||
: mName()
|
||||
, mIsNormalMap(false) {
|
||||
// empty
|
||||
}
|
||||
TexEntry(const std::string& pName, bool pIsNormalMap = false)
|
||||
: mName(pName)
|
||||
, mIsNormalMap(pIsNormalMap) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/** Helper structure representing a XFile material */
|
||||
struct Material
|
||||
{
|
||||
struct Material {
|
||||
std::string mName;
|
||||
bool mIsReference; // if true, mName holds a name by which the actual material can be found in the material list
|
||||
aiColor4D mDiffuse;
|
||||
|
@ -88,19 +89,18 @@ struct Material
|
|||
aiColor3D mSpecular;
|
||||
aiColor3D mEmissive;
|
||||
std::vector<TexEntry> mTextures;
|
||||
|
||||
size_t sceneIndex; ///< the index under which it was stored in the scene's material list
|
||||
|
||||
Material()
|
||||
: mIsReference(false),
|
||||
mSpecularExponent(),
|
||||
sceneIndex(SIZE_MAX)
|
||||
{}
|
||||
Material() AI_NO_EXCEPT
|
||||
: mIsReference(false)
|
||||
, mSpecularExponent()
|
||||
, sceneIndex(SIZE_MAX) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/** Helper structure to represent a bone weight */
|
||||
struct BoneWeight
|
||||
{
|
||||
struct BoneWeight {
|
||||
unsigned int mVertex;
|
||||
ai_real mWeight;
|
||||
};
|
||||
|
@ -114,8 +114,7 @@ struct Bone
|
|||
};
|
||||
|
||||
/** Helper structure to represent an XFile mesh */
|
||||
struct Mesh
|
||||
{
|
||||
struct Mesh {
|
||||
std::string mName;
|
||||
std::vector<aiVector3D> mPositions;
|
||||
std::vector<Face> mPosFaces;
|
||||
|
@ -131,38 +130,65 @@ struct Mesh
|
|||
|
||||
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 */
|
||||
struct Node
|
||||
{
|
||||
struct Node {
|
||||
std::string mName;
|
||||
aiMatrix4x4 mTrafoMatrix;
|
||||
Node* mParent;
|
||||
std::vector<Node*> mChildren;
|
||||
std::vector<Mesh*> mMeshes;
|
||||
|
||||
Node() { mParent = NULL; }
|
||||
explicit Node( Node* pParent) { mParent = pParent; }
|
||||
~Node()
|
||||
{
|
||||
for( unsigned int a = 0; a < mChildren.size(); a++)
|
||||
Node() AI_NO_EXCEPT
|
||||
: mName()
|
||||
, mTrafoMatrix()
|
||||
, mParent(nullptr)
|
||||
, 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];
|
||||
for( unsigned int a = 0; a < mMeshes.size(); a++)
|
||||
}
|
||||
for (unsigned int a = 0; a < mMeshes.size(); ++a) {
|
||||
delete mMeshes[a];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MatrixKey
|
||||
{
|
||||
struct MatrixKey {
|
||||
double mTime;
|
||||
aiMatrix4x4 mMatrix;
|
||||
};
|
||||
|
||||
/** Helper structure representing a single animated bone in a XFile */
|
||||
struct AnimBone
|
||||
{
|
||||
struct AnimBone {
|
||||
std::string mBoneName;
|
||||
std::vector<aiVectorKey> mPosKeys; // either three separate key sequences for position, rotation, scaling
|
||||
std::vector<aiQuatKey> mRotKeys;
|
||||
|
@ -194,14 +220,22 @@ struct Scene
|
|||
std::vector<Animation*> mAnims;
|
||||
unsigned int mAnimTicksPerSecond;
|
||||
|
||||
Scene() { mRootNode = NULL; mAnimTicksPerSecond = 0; }
|
||||
~Scene()
|
||||
{
|
||||
Scene() AI_NO_EXCEPT
|
||||
: mRootNode(nullptr)
|
||||
, mGlobalMeshes()
|
||||
, mGlobalMaterials()
|
||||
, mAnimTicksPerSecond(0) {
|
||||
// empty
|
||||
}
|
||||
~Scene() {
|
||||
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];
|
||||
for( unsigned int a = 0; a < mAnims.size(); a++)
|
||||
}
|
||||
for (unsigned int a = 0; a < mAnims.size(); ++a ) {
|
||||
delete mAnims[a];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -332,6 +332,11 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
|
|||
// collect vertex data for indices of this face
|
||||
for( unsigned int d = 0; d < df.mNumIndices; ++d ) {
|
||||
df.mIndices[d] = newIndex;
|
||||
const unsigned int newIdx( pf.mIndices[ d ] );
|
||||
if ( newIdx > sourceMesh->mPositions.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
orgPoints[newIndex] = pf.mIndices[d];
|
||||
|
||||
// Position
|
||||
|
@ -459,7 +464,7 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
|
|||
nbone->mNodeName.Set( bone->mBoneName);
|
||||
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() )
|
||||
{
|
||||
nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size();
|
||||
|
|
|
@ -471,7 +471,10 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh)
|
|||
unsigned int numIndices = ReadInt();
|
||||
Face& face = pMesh->mPosFaces[a];
|
||||
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();
|
||||
}
|
||||
|
@ -1293,7 +1296,7 @@ unsigned int XFileParser::ReadBinDWord() {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int XFileParser::ReadInt()
|
||||
{
|
||||
if( mIsBinaryFormat)
|
||||
if( mIsBinaryFormat)
|
||||
{
|
||||
if( mBinaryNumCount == 0 && mEnd - mP >= 2)
|
||||
{
|
||||
|
@ -1305,7 +1308,8 @@ unsigned int XFileParser::ReadInt()
|
|||
}
|
||||
|
||||
--mBinaryNumCount;
|
||||
if ( mEnd - mP >= 4) {
|
||||
const size_t len( mEnd - mP );
|
||||
if ( len >= 4) {
|
||||
return ReadBinDWord();
|
||||
} else {
|
||||
mP = mEnd;
|
||||
|
@ -1340,6 +1344,7 @@ unsigned int XFileParser::ReadInt()
|
|||
}
|
||||
|
||||
CheckForSeparator();
|
||||
|
||||
return isNegative ? ((unsigned int) -int( number)) : number;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -766,10 +766,17 @@ namespace glTF2
|
|||
Ref<Accessor> indices;
|
||||
|
||||
Ref<Material> material;
|
||||
|
||||
struct Target {
|
||||
AccessorList position, normal, tangent;
|
||||
};
|
||||
std::vector<Target> targets;
|
||||
};
|
||||
|
||||
std::vector<Primitive> primitives;
|
||||
|
||||
std::vector<float> weights;
|
||||
|
||||
Mesh() {}
|
||||
|
||||
/// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
|
||||
|
|
|
@ -931,6 +931,21 @@ namespace {
|
|||
else return false;
|
||||
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)
|
||||
|
@ -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")) {
|
||||
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*/)
|
||||
|
@ -1216,12 +1261,15 @@ inline void Asset::Load(const std::string& pFile, bool isBinary)
|
|||
|
||||
// Read the "scene" property, which specifies which scene to load
|
||||
// and recursively load everything referenced by it
|
||||
unsigned int sceneIndex = 0;
|
||||
if (Value* scene = FindUInt(doc, "scene")) {
|
||||
unsigned int sceneIndex = scene->GetUint();
|
||||
sceneIndex = scene->GetUint();
|
||||
}
|
||||
|
||||
Ref<Scene> s = scenes.Retrieve(sceneIndex);
|
||||
|
||||
this->scene = s;
|
||||
if (Value* scenesArray = FindArray(doc, "scenes")) {
|
||||
if (sceneIndex < scenesArray->Size()) {
|
||||
this->scene = scenes.Retrieve(sceneIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
|
|
|
@ -94,19 +94,7 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
|
|||
, mIOSystem(pIOSystem)
|
||||
, mProperties(pProperties)
|
||||
{
|
||||
aiScene* sceneCopy_tmp;
|
||||
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();
|
||||
mScene = pScene;
|
||||
|
||||
mAsset.reset( new Asset( pIOSystem ) );
|
||||
|
||||
|
@ -514,9 +502,9 @@ void glTF2Exporter::ExportMaterials()
|
|||
GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -682,12 +670,7 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buf
|
|||
|
||||
void glTF2Exporter::ExportMeshes()
|
||||
{
|
||||
// Not for
|
||||
// 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;
|
||||
typedef decltype(aiFace::mNumIndices) IndicesType;
|
||||
|
||||
std::string fname = std::string(mFilename);
|
||||
std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf"));
|
||||
|
@ -779,11 +762,11 @@ void glTF2Exporter::ExportMeshes()
|
|||
indices.resize(aim->mNumFaces * nIndicesPerFace);
|
||||
for (size_t i = 0; i < aim->mNumFaces; ++i) {
|
||||
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) {
|
||||
|
|
|
@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/ai_assert.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/CreateAnimMesh.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -65,6 +66,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
using namespace Assimp;
|
||||
using namespace glTF2;
|
||||
|
||||
namespace {
|
||||
// generate bitangents from normals and tangents according to spec
|
||||
struct Tangent {
|
||||
aiVector3D xyz;
|
||||
ai_real w;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
//
|
||||
// glTF2Importer
|
||||
|
@ -109,18 +117,29 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool
|
|||
|
||||
if (pIOHandler) {
|
||||
glTF2::Asset asset(pIOHandler);
|
||||
try {
|
||||
asset.Load(pFile, extension == "glb");
|
||||
std::string version = asset.asset.version;
|
||||
return !version.empty() && version[0] == '2';
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
asset.Load(pFile, extension == "glb");
|
||||
std::string version = asset.asset.version;
|
||||
return !version.empty() && version[0] == '2';
|
||||
}
|
||||
|
||||
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)
|
||||
//{
|
||||
|
@ -198,8 +217,10 @@ inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset&
|
|||
mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot));
|
||||
mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot));
|
||||
|
||||
mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
|
||||
mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
|
||||
aiTextureMapMode wrapS = ConvertWrappingMode(sampler->wrapS);
|
||||
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) {
|
||||
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
|
||||
if (attr.tangent.size() > 0 && attr.tangent[0]) {
|
||||
// generate bitangents from normals and tangents according to spec
|
||||
struct Tangent {
|
||||
aiVector3D xyz;
|
||||
ai_real w;
|
||||
} *tangents = nullptr;
|
||||
Tangent *tangents = nullptr;
|
||||
|
||||
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) {
|
||||
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]);
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
aiFace* faces = 0;
|
||||
unsigned int nFaces = 0;
|
||||
|
||||
if (prim.indices) {
|
||||
aiFace* faces = 0;
|
||||
unsigned int nFaces = 0;
|
||||
|
||||
unsigned int count = prim.indices->count;
|
||||
|
||||
Accessor::Indexer data = prim.indices->GetIndexer();
|
||||
|
@ -482,9 +552,18 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
|||
case PrimitiveMode_TRIANGLE_STRIP: {
|
||||
nFaces = count - 2;
|
||||
faces = new aiFace[nFaces];
|
||||
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
|
||||
for (unsigned int i = 3; i < count; ++i) {
|
||||
SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i));
|
||||
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], 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;
|
||||
}
|
||||
|
@ -492,19 +571,92 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
|||
nFaces = count - 2;
|
||||
faces = new aiFace[nFaces];
|
||||
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
|
||||
for (unsigned int i = 3; i < count; ++i) {
|
||||
SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i));
|
||||
for (unsigned int i = 1; i < nFaces; ++i) {
|
||||
SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { // no indices provided so directly generate from counts
|
||||
|
||||
if (faces) {
|
||||
aim->mFaces = faces;
|
||||
aim->mNumFaces = nFaces;
|
||||
ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices));
|
||||
// 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) {
|
||||
aim->mFaces = faces;
|
||||
aim->mNumFaces = nFaces;
|
||||
ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices));
|
||||
}
|
||||
|
||||
if (prim.material) {
|
||||
aim->mMaterialIndex = prim.material.GetIndex();
|
||||
|
@ -716,12 +868,6 @@ void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IO
|
|||
|
||||
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) {
|
||||
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||
}
|
||||
|
|
|
@ -351,10 +351,10 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
|
|||
}
|
||||
|
||||
|
||||
if (prim.indices) {
|
||||
aiFace* faces = 0;
|
||||
unsigned int nFaces = 0;
|
||||
aiFace* faces = 0;
|
||||
unsigned int nFaces = 0;
|
||||
|
||||
if (prim.indices) {
|
||||
unsigned int count = prim.indices->count;
|
||||
|
||||
Accessor::Indexer data = prim.indices->GetIndexer();
|
||||
|
@ -419,14 +419,78 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
|
|||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { // no indices provided so directly generate from counts
|
||||
|
||||
if (faces) {
|
||||
aim->mFaces = faces;
|
||||
aim->mNumFaces = nFaces;
|
||||
ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices));
|
||||
// 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) {
|
||||
aim->mFaces = faces;
|
||||
aim->mNumFaces = nFaces;
|
||||
ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices));
|
||||
}
|
||||
|
||||
if (prim.material) {
|
||||
aim->mMaterialIndex = prim.material.GetIndex();
|
||||
|
@ -676,11 +740,6 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS
|
|||
|
||||
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) {
|
||||
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||
|
|
|
@ -21,8 +21,7 @@ class array
|
|||
{
|
||||
|
||||
public:
|
||||
|
||||
array()
|
||||
array()
|
||||
: data(0), allocated(0), used(0),
|
||||
free_when_destroyed(true), is_sorted(true)
|
||||
{
|
||||
|
|
|
@ -100,9 +100,15 @@ static bool isUnsignedIntegerType( Value::ValueType integerType ) {
|
|||
}
|
||||
|
||||
static DDLNode *createDDLNode( Text *id, OpenDDLParser *parser ) {
|
||||
// Basic checks
|
||||
if( ddl_nullptr == id || ddl_nullptr == parser ) {
|
||||
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 );
|
||||
DDLNode *parent( parser->top() );
|
||||
|
|
|
@ -77,19 +77,17 @@ class IOStream;
|
|||
* imports the given file. ReadFile is not overridable, it just calls
|
||||
* InternReadFile() and catches any ImportErrorException that might occur.
|
||||
*/
|
||||
class ASSIMP_API BaseImporter
|
||||
{
|
||||
class ASSIMP_API BaseImporter {
|
||||
friend class Importer;
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor to be privately used by #Importer */
|
||||
BaseImporter();
|
||||
BaseImporter() AI_NO_EXCEPT;
|
||||
|
||||
/** Destructor, private as well */
|
||||
virtual ~BaseImporter();
|
||||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the class can handle the format of the given file.
|
||||
*
|
||||
|
@ -244,7 +242,8 @@ public: // static utilities
|
|||
const char** tokens,
|
||||
unsigned int numTokens,
|
||||
unsigned int searchBytes = 200,
|
||||
bool tokensSol = false);
|
||||
bool tokensSol = false,
|
||||
bool noAlphaBeforeTokens = false);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Check whether a file has a specific file extension
|
||||
|
|
|
@ -60,9 +60,8 @@ namespace Assimp {
|
|||
* 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. */
|
||||
// --------------------------------------------------------------------------------------
|
||||
class ByteSwap
|
||||
{
|
||||
ByteSwap() {}
|
||||
class ByteSwap {
|
||||
ByteSwap() AI_NO_EXCEPT {}
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ class ASSIMP_API DefaultIOStream : public IOStream
|
|||
#endif // __ANDROID__
|
||||
|
||||
protected:
|
||||
DefaultIOStream();
|
||||
DefaultIOStream() AI_NO_EXCEPT;
|
||||
DefaultIOStream(FILE* pFile, const std::string &strFilename);
|
||||
|
||||
public:
|
||||
|
@ -111,27 +111,25 @@ private:
|
|||
FILE* mFile;
|
||||
// Filename
|
||||
std::string mFilename;
|
||||
|
||||
// Cached file size
|
||||
mutable size_t mCachedSize;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
inline DefaultIOStream::DefaultIOStream () :
|
||||
mFile (NULL),
|
||||
mFilename (""),
|
||||
mCachedSize(SIZE_MAX)
|
||||
{
|
||||
inline
|
||||
DefaultIOStream::DefaultIOStream() AI_NO_EXCEPT
|
||||
: mFile(nullptr)
|
||||
, mFilename("")
|
||||
, mCachedSize(SIZE_MAX) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
inline DefaultIOStream::DefaultIOStream (FILE* pFile,
|
||||
const std::string &strFilename) :
|
||||
mFile(pFile),
|
||||
mFilename(strFilename),
|
||||
mCachedSize(SIZE_MAX)
|
||||
{
|
||||
inline
|
||||
DefaultIOStream::DefaultIOStream (FILE* pFile, const std::string &strFilename)
|
||||
: mFile(pFile)
|
||||
, mFilename(strFilename)
|
||||
, mCachedSize(SIZE_MAX) {
|
||||
// empty
|
||||
}
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
|
|
@ -50,8 +50,7 @@ namespace Assimp {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Default implementation of IOSystem using the standard C file functions */
|
||||
class ASSIMP_API DefaultIOSystem : public IOSystem
|
||||
{
|
||||
class ASSIMP_API DefaultIOSystem : public IOSystem {
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
/** Tests for the existence of a file at the given path. */
|
||||
|
|
|
@ -71,7 +71,7 @@ class ASSIMP_API IOStream
|
|||
{
|
||||
protected:
|
||||
/** Constructor protected, use IOSystem::Open() to create an instance. */
|
||||
IOStream();
|
||||
IOStream() AI_NO_EXCEPT;
|
||||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -126,7 +126,7 @@ public:
|
|||
|
||||
// ----------------------------------------------------------------------------------
|
||||
inline
|
||||
IOStream::IOStream() {
|
||||
IOStream::IOStream() AI_NO_EXCEPT {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
* Create an instance of your derived class and assign it to an
|
||||
* #Assimp::Importer instance by calling Importer::SetIOHandler().
|
||||
*/
|
||||
IOSystem();
|
||||
IOSystem() AI_NO_EXCEPT;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Virtual destructor.
|
||||
|
@ -105,9 +105,6 @@ public:
|
|||
*/
|
||||
virtual ~IOSystem();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief For backward compatibility
|
||||
* @see Exists(const char*)
|
||||
|
@ -233,7 +230,7 @@ private:
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
AI_FORCE_INLINE
|
||||
IOSystem::IOSystem()
|
||||
IOSystem::IOSystem() AI_NO_EXCEPT
|
||||
: m_pathStack() {
|
||||
// empty
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* of a file easily. Works with StreamReader.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef INCLUDED_LINE_SPLITTER_H
|
||||
#define INCLUDED_LINE_SPLITTER_H
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "StreamReader.h"
|
||||
#include "ParsingUtils.h"
|
||||
|
||||
|
@ -81,164 +81,205 @@ public:
|
|||
/** construct from existing stream reader
|
||||
note: trim is *always* assumed true if skyp_empty_lines==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++();
|
||||
LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true);
|
||||
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
~LineSplitter() {
|
||||
// empty
|
||||
}
|
||||
|
||||
public:
|
||||
~LineSplitter();
|
||||
|
||||
// -----------------------------------------
|
||||
/** pseudo-iterator increment */
|
||||
LineSplitter& operator++() {
|
||||
if(swallow) {
|
||||
swallow = false;
|
||||
return *this;
|
||||
}
|
||||
if (!*this) {
|
||||
throw std::logic_error("End of file, no more lines to be retrieved.");
|
||||
}
|
||||
char s;
|
||||
cur.clear();
|
||||
while(stream.GetRemainingSize() && (s = stream.GetI1(),1)) {
|
||||
if (s == '\n' || s == '\r') {
|
||||
if (skip_empty_lines) {
|
||||
while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n'));
|
||||
if (stream.GetRemainingSize()) {
|
||||
stream.IncPtr(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// skip both potential line terminators but don't read past this line.
|
||||
if (stream.GetRemainingSize() && (s == '\r' && stream.GetI1() != '\n')) {
|
||||
stream.IncPtr(-1);
|
||||
}
|
||||
if (trim) {
|
||||
while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\t'));
|
||||
if (stream.GetRemainingSize()) {
|
||||
stream.IncPtr(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
cur += s;
|
||||
}
|
||||
++idx;
|
||||
return *this;
|
||||
}
|
||||
LineSplitter& operator++();
|
||||
|
||||
// -----------------------------------------
|
||||
LineSplitter& operator++(int) {
|
||||
return ++(*this);
|
||||
}
|
||||
LineSplitter& operator++(int);
|
||||
|
||||
// -----------------------------------------
|
||||
/** get a pointer to the beginning of a particular token */
|
||||
const char* operator[] (size_t idx) const {
|
||||
const char* s = operator->()->c_str();
|
||||
|
||||
SkipSpaces(&s);
|
||||
for(size_t i = 0; i < idx; ++i) {
|
||||
|
||||
for(;!IsSpace(*s); ++s) {
|
||||
if(IsLineEnd(*s)) {
|
||||
throw std::range_error("Token index out of range, EOL reached");
|
||||
}
|
||||
}
|
||||
SkipSpaces(&s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
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 {
|
||||
const char* s = operator->()->c_str();
|
||||
|
||||
SkipSpaces(&s);
|
||||
for(size_t i = 0; i < N; ++i) {
|
||||
if(IsLineEnd(*s)) {
|
||||
|
||||
throw std::range_error("Token count out of range, EOL reached");
|
||||
|
||||
}
|
||||
tokens[i] = s;
|
||||
|
||||
for(;*s && !IsSpace(*s); ++s);
|
||||
SkipSpaces(&s);
|
||||
}
|
||||
}
|
||||
void get_tokens(const char* (&tokens)[N]) const;
|
||||
|
||||
// -----------------------------------------
|
||||
/** member access */
|
||||
const std::string* operator -> () const {
|
||||
return &cur;
|
||||
}
|
||||
const std::string* operator -> () const;
|
||||
|
||||
std::string operator* () const {
|
||||
return cur;
|
||||
}
|
||||
std::string operator* () const;
|
||||
|
||||
// -----------------------------------------
|
||||
/** boolean context */
|
||||
operator bool() const {
|
||||
return stream.GetRemainingSize()>0;
|
||||
}
|
||||
operator bool() const;
|
||||
|
||||
// -----------------------------------------
|
||||
/** line indices are zero-based, empty lines are included */
|
||||
operator line_idx() const {
|
||||
return idx;
|
||||
}
|
||||
operator line_idx() const;
|
||||
|
||||
line_idx get_index() const {
|
||||
return idx;
|
||||
}
|
||||
line_idx get_index() const;
|
||||
|
||||
// -----------------------------------------
|
||||
/** access the underlying stream object */
|
||||
StreamReaderLE& get_stream() {
|
||||
return stream;
|
||||
}
|
||||
StreamReaderLE& get_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());
|
||||
}
|
||||
|
||||
bool match_start(const char* check);
|
||||
|
||||
// -----------------------------------------
|
||||
/** swallow the next call to ++, return the previous value. */
|
||||
void swallow_next_increment() {
|
||||
swallow = true;
|
||||
}
|
||||
void swallow_next_increment();
|
||||
|
||||
LineSplitter( const LineSplitter & ) = delete;
|
||||
LineSplitter(LineSplitter &&) = delete;
|
||||
LineSplitter &operator = ( const LineSplitter & ) = delete;
|
||||
|
||||
private:
|
||||
LineSplitter( const LineSplitter & );
|
||||
LineSplitter &operator = ( const LineSplitter & );
|
||||
|
||||
private:
|
||||
line_idx idx;
|
||||
std::string cur;
|
||||
StreamReaderLE& stream;
|
||||
bool swallow, skip_empty_lines, trim;
|
||||
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;
|
||||
}
|
||||
|
||||
if (!*this) {
|
||||
throw std::logic_error("End of file, no more lines to be retrieved.");
|
||||
}
|
||||
|
||||
char s;
|
||||
mCur.clear();
|
||||
while (mStream.GetRemainingSize() && (s = mStream.GetI1(), 1)) {
|
||||
if (s == '\n' || s == '\r') {
|
||||
if (mSkip_empty_lines) {
|
||||
while (mStream.GetRemainingSize() && ((s = mStream.GetI1()) == ' ' || s == '\r' || s == '\n'));
|
||||
if (mStream.GetRemainingSize()) {
|
||||
mStream.IncPtr(-1);
|
||||
}
|
||||
} else {
|
||||
// skip both potential line terminators but don't read past this line.
|
||||
if (mStream.GetRemainingSize() && (s == '\r' && mStream.GetI1() != '\n')) {
|
||||
mStream.IncPtr(-1);
|
||||
}
|
||||
if (mTrim) {
|
||||
while (mStream.GetRemainingSize() && ((s = mStream.GetI1()) == ' ' || s == '\t'));
|
||||
if (mStream.GetRemainingSize()) {
|
||||
mStream.IncPtr(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
mCur += s;
|
||||
}
|
||||
++mIdx;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
LineSplitter &LineSplitter::operator++(int) {
|
||||
return ++(*this);
|
||||
}
|
||||
|
||||
inline
|
||||
const char *LineSplitter::operator[] (size_t idx) const {
|
||||
const char* s = operator->()->c_str();
|
||||
|
||||
SkipSpaces(&s);
|
||||
for (size_t i = 0; i < idx; ++i) {
|
||||
|
||||
for (; !IsSpace(*s); ++s) {
|
||||
if (IsLineEnd(*s)) {
|
||||
throw std::range_error("Token index out of range, EOL reached");
|
||||
}
|
||||
}
|
||||
SkipSpaces(&s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
inline
|
||||
void LineSplitter::get_tokens(const char* (&tokens)[N]) const {
|
||||
const char* s = operator->()->c_str();
|
||||
|
||||
SkipSpaces(&s);
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (IsLineEnd(*s)) {
|
||||
throw std::range_error("Token count out of range, EOL reached");
|
||||
}
|
||||
tokens[i] = s;
|
||||
|
||||
for (; *s && !IsSpace(*s); ++s);
|
||||
SkipSpaces(&s);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -65,7 +65,7 @@ class ASSIMP_API LogStream
|
|||
{
|
||||
protected:
|
||||
/** @brief Default constructor */
|
||||
LogStream();
|
||||
LogStream() AI_NO_EXCEPT;
|
||||
|
||||
public:
|
||||
/** @brief Virtual destructor */
|
||||
|
@ -91,12 +91,12 @@ public:
|
|||
* @return New LogStream instance. */
|
||||
static LogStream* createDefaultStream(aiDefaultLogStream stream,
|
||||
const char* name = "AssimpLog.txt",
|
||||
IOSystem* io = NULL);
|
||||
IOSystem* io = nullptr );
|
||||
|
||||
}; // !class LogStream
|
||||
|
||||
inline
|
||||
LogStream::LogStream() {
|
||||
LogStream::LogStream() AI_NO_EXCEPT {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ protected:
|
|||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
Logger();
|
||||
Logger() AI_NO_EXCEPT;
|
||||
|
||||
/**
|
||||
* Construction with a given log severity
|
||||
|
@ -215,8 +215,9 @@ protected:
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Default constructor
|
||||
inline
|
||||
Logger::Logger() {
|
||||
setLogSeverity(NORMAL);
|
||||
Logger::Logger() AI_NO_EXCEPT
|
||||
: m_Severity(NORMAL) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
@ -229,8 +230,9 @@ Logger::~Logger() {
|
|||
// ----------------------------------------------------------------------------------
|
||||
// Construction with given logging severity
|
||||
inline
|
||||
Logger::Logger(LogSeverity severity) {
|
||||
setLogSeverity(severity);
|
||||
Logger::Logger(LogSeverity severity)
|
||||
: m_Severity(severity) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue