Merge pull request #3 from assimp/master

Merge Master Branch To My Branch
pull/4001/head
xiaohunqupo 2021-07-28 16:17:51 +08:00 committed by GitHub
commit 9923cd0e06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
290 changed files with 8156 additions and 11953 deletions

1
.github/FUNDING.yml vendored
View File

@ -1,2 +1 @@
patreon: assimp
open_collective: assimp open_collective: assimp

View File

@ -1,8 +1,8 @@
--- ---
name: Bug report name: Bug report
about: Create a report to help us improve about: Create a report to help us improve
title: '' title: 'Bug:'
labels: '' labels: 'Bug'
assignees: '' assignees: ''
--- ---
@ -23,16 +23,10 @@ A clear and concise description of what you expected to happen.
**Screenshots** **Screenshots**
If applicable, add screenshots to help explain your problem. If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):** **Platform (please complete the following information):**
- OS: [e.g. iOS] - OS: [e.g. iOS]
- Browser [e.g. chrome, safari] - Browser [e.g. chrome, safari]
- Version [e.g. 22] - Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.

View File

@ -2,7 +2,7 @@
name: Feature request name: Feature request
about: Suggest an idea for this project about: Suggest an idea for this project
title: '' title: ''
labels: '' labels: 'Feature-Request'
assignees: '' assignees: ''
--- ---

View File

@ -0,0 +1,25 @@
---
name: Technical debt
about: Create a report to help us to fix and detect tech debts
title: ''
labels: 'Techdebt'
assignees: ''
---
**Describe the technical debt**
A clear and concise description of what the tech debt is about.
**Better solution**
A clear and concise description of what you would expect.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

5
.gitignore vendored
View File

@ -25,7 +25,7 @@ CMakeSettings.json
# Output # Output
bin/ bin/
lib/ lib/
x64/
# QtCreator # QtCreator
CMakeLists.txt.user CMakeLists.txt.user
@ -116,3 +116,6 @@ tools/assimp_qt_viewer/moc_glview.cpp_parameters
tools/assimp_qt_viewer/moc_mainwindow.cpp tools/assimp_qt_viewer/moc_mainwindow.cpp
tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters
tools/assimp_qt_viewer/ui_mainwindow.h tools/assimp_qt_viewer/ui_mainwindow.h
#Generated directory
generated/*

View File

@ -46,8 +46,8 @@ option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
include("cmake/HunterGate.cmake") include("cmake/HunterGate.cmake")
HunterGate( HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.293.tar.gz" URL "https://github.com/cpp-pm/hunter/archive/v0.23.311.tar.gz"
SHA1 "e8e5470652db77149d9b38656db2a6c0b7642693" SHA1 "1a82b9b73055879181cb1466b2ab5d48ee8ae410"
) )
add_definitions(-DASSIMP_USE_HUNTER) add_definitions(-DASSIMP_USE_HUNTER)
@ -268,6 +268,8 @@ ELSEIF(MSVC)
ADD_COMPILE_OPTIONS(/wd4351) ADD_COMPILE_OPTIONS(/wd4351)
ENDIF() ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD 11)
@ -334,9 +336,9 @@ INCLUDE (FindPkgMacros)
INCLUDE (PrecompiledHeader) INCLUDE (PrecompiledHeader)
# Set Assimp project output directory variables. # Set Assimp project output directory variables.
SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for runtime output files")
SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for library output files")
SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE STRING "Path for archive output files")
# Macro used to set the output directories of a target to the # Macro used to set the output directories of a target to the
# respective Assimp output directories. # respective Assimp output directories.
@ -454,7 +456,7 @@ IF(ASSIMP_HUNTER_ENABLED)
ELSE() ELSE()
# If the zlib is already found outside, add an export in case assimpTargets can't find it. # If the zlib is already found outside, add an export in case assimpTargets can't find it.
IF( ZLIB_FOUND ) IF( ZLIB_FOUND )
INSTALL( TARGETS zlib INSTALL( TARGETS zlib zlibstatic
EXPORT "${TARGETS_EXPORT_NAME}") EXPORT "${TARGETS_EXPORT_NAME}")
ENDIF() ENDIF()
@ -527,12 +529,12 @@ ENDIF()
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER ) MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
"Build the C4D importer, which relies on the non-free Melange SDK." "Build the C4D importer, which relies on the non-free Cineware SDK."
) )
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
IF ( MSVC ) IF ( MSVC )
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes") SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
# pick the correct prebuilt library # pick the correct prebuilt library
IF(MSVC15) IF(MSVC15)
@ -551,22 +553,23 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
) )
ENDIF() ENDIF()
SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/libraries/win") SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/win")
SET(C4D_DEBUG_LIBRARIES SET(C4D_DEBUG_LIBRARIES
"${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_debug.lib" "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_debug.lib"
"${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_debug.lib" "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_debug.lib"
) )
SET(C4D_RELEASE_LIBRARIES SET(C4D_RELEASE_LIBRARIES
"${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_release.lib" "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_release.lib"
"${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_release.lib" "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_release.lib"
) )
# winsock and winmm are necessary dependencies of melange (this is undocumented, but true.) # winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because
# it can be used to communicate with a running Cinema 4D instance
SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib) SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
ELSE () ELSE ()
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR
"C4D is currently only available on Windows with melange SDK installed in contrib/Melange" "C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware"
) )
ENDIF () ENDIF ()
ELSE () ELSE ()

25
Dockerfile 100644
View File

@ -0,0 +1,25 @@
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y \
git cmake build-essential software-properties-common
RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update && apt-get install -y gcc-4.9 g++-4.9 && \
cd /usr/bin && \
rm gcc g++ cpp && \
ln -s gcc-4.9 gcc && \
ln -s g++-4.9 g++ && \
ln -s cpp-4.9 cpp
WORKDIR /opt
# Build Assimp
RUN git clone https://github.com/assimp/assimp.git /opt/assimp
WORKDIR /opt/assimp
RUN git checkout master \
&& mkdir build && cd build && \
cmake \
-DCMAKE_BUILD_TYPE=Release \
.. && \
make && make install

37
INSTALL
View File

@ -8,43 +8,10 @@ Getting the documentation
------------------------------ ------------------------------
A regularly-updated copy is available at A regularly-updated copy is available at
http://assimp.sourceforge.net/lib_html/index.html https://assimp-docs.readthedocs.io/en/latest/
A CHM file is included in the SVN repos: ./doc/AssimpDoc_Html/AssimpDoc.chm.
To build the doxygen documentation on your own, follow these steps:
a) download & install latest doxygen
b) make sure doxygen is in the executable search path
c) navigate to ./doc
d) and run 'doxygen'
Open the generated HTML (AssimpDoc_Html/index.html) in the browser of your choice.
Windows only: To generate the CHM doc, install 'Microsoft HTML Workshop'
and configure the path to it in the DOXYFILE first.
------------------------------ ------------------------------
Building Assimp Building Assimp
------------------------------ ------------------------------
More detailed build instructions can be found in the documentation, Just check the build-instaructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md
this section is just for the inpatient among you.
CMake is the preferred build system for Assimp. The minimum required version
is 2.6. If you don't have it yet, downloads for CMake can be found on
http://www.cmake.org/.
For Unix:
1. mkdir build && cd build
2. cmake .. -G 'Unix Makefiles'
3. make -j4
For Windows:
1. Open a command prompt
2. mkdir build
3. cd build
4. cmake ..
5. cmake --build .
For iOS:
Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS

View File

@ -1,6 +1,6 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -8,10 +8,10 @@ A library to import and export various 3d-model-formats including scene-post-pro
<img alt="Coverity Scan Build Status" <img alt="Coverity Scan Build Status"
src="https://scan.coverity.com/projects/5607/badge.svg"/> src="https://scan.coverity.com/projects/5607/badge.svg"/>
</a> </a>
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master) [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
[![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5be56faac64f46fc941ac890fb4febef)](https://www.codacy.com/app/kimkulling/assimp?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/) [![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
<br> <br>
@ -39,10 +39,10 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
### Ports ### ### Ports ###
* [Android](port/AndroidJNI/README.md) * [Android](port/AndroidJNI/README.md)
* [Python](port/PyAssimp/README.md) * [Python](port/PyAssimp/README.md)
* [.NET](https://github.com/assimp/assimp-net) * [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/)
* [Pascal](port/AssimpPascal/Readme.md) * [Pascal](port/AssimpPascal/Readme.md)
* [Javascript (Alpha)](https://github.com/makc/assimp2json) * [Javascript (Alpha)](https://github.com/makc/assimp2json)
* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777) * [Unity 3d Plugin](https://ricardoreis.net/trilib-2/)
* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status)) * [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status))
* [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port. * [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port.
* [Rust](https://github.com/jkvargas/russimp) * [Rust](https://github.com/jkvargas/russimp)
@ -66,9 +66,9 @@ Open Asset Import Library is implemented in C++. The directory structure looks l
The source code is organized in the following way: The source code is organized in the following way:
code/Common The base implementation for importers and the infrastructure code/Common The base implementation for importers and the infrastructure
code/PostProcessing The post-processing steps code/PostProcessing The post-processing steps
code/<FormatName> Implementation for import and export for the format code/AssetLib/<FormatName> Implementation for import and export for the format
### Where to get help ### ### Where to get help ###
For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format. For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
@ -76,9 +76,6 @@ For more information, visit [our website](http://assimp.org/). Or check out the
If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github. If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_
[(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export. Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br> And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
@ -103,9 +100,6 @@ Become a financial contributor and help us sustain our community. [[Contribute](
<a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a> <a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a>
Monthly donations via Patreon:
<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp)
#### Organizations #### Organizations

View File

@ -9,6 +9,7 @@ find_package(poly2tri CONFIG REQUIRED)
find_package(polyclipping CONFIG REQUIRED) find_package(polyclipping CONFIG REQUIRED)
find_package(zip CONFIG REQUIRED) find_package(zip CONFIG REQUIRED)
find_package(pugixml CONFIG REQUIRED) find_package(pugixml CONFIG REQUIRED)
find_package(stb CONFIG REQUIRED)
if(@ASSIMP_BUILD_DRACO@) if(@ASSIMP_BUILD_DRACO@)
find_package(draco CONFIG REQUIRED) find_package(draco CONFIG REQUIRED)

View File

@ -69,7 +69,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) { for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
std::string s = mScene->mMaterials[i].mName; std::string s = mScene->mMaterials[i].mName;
for (std::string::iterator it = s.begin(); it != s.end(); ++it) { for (std::string::iterator it = s.begin(); it != s.end(); ++it) {
*it = static_cast<char>(::tolower(*it)); *it = static_cast<char>(::tolower(static_cast<unsigned char>(*it)));
} }
if (std::string::npos == s.find("default")) continue; if (std::string::npos == s.find("default")) continue;
@ -212,7 +212,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE); mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
// Be sure this is only done for the first material // Be sure this is only done for the first material
mBackgroundImage = std::string(""); mBackgroundImage = std::string();
} }
// At first add the base ambient color of the scene to the material // At first add the base ambient color of the scene to the material

View File

@ -102,13 +102,14 @@ private:
// preserves the mesh's given name if it has one. |index| is the index // preserves the mesh's given name if it has one. |index| is the index
// of the mesh in |aiScene::mMeshes|. // of the mesh in |aiScene::mMeshes|.
std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) { std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) {
static const std::string underscore = "_"; static const char underscore = '_';
char postfix[10] = { 0 }; char postfix[10] = { 0 };
ASSIMP_itoa10(postfix, index); ASSIMP_itoa10(postfix, index);
std::string result = node.mName.C_Str(); std::string result = node.mName.C_Str();
if (mesh.mName.length > 0) { if (mesh.mName.length > 0) {
result += underscore + mesh.mName.C_Str(); result += underscore;
result += mesh.mName.C_Str();
} }
return result + underscore + postfix; return result + underscore + postfix;
} }
@ -378,7 +379,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type
// TODO: handle embedded textures properly // TODO: handle embedded textures properly
if (path.data[0] == '*') { if (path.data[0] == '*') {
ASSIMP_LOG_ERROR("Ignoring embedded texture for export: " + std::string(path.C_Str())); ASSIMP_LOG_ERROR("Ignoring embedded texture for export: ", path.C_Str());
return; return;
} }
@ -444,7 +445,7 @@ void Discreet3DSExporter::WriteMeshes() {
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices); const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count); writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) { for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D &v = trafo * mesh.mVertices[i]; const aiVector3D &v = mesh.mVertices[i];
writer.PutF4(v.x); writer.PutF4(v.x);
writer.PutF4(v.y); writer.PutF4(v.y);
writer.PutF4(v.z); writer.PutF4(v.z);
@ -506,11 +507,16 @@ void Discreet3DSExporter::WriteMeshes() {
// Transformation matrix by which the mesh vertices have been pre-transformed with. // Transformation matrix by which the mesh vertices have been pre-transformed with.
{ {
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRMATRIX); ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRMATRIX);
for (unsigned int r = 0; r < 4; ++r) { // Store rotation 3x3 matrix row wise
for (unsigned int r = 0; r < 3; ++r) {
for (unsigned int c = 0; c < 3; ++c) { for (unsigned int c = 0; c < 3; ++c) {
writer.PutF4(trafo[r][c]); writer.PutF4(trafo[r][c]);
} }
} }
// Store translation sub vector column wise
for (unsigned int r = 0; r < 3; ++r) {
writer.PutF4(trafo[r][3]);
}
} }
} }
} }

View File

@ -61,20 +61,10 @@ namespace D3DS {
#include <assimp/Compiler/pushpack1.h> #include <assimp/Compiler/pushpack1.h>
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Discreet3DS class: Helper class for loading 3ds files. Defines chunks /** Defines chunks and data structures.
* and data structures.
*/ */
class Discreet3DS { namespace Discreet3DS {
private:
Discreet3DS() AI_NO_EXCEPT {
// empty
}
~Discreet3DS() {
// empty
}
public:
//! data structure for a single chunk in a .3ds file //! data structure for a single chunk in a .3ds file
struct Chunk { struct Chunk {
uint16_t Flag; uint16_t Flag;
@ -314,7 +304,7 @@ public:
// camera sub-chunks // camera sub-chunks
CHUNK_CAM_RANGES = 0x4720 CHUNK_CAM_RANGES = 0x4720
}; };
}; }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing a 3ds mesh face */ /** Helper structure representing a 3ds mesh face */
@ -358,16 +348,16 @@ struct Texture {
// empty // empty
} }
Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)), Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend),
mMapName(std::move(other.mMapName)), mMapName(std::move(other.mMapName)),
mOffsetU(std::move(other.mOffsetU)), mOffsetU(other.mOffsetU),
mOffsetV(std::move(other.mOffsetV)), mOffsetV(other.mOffsetV),
mScaleU(std::move(other.mScaleU)), mScaleU(other.mScaleU),
mScaleV(std::move(other.mScaleV)), mScaleV(other.mScaleV),
mRotation(std::move(other.mRotation)), mRotation(other.mRotation),
mMapMode(std::move(other.mMapMode)), mMapMode(other.mMapMode),
bPrivate(std::move(other.bPrivate)), bPrivate(other.bPrivate),
iUVSrc(std::move(other.iUVSrc)) { iUVSrc(other.iUVSrc) {
// empty // empty
} }
@ -376,16 +366,16 @@ struct Texture {
return *this; return *this;
} }
mTextureBlend = std::move(other.mTextureBlend); mTextureBlend = other.mTextureBlend;
mMapName = std::move(other.mMapName); mMapName = std::move(other.mMapName);
mOffsetU = std::move(other.mOffsetU); mOffsetU = other.mOffsetU;
mOffsetV = std::move(other.mOffsetV); mOffsetV = other.mOffsetV;
mScaleU = std::move(other.mScaleU); mScaleU = other.mScaleU;
mScaleV = std::move(other.mScaleV); mScaleV = other.mScaleV;
mRotation = std::move(other.mRotation); mRotation = other.mRotation;
mMapMode = std::move(other.mMapMode); mMapMode = other.mMapMode;
bPrivate = std::move(other.bPrivate); bPrivate = other.bPrivate;
iUVSrc = std::move(other.iUVSrc); iUVSrc = other.iUVSrc;
return *this; return *this;
} }
@ -471,13 +461,13 @@ struct Material {
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)), Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)),
mDiffuse(std::move(other.mDiffuse)), mDiffuse(other.mDiffuse),
mSpecularExponent(std::move(other.mSpecularExponent)), mSpecularExponent(other.mSpecularExponent),
mShininessStrength(std::move(other.mShininessStrength)), mShininessStrength(other.mShininessStrength),
mSpecular(std::move(other.mSpecular)), mSpecular(other.mSpecular),
mAmbient(std::move(other.mAmbient)), mAmbient(other.mAmbient),
mShading(std::move(other.mShading)), mShading(other.mShading),
mTransparency(std::move(other.mTransparency)), mTransparency(other.mTransparency),
sTexDiffuse(std::move(other.sTexDiffuse)), sTexDiffuse(std::move(other.sTexDiffuse)),
sTexOpacity(std::move(other.sTexOpacity)), sTexOpacity(std::move(other.sTexOpacity)),
sTexSpecular(std::move(other.sTexSpecular)), sTexSpecular(std::move(other.sTexSpecular)),
@ -485,10 +475,10 @@ struct Material {
sTexBump(std::move(other.sTexBump)), sTexBump(std::move(other.sTexBump)),
sTexEmissive(std::move(other.sTexEmissive)), sTexEmissive(std::move(other.sTexEmissive)),
sTexShininess(std::move(other.sTexShininess)), sTexShininess(std::move(other.sTexShininess)),
mBumpHeight(std::move(other.mBumpHeight)), mBumpHeight(other.mBumpHeight),
mEmissive(std::move(other.mEmissive)), mEmissive(other.mEmissive),
sTexAmbient(std::move(other.sTexAmbient)), sTexAmbient(std::move(other.sTexAmbient)),
mTwoSided(std::move(other.mTwoSided)) { mTwoSided(other.mTwoSided) {
// empty // empty
} }
@ -498,13 +488,13 @@ struct Material {
} }
mName = std::move(other.mName); mName = std::move(other.mName);
mDiffuse = std::move(other.mDiffuse); mDiffuse = other.mDiffuse;
mSpecularExponent = std::move(other.mSpecularExponent); mSpecularExponent = other.mSpecularExponent;
mShininessStrength = std::move(other.mShininessStrength), mShininessStrength = other.mShininessStrength,
mSpecular = std::move(other.mSpecular); mSpecular = other.mSpecular;
mAmbient = std::move(other.mAmbient); mAmbient = other.mAmbient;
mShading = std::move(other.mShading); mShading = other.mShading;
mTransparency = std::move(other.mTransparency); mTransparency = other.mTransparency;
sTexDiffuse = std::move(other.sTexDiffuse); sTexDiffuse = std::move(other.sTexDiffuse);
sTexOpacity = std::move(other.sTexOpacity); sTexOpacity = std::move(other.sTexOpacity);
sTexSpecular = std::move(other.sTexSpecular); sTexSpecular = std::move(other.sTexSpecular);
@ -512,10 +502,10 @@ struct Material {
sTexBump = std::move(other.sTexBump); sTexBump = std::move(other.sTexBump);
sTexEmissive = std::move(other.sTexEmissive); sTexEmissive = std::move(other.sTexEmissive);
sTexShininess = std::move(other.sTexShininess); sTexShininess = std::move(other.sTexShininess);
mBumpHeight = std::move(other.mBumpHeight); mBumpHeight = other.mBumpHeight;
mEmissive = std::move(other.mEmissive); mEmissive = other.mEmissive;
sTexAmbient = std::move(other.sTexAmbient); sTexAmbient = std::move(other.sTexAmbient);
mTwoSided = std::move(other.mTwoSided); mTwoSided = other.mTwoSided;
return *this; return *this;
} }

View File

@ -143,7 +143,13 @@ void Discreet3DSImporter::SetupProperties(const Importer * /*pImp*/) {
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void Discreet3DSImporter::InternReadFile(const std::string &pFile, void Discreet3DSImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) { aiScene *pScene, IOSystem *pIOHandler) {
StreamReaderLE theStream(pIOHandler->Open(pFile, "rb"));
auto theFile = pIOHandler->Open(pFile, "rb");
if (!theFile) {
throw DeadlyImportError("3DS: Could not open ", pFile);
}
StreamReaderLE theStream(theFile);
// We should have at least one chunk // We should have at least one chunk
if (theStream.GetRemainingSize() < 16) { if (theStream.GetRemainingSize() < 16) {
@ -164,7 +170,7 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
mRootNode->mHierarchyIndex = -1; mRootNode->mHierarchyIndex = -1;
mRootNode->mParent = nullptr; mRootNode->mParent = nullptr;
mMasterScale = 1.0f; mMasterScale = 1.0f;
mBackgroundImage = ""; mBackgroundImage = std::string();
bHasBG = false; bHasBG = false;
bIsPrj = false; bIsPrj = false;
@ -299,7 +305,7 @@ void Discreet3DSImporter::ParseEditorChunk() {
// print the version number // print the version number
char buff[10]; char buff[10];
ASSIMP_itoa10(buff, stream->GetI2()); ASSIMP_itoa10(buff, stream->GetI2());
ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff); ASSIMP_LOG_INFO("3DS file format version: ", buff);
} break; } break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
@ -928,7 +934,7 @@ void Discreet3DSImporter::ParseFaceChunk() {
} }
} }
if (0xcdcdcdcd == idx) { if (0xcdcdcdcd == idx) {
ASSIMP_LOG_ERROR_F("3DS: Unknown material: ", sz); ASSIMP_LOG_ERROR("3DS: Unknown material: ", sz);
} }
// Now continue and read all material indices // Now continue and read all material indices

View File

@ -44,63 +44,66 @@ namespace Assimp {
namespace D3MF { namespace D3MF {
namespace XmlTag { namespace XmlTag {
// Root tag
const char* const RootTag = "3MF";
// Meta-data // Meta-data
static const std::string meta = "metadata"; const char* const meta = "metadata";
static const std::string meta_name = "name"; const char* const meta_name = "name";
// Model-data specific tags // Model-data specific tags
static const std::string model = "model"; const char* const model = "model";
static const std::string model_unit = "unit"; const char* const model_unit = "unit";
static const std::string metadata = "metadata"; const char* const metadata = "metadata";
static const std::string resources = "resources"; const char* const resources = "resources";
static const std::string object = "object"; const char* const object = "object";
static const std::string mesh = "mesh"; const char* const mesh = "mesh";
static const std::string components = "components"; const char* const components = "components";
static const std::string component = "component"; const char* const component = "component";
static const std::string vertices = "vertices"; const char* const vertices = "vertices";
static const std::string vertex = "vertex"; const char* const vertex = "vertex";
static const std::string triangles = "triangles"; const char* const triangles = "triangles";
static const std::string triangle = "triangle"; const char* const triangle = "triangle";
static const std::string x = "x"; const char* const x = "x";
static const std::string y = "y"; const char* const y = "y";
static const std::string z = "z"; const char* const z = "z";
static const std::string v1 = "v1"; const char* const v1 = "v1";
static const std::string v2 = "v2"; const char* const v2 = "v2";
static const std::string v3 = "v3"; const char* const v3 = "v3";
static const std::string id = "id"; const char* const id = "id";
static const std::string pid = "pid"; const char* const pid = "pid";
static const std::string pindex = "pindex"; const char* const pindex = "pindex";
static const std::string p1 = "p1"; const char* const p1 = "p1";
static const std::string name = "name"; const char* const name = "name";
static const std::string type = "type"; const char* const type = "type";
static const std::string build = "build"; const char* const build = "build";
static const std::string item = "item"; const char* const item = "item";
static const std::string objectid = "objectid"; const char* const objectid = "objectid";
static const std::string transform = "transform"; const char* const transform = "transform";
// Material definitions // Material definitions
static const std::string basematerials = "basematerials"; const char* const basematerials = "basematerials";
static const std::string basematerials_id = "id"; const char* const basematerials_id = "id";
static const std::string basematerials_base = "base"; const char* const basematerials_base = "base";
static const std::string basematerials_name = "name"; const char* const basematerials_name = "name";
static const std::string basematerials_displaycolor = "displaycolor"; const char* const basematerials_displaycolor = "displaycolor";
// Meta info tags // Meta info tags
static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; const char* const SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
static const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; const char* const SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships"; const char* const RELS_RELATIONSHIP_CONTAINER = "Relationships";
static const std::string RELS_RELATIONSHIP_NODE = "Relationship"; const char* const RELS_RELATIONSHIP_NODE = "Relationship";
static const std::string RELS_ATTRIB_TARGET = "Target"; const char* const RELS_ATTRIB_TARGET = "Target";
static const std::string RELS_ATTRIB_TYPE = "Type"; const char* const RELS_ATTRIB_TYPE = "Type";
static const std::string RELS_ATTRIB_ID = "Id"; const char* const RELS_ATTRIB_ID = "Id";
static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel"; const char* const PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket"; const char* const PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
} }
} // Namespace D3MF } // Namespace D3MF
} // Namespace Assimp } // Namespace Assimp

View File

@ -307,18 +307,26 @@ void D3MFExporter::writeMesh(aiMesh *mesh) {
return; return;
} }
mModelOutput << "<" << XmlTag::mesh << ">" << std::endl; mModelOutput << "<"
mModelOutput << "<" << XmlTag::vertices << ">" << std::endl; << XmlTag::mesh
<< ">" << "\n";
mModelOutput << "<"
<< XmlTag::vertices
<< ">" << "\n";
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
writeVertex(mesh->mVertices[i]); writeVertex(mesh->mVertices[i]);
} }
mModelOutput << "</" << XmlTag::vertices << ">" << std::endl; mModelOutput << "</"
<< XmlTag::vertices << ">"
<< "\n";
const unsigned int matIdx(mesh->mMaterialIndex); const unsigned int matIdx(mesh->mMaterialIndex);
writeFaces(mesh, matIdx); writeFaces(mesh, matIdx);
mModelOutput << "</" << XmlTag::mesh << ">" << std::endl; mModelOutput << "</"
<< XmlTag::mesh << ">"
<< "\n";
} }
void D3MFExporter::writeVertex(const aiVector3D &pos) { void D3MFExporter::writeVertex(const aiVector3D &pos) {
@ -334,27 +342,34 @@ void D3MFExporter::writeFaces(aiMesh *mesh, unsigned int matIdx) {
if (!mesh->HasFaces()) { if (!mesh->HasFaces()) {
return; return;
} }
mModelOutput << "<" << XmlTag::triangles << ">" << std::endl; mModelOutput << "<"
<< XmlTag::triangles << ">"
<< "\n";
for (unsigned int i = 0; i < mesh->mNumFaces; ++i) { for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
aiFace &currentFace = mesh->mFaces[i]; aiFace &currentFace = mesh->mFaces[i];
mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\"" mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\""
<< currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2] << currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2]
<< "\" pid=\"1\" p1=\"" + ai_to_string(matIdx) + "\" />"; << "\" pid=\"1\" p1=\"" + ai_to_string(matIdx) + "\" />";
mModelOutput << std::endl; mModelOutput << "\n";
} }
mModelOutput << "</" << XmlTag::triangles << ">"; mModelOutput << "</"
mModelOutput << std::endl; << XmlTag::triangles
<< ">";
mModelOutput << "\n";
} }
void D3MFExporter::writeBuild() { void D3MFExporter::writeBuild() {
mModelOutput << "<" << XmlTag::build << ">" << std::endl; mModelOutput << "<"
<< XmlTag::build
<< ">"
<< "\n";
for (size_t i = 0; i < mBuildItems.size(); ++i) { for (size_t i = 0; i < mBuildItems.size(); ++i) {
mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>"; mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>";
mModelOutput << std::endl; mModelOutput << "\n";
} }
mModelOutput << "</" << XmlTag::build << ">"; mModelOutput << "</" << XmlTag::build << ">";
mModelOutput << std::endl; mModelOutput << "\n";
} }
void D3MFExporter::zipContentType(const std::string &filename) { void D3MFExporter::zipContentType(const std::string &filename) {

View File

@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER #ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
#include "D3MFImporter.h" #include "D3MFImporter.h"
#include "3MFXmlTags.h"
#include "D3MFOpcPackage.h"
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
@ -51,17 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/fast_atof.h>
#include <cassert> #include <cassert>
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "3MFXmlTags.h"
#include "D3MFOpcPackage.h"
#include <assimp/fast_atof.h>
#include <iomanip> #include <iomanip>
#include <string.h>
namespace Assimp { namespace Assimp {
namespace D3MF { namespace D3MF {
@ -72,32 +72,39 @@ enum class ResourceType {
RT_Unknown RT_Unknown
}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...) }; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
class Resource class Resource {
{
public: public:
Resource(int id) :
mId(id) {}
virtual ~Resource() {}
int mId; int mId;
virtual ResourceType getType() { Resource(int id) :
mId(id) {
// empty
}
virtual ~Resource() {
// empty
}
virtual ResourceType getType() const {
return ResourceType::RT_Unknown; return ResourceType::RT_Unknown;
} }
}; };
class BaseMaterials : public Resource { class BaseMaterials : public Resource {
public: public:
BaseMaterials(int id) :
Resource(id),
mMaterials(),
mMaterialIndex() {}
std::vector<aiMaterial *> mMaterials; std::vector<aiMaterial *> mMaterials;
std::vector<unsigned int> mMaterialIndex; std::vector<unsigned int> mMaterialIndex;
virtual ResourceType getType() { BaseMaterials(int id) :
Resource(id),
mMaterials(),
mMaterialIndex() {
// empty
}
~BaseMaterials() = default;
ResourceType getType() const override {
return ResourceType::RT_BaseMaterials; return ResourceType::RT_BaseMaterials;
} }
}; };
@ -109,24 +116,26 @@ struct Component {
class Object : public Resource { class Object : public Resource {
public: public:
std::vector<aiMesh*> mMeshes; std::vector<aiMesh *> mMeshes;
std::vector<unsigned int> mMeshIndex; std::vector<unsigned int> mMeshIndex;
std::vector<Component> mComponents; std::vector<Component> mComponents;
std::string mName; std::string mName;
Object(int id) : Object(int id) :
Resource(id), Resource(id),
mName(std::string("Object_") + ai_to_string(id)) {} mName(std::string("Object_") + ai_to_string(id)) {
// empty
}
virtual ResourceType getType() { ~Object() = default;
ResourceType getType() const override {
return ResourceType::RT_Object; return ResourceType::RT_Object;
} }
}; };
class XmlSerializer { class XmlSerializer {
public: public:
XmlSerializer(XmlParser *xmlParser) : XmlSerializer(XmlParser *xmlParser) :
mResourcesDictionnary(), mResourcesDictionnary(),
mMaterialCount(0), mMaterialCount(0),
@ -136,7 +145,7 @@ public:
} }
~XmlSerializer() { ~XmlSerializer() {
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) { for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) {
delete it->second; delete it->second;
} }
} }
@ -146,28 +155,28 @@ public:
return; return;
} }
scene->mRootNode = new aiNode("3MF"); scene->mRootNode = new aiNode(XmlTag::RootTag);
XmlNode node = mXmlParser->getRootNode().child("model"); XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
if (node.empty()) { if (node.empty()) {
return; return;
} }
XmlNode resNode = node.child("resources"); XmlNode resNode = node.child(XmlTag::resources);
for (XmlNode currentNode = resNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : resNode.children()) {
const std::string &currentNodeName = currentNode.name(); const std::string currentNodeName = currentNode.name();
if (currentNodeName == D3MF::XmlTag::object) { if (currentNodeName == XmlTag::object) {
ReadObject(currentNode);; ReadObject(currentNode);
} else if (currentNodeName == D3MF::XmlTag::basematerials) { } else if (currentNodeName == XmlTag::basematerials) {
ReadBaseMaterials(currentNode); ReadBaseMaterials(currentNode);
} else if (currentNodeName == D3MF::XmlTag::meta) { } else if (currentNodeName == XmlTag::meta) {
ReadMetadata(currentNode); ReadMetadata(currentNode);
} }
} }
XmlNode buildNode = node.child("build"); XmlNode buildNode = node.child(XmlTag::build);
for (XmlNode currentNode = buildNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : buildNode.children()) {
const std::string &currentNodeName = currentNode.name(); const std::string currentNodeName = currentNode.name();
if (currentNodeName == D3MF::XmlTag::item) { if (currentNodeName == XmlTag::item) {
int objectId = -1; int objectId = -1;
std::string transformationMatrixStr; std::string transformationMatrixStr;
aiMatrix4x4 transformationMatrix; aiMatrix4x4 transformationMatrix;
@ -186,10 +195,9 @@ public:
} }
} }
// import the metadata // import the metadata
if (!mMetaData.empty()) { if (!mMetaData.empty()) {
const size_t numMeta(mMetaData.size()); const size_t numMeta = mMetaData.size();
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta)); scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
for (size_t i = 0; i < numMeta; ++i) { for (size_t i = 0; i < numMeta; ++i) {
aiString val(mMetaData[i].value); aiString val(mMetaData[i].value);
@ -201,22 +209,22 @@ public:
scene->mNumMeshes = static_cast<unsigned int>(mMeshCount); scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
if (scene->mNumMeshes != 0) { if (scene->mNumMeshes != 0) {
scene->mMeshes = new aiMesh *[scene->mNumMeshes](); scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) { for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
if (it->second->getType() == ResourceType::RT_Object) { if (it->second->getType() == ResourceType::RT_Object) {
Object *obj = static_cast<Object*>(it->second); Object *obj = static_cast<Object *>(it->second);
ai_assert(nullptr != obj);
for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) { for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i]; scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
} }
} }
} }
} }
// import the materials // import the materials
scene->mNumMaterials = static_cast<unsigned int>(mMaterialCount); scene->mNumMaterials = mMaterialCount;
if (scene->mNumMaterials != 0) { if (scene->mNumMaterials != 0) {
scene->mMaterials = new aiMaterial *[scene->mNumMaterials]; scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) { for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
if (it->second->getType() == ResourceType::RT_BaseMaterials) { if (it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second); BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) { for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
@ -228,35 +236,36 @@ public:
} }
private: private:
void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
ai_assert(nullptr != obj);
void addObjectToNode(aiNode* parent, Object* obj, aiMatrix4x4 nodeTransform) {
aiNode *sceneNode = new aiNode(obj->mName); aiNode *sceneNode = new aiNode(obj->mName);
sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size()); sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes]; sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes); std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
sceneNode->mTransformation = nodeTransform; sceneNode->mTransformation = nodeTransform;
if (nullptr != parent) {
parent->addChildren(1, &sceneNode); parent->addChildren(1, &sceneNode);
}
for (size_t i = 0; i < obj->mComponents.size(); ++i) { for (size_t i = 0; i < obj->mComponents.size(); ++i) {
Component c = obj->mComponents[i]; Component c = obj->mComponents[i];
auto it = mResourcesDictionnary.find(c.mObjectId); auto it = mResourcesDictionnary.find(c.mObjectId);
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) { if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
addObjectToNode(sceneNode, static_cast<Object*>(it->second), c.mTransformation); addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
} }
} }
} }
bool getNodeAttribute(const XmlNode& node, const std::string& attribute, std::string& value) { bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str()); pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
if (!objectAttribute.empty()) { if (!objectAttribute.empty()) {
value = objectAttribute.as_string(); value = objectAttribute.as_string();
return true; return true;
} else {
return false;
} }
return false;
} }
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) { bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
@ -265,9 +274,9 @@ private:
if (ret) { if (ret) {
value = std::atoi(strValue.c_str()); value = std::atoi(strValue.c_str());
return true; return true;
} else { }
return false;
} return false;
} }
aiMatrix4x4 parseTransformMatrix(std::string matrixStr) { aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
@ -287,7 +296,7 @@ private:
} }
} }
if (currentNumber.size() > 0) { if (currentNumber.size() > 0) {
float f = std::stof(currentNumber); const float f = std::stof(currentNumber);
numbers.push_back(f); numbers.push_back(f);
} }
@ -311,29 +320,26 @@ private:
transformMatrix.b4 = numbers[10]; transformMatrix.b4 = numbers[10];
transformMatrix.c4 = numbers[11]; transformMatrix.c4 = numbers[11];
transformMatrix.d4 = 1; transformMatrix.d4 = 1;
return transformMatrix; return transformMatrix;
} }
void ReadObject(XmlNode &node) { void ReadObject(XmlNode &node) {
int id = -1, pid = -1, pindex = -1; int id = -1, pid = -1, pindex = -1;
bool hasId = getNodeAttribute(node, D3MF::XmlTag::id, id); bool hasId = getNodeAttribute(node, XmlTag::id, id);
//bool hasType = getNodeAttribute(node, D3MF::XmlTag::type, type); not used currently bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
bool hasPid = getNodeAttribute(node, D3MF::XmlTag::pid, pid); bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
bool hasPindex = getNodeAttribute(node, D3MF::XmlTag::pindex, pindex);
std::string idStr = ai_to_string(id);
if (!hasId) { if (!hasId) {
return; return;
} }
Object *obj = new Object(id); Object *obj = new Object(id);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == D3MF::XmlTag::mesh) { if (currentName == D3MF::XmlTag::mesh) {
auto mesh = ReadMesh(currentNode); auto mesh = ReadMesh(currentNode);
mesh->mName.Set(idStr); mesh->mName.Set(ai_to_string(id));
if (hasPid) { if (hasPid) {
auto it = mResourcesDictionnary.find(pid); auto it = mResourcesDictionnary.find(pid);
@ -347,8 +353,9 @@ private:
obj->mMeshIndex.push_back(mMeshCount); obj->mMeshIndex.push_back(mMeshCount);
mMeshCount++; mMeshCount++;
} else if (currentName == D3MF::XmlTag::components) { } else if (currentName == D3MF::XmlTag::components) {
for (XmlNode currentSubNode = currentNode.first_child(); currentSubNode; currentSubNode = currentSubNode.next_sibling()) { for (XmlNode &currentSubNode : currentNode.children()) {
if (currentSubNode.name() == D3MF::XmlTag::component) { const std::string subNodeName = currentSubNode.name();
if (subNodeName == D3MF::XmlTag::component) {
int objectId = -1; int objectId = -1;
std::string componentTransformStr; std::string componentTransformStr;
aiMatrix4x4 componentTransform; aiMatrix4x4 componentTransform;
@ -356,8 +363,9 @@ private:
componentTransform = parseTransformMatrix(componentTransformStr); componentTransform = parseTransformMatrix(componentTransformStr);
} }
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
obj->mComponents.push_back({ objectId, componentTransform }); obj->mComponents.push_back({ objectId, componentTransform });
}
} }
} }
} }
@ -369,21 +377,20 @@ private:
aiMesh *ReadMesh(XmlNode &node) { aiMesh *ReadMesh(XmlNode &node) {
aiMesh *mesh = new aiMesh(); aiMesh *mesh = new aiMesh();
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::vertices) { if (currentName == XmlTag::vertices) {
ImportVertices(currentNode, mesh); ImportVertices(currentNode, mesh);
} else if (currentName == D3MF::XmlTag::triangles) { } else if (currentName == XmlTag::triangles) {
ImportTriangles(currentNode, mesh); ImportTriangles(currentNode, mesh);
} }
} }
return mesh; return mesh;
} }
void ReadMetadata(XmlNode &node) { void ReadMetadata(XmlNode &node) {
pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name.c_str()); pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
const std::string name = attribute.as_string(); const std::string name = attribute.as_string();
const std::string value = node.value(); const std::string value = node.value();
if (name.empty()) { if (name.empty()) {
@ -398,9 +405,9 @@ private:
void ImportVertices(XmlNode &node, aiMesh *mesh) { void ImportVertices(XmlNode &node, aiMesh *mesh) {
std::vector<aiVector3D> vertices; std::vector<aiVector3D> vertices;
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::vertex) { if (currentName == XmlTag::vertex) {
vertices.push_back(ReadVertex(currentNode)); vertices.push_back(ReadVertex(currentNode));
} }
} }
@ -412,29 +419,28 @@ private:
aiVector3D ReadVertex(XmlNode &node) { aiVector3D ReadVertex(XmlNode &node) {
aiVector3D vertex; aiVector3D vertex;
vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::x.c_str()).as_string(), nullptr); vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
vertex.y = ai_strtof(node.attribute(D3MF::XmlTag::y.c_str()).as_string(), nullptr); vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
vertex.z = ai_strtof(node.attribute(D3MF::XmlTag::z.c_str()).as_string(), nullptr); vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
return vertex; return vertex;
} }
void ImportTriangles(XmlNode &node, aiMesh *mesh) { void ImportTriangles(XmlNode &node, aiMesh *mesh) {
std::vector<aiFace> faces; std::vector<aiFace> faces;
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::triangle) { if (currentName == XmlTag::triangle) {
aiFace face = ReadTriangle(currentNode); aiFace face = ReadTriangle(currentNode);
faces.push_back(face); faces.push_back(face);
int pid = 0, p1; int pid = 0, p1 = 0;
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid); bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1); bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
if (hasPid && hasP1) { if (hasPid && hasP1) {
auto it = mResourcesDictionnary.find(pid); auto it = mResourcesDictionnary.find(pid);
if (it != mResourcesDictionnary.end()) if (it != mResourcesDictionnary.end()) {
{
if (it->second->getType() == ResourceType::RT_BaseMaterials) { if (it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second); BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1]; mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
@ -457,9 +463,9 @@ private:
face.mNumIndices = 3; face.mNumIndices = 3;
face.mIndices = new unsigned int[face.mNumIndices]; face.mIndices = new unsigned int[face.mNumIndices];
face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v1.c_str()).as_string())); face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v2.c_str()).as_string())); face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v3.c_str()).as_string())); face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
return face; return face;
} }
@ -467,14 +473,14 @@ private:
void ReadBaseMaterials(XmlNode &node) { void ReadBaseMaterials(XmlNode &node) {
int id = -1; int id = -1;
if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) { if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
BaseMaterials* baseMaterials = new BaseMaterials(id); BaseMaterials *baseMaterials = new BaseMaterials(id);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) for (XmlNode &currentNode : node.children()) {
{ const std::string currentName = currentNode.name();
if (currentNode.name() == D3MF::XmlTag::basematerials_base) { if (currentName == XmlTag::basematerials_base) {
baseMaterials->mMaterialIndex.push_back(mMaterialCount); baseMaterials->mMaterialIndex.push_back(mMaterialCount);
baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id)); baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
mMaterialCount++; ++mMaterialCount;
} }
} }
@ -488,7 +494,7 @@ private:
} }
//format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1) //format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
const size_t len(strlen(color)); const size_t len = strlen(color);
if (9 != len && 7 != len) { if (9 != len && 7 != len) {
return false; return false;
} }
@ -517,7 +523,7 @@ private:
} }
void assignDiffuseColor(XmlNode &node, aiMaterial *mat) { void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
const char *color = node.attribute(D3MF::XmlTag::basematerials_displaycolor.c_str()).as_string(); const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
aiColor4D diffuse; aiColor4D diffuse;
if (parseColor(color, diffuse)) { if (parseColor(color, diffuse)) {
mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
@ -531,7 +537,7 @@ private:
bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name); bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
std::string stdMaterialName; std::string stdMaterialName;
std::string strId(ai_to_string(basematerialsId)); const std::string strId(ai_to_string(basematerialsId));
stdMaterialName += "id"; stdMaterialName += "id";
stdMaterialName += strId; stdMaterialName += strId;
stdMaterialName += "_"; stdMaterialName += "_";
@ -556,13 +562,15 @@ private:
std::string value; std::string value;
}; };
std::vector<MetaEntry> mMetaData; std::vector<MetaEntry> mMetaData;
std::map<unsigned int, Resource*> mResourcesDictionnary; std::map<unsigned int, Resource *> mResourcesDictionnary;
unsigned int mMaterialCount, mMeshCount; unsigned int mMaterialCount, mMeshCount;
XmlParser *mXmlParser; XmlParser *mXmlParser;
}; };
} //namespace D3MF } //namespace D3MF
using namespace D3MF;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"3mf Importer", "3mf Importer",
"", "",
@ -596,7 +604,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
return false; return false;
} }
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); D3MFOpcPackage opcPackage(pIOHandler, filename);
return opcPackage.validate(); return opcPackage.validate();
} }
@ -612,11 +620,11 @@ const aiImporterDesc *D3MFImporter::GetInfo() const {
} }
void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) { void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); D3MFOpcPackage opcPackage(pIOHandler, filename);
XmlParser xmlParser; XmlParser xmlParser;
if (xmlParser.parse(opcPackage.RootStream())) { if (xmlParser.parse(opcPackage.RootStream())) {
D3MF::XmlSerializer xmlSerializer(&xmlParser); XmlSerializer xmlSerializer(&xmlParser);
xmlSerializer.ImportXml(pScene); xmlSerializer.ImportXml(pScene);
} }
} }

View File

@ -47,9 +47,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
/// @brief The 3MF-importer class.
class D3MFImporter : public BaseImporter { class D3MFImporter : public BaseImporter {
public: public:
// BaseImporter interface
D3MFImporter(); D3MFImporter();
~D3MFImporter(); ~D3MFImporter();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const; bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;

View File

@ -103,9 +103,9 @@ public:
std::string name = currentNode.name(); std::string name = currentNode.name();
if (name == "Relationship") { if (name == "Relationship") {
OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship()); OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID.c_str()).as_string(); relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string();
relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE.c_str()).as_string(); relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string();
relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET.c_str()).as_string(); relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string();
if (validateRels(relPtr)) { if (validateRels(relPtr)) {
m_relationShips.push_back(relPtr); m_relationShips.push_back(relPtr);
} }
@ -156,13 +156,13 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
mRootStream = mZipArchive->Open(rootFile.c_str()); mRootStream = mZipArchive->Open(rootFile.c_str());
ai_assert(mRootStream != nullptr); ai_assert(mRootStream != nullptr);
if (nullptr == mRootStream) { if (nullptr == mRootStream) {
throw DeadlyExportError("Cannot open root-file in archive : " + rootFile); throw DeadlyImportError("Cannot open root-file in archive : " + rootFile);
} }
} else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file); ASSIMP_LOG_WARN("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file);
} else { } else {
ASSIMP_LOG_WARN_F("Ignored file of unknown type: ", file); ASSIMP_LOG_WARN("Ignored file of unknown type: ", file);
} }
} }
} }
@ -188,7 +188,7 @@ bool D3MFOpcPackage::validate() {
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) { std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
XmlParser xmlParser; XmlParser xmlParser;
if (!xmlParser.parse(stream)) { if (!xmlParser.parse(stream)) {
return ""; return std::string();
} }
OpcPackageRelationshipReader reader(xmlParser); OpcPackageRelationshipReader reader(xmlParser);

View File

@ -116,7 +116,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name
buffer = AcSkipToNextToken(buffer); buffer = AcSkipToNextToken(buffer);
if (0 != name_length) { if (0 != name_length) {
if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) {
ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " + std::string(name) + " was expected."); ASSIMP_LOG_ERROR("AC3D: Unexpected token. ", name, " was expected.");
return buffer; return buffer;
} }
buffer += name_length + 1; buffer += name_length + 1;
@ -492,7 +492,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
default: default:
// Coerce unknowns to a polygon and warn // Coerce unknowns to a polygon and warn
ASSIMP_LOG_WARN_F("AC3D: The type flag of a surface is unknown: ", (*it).flags); ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown: ", (*it).flags);
(*it).flags &= ~(Surface::Mask); (*it).flags &= ~(Surface::Mask);
// fallthrough // fallthrough
@ -690,7 +690,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
if (object.subDiv) { if (object.subDiv) {
if (configEvalSubdivision) { if (configEvalSubdivision) {
std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: " + object.name); ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: ", object.name);
std::vector<aiMesh *> cpy(meshes.size() - oldm, nullptr); std::vector<aiMesh *> cpy(meshes.size() - oldm, nullptr);
div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true); div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true);
@ -698,7 +698,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
// previous meshes are deleted vy Subdivide(). // previous meshes are deleted vy Subdivide().
} else { } else {
ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: " + object.name); ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: ", object.name);
} }
} }
} }
@ -782,7 +782,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
unsigned int version = HexDigitToDecimal(buffer[4]); unsigned int version = HexDigitToDecimal(buffer[4]);
char msg[3]; char msg[3];
ASSIMP_itoa10(msg, 3, version); ASSIMP_itoa10(msg, 3, version);
ASSIMP_LOG_INFO_F("AC3D file format version: ", msg); ASSIMP_LOG_INFO("AC3D file format version: ", msg);
std::vector<Material> materials; std::vector<Material> materials;
materials.reserve(5); materials.reserve(5);

View File

@ -116,16 +116,16 @@ public:
Mask = 0xf, Mask = 0xf,
}; };
inline const uint8_t GetType() const { return (flags & Mask); } inline uint8_t GetType() const { return (flags & Mask); }
}; };
// Represents an AC3D object // Represents an AC3D object
struct Object { struct Object {
Object() : Object() :
type(World), type(World),
name(""), name(),
children(), children(),
texture(""), texture(),
texRepeat(1.f, 1.f), texRepeat(1.f, 1.f),
texOffset(0.0f, 0.0f), texOffset(0.0f, 0.0f),
rotation(), rotation(),

View File

@ -39,16 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
/// \file AMFImporter.cpp
/// \brief AMF-format files importer for Assimp: main algorithm implementation.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
// Header files, Assimp. // Header files, Assimp.
#include "AMFImporter.hpp" #include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include <assimp/DefaultIOSystem.h> #include <assimp/DefaultIOSystem.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
@ -211,7 +205,7 @@ void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::s
} }
static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) { static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) {
return (isalnum(pChar) || (pChar == '+') || (pChar == '/')); return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/'));
} }
void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector<uint8_t> &pOutputData) const { void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector<uint8_t> &pOutputData) const {
@ -274,7 +268,8 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
mXmlParser = new XmlParser(); mXmlParser = new XmlParser();
if (!mXmlParser->parse(file.get())) { if (!mXmlParser->parse(file.get())) {
delete mXmlParser; delete mXmlParser;
throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); mXmlParser = nullptr;
throw DeadlyImportError("Failed to create XML reader for file ", pFile, ".");
} }
// Start reading, search for root tag <amf> // Start reading, search for root tag <amf>
@ -307,14 +302,14 @@ void AMFImporter::ParseNode_Root() {
throw DeadlyImportError("Root node \"amf\" not found."); throw DeadlyImportError("Root node \"amf\" not found.");
} }
XmlNode node = *root; XmlNode node = *root;
mUnit = ai_str_tolower(std::string(node.attribute("unit").as_string())); mUnit = ai_tolower(std::string(node.attribute("unit").as_string()));
mVersion = node.attribute("version").as_string(); mVersion = node.attribute("version").as_string();
// Read attributes for node <amf>. // Read attributes for node <amf>.
// Check attributes // Check attributes
if (!mUnit.empty()) { if (!mUnit.empty()) {
if ((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) { if ((mUnit != "inch") && (mUnit != "millimeters") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) {
Throw_IncorrectAttrValue("unit", mUnit); Throw_IncorrectAttrValue("unit", mUnit);
} }
} }
@ -409,20 +404,20 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "deltax") { if (currentName == "deltax") {
als.Delta.x = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "deltay") { } else if (currentName == "deltay") {
als.Delta.y = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "deltaz") { } else if (currentName == "deltaz") {
als.Delta.z = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} else if (currentName == "rx") { } else if (currentName == "rx") {
als.Delta.x = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "ry") { } else if (currentName == "ry") {
als.Delta.y = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "rz") { } else if (currentName == "rz") {
als.Delta.z = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
@ -458,7 +453,7 @@ void AMFImporter::ParseNode_Object(XmlNode &node) {
// Check for child nodes // Check for child nodes
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
ParseNode_Color(currentNode); ParseNode_Color(currentNode);
@ -523,10 +518,6 @@ bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool p
return false; return false;
} }
void AMFImporter::GetExtensionList(std::set<std::string> &pExtensionList) {
pExtensionList.insert("amf");
}
const aiImporterDesc *AMFImporter::GetInfo() const { const aiImporterDesc *AMFImporter::GetInfo() const {
return &Description; return &Description;
} }

View File

@ -277,7 +277,6 @@ public:
void ParseHelper_Node_Enter(AMFNodeElementBase *child); void ParseHelper_Node_Enter(AMFNodeElementBase *child);
void ParseHelper_Node_Exit(); void ParseHelper_Node_Exit();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const; bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
void GetExtensionList(std::set<std::string> &pExtensionList);
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
const aiImporterDesc *GetInfo() const; const aiImporterDesc *GetInfo() const;
bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const; bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;

View File

@ -39,16 +39,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
/// \file AMFImporter_Geometry.cpp
/// \brief Parsing data from geometry nodes.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
#include "AMFImporter.hpp" #include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
namespace Assimp { namespace Assimp {
@ -103,18 +96,18 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) {
// create new mesh object. // create new mesh object.
ne = new AMFVertices(mNodeElement_Cur); ne = new AMFVertices(mNodeElement_Cur);
// Check for child nodes // Check for child nodes
pugi::xml_node vertexNode = node.child("vertex"); if (node.empty()) {
if (!vertexNode.empty()) {
ParseHelper_Node_Enter(ne);
ParseNode_Vertex(vertexNode);
ParseHelper_Node_Exit();
} else {
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
} // if(!mReader->isEmptyElement()) else return;
}
ParseHelper_Node_Enter(ne);
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "vertex") {
ParseNode_Vertex(currentNode);
}
}
ParseHelper_Node_Exit();
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
} }
@ -166,27 +159,25 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) {
// X, Y, or Z coordinate, respectively, of a vertex position in space. // X, Y, or Z coordinate, respectively, of a vertex position in space.
void AMFImporter::ParseNode_Coordinates(XmlNode &node) { void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
AMFNodeElementBase *ne = nullptr; AMFNodeElementBase *ne = nullptr;
// create new color object.
ne = new AMFCoordinates(mNodeElement_Cur);
AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
if (!node.empty()) { if (!node.empty()) {
ne = new AMFCoordinates(mNodeElement_Cur);
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); // create new color object.
if (currentName == "X") { AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
const std::string &currentName = ai_tolower(currentNode.name());
if (currentName == "x") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.x); XmlParser::getValueAsFloat(currentNode, als.Coordinate.x);
} else if (currentName == "Y") { } else if (currentName == "y") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.y); XmlParser::getValueAsFloat(currentNode, als.Coordinate.y);
} else if (currentName == "Z") { } else if (currentName == "z") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.z); XmlParser::getValueAsFloat(currentNode, als.Coordinate.z);
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
} else { } else {
mNodeElement_Cur->Child.push_back(ne); mNodeElement_Cur->Child.push_back(new AMFCoordinates(mNodeElement_Cur));
} }
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
@ -216,7 +207,7 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
bool col_read = false; bool col_read = false;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : node.children()) {
const std::string currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <volume>."); if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <volume>.");
@ -258,7 +249,8 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) {
bool col_read = false; bool col_read = false;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { std::string v;
for (auto &currentNode : node.children()) {
const std::string currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <triangle>."); if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <triangle>.");
@ -269,11 +261,14 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) {
} else if (currentName == "map") { } else if (currentName == "map") {
ParseNode_TexMap(currentNode, true); ParseNode_TexMap(currentNode, true);
} else if (currentName == "v1") { } else if (currentName == "v1") {
als.V[0] = std::atoi(currentNode.value()); XmlParser::getValueAsString(currentNode, v);
als.V[0] = std::atoi(v.c_str());
} else if (currentName == "v2") { } else if (currentName == "v2") {
als.V[1] = std::atoi(currentNode.value()); XmlParser::getValueAsString(currentNode, v);
als.V[1] = std::atoi(v.c_str());
} else if (currentName == "v3") { } else if (currentName == "v3") {
als.V[2] = std::atoi(currentNode.value()); XmlParser::getValueAsString(currentNode, v);
als.V[2] = std::atoi(v.c_str());
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();

View File

@ -1,164 +0,0 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2021, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/// \file AMFImporter_Macro.hpp
/// \brief Useful macrodefines.
/// \date 2016
/// \author smal.root@gmail.com
#pragma once
#ifndef AMFIMPORTER_MACRO_HPP_INCLUDED
#define AMFIMPORTER_MACRO_HPP_INCLUDED
/// \def MACRO_ATTRREAD_LOOPBEG
/// Begin of loop that read attributes values.
#define MACRO_ATTRREAD_LOOPBEG \
for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \
{ \
std::string an(mReader->getAttributeName(idx));
/// \def MACRO_ATTRREAD_LOOPEND
/// End of loop that read attributes values.
#define MACRO_ATTRREAD_LOOPEND \
Throw_IncorrectAttr(an); \
}
/// \def MACRO_ATTRREAD_LOOPEND_WSKIP
/// End of loop that read attributes values. Difference from \ref MACRO_ATTRREAD_LOOPEND in that: current macro skip unknown attributes, but
/// \ref MACRO_ATTRREAD_LOOPEND throw an exception.
#define MACRO_ATTRREAD_LOOPEND_WSKIP \
continue; \
}
/// \def MACRO_ATTRREAD_CHECK_REF
/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
/// "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \
if(an == pAttrName) \
{ \
pFunction(idx, pVarName); \
continue; \
}
/// \def MACRO_ATTRREAD_CHECK_RET
/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
/// If result was read then "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \
if(an == pAttrName) \
{ \
pVarName = pFunction(idx); \
continue; \
}
/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName)
/// Begin of loop of parsing child nodes. Do not add ';' at end.
/// \param [in] pNodeName - current node name.
#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
do { \
bool close_found = false; \
\
while(mReader->read()) \
{ \
if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \
{
/// \def MACRO_NODECHECK_LOOPEND(pNodeName)
/// End of loop of parsing child nodes.
/// \param [in] pNodeName - current node name.
#define MACRO_NODECHECK_LOOPEND(pNodeName) \
XML_CheckNode_SkipUnsupported(pNodeName); \
}/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \
else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \
{ \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
close_found = true; \
\
break; \
} \
}/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \
}/* while(mReader->read()) */ \
\
if(!close_found) Throw_CloseNotFound(pNodeName); \
\
} while(false)
/// \def MACRO_NODECHECK_READCOMP_F
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "float".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.
/// \param [out] pVarName - output variable name.
#define MACRO_NODECHECK_READCOMP_F(pNodeName, pReadFlag, pVarName) \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
/* Check if field already read before. */ \
if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
/* Read color component and assign it to object. */ \
pVarName = XML_ReadNode_GetVal_AsFloat(); \
pReadFlag = true; \
continue; \
}
/// \def MACRO_NODECHECK_READCOMP_U32
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.
/// \param [out] pVarName - output variable name.
#define MACRO_NODECHECK_READCOMP_U32(pNodeName, pReadFlag, pVarName) \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
/* Check if field already read before. */ \
if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
/* Read color component and assign it to object. */ \
pVarName = XML_ReadNode_GetVal_AsU32(); \
pReadFlag = true; \
continue; \
}
#endif // AMFIMPORTER_MACRO_HPP_INCLUDED

View File

@ -65,48 +65,45 @@ namespace Assimp {
// Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The // Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The
// values can be specified as constants, or as a formula depending on the coordinates. // values can be specified as constants, or as a formula depending on the coordinates.
void AMFImporter::ParseNode_Color(XmlNode &node) { void AMFImporter::ParseNode_Color(XmlNode &node) {
std::string profile = node.attribute("profile").as_string(); if (node.empty()) {
return;
// create new color object. }
AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur);
AMFColor& als = *((AMFColor*)ne);// alias for convenience
als.Profile = profile; const std::string &profile = node.attribute("profile").as_string();
if (!node.empty()) { bool read_flag[4] = { false, false, false, false };
ParseHelper_Node_Enter(ne); AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur);
bool read_flag[4] = { false, false, false, false }; AMFColor &als = *((AMFColor *)ne); // alias for convenience
for (pugi::xml_node &child : node.children()) { ParseHelper_Node_Enter(ne);
std::string name = child.name(); for (pugi::xml_node &child : node.children()) {
if ( name == "r") { // create new color object.
read_flag[0] = true; als.Profile = profile;
XmlParser::getValueAsFloat(child, als.Color.r);
} else if (name == "g") { const std::string &name = child.name();
read_flag[1] = true; if ( name == "r") {
XmlParser::getValueAsFloat(child, als.Color.g); read_flag[0] = true;
} else if (name == "b") { XmlParser::getValueAsFloat(child, als.Color.r);
read_flag[2] = true; } else if (name == "g") {
XmlParser::getValueAsFloat(child, als.Color.b); read_flag[1] = true;
} else if (name == "a") { XmlParser::getValueAsFloat(child, als.Color.g);
read_flag[3] = true; } else if (name == "b") {
XmlParser::getValueAsFloat(child, als.Color.a); read_flag[2] = true;
} XmlParser::getValueAsFloat(child, als.Color.b);
ParseHelper_Node_Exit(); } else if (name == "a") {
read_flag[3] = true;
XmlParser::getValueAsFloat(child, als.Color.a);
} }
// check that all components was defined // check if <a> is absent. Then manually add "a == 1".
if (!(read_flag[0] && read_flag[1] && read_flag[2])) { if (!read_flag[3]) {
throw DeadlyImportError("Not all color components are defined."); als.Color.a = 1;
} }
}
// check if <a> is absent. Then manually add "a == 1". als.Composed = false;
if (!read_flag[3]) { mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
als.Color.a = 1; ParseHelper_Node_Exit();
} // check that all components was defined
} else { if (!(read_flag[0] && read_flag[1] && read_flag[2])) {
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element throw DeadlyImportError("Not all color components are defined.");
} }
als.Composed = false;
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
} }
// <material // <material
@ -158,11 +155,11 @@ void AMFImporter::ParseNode_Material(XmlNode &node) {
// Multi elements - Yes. // Multi elements - Yes.
// Parent element - <amf>. // Parent element - <amf>.
void AMFImporter::ParseNode_Texture(XmlNode &node) { void AMFImporter::ParseNode_Texture(XmlNode &node) {
std::string id = node.attribute("id").as_string(); const std::string id = node.attribute("id").as_string();
uint32_t width = node.attribute("width").as_uint(); const uint32_t width = node.attribute("width").as_uint();
uint32_t height = node.attribute("height").as_uint(); const uint32_t height = node.attribute("height").as_uint();
uint32_t depth = node.attribute("depth").as_uint(); uint32_t depth = node.attribute("depth").as_uint();
std::string type = node.attribute("type").as_string(); const std::string type = node.attribute("type").as_string();
bool tiled = node.attribute("tiled").as_bool(); bool tiled = node.attribute("tiled").as_bool();
if (node.empty()) { if (node.empty()) {
@ -174,22 +171,20 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
AMFTexture& als = *((AMFTexture*)ne);// alias for convenience AMFTexture& als = *((AMFTexture*)ne);// alias for convenience
std::string enc64_data = node.value(); std::string enc64_data;
// Check for child nodes XmlParser::getValueAsString(node, enc64_data);
// Check for child nodes
// check that all components was defined // check that all components was defined
if (id.empty()) { if (id.empty()) {
throw DeadlyImportError("ID for texture must be defined."); throw DeadlyImportError("ID for texture must be defined.");
} }
if (width < 1) { if (width < 1) {
throw DeadlyImportError("INvalid width for texture."); throw DeadlyImportError("Invalid width for texture.");
} }
if (height < 1) { if (height < 1) {
throw DeadlyImportError("Invalid height for texture."); throw DeadlyImportError("Invalid height for texture.");
} }
if (depth < 1) {
throw DeadlyImportError("Invalid depth for texture.");
}
if (type != "grayscale") { if (type != "grayscale") {
throw DeadlyImportError("Invalid type for texture."); throw DeadlyImportError("Invalid type for texture.");
} }
@ -203,7 +198,9 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
als.Depth = depth; als.Depth = depth;
als.Tiled = tiled; als.Tiled = tiled;
ParseHelper_Decode_Base64(enc64_data, als.Data); ParseHelper_Decode_Base64(enc64_data, als.Data);
if (depth == 0) {
depth = (uint32_t)(als.Data.size() / (width * height));
}
// check data size // check data size
if ((width * height * depth) != als.Data.size()) { if ((width * height * depth) != als.Data.size()) {
throw DeadlyImportError("Texture has incorrect data size."); throw DeadlyImportError("Texture has incorrect data size.");
@ -233,20 +230,18 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
AMFTexMap &als = *((AMFTexMap *)ne); // AMFTexMap &als = *((AMFTexMap *)ne); //
std::string rtexid, gtexid, btexid, atexid; std::string rtexid, gtexid, btexid, atexid;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); for (pugi::xml_attribute &attr : node.attributes()) {
for (XmlNode &currentNode : node.children()) { const std::string &currentAttr = attr.name();
const std::string &currentName = currentNode.name(); if (currentAttr == "rtexid") {
if (currentName == "rtexid") { rtexid = attr.as_string();
XmlParser::getValueAsString(node, rtexid); } else if (currentAttr == "gtexid") {
} else if (currentName == "gtexid") { gtexid = attr.as_string();
XmlParser::getValueAsString(node, gtexid); } else if (currentAttr == "btexid") {
} else if (currentName == "btexid") { btexid = attr.as_string();
XmlParser::getValueAsString(node, btexid); } else if (currentAttr == "atexid") {
} else if (currentName == "atexid") { atexid = attr.as_string();
XmlParser::getValueAsString(node, atexid);
} }
} }
ParseHelper_Node_Exit();
} }
// create new texture coordinates object, alias for convenience // create new texture coordinates object, alias for convenience
@ -256,7 +251,6 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
} }
// Check for children nodes // Check for children nodes
//XML_CheckNode_MustHaveChildren();
if (node.children().begin() == node.children().end()) { if (node.children().begin() == node.children().end()) {
throw DeadlyImportError("Invalid children definition."); throw DeadlyImportError("Invalid children definition.");
} }
@ -264,28 +258,31 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
bool read_flag[6] = { false, false, false, false, false, false }; bool read_flag[6] = { false, false, false, false, false, false };
if (!pUseOldName) { if (!pUseOldName) {
for (pugi::xml_attribute &attr : node.attributes()) { ParseHelper_Node_Enter(ne);
const std::string name = attr.name(); for ( XmlNode &currentNode : node.children()) {
const std::string &name = currentNode.name();
if (name == "utex1") { if (name == "utex1") {
read_flag[0] = true; read_flag[0] = true;
als.TextureCoordinate[0].x = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].x);
} else if (name == "utex2") { } else if (name == "utex2") {
read_flag[1] = true; read_flag[1] = true;
als.TextureCoordinate[1].x = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].x);
} else if (name == "utex3") { } else if (name == "utex3") {
read_flag[2] = true; read_flag[2] = true;
als.TextureCoordinate[2].x = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].x);
} else if (name == "vtex1") { } else if (name == "vtex1") {
read_flag[3] = true; read_flag[3] = true;
als.TextureCoordinate[0].y = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].y);
} else if (name == "vtex2") { } else if (name == "vtex2") {
read_flag[4] = true; read_flag[4] = true;
als.TextureCoordinate[1].y = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].y);
} else if (name == "vtex3") { } else if (name == "vtex3") {
read_flag[5] = true; read_flag[5] = true;
als.TextureCoordinate[0].y = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].y);
} }
} }
ParseHelper_Node_Exit();
} else { } else {
for (pugi::xml_attribute &attr : node.attributes()) { for (pugi::xml_attribute &attr : node.attributes()) {
const std::string name = attr.name(); const std::string name = attr.name();

View File

@ -62,12 +62,14 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
// Check if stored data are supported. // Check if stored data are supported.
if (!Composition.empty()) { if (!Composition.empty()) {
throw DeadlyImportError("IME. GetColor for composition"); throw DeadlyImportError("IME. GetColor for composition");
} else if (Color->Composed) {
throw DeadlyImportError("IME. GetColor, composed color");
} else {
tcol = Color->Color;
} }
if (Color->Composed) {
throw DeadlyImportError("IME. GetColor, composed color");
}
tcol = Color->Color;
// Check if default color must be used // Check if default color must be used
if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) { if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) {
tcol.r = 0.5f; tcol.r = 0.5f;
@ -79,13 +81,13 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
return tcol; return tcol;
} }
void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElement, std::vector<aiVector3D> &pVertexCoordinateArray, void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &nodeElement, std::vector<aiVector3D> &vertexCoordinateArray,
std::vector<AMFColor *> &pVertexColorArray) const { std::vector<AMFColor *> &pVertexColorArray) const {
AMFVertices *vn = nullptr; AMFVertices *vn = nullptr;
size_t col_idx; size_t col_idx;
// All data stored in "vertices", search for it. // All data stored in "vertices", search for it.
for (AMFNodeElementBase *ne_child : pNodeElement.Child) { for (AMFNodeElementBase *ne_child : nodeElement.Child) {
if (ne_child->Type == AMFNodeElementBase::ENET_Vertices) { if (ne_child->Type == AMFNodeElementBase::ENET_Vertices) {
vn = (AMFVertices*)ne_child; vn = (AMFVertices*)ne_child;
} }
@ -97,7 +99,7 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElem
} }
// all coordinates stored as child and we need to reserve space for future push_back's. // all coordinates stored as child and we need to reserve space for future push_back's.
pVertexCoordinateArray.reserve(vn->Child.size()); vertexCoordinateArray.reserve(vn->Child.size());
// colors count equal vertices count. // colors count equal vertices count.
pVertexColorArray.resize(vn->Child.size()); pVertexColorArray.resize(vn->Child.size());
@ -112,7 +114,7 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElem
for (AMFNodeElementBase *vtx : vn_child->Child) { for (AMFNodeElementBase *vtx : vn_child->Child) {
if (vtx->Type == AMFNodeElementBase::ENET_Coordinates) { if (vtx->Type == AMFNodeElementBase::ENET_Coordinates) {
pVertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate); vertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate);
continue; continue;
} }
@ -426,10 +428,10 @@ void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const st
if (pBiggerThan != nullptr) { if (pBiggerThan != nullptr) {
bool found = false; bool found = false;
const size_t biggerThan = *pBiggerThan;
for (const SComplexFace &face : pFaceList) { for (const SComplexFace &face : pFaceList) {
for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) { for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) {
if (face.Face.mIndices[idx_vert] > *pBiggerThan) { if (face.Face.mIndices[idx_vert] > biggerThan) {
rv = face.Face.mIndices[idx_vert]; rv = face.Face.mIndices[idx_vert];
found = true; found = true;
break; break;

View File

@ -614,7 +614,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
node->mNumChildren++; node->mNumChildren++;
// What we did is so great, it is at least worth a debug message // What we did is so great, it is at least worth a debug message
ASSIMP_LOG_VERBOSE_DEBUG("ASE: Generating separate target node (" + snode->mName + ")"); ASSIMP_LOG_VERBOSE_DEBUG("ASE: Generating separate target node (", snode->mName, ")");
} }
} }

View File

@ -498,6 +498,12 @@ void Parser::ParseLV1MaterialListBlock() {
ParseLV2MaterialBlock(sMat); ParseLV2MaterialBlock(sMat);
continue; continue;
} }
if( iDepth == 1 ){
// CRUDE HACK: support missing brace after "Ascii Scene Exporter v2.51"
LogWarning("Missing closing brace in material list");
--filePtr;
return;
}
} }
AI_ASE_HANDLE_TOP_LEVEL_SECTION(); AI_ASE_HANDLE_TOP_LEVEL_SECTION();
} }
@ -671,7 +677,7 @@ void Parser::ParseLV3MapBlock(Texture &map) {
if (!ParseString(temp, "*MAP_CLASS")) if (!ParseString(temp, "*MAP_CLASS"))
SkipToNextToken(); SkipToNextToken();
if (temp != "Bitmap" && temp != "Normal Bump") { if (temp != "Bitmap" && temp != "Normal Bump") {
ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp); ASSIMP_LOG_WARN("ASE: Skipping unknown map type: ", temp);
parsePath = false; parsePath = false;
} }
continue; continue;
@ -685,7 +691,7 @@ void Parser::ParseLV3MapBlock(Texture &map) {
// Files with 'None' as map name are produced by // Files with 'None' as map name are produced by
// an Maja to ASE exporter which name I forgot .. // an Maja to ASE exporter which name I forgot ..
ASSIMP_LOG_WARN("ASE: Skipping invalid map entry"); ASSIMP_LOG_WARN("ASE: Skipping invalid map entry");
map.mMapName = ""; map.mMapName = std::string();
} }
continue; continue;
@ -1119,7 +1125,7 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) {
"this is no spot light or target camera"); "this is no spot light or target camera");
} }
} else { } else {
ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp); ASSIMP_LOG_ERROR("ASE: Unknown node transformation: ", temp);
// mode = 0 // mode = 0
} }
continue; continue;

View File

@ -95,8 +95,8 @@ struct Material : public D3DS::Material {
Material(Material &&other) AI_NO_EXCEPT Material(Material &&other) AI_NO_EXCEPT
: D3DS::Material(std::move(other)), : D3DS::Material(std::move(other)),
avSubMaterials(std::move(other.avSubMaterials)), avSubMaterials(std::move(other.avSubMaterials)),
pcInstance(std::move(other.pcInstance)), pcInstance(other.pcInstance),
bNeed(std::move(other.bNeed)) { bNeed(other.bNeed) {
other.pcInstance = nullptr; other.pcInstance = nullptr;
} }
@ -108,8 +108,8 @@ struct Material : public D3DS::Material {
//D3DS::Material::operator=(std::move(other)); //D3DS::Material::operator=(std::move(other));
avSubMaterials = std::move(other.avSubMaterials); avSubMaterials = std::move(other.avSubMaterials);
pcInstance = std::move(other.pcInstance); pcInstance = other.pcInstance;
bNeed = std::move(other.bNeed); bNeed = other.bNeed;
other.pcInstance = nullptr; other.pcInstance = nullptr;

View File

@ -671,7 +671,7 @@ void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) {
void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
IOStream *stream = pIOHandler->Open(pFile, "rb"); IOStream *stream = pIOHandler->Open(pFile, "rb");
if (nullptr == stream) { if (nullptr == stream) {
return; throw DeadlyImportError("ASSBIN: Could not open ", pFile);
} }
// signature // signature

View File

@ -598,8 +598,11 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
if (!mesh->mTextureCoords[a]) if (!mesh->mTextureCoords[a])
break; break;
ioprintf(io, "\t\t<TextureCoords num=\"%u\" set=\"%u\" num_components=\"%u\"> \n", mesh->mNumVertices, ioprintf(io, "\t\t<TextureCoords num=\"%u\" set=\"%u\" name=\"%s\" num_components=\"%u\"> \n",
a, mesh->mNumUVComponents[a]); mesh->mNumVertices,
a,
mesh->mTextureCoordsNames[a].C_Str(),
mesh->mNumUVComponents[a]);
if (!shortened) { if (!shortened) {
if (mesh->mNumUVComponents[a] == 3) { if (mesh->mNumUVComponents[a] == 3) {

View File

@ -143,9 +143,9 @@ AI_WONT_RETURN void B3DImporter::Oops() {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AI_WONT_RETURN void B3DImporter::Fail(string str) { AI_WONT_RETURN void B3DImporter::Fail(const string &str) {
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F("Error in B3D file data: ", str); ASSIMP_LOG_ERROR("Error in B3D file data: ", str);
#endif #endif
throw DeadlyImportError("B3D Importer - error in B3D file data: ", str); throw DeadlyImportError("B3D Importer - error in B3D file data: ", str);
} }
@ -233,7 +233,7 @@ string B3DImporter::ReadChunk() {
tag += char(ReadByte()); tag += char(ReadByte());
} }
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
ASSIMP_LOG_DEBUG_F("ReadChunk: ", tag); ASSIMP_LOG_DEBUG("ReadChunk: ", tag);
#endif #endif
unsigned sz = (unsigned)ReadInt(); unsigned sz = (unsigned)ReadInt();
_stack.push_back(_pos + sz); _stack.push_back(_pos + sz);
@ -397,7 +397,7 @@ void B3DImporter::ReadTRIS(int v0) {
matid = 0; matid = 0;
} else if (matid < 0 || matid >= (int)_materials.size()) { } else if (matid < 0 || matid >= (int)_materials.size()) {
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F("material id=", matid); ASSIMP_LOG_ERROR("material id=", matid);
#endif #endif
Fail("Bad material id"); Fail("Bad material id");
} }
@ -417,7 +417,7 @@ void B3DImporter::ReadTRIS(int v0) {
int i2 = ReadInt() + v0; int i2 = ReadInt() + v0;
if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) { if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) {
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2); ASSIMP_LOG_ERROR("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2);
#endif #endif
Fail("Bad triangle index"); Fail("Bad triangle index");
continue; continue;

View File

@ -96,7 +96,7 @@ private:
}; };
AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void Fail(const std::string &str) AI_WONT_RETURN_SUFFIX;
void ReadTEXS(); void ReadTEXS();
void ReadBRUS(); void ReadBRUS();

View File

@ -359,7 +359,7 @@ void BVHLoader::ReadMotion(aiScene * /*pScene*/) {
std::string BVHLoader::GetNextToken() { std::string BVHLoader::GetNextToken() {
// skip any preceding whitespace // skip any preceding whitespace
while (mReader != mBuffer.end()) { while (mReader != mBuffer.end()) {
if (!isspace(*mReader)) if (!isspace((unsigned char)*mReader))
break; break;
// count lines // count lines
@ -372,7 +372,7 @@ std::string BVHLoader::GetNextToken() {
// collect all chars till the next whitespace. BVH is easy in respect to that. // collect all chars till the next whitespace. BVH is easy in respect to that.
std::string token; std::string token;
while (mReader != mBuffer.end()) { while (mReader != mBuffer.end()) {
if (isspace(*mReader)) if (isspace((unsigned char)*mReader))
break; break;
token.push_back(*mReader); token.push_back(*mReader);

View File

@ -198,9 +198,9 @@ void DNAParser::Parse() {
s.size = offset; s.size = offset;
} }
ASSIMP_LOG_DEBUG_F("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields"); ASSIMP_LOG_DEBUG("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields");
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #if ASSIMP_BUILD_BLENDER_DEBUG_DNA
dna.DumpToFile(); dna.DumpToFile();
#endif #endif
@ -208,7 +208,7 @@ void DNAParser::Parse() {
dna.RegisterConverters(); dna.RegisterConverters();
} }
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #if ASSIMP_BUILD_BLENDER_DEBUG_DNA
#include <fstream> #include <fstream>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -237,7 +237,7 @@ void DNA ::DumpToFile() {
ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt"); ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt");
} }
#endif #endif // ASSIMP_BUILD_BLENDER_DEBUG_DNA
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/*static*/ void DNA ::ExtractArraySize( /*static*/ void DNA ::ExtractArraySize(

View File

@ -59,6 +59,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ASSIMP_BUILD_BLENDER_DEBUG #define ASSIMP_BUILD_BLENDER_DEBUG
#endif #endif
// set this to non-zero to dump BlenderDNA stuff to dna.txt.
// you could set it on the assimp build command line too without touching it here.
// !!! please make sure this is set to 0 in the repo !!!
#ifndef ASSIMP_BUILD_BLENDER_DEBUG_DNA
#define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0
#endif
// #define ASSIMP_BUILD_BLENDER_NO_STATS // #define ASSIMP_BUILD_BLENDER_NO_STATS
namespace Assimp { namespace Assimp {
@ -495,7 +502,7 @@ public:
const Structure &structure, const Structure &structure,
const FileDatabase &db) const; const FileDatabase &db) const;
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #if ASSIMP_BUILD_BLENDER_DEBUG_DNA
// -------------------------------------------------------- // --------------------------------------------------------
/** Dump the DNA to a text file. This is for debugging purposes. /** Dump the DNA to a text file. This is for debugging purposes.
* The output file is `dna.txt` in the current working folder*/ * The output file is `dna.txt` in the current working folder*/

View File

@ -565,7 +565,7 @@ template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shar
// this might happen if DNA::RegisterConverters hasn't been called so far // this might happen if DNA::RegisterConverters hasn't been called so far
// or if the target type is not contained in `our` DNA. // or if the target type is not contained in `our` DNA.
out.reset(); out.reset();
ASSIMP_LOG_WARN_F( "Failed to find a converter for the `",s.name,"` structure" ); ASSIMP_LOG_WARN( "Failed to find a converter for the `",s.name,"` structure" );
return false; return false;
} }

View File

@ -88,7 +88,7 @@ using namespace Assimp::Blender;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
static const aiImporterDesc blenderDesc = { static const aiImporterDesc blenderDesc = {
"Blender 3D Importer \nhttp://www.blender3d.org", "Blender 3D Importer (http://www.blender3d.org)",
"", "",
"", "",
"No animation support yet", "No animation support yet",
@ -132,12 +132,6 @@ bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bo
return false; return false;
} }
// ------------------------------------------------------------------------------------------------
// List all extensions handled by this loader
void BlenderImporter::GetExtensionList(std::set<std::string> &app) {
app.insert("blend");
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Loader registry entry // Loader registry entry
const aiImporterDesc *BlenderImporter::GetInfo() const { const aiImporterDesc *BlenderImporter::GetInfo() const {
@ -241,9 +235,9 @@ void BlenderImporter::InternReadFile(const std::string &pFile,
stream->Read(magic, 3, 1); stream->Read(magic, 3, 1);
magic[3] = '\0'; magic[3] = '\0';
LogInfo((format(), "Blender version is ", magic[0], ".", magic + 1, LogInfo("Blender version is ", magic[0], ".", magic + 1,
" (64bit: ", file.i64bit ? "true" : "false", " (64bit: ", file.i64bit ? "true" : "false",
", little endian: ", file.little ? "true" : "false", ")")); ", little endian: ", file.little ? "true" : "false", ")");
ParseBlendFile(file, stream); ParseBlendFile(file, stream);
@ -316,7 +310,7 @@ void BlenderImporter::ExtractScene(Scene &out, const FileDatabase &file) {
ss.Convert(out, file); ss.Convert(out, file);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
ASSIMP_LOG_INFO_F( ASSIMP_LOG_INFO(
"(Stats) Fields read: ", file.stats().fields_read, "(Stats) Fields read: ", file.stats().fields_read,
", pointers resolved: ", file.stats().pointers_resolved, ", pointers resolved: ", file.stats().pointers_resolved,
", cache hits: ", file.stats().cache_hits, ", cache hits: ", file.stats().cache_hits,
@ -426,9 +420,9 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
--s; --s;
} }
curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower(s[1]); curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower((unsigned char)s[1]);
curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower(s[2]); curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower((unsigned char)s[2]);
curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower(s[3]); curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower((unsigned char)s[3]);
curTex->achFormatHint[3] = '\0'; curTex->achFormatHint[3] = '\0';
// tex->mHeight = 0; // tex->mHeight = 0;
@ -440,7 +434,7 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
curTex->pcData = reinterpret_cast<aiTexel *>(ch); curTex->pcData = reinterpret_cast<aiTexel *>(ch);
LogInfo("Reading embedded texture, original file was " + std::string(img->name)); LogInfo("Reading embedded texture, original file was ", img->name);
} else { } else {
name = aiString(img->name); name = aiString(img->name);
} }
@ -522,7 +516,7 @@ void BlenderImporter::ResolveTexture(aiMaterial *out, const Material *mat, const
case Tex::Type_POINTDENSITY: case Tex::Type_POINTDENSITY:
case Tex::Type_VOXELDATA: case Tex::Type_VOXELDATA:
LogWarn(std::string("Encountered a texture with an unsupported type: ") + dispnam); LogWarn("Encountered a texture with an unsupported type: ", dispnam);
AddSentinelTexture(out, mat, tex, conv_data); AddSentinelTexture(out, mat, tex, conv_data);
break; break;
@ -685,7 +679,7 @@ void BlenderImporter::BuildMaterials(ConversionData &conv_data) {
BuildDefaultMaterial(conv_data); BuildDefaultMaterial(conv_data);
for (std::shared_ptr<Material> mat : conv_data.materials_raw) { for (const std::shared_ptr<Material> &mat : conv_data.materials_raw) {
// reset per material global counters // reset per material global counters
for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) { for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) {
@ -758,7 +752,7 @@ void BlenderImporter::CheckActualType(const ElemBase *dt, const char *check) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::NotSupportedObjectType(const Object *obj, const char *type) { void BlenderImporter::NotSupportedObjectType(const Object *obj, const char *type) {
LogWarn((format(), "Object `", obj->id.name, "` - type is unsupported: `", type, "`, skipping")); LogWarn("Object `", obj->id.name, "` - type is unsupported: `", type, "`, skipping");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -110,7 +110,6 @@ public:
protected: protected:
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
void GetExtensionList(std::set<std::string>& app);
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream); void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream);

View File

@ -90,7 +90,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_d
const Structure *s = conv_data.db.dna.Get(cur->dna_type); const Structure *s = conv_data.db.dna.Get(cur->dna_type);
if (!s) { if (!s) {
ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ", cur->dna_type); ASSIMP_LOG_WARN("BlendModifier: could not resolve DNA name: ", cur->dna_type);
continue; continue;
} }
@ -132,7 +132,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_d
} }
} }
if (curgod) { if (curgod) {
ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ", dat.name); ASSIMP_LOG_WARN("Couldn't find a handler for modifier: ", dat.name);
} }
} }
@ -140,7 +140,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_d
// object, we still can't say whether our modifier implementations were // object, we still can't say whether our modifier implementations were
// able to fully do their job. // able to fully do their job.
if (ful) { if (ful) {
ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ", cnt, " of ", ful, " modifiers on `", orig_object.id.name, ASSIMP_LOG_DEBUG("BlendModifier: found handlers for ", cnt, " of ", ful, " modifiers on `", orig_object.id.name,
"`, check log messages above for errors"); "`, check log messages above for errors");
} }
} }
@ -248,7 +248,7 @@ void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const
out.mMeshes = nind; out.mMeshes = nind;
out.mNumMeshes *= 2; out.mNumMeshes *= 2;
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `", ASSIMP_LOG_INFO("BlendModifier: Applied the `Mirror` modifier to `",
orig_object.id.name, "`"); orig_object.id.name, "`");
} }
@ -277,7 +277,7 @@ void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data,
break; break;
default: default:
ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ", mir.subdivType); ASSIMP_LOG_WARN("BlendModifier: Unrecognized subdivision algorithm: ", mir.subdivType);
return; return;
}; };
@ -292,7 +292,7 @@ void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data,
subd->Subdivide(meshes, out.mNumMeshes, tempmeshes.get(), std::max(mir.renderLevels, mir.levels), true); subd->Subdivide(meshes, out.mNumMeshes, tempmeshes.get(), std::max(mir.renderLevels, mir.levels), true);
std::copy(tempmeshes.get(), tempmeshes.get() + out.mNumMeshes, meshes); std::copy(tempmeshes.get(), tempmeshes.get() + out.mNumMeshes, meshes);
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `", ASSIMP_LOG_INFO("BlendModifier: Applied the `Subdivision` modifier to `",
orig_object.id.name, "`"); orig_object.id.name, "`");
} }

View File

@ -86,7 +86,7 @@ public:
const Scene& /*in*/, const Scene& /*in*/,
const Object& /*orig_object*/ const Object& /*orig_object*/
) { ) {
ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: ",orig_modifier.dna_type ); ASSIMP_LOG_INFO("This modifier is not supported, skipping: ",orig_modifier.dna_type );
return; return;
} }
}; };

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
#include "C4DImporter.h" #include "C4DImporter.h"
#include <assimp/TinyFormatter.h>
#include <memory> #include <memory>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/scene.h> #include <assimp/scene.h>
@ -65,7 +64,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "c4d_file.h" #include "c4d_file.h"
#include "default_alien_overloads.h" #include "default_alien_overloads.h"
using namespace melange; namespace {
aiString aiStringFrom(cineware::String const & cinestring) {
aiString result;
cinestring.GetCString(result.data, MAXLEN-1);
result.length = static_cast<ai_uint32>(cinestring.GetLength());
return result;
}
}
using namespace Assimp;
using namespace cineware;
// overload this function and fill in your own unique data // overload this function and fill in your own unique data
void GetWriterInfo(int &id, String &appname) { void GetWriterInfo(int &id, String &appname) {
@ -73,9 +84,6 @@ void GetWriterInfo(int &id, String &appname) {
appname = "Open Asset Import Library"; appname = "Open Asset Import Library";
} }
using namespace Assimp;
using namespace Assimp::Formatter;
namespace Assimp { namespace Assimp {
template<> const char* LogFunctions<C4DImporter>::Prefix() { template<> const char* LogFunctions<C4DImporter>::Prefix() {
static auto prefix = "C4D: "; static auto prefix = "C4D: ";
@ -97,17 +105,6 @@ static const aiImporterDesc desc = {
}; };
// ------------------------------------------------------------------------------------------------
C4DImporter::C4DImporter()
: BaseImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
C4DImporter::~C4DImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
const std::string& extension = GetExtension(pFile); const std::string& extension = GetExtension(pFile);
@ -125,11 +122,6 @@ const aiImporterDesc* C4DImporter::GetInfo () const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------
void C4DImporter::SetupProperties(const Importer* /*pImp*/) {
// nothing to be done for the moment
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
@ -199,8 +191,8 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) { bool C4DImporter::ReadShader(aiMaterial* out, BaseShader* shader) {
// based on Melange sample code (C4DImportExport.cpp) // based on Cineware sample code (C4DImportExport.cpp)
while(shader) { while(shader) {
if(shader->GetType() == Xlayer) { if(shader->GetType() == Xlayer) {
BaseContainer* container = shader->GetDataInstance(); BaseContainer* container = shader->GetDataInstance();
@ -242,13 +234,11 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
lsl = lsl->GetNext(); lsl = lsl->GetNext();
} }
} else if ( shader->GetType() == Xbitmap ) { } else if ( shader->GetType() == Xbitmap ) {
aiString path; auto const path = aiStringFrom(shader->GetFileName().GetString());
shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
path.length = ::strlen(path.data);
out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0)); out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
return true; return true;
} else { } else {
LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType()))); LogWarn("ignoring shader type: ", GetObjectTypeName(shader->GetType()));
} }
shader = shader->GetNext(); shader = shader->GetNext();
} }
@ -257,18 +247,15 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) { void C4DImporter::ReadMaterials(BaseMaterial* mat) {
// based on Melange sample code // based on Cineware sample code
while (mat) { while (mat) {
const String& name = mat->GetName();
if (mat->GetType() == Mmaterial) { if (mat->GetType() == Mmaterial) {
aiMaterial* out = new aiMaterial(); aiMaterial* out = new aiMaterial();
material_mapping[mat] = static_cast<unsigned int>(materials.size()); material_mapping[mat] = static_cast<unsigned int>(materials.size());
materials.push_back(out); materials.push_back(out);
aiString ai_name; auto const ai_name = aiStringFrom(mat->GetName());
name.GetCString(ai_name.data, MAXLEN-1);
ai_name.length = ::strlen(ai_name.data);
out->AddProperty(&ai_name, AI_MATKEY_NAME); out->AddProperty(&ai_name, AI_MATKEY_NAME);
Material& m = dynamic_cast<Material&>(*mat); Material& m = dynamic_cast<Material&>(*mat);
@ -294,7 +281,7 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) {
ReadShader(out, shader); ReadShader(out, shader);
} }
} else { } else {
LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType()))); LogWarn("ignoring plugin material: ", GetObjectTypeName(mat->GetType()));
} }
mat = mat->GetNext(); mat = mat->GetNext();
} }
@ -305,19 +292,15 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
ai_assert(parent != nullptr ); ai_assert(parent != nullptr );
std::vector<aiNode*> nodes; std::vector<aiNode*> nodes;
// based on Melange sample code // based on Cineware sample code
while (object) { while (object) {
const String& name = object->GetName();
const LONG type = object->GetType(); const LONG type = object->GetType();
const Matrix& ml = object->GetMl(); const Matrix& ml = object->GetMl();
aiString string;
name.GetCString(string.data, MAXLEN-1);
string.length = ::strlen(string.data);
aiNode* const nd = new aiNode(); aiNode* const nd = new aiNode();
nd->mParent = parent; nd->mParent = parent;
nd->mName = string; nd->mName = aiStringFrom(object->GetName());
nd->mTransformation.a1 = ml.v1.x; nd->mTransformation.a1 = ml.v1.x;
nd->mTransformation.b1 = ml.v1.y; nd->mTransformation.b1 = ml.v1.y;
@ -352,7 +335,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
meshes.push_back(mesh); meshes.push_back(mesh);
} }
} else { } else {
LogWarn("ignoring object: " + std::string(GetObjectTypeName(type))); LogWarn("ignoring object: ", GetObjectTypeName(type));
} }
RecurseHierarchy(object->GetDown(), nd); RecurseHierarchy(object->GetDown(), nd);
@ -370,7 +353,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
ai_assert(object != nullptr); ai_assert(object != nullptr);
ai_assert( object->GetType() == Opolygon ); ai_assert( object->GetType() == Opolygon );
// based on Melange sample code // based on Cineware sample code
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object); PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
ai_assert(polyObject != nullptr); ai_assert(polyObject != nullptr);
@ -618,4 +601,3 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) {
} }
#endif // ASSIMP_BUILD_NO_C4D_IMPORTER #endif // ASSIMP_BUILD_NO_C4D_IMPORTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -56,8 +56,8 @@ struct aiMaterial;
struct aiImporterDesc; struct aiImporterDesc;
namespace melange { namespace cineware {
class BaseObject; // c4d_file.h class BaseObject;
class PolygonObject; class PolygonObject;
class BaseMaterial; class BaseMaterial;
class BaseShader; class BaseShader;
@ -71,43 +71,34 @@ namespace Assimp {
} }
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
/** Importer class to load Cinema4D files using the Melange library to be obtained from /** Importer class to load Cinema4D files using the Cineware library to be obtained from
* www.plugincafe.com * https://developers.maxon.net
* *
* Note that Melange is not free software. */ * Note that Cineware is not free software. */
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> { class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
public: public:
C4DImporter(); bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override;
~C4DImporter();
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
protected: protected:
// -------------------- const aiImporterDesc* GetInfo () const override;
const aiImporterDesc* GetInfo () const;
// -------------------- void InternReadFile( const std::string& pFile, aiScene*, IOSystem* ) override;
void SetupProperties(const Importer* pImp);
// --------------------
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private: private:
void ReadMaterials(melange::BaseMaterial* mat); void ReadMaterials(cineware::BaseMaterial* mat);
void RecurseHierarchy(melange::BaseObject* object, aiNode* parent); void RecurseHierarchy(cineware::BaseObject* object, aiNode* parent);
aiMesh* ReadMesh(melange::BaseObject* object); aiMesh* ReadMesh(cineware::BaseObject* object);
unsigned int ResolveMaterial(melange::PolygonObject* obj); unsigned int ResolveMaterial(cineware::PolygonObject* obj);
bool ReadShader(aiMaterial* out, melange::BaseShader* shader); bool ReadShader(aiMaterial* out, cineware::BaseShader* shader);
std::vector<aiMesh*> meshes; std::vector<aiMesh*> meshes;
std::vector<aiMaterial*> materials; std::vector<aiMaterial*> materials;
typedef std::map<melange::BaseMaterial*, unsigned int> MaterialMap; typedef std::map<cineware::BaseMaterial*, unsigned int> MaterialMap;
MaterialMap material_mapping; MaterialMap material_mapping;
}; // !class C4DImporter }; // !class C4DImporter

View File

@ -137,7 +137,13 @@ void COBImporter::SetupProperties(const Importer * /*pImp*/) {
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
COB::Scene scene; COB::Scene scene;
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(pIOHandler->Open(pFile, "rb")));
auto file = pIOHandler->Open(pFile, "rb");
if (!file) {
ThrowException("Could not open " + pFile);
}
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(file));
// check header // check header
char head[32]; char head[32];
@ -146,7 +152,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
ThrowException("Could not found magic id: `Caligari`"); ThrowException("Could not found magic id: `Caligari`");
} }
ASSIMP_LOG_INFO_F("File format tag: ", std::string(head + 9, 6)); ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6));
if (head[16] != 'L') { if (head[16] != 'L') {
ThrowException("File is big-endian, which is not supported"); ThrowException("File is big-endian, which is not supported");
} }
@ -224,7 +230,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertTexture(std::shared_ptr<Texture> tex, aiMaterial *out, aiTextureType type) { void ConvertTexture(const std::shared_ptr<Texture> &tex, aiMaterial *out, aiTextureType type) {
const aiString path(tex->path); const aiString path(tex->path);
out->AddProperty(&path, AI_MATKEY_TEXTURE(type, 0)); out->AddProperty(&path, AI_MATKEY_TEXTURE(type, 0));
out->AddProperty(&tex->transform, 1, AI_MATKEY_UVTRANSFORM(type, 0)); out->AddProperty(&tex->transform, 1, AI_MATKEY_UVTRANSFORM(type, 0));
@ -295,8 +301,7 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
} }
std::unique_ptr<const Material> defmat; std::unique_ptr<const Material> defmat;
if (!min) { if (!min) {
ASSIMP_LOG_VERBOSE_DEBUG(format() << "Could not resolve material index " ASSIMP_LOG_VERBOSE_DEBUG("Could not resolve material index ", reflist.first, " - creating default material for this slot");
<< reflist.first << " - creating default material for this slot");
defmat.reset(min = new Material()); defmat.reset(min = new Material());
} }
@ -521,7 +526,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
++splitter; ++splitter;
if (!splitter.match_start("mat# ")) { if (!splitter.match_start("mat# ")) {
ASSIMP_LOG_WARN_F("Expected `mat#` line in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `mat#` line in `Mat1` chunk ", nfo.id);
return; return;
} }
@ -533,7 +538,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
++splitter; ++splitter;
if (!splitter.match_start("shader: ")) { if (!splitter.match_start("shader: ")) {
ASSIMP_LOG_WARN_F("Expected `mat#` line in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `mat#` line in `Mat1` chunk ", nfo.id);
return; return;
} }
std::string shader = std::string(splitter[1]); std::string shader = std::string(splitter[1]);
@ -544,12 +549,12 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
} else if (shader == "phong") { } else if (shader == "phong") {
mat.shader = Material::PHONG; mat.shader = Material::PHONG;
} else if (shader != "flat") { } else if (shader != "flat") {
ASSIMP_LOG_WARN_F("Unknown value for `shader` in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Unknown value for `shader` in `Mat1` chunk ", nfo.id);
} }
++splitter; ++splitter;
if (!splitter.match_start("rgb ")) { if (!splitter.match_start("rgb ")) {
ASSIMP_LOG_WARN_F("Expected `rgb` line in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `rgb` line in `Mat1` chunk ", nfo.id);
} }
const char *rgb = splitter[1]; const char *rgb = splitter[1];
@ -557,7 +562,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
++splitter; ++splitter;
if (!splitter.match_start("alpha ")) { if (!splitter.match_start("alpha ")) {
ASSIMP_LOG_WARN_F("Expected `alpha` line in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `alpha` line in `Mat1` chunk ", nfo.id);
} }
const char *tokens[10]; const char *tokens[10];
@ -577,7 +582,7 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk
} }
++splitter; ++splitter;
if (!splitter.match_start("Units ")) { if (!splitter.match_start("Units ")) {
ASSIMP_LOG_WARN_F("Expected `Units` line in `Unit` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `Units` line in `Unit` chunk ", nfo.id);
return; return;
} }
@ -588,12 +593,12 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk
const unsigned int t = strtoul10(splitter[1]); const unsigned int t = strtoul10(splitter[1]);
nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? ( nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? (
ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) : ASSIMP_LOG_WARN(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) :
units[t]; units[t];
return; return;
} }
} }
ASSIMP_LOG_WARN_F("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -622,13 +627,13 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk
} else if (splitter.match_start("Spot ")) { } else if (splitter.match_start("Spot ")) {
msh.ltype = Light::SPOT; msh.ltype = Light::SPOT;
} else { } else {
ASSIMP_LOG_WARN_F("Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter); ASSIMP_LOG_WARN("Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter);
msh.ltype = Light::SPOT; msh.ltype = Light::SPOT;
} }
++splitter; ++splitter;
if (!splitter.match_start("color ")) { if (!splitter.match_start("color ")) {
ASSIMP_LOG_WARN_F("Expected `color` line in `Lght` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `color` line in `Lght` chunk ", nfo.id);
} }
const char *rgb = splitter[1]; const char *rgb = splitter[1];
@ -636,14 +641,14 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk
SkipSpaces(&rgb); SkipSpaces(&rgb);
if (strncmp(rgb, "cone angle", 10) != 0) { if (strncmp(rgb, "cone angle", 10) != 0) {
ASSIMP_LOG_WARN_F("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id);
} }
SkipSpaces(rgb + 10, &rgb); SkipSpaces(rgb + 10, &rgb);
msh.angle = fast_atof(&rgb); msh.angle = fast_atof(&rgb);
SkipSpaces(&rgb); SkipSpaces(&rgb);
if (strncmp(rgb, "inner angle", 11) != 0) { if (strncmp(rgb, "inner angle", 11) != 0) {
ASSIMP_LOG_WARN_F("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
} }
SkipSpaces(rgb + 11, &rgb); SkipSpaces(rgb + 11, &rgb);
msh.inner_angle = fast_atof(&rgb); msh.inner_angle = fast_atof(&rgb);
@ -1027,7 +1032,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
mat.type = Material::METAL; mat.type = Material::METAL;
break; break;
default: default:
ASSIMP_LOG_ERROR_F("Unrecognized shader type in `Mat1` chunk with id ", nfo.id); ASSIMP_LOG_ERROR("Unrecognized shader type in `Mat1` chunk with id ", nfo.id);
mat.type = Material::FLAT; mat.type = Material::FLAT;
} }
@ -1042,7 +1047,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
mat.autofacet = Material::SMOOTH; mat.autofacet = Material::SMOOTH;
break; break;
default: default:
ASSIMP_LOG_ERROR_F("Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id); ASSIMP_LOG_ERROR("Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id);
mat.autofacet = Material::FACETED; mat.autofacet = Material::FACETED;
} }
mat.autofacet_angle = static_cast<float>(reader.GetI1()); mat.autofacet_angle = static_cast<float>(reader.GetI1());
@ -1170,13 +1175,13 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
if (nd->id == nfo.parent_id) { if (nd->id == nfo.parent_id) {
const unsigned int t = reader.GetI2(); const unsigned int t = reader.GetI2();
nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? ( nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? (
ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) : ASSIMP_LOG_WARN(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) :
units[t]; units[t];
return; return;
} }
} }
ASSIMP_LOG_WARN_F("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
} }
#endif // ASSIMP_BUILD_NO_COB_IMPORTER #endif // ASSIMP_BUILD_NO_COB_IMPORTER

View File

@ -75,7 +75,7 @@ static const aiImporterDesc desc = {
3, 3,
1, 1,
5, 5,
"dae zae" "dae xml zae"
}; };
static const float kMillisecondsFromSeconds = 1000.f; static const float kMillisecondsFromSeconds = 1000.f;
@ -317,7 +317,7 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Nod
nd = FindNode(pParser.mRootNode, nodeInst.mNode); nd = FindNode(pParser.mRootNode, nodeInst.mNode);
} }
if (nullptr == nd) { if (nullptr == nd) {
ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode); ASSIMP_LOG_ERROR("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
} else { } else {
// attach this node to the list of children // attach this node to the list of children
resolved.push_back(nd); resolved.push_back(nd);
@ -347,7 +347,7 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
// find the referred light // find the referred light
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find(lid.mLight); ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find(lid.mLight);
if (srcLightIt == pParser.mLightLibrary.end()) { if (srcLightIt == pParser.mLightLibrary.end()) {
ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping."); ASSIMP_LOG_WARN("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping.");
continue; continue;
} }
const Collada::Light *srcLight = &srcLightIt->second; const Collada::Light *srcLight = &srcLightIt->second;
@ -412,7 +412,7 @@ void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Node
// find the referred light // find the referred light
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera); ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera);
if (srcCameraIt == pParser.mCameraLibrary.end()) { if (srcCameraIt == pParser.mCameraLibrary.end()) {
ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping."); ASSIMP_LOG_WARN("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping.");
continue; continue;
} }
const Collada::Camera *srcCamera = &srcCameraIt->second; const Collada::Camera *srcCamera = &srcCameraIt->second;
@ -486,7 +486,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
} }
if (nullptr == srcMesh) { if (nullptr == srcMesh) {
ASSIMP_LOG_WARN_F("Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping."); ASSIMP_LOG_WARN("Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping.");
continue; continue;
} }
} else { } else {
@ -511,7 +511,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
table = &meshMatIt->second; table = &meshMatIt->second;
meshMaterial = table->mMatName; meshMaterial = table->mMatName;
} else { } else {
ASSIMP_LOG_WARN_F("Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <", ASSIMP_LOG_WARN("Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
mid.mMeshOrController, ">."); mid.mMeshOrController, ">.");
if (!mid.mMaterials.empty()) { if (!mid.mMaterials.empty()) {
meshMaterial = mid.mMaterials.begin()->second.mMatName; meshMaterial = mid.mMaterials.begin()->second.mMatName;
@ -619,6 +619,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
dstMesh->mName = pSrcMesh->mId; dstMesh->mName = pSrcMesh->mId;
} }
if (pSrcMesh->mPositions.empty()) {
return dstMesh.release();
}
// count the vertices addressed by its faces // count the vertices addressed by its faces
const size_t numVertices = std::accumulate(pSrcMesh->mFaceSize.begin() + pStartFace, const size_t numVertices = std::accumulate(pSrcMesh->mFaceSize.begin() + pStartFace,
pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0)); pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0));
@ -883,7 +887,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
if (nullptr != bnode) { if (nullptr != bnode) {
bone->mName.Set(FindNameForNode(bnode)); bone->mName.Set(FindNameForNode(bnode));
} else { } else {
ASSIMP_LOG_WARN_F("ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"."); ASSIMP_LOG_WARN("ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\".");
} }
// and insert bone // and insert bone
@ -1184,7 +1188,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
else if (subElement == "Z") else if (subElement == "Z")
entry.mSubElement = 2; entry.mSubElement = 2;
else else
ASSIMP_LOG_WARN_F("Unknown anim subelement <", subElement, ">. Ignoring"); ASSIMP_LOG_WARN("Unknown anim subelement <", subElement, ">. Ignoring");
} else { } else {
// no sub-element following, transformId is remaining string // no sub-element following, transformId is remaining string
entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1); entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1);
@ -1241,7 +1245,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
continue; continue;
} }
entry.mTargetId = entry.mTransformId; entry.mTargetId = entry.mTransformId;
entry.mTransformId = ""; entry.mTransformId = std::string();
} }
entry.mChannel = &(*cit); entry.mChannel = &(*cit);
@ -1711,7 +1715,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
// find the image referred by this name in the image library of the scene // find the image referred by this name in the image library of the scene
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find(name); ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find(name);
if (imIt == pParser.mImageLibrary.end()) { if (imIt == pParser.mImageLibrary.end()) {
ASSIMP_LOG_WARN_F("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\"."); ASSIMP_LOG_WARN("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\".");
//set default texture file name //set default texture file name
result.Set(name + ".jpg"); result.Set(name + ".jpg");

View File

@ -71,7 +71,7 @@ static void ReportWarning(const char *msg, ...) {
ai_assert(iLen > 0); ai_assert(iLen > 0);
va_end(args); va_end(args);
ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer, iLen)); ASSIMP_LOG_WARN("Validation warning: ", std::string(szBuffer, iLen));
} }
static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) { static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) {
@ -170,10 +170,10 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
ColladaParser::~ColladaParser() { ColladaParser::~ColladaParser() {
for (auto & it : mNodeLibrary) { for (auto &it : mNodeLibrary) {
delete it.second; delete it.second;
} }
for (auto & it : mMeshLibrary) { for (auto &it : mMeshLibrary) {
delete it.second; delete it.second;
} }
} }
@ -234,7 +234,7 @@ void ColladaParser::UriDecodePath(aiString &ss) {
#if defined(_MSC_VER) #if defined(_MSC_VER)
if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') { if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
#else #else
if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') { if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
#endif #endif
--ss.length; --ss.length;
::memmove(ss.data, ss.data + 1, ss.length); ::memmove(ss.data, ss.data + 1, ss.length);
@ -396,7 +396,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
std::string animName; std::string animName;
if (!XmlParser::getStdStrAttribute(node, "name", animName)) { if (!XmlParser::getStdStrAttribute(node, "name", animName)) {
if (!XmlParser::getStdStrAttribute( node, "id", animName )) { if (!XmlParser::getStdStrAttribute(node, "id", animName)) {
animName = std::string("animation_") + ai_to_string(mAnimationClipLibrary.size()); animName = std::string("animation_") + ai_to_string(mAnimationClipLibrary.size());
} }
} }
@ -420,7 +420,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
void ColladaParser::PostProcessControllers() { void ColladaParser::PostProcessControllers() {
std::string meshId; std::string meshId;
for (auto & it : mControllerLibrary) { for (auto &it : mControllerLibrary) {
meshId = it.second.mMeshId; meshId = it.second.mMeshId;
if (meshId.empty()) { if (meshId.empty()) {
continue; continue;
@ -445,7 +445,7 @@ void ColladaParser::PostProcessRootAnimations() {
} }
Animation temp; Animation temp;
for (auto & it : mAnimationClipLibrary) { for (auto &it : mAnimationClipLibrary) {
std::string clipName = it.first; std::string clipName = it.first;
Animation *clip = new Animation(); Animation *clip = new Animation();
@ -453,7 +453,7 @@ void ColladaParser::PostProcessRootAnimations() {
temp.mSubAnims.push_back(clip); temp.mSubAnims.push_back(clip);
for (std::string animationID : it.second) { for (const std::string &animationID : it.second) {
AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID); AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID);
if (animation != mAnimationLibrary.end()) { if (animation != mAnimationLibrary.end()) {
@ -529,7 +529,7 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
// have it read into a channel // have it read into a channel
ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first; ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
ReadAnimationSampler(currentNode, newChannel->second); ReadAnimationSampler(currentNode, newChannel->second);
} }
} else if (currentName == "channel") { } else if (currentName == "channel") {
std::string source_name, target; std::string source_name, target;
XmlParser::getStdStrAttribute(currentNode, "source", source_name); XmlParser::getStdStrAttribute(currentNode, "source", source_name);
@ -552,7 +552,7 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
pParent->mSubAnims.push_back(anim); pParent->mSubAnims.push_back(anim);
} }
for (const auto & channel : channels) { for (const auto &channel : channels) {
anim->mChannels.push_back(channel.second); anim->mChannels.push_back(channel.second);
} }
@ -623,12 +623,9 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
controller.mType = Skin; controller.mType = Skin;
controller.mMethod = Normalized; controller.mMethod = Normalized;
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
//for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "morph") { if (currentName == "morph") {
controller.mType = Morph; controller.mType = Morph;
@ -645,7 +642,7 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
} else if (currentName == "skin") { } else if (currentName == "skin") {
std::string id; std::string id;
if (XmlParser::getStdStrAttribute(currentNode, "source", id)) { if (XmlParser::getStdStrAttribute(currentNode, "source", id)) {
controller.mMeshId = id.substr(1, id.size()-1); controller.mMeshId = id.substr(1, id.size() - 1);
} }
} else if (currentName == "bind_shape_matrix") { } else if (currentName == "bind_shape_matrix") {
std::string v; std::string v;
@ -699,7 +696,7 @@ void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pCo
} else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) { } else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) {
pController.mJointOffsetMatrixSource = attrSource; pController.mJointOffsetMatrixSource = attrSource;
} else { } else {
throw DeadlyImportError("Unknown semantic \"" , attrSemantic , "\" in <joints> data <input> element"); throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <joints> data <input> element");
} }
} }
} }
@ -709,7 +706,7 @@ void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pCo
// Reads the joint weights for the given controller // Reads the joint weights for the given controller
void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) { void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) {
// Read vertex count from attributes and resize the array accordingly // Read vertex count from attributes and resize the array accordingly
int vertexCount=0; int vertexCount = 0;
XmlParser::getIntAttribute(node, "count", vertexCount); XmlParser::getIntAttribute(node, "count", vertexCount);
pController.mWeightCounts.resize(vertexCount); pController.mWeightCounts.resize(vertexCount);
@ -724,7 +721,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
// local URLS always start with a '#'. We don't support global URLs // local URLS always start with a '#'. We don't support global URLs
if (attrSource[0] != '#') { if (attrSource[0] != '#') {
throw DeadlyImportError( "Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element"); throw DeadlyImportError("Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element");
} }
channel.mAccessor = attrSource + 1; channel.mAccessor = attrSource + 1;
@ -778,7 +775,7 @@ void ColladaParser::ReadImageLibrary(XmlNode &node) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "image") { if (currentName == "image") {
std::string id; std::string id;
if (XmlParser::getStdStrAttribute( currentNode, "id", id )) { if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
mImageLibrary[id] = Image(); mImageLibrary[id] = Image();
// read on from there // read on from there
ReadImage(currentNode, mImageLibrary[id]); ReadImage(currentNode, mImageLibrary[id]);
@ -908,7 +905,7 @@ void ColladaParser::ReadCameraLibrary(XmlNode &node) {
if (!name.empty()) { if (!name.empty()) {
cam.mName = name; cam.mName = name;
} }
ReadCamera(currentNode, cam); ReadCamera(currentNode, cam);
} }
} }
} }
@ -929,8 +926,7 @@ void ColladaParser::ReadMaterial(XmlNode &node, Collada::Material &pMaterial) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a light entry into the given light // Reads a light entry into the given light
void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) { void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -991,10 +987,8 @@ void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a camera entry into the given light // Reads a camera entry into the given light
void ColladaParser::ReadCamera(XmlNode &node, Collada::Camera &camera) { void ColladaParser::ReadCamera(XmlNode &node, Collada::Camera &camera) {
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "orthographic") { if (currentName == "orthographic") {
@ -1050,11 +1044,10 @@ void ColladaParser::ReadEffect(XmlNode &node, Collada::Effect &pEffect) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads an COMMON effect profile // Reads an COMMON effect profile
void ColladaParser::ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEffect) { void ColladaParser::ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEffect) {
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == "newparam") { if (currentName == "newparam") {
// save ID // save ID
std::string sid = currentNode.attribute("sid").as_string(); std::string sid = currentNode.attribute("sid").as_string();
@ -1145,10 +1138,9 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
if (node.empty()) { if (node.empty()) {
return; return;
} }
XmlNodeIterator xmlIt(node);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode;
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
// MAYA extensions // MAYA extensions
@ -1208,10 +1200,9 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
if (node.empty()) { if (node.empty()) {
return; return;
} }
XmlNodeIterator xmlIt(node);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode;
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
@ -1273,8 +1264,7 @@ void ColladaParser::ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam)
return; return;
} }
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1360,8 +1350,7 @@ void ColladaParser::ReadMesh(XmlNode &node, Mesh &pMesh) {
return; return;
} }
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1370,8 +1359,8 @@ void ColladaParser::ReadMesh(XmlNode &node, Mesh &pMesh) {
} else if (currentName == "vertices") { } else if (currentName == "vertices") {
ReadVertexData(currentNode, pMesh); ReadVertexData(currentNode, pMesh);
} else if (currentName == "triangles" || currentName == "lines" || currentName == "linestrips" || } else if (currentName == "triangles" || currentName == "lines" || currentName == "linestrips" ||
currentName == "polygons" || currentName == "polylist" || currentName == "trifans" || currentName == "polygons" || currentName == "polylist" || currentName == "trifans" ||
currentName == "tristrips") { currentName == "tristrips") {
ReadIndexData(currentNode, pMesh); ReadIndexData(currentNode, pMesh);
} }
} }
@ -1386,8 +1375,7 @@ void ColladaParser::ReadSource(XmlNode &node) {
std::string sourceID; std::string sourceID;
XmlParser::getStdStrAttribute(node, "id", sourceID); XmlParser::getStdStrAttribute(node, "id", sourceID);
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1449,9 +1437,8 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
throw DeadlyImportError("Expected more values while reading float_array contents."); throw DeadlyImportError("Expected more values while reading float_array contents.");
} }
ai_real value;
// read a number // read a number
//SkipSpacesAndLineEnd(&content); ai_real value;
content = fast_atoreal_move<ai_real>(content, value); content = fast_atoreal_move<ai_real>(content, value);
data.mValues.push_back(value); data.mValues.push_back(value);
// skip whitespace after it // skip whitespace after it
@ -1490,8 +1477,7 @@ void ColladaParser::ReadAccessor(XmlNode &node, const std::string &pID) {
acc.mSource = source.c_str() + 1; // ignore the leading '#' acc.mSource = source.c_str() + 1; // ignore the leading '#'
acc.mSize = 0; // gets incremented with every param acc.mSize = 0; // gets incremented with every param
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1500,11 +1486,10 @@ void ColladaParser::ReadAccessor(XmlNode &node, const std::string &pID) {
std::string name; std::string name;
if (XmlParser::hasAttribute(currentNode, "name")) { if (XmlParser::hasAttribute(currentNode, "name")) {
XmlParser::getStdStrAttribute(currentNode, "name", name); XmlParser::getStdStrAttribute(currentNode, "name", name);
//name = mReader->getAttributeValue(attrName);
// analyse for common type components and store it's sub-offset in the corresponding field // analyse for common type components and store it's sub-offset in the corresponding field
/* Cartesian coordinates */ // Cartesian coordinates
if (name == "X") if (name == "X")
acc.mSubOffset[0] = acc.mParams.size(); acc.mSubOffset[0] = acc.mParams.size();
else if (name == "Y") else if (name == "Y")
@ -1608,8 +1593,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
ai_assert(primType != Prim_Invalid); ai_assert(primType != Prim_Invalid);
// also a number of <input> elements, but in addition a <p> primitive collection and probably index counts for all primitives // also a number of <input> elements, but in addition a <p> primitive collection and probably index counts for all primitives
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1686,12 +1670,9 @@ void ColladaParser::ReadInputChannel(XmlNode &node, std::vector<InputChannel> &p
// read set if texture coordinates // read set if texture coordinates
if (channel.mType == IT_Texcoord || channel.mType == IT_Color) { if (channel.mType == IT_Texcoord || channel.mType == IT_Color) {
int attrSet = -1; unsigned int attrSet = 0;
if (XmlParser::hasAttribute(node, "set")) { if (XmlParser::getUIntAttribute(node, "set", attrSet))
XmlParser::getIntAttribute(node, "set", attrSet); channel.mIndex = attrSet;
}
channel.mIndex = attrSet;
} }
// store, if valid type // store, if valid type
@ -1716,20 +1697,20 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
// determine the expected number of indices // determine the expected number of indices
size_t expectedPointCount = 0; size_t expectedPointCount = 0;
switch (pPrimType) { switch (pPrimType) {
case Prim_Polylist: { case Prim_Polylist: {
for (size_t i : pVCount) for (size_t i : pVCount)
expectedPointCount += i; expectedPointCount += i;
break; break;
} }
case Prim_Lines: case Prim_Lines:
expectedPointCount = 2 * pNumPrimitives; expectedPointCount = 2 * pNumPrimitives;
break; break;
case Prim_Triangles: case Prim_Triangles:
expectedPointCount = 3 * pNumPrimitives; expectedPointCount = 3 * pNumPrimitives;
break; break;
default: default:
// other primitive types don't state the index count upfront... we need to guess // other primitive types don't state the index count upfront... we need to guess
break; break;
} }
// and read all indices into a temporary array // and read all indices into a temporary array
@ -1739,7 +1720,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
} }
// It is possible to not contain any indices // It is possible to not contain any indices
if (pNumPrimitives > 0) { if (pNumPrimitives > 0) {
std::string v; std::string v;
XmlParser::getValueAsString(node, v); XmlParser::getValueAsString(node, v);
const char *content = v.c_str(); const char *content = v.c_str();
@ -1937,87 +1918,87 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
// now we reinterpret it according to the type we're reading here // now we reinterpret it according to the type we're reading here
switch (pInput.mType) { switch (pInput.mType) {
case IT_Position: // ignore all position streams except 0 - there can be only one position case IT_Position: // ignore all position streams except 0 - there can be only one position
if (pInput.mIndex == 0) { if (pInput.mIndex == 0) {
pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2])); pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2]));
} else { } else {
ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported"); ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
} }
break; break;
case IT_Normal: case IT_Normal:
// pad to current vertex count if necessary
if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1)
pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0));
// ignore all normal streams except 0 - there can be only one normal
if (pInput.mIndex == 0) {
pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
} else {
ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
}
break;
case IT_Tangent:
// pad to current vertex count if necessary
if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1)
pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0));
// ignore all tangent streams except 0 - there can be only one tangent
if (pInput.mIndex == 0) {
pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
} else {
ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
}
break;
case IT_Bitangent:
// pad to current vertex count if necessary
if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) {
pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
}
// ignore all bitangent streams except 0 - there can be only one bitangent
if (pInput.mIndex == 0) {
pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
} else {
ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
}
break;
case IT_Texcoord:
// up to 4 texture coord sets are fine, ignore the others
if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
// pad to current vertex count if necessary // pad to current vertex count if necessary
if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1) if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0)); pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
// ignore all normal streams except 0 - there can be only one normal pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
if (pInput.mIndex == 0) { if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2])); pMesh.mNumUVComponents[pInput.mIndex] = 3;
} else {
ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
} }
break; } else {
case IT_Tangent: ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
}
break;
case IT_Color:
// up to 4 color sets are fine, ignore the others
if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
// pad to current vertex count if necessary // pad to current vertex count if necessary
if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1) if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0)); pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
// ignore all tangent streams except 0 - there can be only one tangent aiColor4D result(0, 0, 0, 1);
if (pInput.mIndex == 0) { for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2])); result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
} else {
ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
}
break;
case IT_Bitangent:
// pad to current vertex count if necessary
if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) {
pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
} }
pMesh.mColors[pInput.mIndex].push_back(result);
} else {
ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
}
// ignore all bitangent streams except 0 - there can be only one bitangent break;
if (pInput.mIndex == 0) { default:
pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2])); // IT_Invalid and IT_Vertex
} else { ai_assert(false && "shouldn't ever get here");
ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
}
break;
case IT_Texcoord:
// up to 4 texture coord sets are fine, ignore the others
if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
// pad to current vertex count if necessary
if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
pMesh.mNumUVComponents[pInput.mIndex] = 3;
}
} else {
ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
}
break;
case IT_Color:
// up to 4 color sets are fine, ignore the others
if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
// pad to current vertex count if necessary
if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
aiColor4D result(0, 0, 0, 1);
for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
}
pMesh.mColors[pInput.mIndex].push_back(result);
} else {
ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
}
break;
default:
// IT_Invalid and IT_Vertex
ai_assert(false && "shouldn't ever get here");
} }
} }
@ -2182,10 +2163,10 @@ void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, Transform
// read as many parameters and store in the transformation // read as many parameters and store in the transformation
for (unsigned int a = 0; a < sNumParameters[pType]; a++) { for (unsigned int a = 0; a < sNumParameters[pType]; a++) {
// skip whitespace before the number
SkipSpacesAndLineEnd(&content);
// read a number // read a number
content = fast_atoreal_move<ai_real>(content, tf.f[a]); content = fast_atoreal_move<ai_real>(content, tf.f[a]);
// skip whitespace after it
SkipSpacesAndLineEnd(&content);
} }
// place the transformation at the queue of the node // place the transformation at the queue of the node
@ -2400,7 +2381,7 @@ Collada::InputType ColladaParser::GetTypeForSemantic(const std::string &semantic
else if (semantic == "TANGENT" || semantic == "TEXTANGENT") else if (semantic == "TANGENT" || semantic == "TEXTANGENT")
return IT_Tangent; return IT_Tangent;
ASSIMP_LOG_WARN_F("Unknown vertex input type \"", semantic, "\". Ignoring."); ASSIMP_LOG_WARN("Unknown vertex input type \"", semantic, "\". Ignoring.");
return IT_Invalid; return IT_Invalid;
} }

View File

@ -135,7 +135,7 @@ public:
for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++); for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
splitter++; splitter++;
ASSIMP_LOG_VERBOSE_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)")); ASSIMP_LOG_VERBOSE_DEBUG("DXF: skipped over control group (",cnt," lines)");
} }
} catch(std::logic_error&) { } catch(std::logic_error&) {
ai_assert(!splitter); ai_assert(!splitter);

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2021, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -63,11 +61,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
// AutoCAD Binary DXF<CR><LF><SUB><NULL> // AutoCAD Binary DXF<CR><LF><SUB><NULL>
const std::string AI_DXF_BINARY_IDENT = std::string("AutoCAD Binary DXF\r\n\x1a\0"); static constexpr char AI_DXF_BINARY_IDENT[] = "AutoCAD Binary DXF\r\n\x1a";
const size_t AI_DXF_BINARY_IDENT_LEN = 24u; static constexpr size_t AI_DXF_BINARY_IDENT_LEN = sizeof AI_DXF_BINARY_IDENT;
// default vertex color that all uncolored vertices will receive // default vertex color that all uncolored vertices will receive
const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f)); static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f));
// color indices for DXF - 16 are supported, the table is // color indices for DXF - 16 are supported, the table is
// taken directly from the DXF spec. // taken directly from the DXF spec.
@ -156,10 +154,10 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene,
} }
// Check whether this is a binary DXF file - we can't read binary DXF files :-( // Check whether this is a binary DXF file - we can't read binary DXF files :-(
char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0}; char buff[AI_DXF_BINARY_IDENT_LEN] = {0};
file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1); file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1);
if (0 == strncmp(AI_DXF_BINARY_IDENT.c_str(),buff,AI_DXF_BINARY_IDENT_LEN)) { if (0 == memcmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) {
throw DeadlyImportError("DXF: Binary files are not supported at the moment"); throw DeadlyImportError("DXF: Binary files are not supported at the moment");
} }
@ -202,7 +200,7 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene,
// comments // comments
else if (reader.Is(999)) { else if (reader.Is(999)) {
ASSIMP_LOG_INFO_F("DXF Comment: ", reader.Value()); ASSIMP_LOG_INFO("DXF Comment: ", reader.Value());
} }
// don't read past the official EOF sign // don't read past the official EOF sign
@ -241,7 +239,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) {
} }
} }
ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); ASSIMP_LOG_VERBOSE_DEBUG("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount);
} }
if (! output.blocks.size() ) { if (! output.blocks.size() ) {
@ -372,7 +370,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
// first check if the referenced blocks exists ... // first check if the referenced blocks exists ...
const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name); const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name);
if (it == blocks_by_name.end()) { if (it == blocks_by_name.end()) {
ASSIMP_LOG_ERROR_F("DXF: Failed to resolve block reference: ", insert.name,"; skipping" ); ASSIMP_LOG_ERROR("DXF: Failed to resolve block reference: ", insert.name,"; skipping" );
continue; continue;
} }
@ -473,7 +471,7 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) {
++reader; ++reader;
} }
ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" ); ASSIMP_LOG_VERBOSE_DEBUG("DXF: got ", output.blocks.size()," entries in BLOCKS" );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -549,7 +547,7 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
++reader; ++reader;
} }
ASSIMP_LOG_VERBOSE_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), ASSIMP_LOG_VERBOSE_DEBUG( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(),
" inserted blocks in ENTITIES" ); " inserted blocks in ENTITIES" );
} }
@ -654,7 +652,7 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
//} //}
if (vguess && line.positions.size() != vguess) { if (vguess && line.positions.size() != vguess) {
ASSIMP_LOG_WARN_F("DXF: unexpected vertex count in polymesh: ", ASSIMP_LOG_WARN("DXF: unexpected vertex count in polymesh: ",
line.positions.size(),", expected ", vguess ); line.positions.size(),", expected ", vguess );
} }
@ -670,7 +668,7 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
// to set the 71 and 72 fields, respectively, to valid values. // to set the 71 and 72 fields, respectively, to valid values.
// So just fire a warning. // So just fire a warning.
if (iguess && line.counts.size() != iguess) { if (iguess && line.counts.size() != iguess) {
ASSIMP_LOG_WARN_F( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess ); ASSIMP_LOG_WARN( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess );
} }
} }
else if (!line.indices.size() && !line.counts.size()) { else if (!line.indices.size() && !line.counts.size()) {

View File

@ -459,7 +459,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
/*Result ignored*/ ReadByte(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length);
/*Result ignored*/ ReadByte(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length);
const uint32_t version = ReadWord(input, cursor, input + length); const uint32_t version = ReadWord(input, cursor, input + length);
ASSIMP_LOG_DEBUG_F("FBX version: ", version); ASSIMP_LOG_DEBUG("FBX version: ", version);
const bool is64bits = version >= 7500; const bool is64bits = version >= 7500;
const char *end = input + length; const char *end = input + length;
try try

View File

@ -62,16 +62,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP #ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP
# include <unordered_map> # include <unordered_map>
# include <unordered_set> # include <unordered_set>
# if _MSC_VER > 1600 # if defined(_MSC_VER) && _MSC_VER <= 1600
# define fbx_unordered_map unordered_map
# define fbx_unordered_multimap unordered_multimap
# define fbx_unordered_set unordered_set
# define fbx_unordered_multiset unordered_multiset
# else
# define fbx_unordered_map tr1::unordered_map # define fbx_unordered_map tr1::unordered_map
# define fbx_unordered_multimap tr1::unordered_multimap # define fbx_unordered_multimap tr1::unordered_multimap
# define fbx_unordered_set tr1::unordered_set # define fbx_unordered_set tr1::unordered_set
# define fbx_unordered_multiset tr1::unordered_multiset # define fbx_unordered_multiset tr1::unordered_multiset
# else
# define fbx_unordered_map unordered_map
# define fbx_unordered_multimap unordered_multimap
# define fbx_unordered_set unordered_set
# define fbx_unordered_multiset unordered_multiset
# endif # endif
#endif #endif

View File

@ -811,7 +811,7 @@ bool FBXConverter::GenerateTransformationNodeChain(const Model &model, const std
// we need to generate a full node chain to accommodate for assimp's // we need to generate a full node chain to accommodate for assimp's
// lack to express pivots and offsets. // lack to express pivots and offsets.
if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) { if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) {
FBXImporter::LogInfo("generating full transformation chain for node: " + name); FBXImporter::LogInfo("generating full transformation chain for node: ", name);
// query the anim_chain_bits dictionary to find out which chain elements // query the anim_chain_bits dictionary to find out which chain elements
// have associated node animation channels. These can not be dropped // have associated node animation channels. These can not be dropped
@ -918,7 +918,7 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root
const std::vector<unsigned int> &indices = ConvertLine(*line, root_node); const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
} else { } else {
FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name()); FBXImporter::LogWarn("ignoring unrecognized geometry: ", geo->Name());
} }
} }
@ -944,7 +944,7 @@ FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *
const std::vector<aiVector3D> &vertices = mesh.GetVertices(); const std::vector<aiVector3D> &vertices = mesh.GetVertices();
const std::vector<unsigned int> &faces = mesh.GetFaceIndexCounts(); const std::vector<unsigned int> &faces = mesh.GetFaceIndexCounts();
if (vertices.empty() || faces.empty()) { if (vertices.empty() || faces.empty()) {
FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name()); FBXImporter::LogWarn("ignoring empty geometry: ", mesh.Name());
return temp; return temp;
} }
@ -971,7 +971,7 @@ std::vector<unsigned int> FBXConverter::ConvertLine(const LineGeometry &line, ai
const std::vector<aiVector3D> &vertices = line.GetVertices(); const std::vector<aiVector3D> &vertices = line.GetVertices();
const std::vector<int> &indices = line.GetIndices(); const std::vector<int> &indices = line.GetIndices();
if (vertices.empty() || indices.empty()) { if (vertices.empty() || indices.empty()) {
FBXImporter::LogWarn("ignoring empty line: " + line.Name()); FBXImporter::LogWarn("ignoring empty line: ", line.Name());
return temp; return temp;
} }
@ -1126,6 +1126,8 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
*out_uv++ = aiVector3D(v.x, v.y, 0.0f); *out_uv++ = aiVector3D(v.x, v.y, 0.0f);
} }
out_mesh->mTextureCoordsNames[i] = mesh.GetTextureCoordChannelName(i);
out_mesh->mNumUVComponents[i] = 2; out_mesh->mNumUVComponents[i] = 2;
} }
@ -1542,10 +1544,10 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
aiBone *bone = nullptr; aiBone *bone = nullptr;
if (bone_map.count(deformer_name)) { if (bone_map.count(deformer_name)) {
ASSIMP_LOG_VERBOSE_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); ASSIMP_LOG_VERBOSE_DEBUG("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name);
bone = bone_map[deformer_name]; bone = bone_map[deformer_name];
} else { } else {
ASSIMP_LOG_VERBOSE_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); ASSIMP_LOG_VERBOSE_DEBUG("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name);
bone = new aiBone(); bone = new aiBone();
bone->mName = bone_name; bone->mName = bone_name;
@ -1591,7 +1593,7 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
bone_map.insert(std::pair<const std::string, aiBone *>(deformer_name, bone)); bone_map.insert(std::pair<const std::string, aiBone *>(deformer_name, bone));
} }
ASSIMP_LOG_DEBUG_F("bone research: Indicies size: ", out_indices.size()); ASSIMP_LOG_DEBUG("bone research: Indicies size: ", out_indices.size());
// lookup must be populated in case something goes wrong // lookup must be populated in case something goes wrong
// this also allocates bones to mesh instance outside // this also allocates bones to mesh instance outside
@ -1764,6 +1766,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
// XXX handle all kinds of UV transformations // XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation(); uvTrafo.mTranslation = tex->UVTranslation();
uvTrafo.mRotation = tex->UVRotation();
out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0); out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0);
const PropertyTable &props = tex->Props(); const PropertyTable &props = tex->Props();
@ -1815,14 +1818,14 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
continue; continue;
} }
if (uvIndex == -1) { if (uvIndex == -1) {
uvIndex = index; uvIndex = index;
} else { } else {
FBXImporter::LogWarn("the UV channel named " + uvSet + FBXImporter::LogWarn("the UV channel named ", uvSet,
" appears at different positions in meshes, results will be wrong"); " appears at different positions in meshes, results will be wrong");
} }
} }
@ -1839,7 +1842,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
} }
if (uvIndex == -1) { if (uvIndex == -1) {
@ -1848,7 +1851,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
} }
if (uvIndex == -1) { if (uvIndex == -1) {
FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); FBXImporter::LogWarn("failed to resolve UV channel ", uvSet, ", using first UV channel");
uvIndex = 0; uvIndex = 0;
} }
} }
@ -1883,6 +1886,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
// XXX handle all kinds of UV transformations // XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation(); uvTrafo.mTranslation = tex->UVTranslation();
uvTrafo.mRotation = tex->UVRotation();
out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex); out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex);
const PropertyTable &props = tex->Props(); const PropertyTable &props = tex->Props();
@ -1934,14 +1938,14 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
continue; continue;
} }
if (uvIndex == -1) { if (uvIndex == -1) {
uvIndex = index; uvIndex = index;
} else { } else {
FBXImporter::LogWarn("the UV channel named " + uvSet + FBXImporter::LogWarn("the UV channel named ", uvSet,
" appears at different positions in meshes, results will be wrong"); " appears at different positions in meshes, results will be wrong");
} }
} }
@ -1958,7 +1962,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
} }
if (uvIndex == -1) { if (uvIndex == -1) {
@ -1967,7 +1971,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
} }
if (uvIndex == -1) { if (uvIndex == -1) {
FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); FBXImporter::LogWarn("failed to resolve UV channel ", uvSet, ", using first UV channel");
uvIndex = 0; uvIndex = 0;
} }
} }
@ -2126,7 +2130,12 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
const aiColor3D &Emissive = GetColorPropertyFromMaterial(props, "Emissive", ok); const aiColor3D &Emissive = GetColorPropertyFromMaterial(props, "Emissive", ok);
if (ok) { if (ok) {
out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE); out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE);
} } else {
const aiColor3D &emissiveColor = GetColorPropertyFromMaterial(props, "Maya|emissive", ok);
if (ok) {
out_mat->AddProperty(&emissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
}
}
const aiColor3D &Ambient = GetColorPropertyFromMaterial(props, "Ambient", ok); const aiColor3D &Ambient = GetColorPropertyFromMaterial(props, "Ambient", ok);
if (ok) { if (ok) {
@ -2207,6 +2216,52 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
if (ok) { if (ok) {
out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0); out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0);
} }
// PBR material information
const aiColor3D &baseColor = GetColorPropertyFromMaterial(props, "Maya|base_color", ok);
if (ok) {
out_mat->AddProperty(&baseColor, 1, AI_MATKEY_BASE_COLOR);
}
const float useColorMap = PropertyGet<float>(props, "Maya|use_color_map", ok);
if (ok) {
out_mat->AddProperty(&useColorMap, 1, AI_MATKEY_USE_COLOR_MAP);
}
const float useMetallicMap = PropertyGet<float>(props, "Maya|use_metallic_map", ok);
if (ok) {
out_mat->AddProperty(&useMetallicMap, 1, AI_MATKEY_USE_METALLIC_MAP);
}
const float metallicFactor = PropertyGet<float>(props, "Maya|metallic", ok);
if (ok) {
out_mat->AddProperty(&metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR);
}
const float useRoughnessMap = PropertyGet<float>(props, "Maya|use_roughness_map", ok);
if (ok) {
out_mat->AddProperty(&useRoughnessMap, 1, AI_MATKEY_USE_ROUGHNESS_MAP);
}
const float roughnessFactor = PropertyGet<float>(props, "Maya|roughness", ok);
if (ok) {
out_mat->AddProperty(&roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR);
}
const float useEmissiveMap = PropertyGet<float>(props, "Maya|use_emissive_map", ok);
if (ok) {
out_mat->AddProperty(&useEmissiveMap, 1, AI_MATKEY_USE_EMISSIVE_MAP);
}
const float emissiveIntensity = PropertyGet<float>(props, "Maya|emissive_intensity", ok);
if (ok) {
out_mat->AddProperty(&emissiveIntensity, 1, AI_MATKEY_EMISSIVE_INTENSITY);
}
const float useAOMap = PropertyGet<float>(props, "Maya|use_ao_map", ok);
if (ok) {
out_mat->AddProperty(&useAOMap, 1, AI_MATKEY_USE_AO_MAP);
}
} }
void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTable &props, const TextureMap &_textures, const MeshGeometry *const mesh) { void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTable &props, const TextureMap &_textures, const MeshGeometry *const mesh) {
@ -2271,6 +2326,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
// XXX handle all kinds of UV transformations // XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation(); uvTrafo.mTranslation = tex->UVTranslation();
uvTrafo.mRotation = tex->UVRotation();
out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0); out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0);
int uvIndex = 0; int uvIndex = 0;
@ -2319,14 +2375,14 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
continue; continue;
} }
if (uvIndex == -1) { if (uvIndex == -1) {
uvIndex = index; uvIndex = index;
} else { } else {
FBXImporter::LogWarn("the UV channel named " + uvSet + " appears at different positions in meshes, results will be wrong"); FBXImporter::LogWarn("the UV channel named ", uvSet, " appears at different positions in meshes, results will be wrong");
} }
} }
} else { } else {
@ -2342,7 +2398,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
} }
if (uvIndex == -1) { if (uvIndex == -1) {
@ -2351,7 +2407,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
} }
if (uvIndex == -1) { if (uvIndex == -1) {
FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); FBXImporter::LogWarn("failed to resolve UV channel ", uvSet, ", using first UV channel");
uvIndex = 0; uvIndex = 0;
} }
} }
@ -2546,7 +2602,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
anim->mMorphMeshChannels = new aiMeshMorphAnim *[numMorphMeshChannels]; anim->mMorphMeshChannels = new aiMeshMorphAnim *[numMorphMeshChannels];
anim->mNumMorphMeshChannels = numMorphMeshChannels; anim->mNumMorphMeshChannels = numMorphMeshChannels;
unsigned int i = 0; unsigned int i = 0;
for (auto morphAnimIt : morphAnimDatas) { for (const auto &morphAnimIt : morphAnimDatas) {
morphAnimData *animData = morphAnimIt.second; morphAnimData *animData = morphAnimIt.second;
unsigned int numKeys = static_cast<unsigned int>(animData->size()); unsigned int numKeys = static_cast<unsigned int>(animData->size());
aiMeshMorphAnim *meshMorphAnim = new aiMeshMorphAnim(); aiMeshMorphAnim *meshMorphAnim = new aiMeshMorphAnim();
@ -2574,7 +2630,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
// empty animations would fail validation, so drop them // empty animations would fail validation, so drop them
delete anim; delete anim;
animations.pop_back(); animations.pop_back();
FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): " + name); FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): ", name);
return; return;
} }
@ -2707,13 +2763,13 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
ai_assert(node); ai_assert(node);
if (node->TargetProperty().empty()) { if (node->TargetProperty().empty()) {
FBXImporter::LogWarn("target property for animation curve not set: " + node->Name()); FBXImporter::LogWarn("target property for animation curve not set: ", node->Name());
continue; continue;
} }
curve_node = node; curve_node = node;
if (node->Curves().empty()) { if (node->Curves().empty()) {
FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: " + node->Name()); FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: ", node->Name());
continue; continue;
} }
@ -2748,7 +2804,7 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
if (doc.Settings().optimizeEmptyAnimationCurves && if (doc.Settings().optimizeEmptyAnimationCurves &&
IsRedundantAnimationData(target, comp, (chain[i]->second))) { IsRedundantAnimationData(target, comp, (chain[i]->second))) {
FBXImporter::LogVerboseDebug("dropping redundant animation channel for node " + target.Name()); FBXImporter::LogVerboseDebug("dropping redundant animation channel for node ", target.Name());
continue; continue;
} }

View File

@ -57,9 +57,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <memory>
#include <functional> #include <functional>
#include <map> #include <map>
#include <memory>
#include <utility>
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
@ -248,10 +249,8 @@ Object::~Object()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props) FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<const PropertyTable> props) :
: props(props) props(std::move(props)), doc(doc) {
, doc(doc)
{
// empty // empty
} }
@ -312,7 +311,7 @@ void Document::ReadHeader() {
const Scope& shead = *ehead->Compound(); const Scope& shead = *ehead->Compound();
fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0)); fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
ASSIMP_LOG_DEBUG_F("FBX Version: ", fbxVersion); ASSIMP_LOG_DEBUG("FBX Version: ", fbxVersion);
// While we may have some success with newer files, we don't support // While we may have some success with newer files, we don't support
// the older 6.n fbx format // the older 6.n fbx format

View File

@ -500,6 +500,10 @@ public:
return uvScaling; return uvScaling;
} }
const ai_real &UVRotation() const {
return uvRotation;
}
const PropertyTable& Props() const { const PropertyTable& Props() const {
ai_assert(props.get()); ai_assert(props.get());
return *props.get(); return *props.get();
@ -517,6 +521,7 @@ public:
private: private:
aiVector2D uvTrans; aiVector2D uvTrans;
aiVector2D uvScaling; aiVector2D uvScaling;
ai_real uvRotation;
std::string type; std::string type;
std::string relativeFileName; std::string relativeFileName;

View File

@ -79,7 +79,7 @@ void DOMError(const std::string& message, const Element* element /*= nullptr*/)
void DOMWarning(const std::string& message, const Token& token) void DOMWarning(const std::string& message, const Token& token)
{ {
if(DefaultLogger::get()) { if(DefaultLogger::get()) {
ASSIMP_LOG_WARN_F("FBX-DOM", Util::GetTokenText(&token), message); ASSIMP_LOG_WARN("FBX-DOM", Util::GetTokenText(&token), message);
} }
} }
@ -91,7 +91,7 @@ void DOMWarning(const std::string& message, const Element* element /*= nullptr*/
return; return;
} }
if(DefaultLogger::get()) { if(DefaultLogger::get()) {
ASSIMP_LOG_WARN("FBX-DOM: " + message); ASSIMP_LOG_WARN("FBX-DOM: ", message);
} }
} }

View File

@ -144,9 +144,8 @@ void FBX::Node::AddP70time(
// public member functions for writing nodes to stream // public member functions for writing nodes to stream
void FBX::Node::Dump( void FBX::Node::Dump(
std::shared_ptr<Assimp::IOStream> outfile, const std::shared_ptr<Assimp::IOStream> &outfile,
bool binary, int indent bool binary, int indent) {
) {
if (binary) { if (binary) {
Assimp::StreamWriterLE outstream(outfile); Assimp::StreamWriterLE outstream(outfile);
DumpBinary(outstream); DumpBinary(outstream);

View File

@ -157,9 +157,8 @@ public: // member functions for writing data to a file or stream
// write the full node to the given file or stream // write the full node to the given file or stream
void Dump( void Dump(
std::shared_ptr<Assimp::IOStream> outfile, const std::shared_ptr<Assimp::IOStream> &outfile,
bool binary, int indent bool binary, int indent);
);
void Dump(Assimp::StreamWriterLE &s, bool binary, int indent); void Dump(Assimp::StreamWriterLE &s, bool binary, int indent);
// these other functions are for writing data piece by piece. // these other functions are for writing data piece by piece.

View File

@ -541,10 +541,17 @@ void FBXExporter::WriteReferences ()
// (before any actual data is written) // (before any actual data is written)
// --------------------------------------------------------------- // ---------------------------------------------------------------
size_t count_nodes(const aiNode* n) { size_t count_nodes(const aiNode* n, const aiNode* root) {
size_t count = 1; size_t count;
if (n == root) {
count = n->mNumMeshes; // (not counting root node)
} else if (n->mNumMeshes > 1) {
count = n->mNumMeshes + 1;
} else {
count = 1;
}
for (size_t i = 0; i < n->mNumChildren; ++i) { for (size_t i = 0; i < n->mNumChildren; ++i) {
count += count_nodes(n->mChildren[i]); count += count_nodes(n->mChildren[i], root);
} }
return count; return count;
} }
@ -714,7 +721,7 @@ void FBXExporter::WriteDefinitions ()
// Model / FbxNode // Model / FbxNode
// <~~ node hierarchy // <~~ node hierarchy
count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node) count = int32_t(count_nodes(mScene->mRootNode, mScene->mRootNode));
if (count) { if (count) {
n = FBX::Node("ObjectType", "Model"); n = FBX::Node("ObjectType", "Model");
n.AddChild("Count", count); n.AddChild("Count", count);
@ -812,6 +819,18 @@ void FBXExporter::WriteDefinitions ()
// Geometry / FbxMesh // Geometry / FbxMesh
// <~~ aiMesh // <~~ aiMesh
count = mScene->mNumMeshes; count = mScene->mNumMeshes;
// Blendshapes are considered Geometry
int32_t bsDeformerCount=0;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
aiMesh* m = mScene->mMeshes[mi];
if (m->mNumAnimMeshes > 0) {
count+=m->mNumAnimMeshes;
bsDeformerCount+=m->mNumAnimMeshes; // One deformer per blendshape
bsDeformerCount++; // Plus one master blendshape deformer
}
}
if (count) { if (count) {
n = FBX::Node("ObjectType", "Geometry"); n = FBX::Node("ObjectType", "Geometry");
n.AddChild("Count", count); n.AddChild("Count", count);
@ -978,7 +997,7 @@ void FBXExporter::WriteDefinitions ()
} }
// Deformer // Deformer
count = int32_t(count_deformers(mScene)); count = int32_t(count_deformers(mScene))+bsDeformerCount;
if (count) { if (count) {
n = FBX::Node("ObjectType", "Deformer"); n = FBX::Node("ObjectType", "Deformer");
n.AddChild("Count", count); n.AddChild("Count", count);
@ -1363,6 +1382,7 @@ void FBXExporter::WriteObjects ()
n.End(outstream, binary, indent, true); n.End(outstream, binary, indent, true);
} }
// aiMaterial // aiMaterial
material_uids.clear(); material_uids.clear();
for (size_t i = 0; i < mScene->mNumMaterials; ++i) { for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
@ -1668,6 +1688,10 @@ void FBXExporter::WriteObjects ()
// link the image data to the texture // link the image data to the texture
connections.emplace_back("C", "OO", image_uid, texture_uid); connections.emplace_back("C", "OO", image_uid, texture_uid);
aiUVTransform trafo;
unsigned int max = sizeof(aiUVTransform);
aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE, 0), (ai_real *)&trafo, &max);
// now write the actual texture node // now write the actual texture node
FBX::Node tnode("Texture"); FBX::Node tnode("Texture");
// TODO: some way to determine texture name? // TODO: some way to determine texture name?
@ -1678,6 +1702,9 @@ void FBXExporter::WriteObjects ()
tnode.AddChild("Version", int32_t(202)); tnode.AddChild("Version", int32_t(202));
tnode.AddChild("TextureName", texture_name); tnode.AddChild("TextureName", texture_name);
FBX::Node p("Properties70"); FBX::Node p("Properties70");
p.AddP70vectorA("Translation", trafo.mTranslation[0], trafo.mTranslation[1], 0.0);
p.AddP70vectorA("Rotation", 0, 0, trafo.mRotation);
p.AddP70vectorA("Scaling", trafo.mScaling[0], trafo.mScaling[1], 0.0);
p.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify p.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify
//p.AddP70string("UVSet", ""); // TODO: how should this work? //p.AddP70string("UVSet", ""); // TODO: how should this work?
p.AddP70bool("UseMaterial", 1); p.AddP70bool("UseMaterial", 1);
@ -1697,6 +1724,100 @@ void FBXExporter::WriteObjects ()
} }
} }
// Blendshapes, if any
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
const aiMesh* m = mScene->mMeshes[mi];
if (m->mNumAnimMeshes == 0) {
continue;
}
// make a deformer for this mesh
int64_t deformer_uid = generate_uid();
FBX::Node dnode("Deformer");
dnode.AddProperties(deformer_uid, m->mName.data + FBX::SEPARATOR + "Blendshapes", "BlendShape");
dnode.AddChild("Version", int32_t(101));
dnode.Dump(outstream, binary, indent);
// connect it
connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
std::vector<int32_t> vertex_indices = vVertexIndice[mi];
for (unsigned int am = 0; am < m->mNumAnimMeshes; ++am) {
aiAnimMesh *pAnimMesh = m->mAnimMeshes[am];
std::string blendshape_name = pAnimMesh->mName.data;
// start the node record
FBX::Node bsnode("Geometry");
int64_t blendshape_uid = generate_uid();
mesh_uids.push_back(blendshape_uid);
bsnode.AddProperty(blendshape_uid);
bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Blendshape");
bsnode.AddProperty("Shape");
bsnode.AddChild("Version", int32_t(100));
bsnode.Begin(outstream, binary, indent);
bsnode.DumpProperties(outstream, binary, indent);
bsnode.EndProperties(outstream, binary, indent);
bsnode.BeginChildren(outstream, binary, indent);
indent++;
if (pAnimMesh->HasPositions()) {
std::vector<int32_t>shape_indices;
std::vector<double>pPositionDiff;
std::vector<double>pNormalDiff;
for (unsigned int vt = 0; vt < vertex_indices.size(); ++vt) {
aiVector3D pDiff = (pAnimMesh->mVertices[vertex_indices[vt]] - m->mVertices[vertex_indices[vt]]);
if(pDiff.Length()>1e-8){
shape_indices.push_back(vertex_indices[vt]);
pPositionDiff.push_back(pDiff[0]);
pPositionDiff.push_back(pDiff[1]);
pPositionDiff.push_back(pDiff[2]);
if (pAnimMesh->HasNormals()) {
aiVector3D nDiff = (pAnimMesh->mNormals[vertex_indices[vt]] - m->mNormals[vertex_indices[vt]]);
pNormalDiff.push_back(nDiff[0]);
pNormalDiff.push_back(nDiff[1]);
pNormalDiff.push_back(nDiff[2]);
}
}
}
FBX::Node::WritePropertyNode(
"Indexes", shape_indices, outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"Vertices", pPositionDiff, outstream, binary, indent
);
if (pNormalDiff.size()>0) {
FBX::Node::WritePropertyNode(
"Normals", pNormalDiff, outstream, binary, indent
);
}
}
indent--;
bsnode.End(outstream, binary, indent, true);
// Add blendshape Channel Deformer
FBX::Node sdnode("Deformer");
const int64_t blendchannel_uid = generate_uid();
sdnode.AddProperties(
blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel"
);
sdnode.AddChild("Version", int32_t(100));
sdnode.AddChild("DeformPercent", float_t(0.0));
FBX::Node p("Properties70");
p.AddP70numberA("DeformPercent", 0.0);
sdnode.AddChild(p);
// TODO: Normally just one weight per channel, adding stub for later development
std::vector<float>fFullWeights;
fFullWeights.push_back(100.);
sdnode.AddChild("FullWeights", fFullWeights);
sdnode.Dump(outstream, binary, indent);
connections.emplace_back("C", "OO", blendchannel_uid, deformer_uid);
connections.emplace_back("C", "OO", blendshape_uid, blendchannel_uid);
}
}
// bones. // bones.
// //
// output structure: // output structure:
@ -2089,7 +2210,65 @@ void FBXExporter::WriteObjects ()
bpnode.Dump(outstream, binary, indent); bpnode.Dump(outstream, binary, indent);
}*/ }*/
// TODO: cameras, lights // lights
indent = 1;
lights_uids.clear();
for (size_t li = 0; li < mScene->mNumLights; ++li) {
aiLight* l = mScene->mLights[li];
int64_t uid = generate_uid();
const std::string lightNodeAttributeName = l->mName.C_Str() + FBX::SEPARATOR + "NodeAttribute";
FBX::Node lna("NodeAttribute");
lna.AddProperties(uid, lightNodeAttributeName, "Light");
FBX::Node lnap("Properties70");
// Light color.
lnap.AddP70colorA("Color", l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b);
// TODO Assimp light description is quite concise and do not handle light intensity.
// Default value to 1000W.
lnap.AddP70numberA("Intensity", 1000);
// FBXLight::EType conversion
switch (l->mType) {
case aiLightSource_POINT:
lnap.AddP70enum("LightType", 0);
break;
case aiLightSource_DIRECTIONAL:
lnap.AddP70enum("LightType", 1);
break;
case aiLightSource_SPOT:
lnap.AddP70enum("LightType", 2);
lnap.AddP70numberA("InnerAngle", AI_RAD_TO_DEG(l->mAngleInnerCone));
lnap.AddP70numberA("OuterAngle", AI_RAD_TO_DEG(l->mAngleOuterCone));
break;
// TODO Assimp do not handle 'area' nor 'volume' lights, but FBX does.
/*case aiLightSource_AREA:
lnap.AddP70enum("LightType", 3);
lnap.AddP70enum("AreaLightShape", 0); // 0=Rectangle, 1=Sphere
break;
case aiLightSource_VOLUME:
lnap.AddP70enum("LightType", 4);
break;*/
default:
break;
}
// Did not understood how to configure the decay so disabling attenuation.
lnap.AddP70enum("DecayType", 0);
// Dump to FBX stream
lna.AddChild(lnap);
lna.AddChild("TypeFlags", FBX::FBXExportProperty("Light"));
lna.AddChild("GeometryVersion", FBX::FBXExportProperty(int32_t(124)));
lna.Dump(outstream, binary, indent);
// Store name and uid (will be used later when parsing scene nodes)
lights_uids[l->mName.C_Str()] = uid;
}
// TODO: cameras
// write nodes (i.e. model hierarchy) // write nodes (i.e. model hierarchy)
// start at root node // start at root node
@ -2493,10 +2672,19 @@ void FBXExporter::WriteModelNodes(
// and connect them // and connect them
connections.emplace_back("C", "OO", node_attribute_uid, node_uid); connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
} else { } else {
// generate a null node so we can add children to it const auto& lightIt = lights_uids.find(node->mName.C_Str());
WriteModelNode( if(lightIt != lights_uids.end()) {
outstream, binary, node, node_uid, "Null", transform_chain // Node has a light connected to it.
); WriteModelNode(
outstream, binary, node, node_uid, "Light", transform_chain
);
connections.emplace_back("C", "OO", lightIt->second, node_uid);
} else {
// generate a null node so we can add children to it
WriteModelNode(
outstream, binary, node, node_uid, "Null", transform_chain
);
}
} }
// if more than one child mesh, make nodes for each mesh // if more than one child mesh, make nodes for each mesh
@ -2518,17 +2706,14 @@ void FBXExporter::WriteModelNodes(
], ],
new_node_uid new_node_uid
); );
// write model node
FBX::Node m("Model"); aiNode new_node;
// take name from mesh name, if it exists // take name from mesh name, if it exists
std::string name = mScene->mMeshes[node->mMeshes[i]]->mName.C_Str(); new_node.mName = mScene->mMeshes[node->mMeshes[i]]->mName;
name += FBX::SEPARATOR + "Model"; // write model node
m.AddProperties(new_node_uid, name, "Mesh"); WriteModelNode(
m.AddChild("Version", int32_t(232)); outstream, binary, &new_node, new_node_uid, "Mesh", std::vector<std::pair<std::string,aiVector3D>>()
FBX::Node p("Properties70"); );
p.AddP70enum("InheritType", 1);
m.AddChild(p);
m.Dump(outstream, binary, 1);
} }
} }
@ -2540,16 +2725,14 @@ void FBXExporter::WriteModelNodes(
} }
} }
void FBXExporter::WriteAnimationCurveNode( void FBXExporter::WriteAnimationCurveNode(
StreamWriterLE& outstream, StreamWriterLE &outstream,
int64_t uid, int64_t uid,
const std::string& name, // "T", "R", or "S" const std::string &name, // "T", "R", or "S"
aiVector3D default_value, aiVector3D default_value,
std::string property_name, // "Lcl Translation" etc const std::string &property_name, // "Lcl Translation" etc
int64_t layer_uid, int64_t layer_uid,
int64_t node_uid int64_t node_uid) {
) {
FBX::Node n("AnimationCurveNode"); FBX::Node n("AnimationCurveNode");
n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", ""); n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", "");
FBX::Node p("Properties70"); FBX::Node p("Properties70");
@ -2564,7 +2747,6 @@ void FBXExporter::WriteAnimationCurveNode(
this->connections.emplace_back("C", "OP", uid, node_uid, property_name); this->connections.emplace_back("C", "OP", uid, node_uid, property_name);
} }
void FBXExporter::WriteAnimationCurve( void FBXExporter::WriteAnimationCurve(
StreamWriterLE& outstream, StreamWriterLE& outstream,
double default_value, double default_value,

View File

@ -63,10 +63,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiScene; struct aiScene;
struct aiNode; struct aiNode;
//struct aiMaterial; struct aiLight;
namespace Assimp namespace Assimp {
{
class IOSystem; class IOSystem;
class IOStream; class IOStream;
class ExportProperties; class ExportProperties;
@ -95,6 +94,7 @@ namespace Assimp
std::vector<int64_t> mesh_uids; std::vector<int64_t> mesh_uids;
std::vector<int64_t> material_uids; std::vector<int64_t> material_uids;
std::map<const aiNode*,int64_t> node_uids; std::map<const aiNode*,int64_t> node_uids;
std::map<std::string,int64_t> lights_uids;
// this crude unique-ID system is actually fine // this crude unique-ID system is actually fine
int64_t last_uid = 999999; int64_t last_uid = 999999;
@ -154,14 +154,13 @@ namespace Assimp
FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs
); );
void WriteAnimationCurveNode( void WriteAnimationCurveNode(
StreamWriterLE& outstream, StreamWriterLE &outstream,
int64_t uid, int64_t uid,
const std::string& name, // "T", "R", or "S" const std::string &name, // "T", "R", or "S"
aiVector3D default_value, aiVector3D default_value,
std::string property_name, // "Lcl Translation" etc const std::string &property_name, // "Lcl Translation" etc
int64_t animation_layer_uid, int64_t animation_layer_uid,
int64_t node_uid int64_t node_uid);
);
void WriteAnimationCurve( void WriteAnimationCurve(
StreamWriterLE& outstream, StreamWriterLE& outstream,
double default_value, double default_value,

View File

@ -82,7 +82,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
// lower-case shading because Blender (for example) writes "Phong" // lower-case shading because Blender (for example) writes "Phong"
for (size_t i = 0; i < shading.length(); ++i) { for (size_t i = 0; i < shading.length(); ++i) {
shading[i] = static_cast<char>(tolower(shading[i])); shading[i] = static_cast<char>(tolower(static_cast<unsigned char>(shading[i])));
} }
std::string templateName; std::string templateName;
if(shading == "phong") { if(shading == "phong") {
@ -210,6 +210,11 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
uvTrans.y = trans.y; uvTrans.y = trans.y;
} }
const aiVector3D &rotation = PropertyGet<aiVector3D>(*props, "Rotation", ok);
if (ok) {
uvRotation = rotation.z;
}
// resolve video links // resolve video links
if(doc.Settings().readTextures) { if(doc.Settings().readTextures) {
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID()); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
@ -352,7 +357,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
} }
} catch (const runtime_error& runtimeError) { } catch (const runtime_error& runtimeError) {
//we don't need the content data for contents that has already been loaded //we don't need the content data for contents that has already been loaded
ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ", ASSIMP_LOG_VERBOSE_DEBUG("Caught exception in FBXMaterial (likely because content was already loaded): ",
runtimeError.what()); runtimeError.what());
} }
} }

View File

@ -307,8 +307,8 @@ void MeshGeometry::ReadLayerElement(const Scope& layerElement)
} }
} }
FBXImporter::LogError(Formatter::format("failed to resolve vertex layer element: ") FBXImporter::LogError("failed to resolve vertex layer element: ",
<< type << ", index: " << typedIndex); type, ", index: ", typedIndex);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -324,13 +324,13 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
if (type == "LayerElementUV") { if (type == "LayerElementUV") {
if(index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { if(index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
FBXImporter::LogError(Formatter::format("ignoring UV layer, maximum number of UV channels exceeded: ") FBXImporter::LogError("ignoring UV layer, maximum number of UV channels exceeded: ",
<< index << " (limit is " << AI_MAX_NUMBER_OF_TEXTURECOORDS << ")" ); index, " (limit is ", AI_MAX_NUMBER_OF_TEXTURECOORDS, ")" );
return; return;
} }
const Element* Name = source["Name"]; const Element* Name = source["Name"];
m_uvNames[index] = ""; m_uvNames[index] = std::string();
if(Name) { if(Name) {
m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0)); m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
} }
@ -402,8 +402,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
} }
else if (type == "LayerElementColor") { else if (type == "LayerElementColor") {
if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) { if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ") FBXImporter::LogError("ignoring vertex color layer, maximum number of color sets exceeded: ",
<< index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")" ); index, " (limit is ", AI_MAX_NUMBER_OF_COLOR_SETS, ")" );
return; return;
} }
@ -449,8 +449,8 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
if (tempData.size() != mapping_offsets.size()) { if (tempData.size() != mapping_offsets.size()) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") FBXImporter::LogError("length of input data unexpected for ByVertice mapping: ",
<< tempData.size() << ", expected " << mapping_offsets.size()); tempData.size(), ", expected ", mapping_offsets.size());
return; return;
} }
@ -470,8 +470,8 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
if (uvIndices.size() != vertex_count) { if (uvIndices.size() != vertex_count) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") FBXImporter::LogError("length of input data unexpected for ByVertice mapping: ",
<< uvIndices.size() << ", expected " << vertex_count); uvIndices.size(), ", expected ", vertex_count);
return; return;
} }
@ -493,8 +493,8 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
if (tempData.size() != vertex_count) { if (tempData.size() != vertex_count) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ") FBXImporter::LogError("length of input data unexpected for ByPolygon mapping: ",
<< tempData.size() << ", expected " << vertex_count tempData.size(), ", expected ", vertex_count
); );
return; return;
} }
@ -508,9 +508,15 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
std::vector<int> uvIndices; std::vector<int> uvIndices;
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
if (uvIndices.size() > vertex_count) {
FBXImporter::LogWarn("trimming length of input array for ByPolygonVertex mapping: ",
uvIndices.size(), ", expected ", vertex_count);
uvIndices.resize(vertex_count);
}
if (uvIndices.size() != vertex_count) { if (uvIndices.size() != vertex_count) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping: ",
<< uvIndices.size() << ", expected " << vertex_count); uvIndices.size(), ", expected ", vertex_count);
return; return;
} }
@ -531,8 +537,8 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
} }
} }
else { else {
FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ") FBXImporter::LogError("ignoring vertex data channel, access type not implemented: ",
<< MappingInformationType << "," << ReferenceInformationType); MappingInformationType, ",", ReferenceInformationType);
} }
} }
@ -598,15 +604,15 @@ void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static const std::string BinormalIndexToken = "BinormalIndex"; static const char * BinormalIndexToken = "BinormalIndex";
static const std::string BinormalsIndexToken = "BinormalsIndex"; static const char * BinormalsIndexToken = "BinormalsIndex";
void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_out, const Scope& source, void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_out, const Scope& source,
const std::string& MappingInformationType, const std::string& MappingInformationType,
const std::string& ReferenceInformationType) const std::string& ReferenceInformationType)
{ {
const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal"; const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str(); const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken : BinormalIndexToken;
ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType, ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
str, str,
strIdx, strIdx,
@ -636,10 +642,10 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
if (MappingInformationType == "AllSame") { if (MappingInformationType == "AllSame") {
// easy - same material for all faces // easy - same material for all faces
if (materials_out.empty()) { if (materials_out.empty()) {
FBXImporter::LogError(Formatter::format("expected material index, ignoring")); FBXImporter::LogError("expected material index, ignoring");
return; return;
} else if (materials_out.size() > 1) { } else if (materials_out.size() > 1) {
FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one")); FBXImporter::LogWarn("expected only a single material index, ignoring all except the first one");
materials_out.clear(); materials_out.clear();
} }
@ -649,14 +655,14 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
materials_out.resize(face_count); materials_out.resize(face_count);
if(materials_out.size() != face_count) { if(materials_out.size() != face_count) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ") FBXImporter::LogError("length of input data unexpected for ByPolygon mapping: ",
<< materials_out.size() << ", expected " << face_count materials_out.size(), ", expected ", face_count
); );
return; return;
} }
} else { } else {
FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ") FBXImporter::LogError("ignoring material assignments, access type not implemented: ",
<< MappingInformationType << "," << ReferenceInformationType); MappingInformationType, ",", ReferenceInformationType);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -462,7 +462,7 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
err_out = "expected TOK_DATA token"; err_out = "expected TOK_DATA token";
return ""; return std::string();
} }
if(t.IsBinary()) if(t.IsBinary())
@ -470,7 +470,7 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
const char* data = t.begin(); const char* data = t.begin();
if (data[0] != 'S') { if (data[0] != 'S') {
err_out = "failed to parse S(tring), unexpected data type (binary)"; err_out = "failed to parse S(tring), unexpected data type (binary)";
return ""; return std::string();
} }
// read string length // read string length
@ -484,13 +484,13 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
const size_t length = static_cast<size_t>(t.end() - t.begin()); const size_t length = static_cast<size_t>(t.end() - t.begin());
if(length < 2) { if(length < 2) {
err_out = "token is too short to hold a string"; err_out = "token is too short to hold a string";
return ""; return std::string();
} }
const char* s = t.begin(), *e = t.end() - 1; const char* s = t.begin(), *e = t.end() - 1;
if (*s != '\"' || *e != '\"') { if (*s != '\"' || *e != '\"') {
err_out = "expected double quoted string"; err_out = "expected double quoted string";
return ""; return std::string();
} }
return std::string(s+1,length-2); return std::string(s+1,length-2);

View File

@ -52,6 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXDocumentUtil.h" #include "FBXDocumentUtil.h"
#include "FBXProperties.h" #include "FBXProperties.h"
#include <utility>
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
@ -131,7 +133,7 @@ Property* ReadTypedProperty(const Element& element)
ParseTokenAsFloat(*tok[6])) ParseTokenAsFloat(*tok[6]))
); );
} }
else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) { else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"float") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) {
checkTokenCount(tok, 5); checkTokenCount(tok, 5);
return new TypedProperty<float>(ParseTokenAsFloat(*tok[4])); return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
} }
@ -155,7 +157,7 @@ std::string PeekPropertyName(const Element& element)
ai_assert(element.KeyToken().StringContents() == "P"); ai_assert(element.KeyToken().StringContents() == "P");
const TokenList& tok = element.Tokens(); const TokenList& tok = element.Tokens();
if(tok.size() < 4) { if(tok.size() < 4) {
return ""; return std::string();
} }
return ParseTokenAsString(*tok[0]); return ParseTokenAsString(*tok[0]);
@ -172,10 +174,8 @@ PropertyTable::PropertyTable()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps) PropertyTable::PropertyTable(const Element &element, std::shared_ptr<const PropertyTable> templateProps) :
: templateProps(templateProps) templateProps(std::move(templateProps)), element(&element) {
, element(&element)
{
const Scope& scope = GetRequiredScope(element); const Scope& scope = GetRequiredScope(element);
for(const ElementMap::value_type& v : scope.Elements()) { for(const ElementMap::value_type& v : scope.Elements()) {
if(v.first != "P") { if(v.first != "P") {
@ -199,7 +199,6 @@ PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const Prope
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
PropertyTable::~PropertyTable() PropertyTable::~PropertyTable()
{ {

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssetLib/HMP/HMPLoader.h" #include "AssetLib/HMP/HMPLoader.h"
#include "AssetLib/MD2/MD2FileData.h" #include "AssetLib/MD2/MD2FileData.h"
#include <assimp/StringUtils.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
@ -151,13 +152,11 @@ void HMPImporter::InternReadFile(const std::string &pFile,
InternReadFile_HMP7(); InternReadFile_HMP7();
} else { } else {
// Print the magic word to the logger // Print the magic word to the logger
char szBuffer[5]; std::string szBuffer = ai_str_toprintable((const char *)&iMagic, sizeof(iMagic));
szBuffer[0] = ((char *)&iMagic)[0];
szBuffer[1] = ((char *)&iMagic)[1]; delete[] mBuffer;
szBuffer[2] = ((char *)&iMagic)[2]; mBuffer = nullptr;
szBuffer[3] = ((char *)&iMagic)[3];
szBuffer[4] = '\0';
// We're definitely unable to load this file // We're definitely unable to load this file
throw DeadlyImportError("Unknown HMP subformat ", pFile, throw DeadlyImportError("Unknown HMP subformat ", pFile,
". Magic word (", szBuffer, ") is not known"); ". Magic word (", szBuffer, ") is not known");

View File

@ -513,7 +513,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
} }
// we got a list of in-out-combinations of intersections. That should be an even number of intersections, or // we got a list of in-out-combinations of intersections. That should be an even number of intersections, or
// we're fucked. // we are facing a non-recoverable error.
if ((intersections.size() & 1) != 0) { if ((intersections.size() & 1) != 0) {
IFCImporter::LogWarn("Odd number of intersections, can't work with that. Omitting half space boundary check."); IFCImporter::LogWarn("Odd number of intersections, can't work with that. Omitting half space boundary check.");
continue; continue;
@ -715,7 +715,7 @@ void ProcessBoolean(const Schema_2x3::IfcBooleanResult &boolean, TempMesh &resul
// DIFFERENCE // DIFFERENCE
if (const Schema_2x3::IfcBooleanResult *const clip = boolean.ToPtr<Schema_2x3::IfcBooleanResult>()) { if (const Schema_2x3::IfcBooleanResult *const clip = boolean.ToPtr<Schema_2x3::IfcBooleanResult>()) {
if (clip->Operator != "DIFFERENCE") { if (clip->Operator != "DIFFERENCE") {
IFCImporter::LogWarn("encountered unsupported boolean operator: " + (std::string)clip->Operator); IFCImporter::LogWarn("encountered unsupported boolean operator: ", (std::string)clip->Operator);
return; return;
} }
@ -756,7 +756,7 @@ void ProcessBoolean(const Schema_2x3::IfcBooleanResult &boolean, TempMesh &resul
ProcessBooleanExtrudedAreaSolidDifference(as, result, first_operand, conv); ProcessBooleanExtrudedAreaSolidDifference(as, result, first_operand, conv);
} }
} else { } else {
IFCImporter::LogWarn("skipping unknown IfcBooleanResult entity, type is " + boolean.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcBooleanResult entity, type is ", boolean.GetClassName());
} }
} }

View File

@ -216,7 +216,7 @@ void ProcessConnectedFaceSet(const Schema_2x3::IfcConnectedFaceSet& fset, TempMe
} }
} }
else { else {
IFCImporter::LogWarn("skipping unknown IfcFaceBound entity, type is " + bound.Bound->GetClassName()); IFCImporter::LogWarn("skipping unknown IfcFaceBound entity, type is ", bound.Bound->GetClassName());
continue; continue;
} }
@ -729,7 +729,7 @@ void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept, TempMesh&
ProcessRevolvedAreaSolid(*rev,meshout,conv); ProcessRevolvedAreaSolid(*rev,meshout,conv);
} }
else { else {
IFCImporter::LogWarn("skipping unknown IfcSweptAreaSolid entity, type is " + swept.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcSweptAreaSolid entity, type is ", swept.GetClassName());
} }
} }
@ -740,7 +740,7 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
bool fix_orientation = false; bool fix_orientation = false;
std::shared_ptr< TempMesh > meshtmp = std::make_shared<TempMesh>(); std::shared_ptr< TempMesh > meshtmp = std::make_shared<TempMesh>();
if(const Schema_2x3::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<Schema_2x3::IfcShellBasedSurfaceModel>()) { if(const Schema_2x3::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<Schema_2x3::IfcShellBasedSurfaceModel>()) {
for(std::shared_ptr<const Schema_2x3::IfcShell> shell :shellmod->SbsmBoundary) { for (const std::shared_ptr<const Schema_2x3::IfcShell> &shell : shellmod->SbsmBoundary) {
try { try {
const ::Assimp::STEP::EXPRESS::ENTITY& e = shell->To<::Assimp::STEP::EXPRESS::ENTITY>(); const ::Assimp::STEP::EXPRESS::ENTITY& e = shell->To<::Assimp::STEP::EXPRESS::ENTITY>();
const Schema_2x3::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<Schema_2x3::IfcConnectedFaceSet>(); const Schema_2x3::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<Schema_2x3::IfcConnectedFaceSet>();
@ -781,7 +781,7 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
return false; return false;
} }
else { else {
IFCImporter::LogWarn("skipping unknown IfcGeometricRepresentationItem entity, type is " + geo.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcGeometricRepresentationItem entity, type is ", geo.GetClassName());
return false; return false;
} }

View File

@ -115,7 +115,7 @@ static const aiImporterDesc desc = {
0, 0,
0, 0,
0, 0,
"ifc ifczip stp" "ifc ifczip step stp"
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -243,12 +243,12 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
LogDebug("File schema is \'" + head.fileSchema + '\''); LogDebug("File schema is \'", head.fileSchema, '\'');
if (head.timestamp.length()) { if (head.timestamp.length()) {
LogDebug("Timestamp \'" + head.timestamp + '\''); LogDebug("Timestamp \'", head.timestamp, '\'');
} }
if (head.app.length()) { if (head.app.length()) {
LogDebug("Application/Exporter identline is \'" + head.app + '\''); LogDebug("Application/Exporter identline is \'", head.app, '\'');
} }
} }
@ -315,7 +315,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// this must be last because objects are evaluated lazily as we process them // this must be last because objects are evaluated lazily as we process them
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
LogDebug((Formatter::format(), "STEP: evaluated ", db->GetEvaluatedObjectCount(), " object records")); LogDebug("STEP: evaluated ", db->GetEvaluatedObjectCount(), " object records");
} }
} }
@ -403,7 +403,7 @@ void ResolveObjectPlacement(aiMatrix4x4 &m, const Schema_2x3::IfcObjectPlacement
m = tmpM * m; m = tmpM * m;
} }
} else { } else {
IFCImporter::LogWarn("skipping unknown IfcObjectPlacement entity, type is " + place.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcObjectPlacement entity, type is ", place.GetClassName());
} }
} }
@ -438,7 +438,7 @@ bool ProcessMappedItem(const Schema_2x3::IfcMappedItem &mapped, aiNode *nd_src,
bool got = false; bool got = false;
for (const Schema_2x3::IfcRepresentationItem &item : repr.Items) { for (const Schema_2x3::IfcRepresentationItem &item : repr.Items) {
if (!ProcessRepresentationItem(item, localmatid, meshes, conv)) { if (!ProcessRepresentationItem(item, localmatid, meshes, conv)) {
IFCImporter::LogWarn("skipping mapped entity of type " + item.GetClassName() + ", no representations could be generated"); IFCImporter::LogWarn("skipping mapped entity of type ", item.GetClassName(), ", no representations could be generated");
} else } else
got = true; got = true;
} }
@ -567,7 +567,7 @@ typedef std::map<std::string, std::string> Metadata;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessMetadata(const Schema_2x3::ListOf<Schema_2x3::Lazy<Schema_2x3::IfcProperty>, 1, 0> &set, ConversionData &conv, Metadata &properties, void ProcessMetadata(const Schema_2x3::ListOf<Schema_2x3::Lazy<Schema_2x3::IfcProperty>, 1, 0> &set, ConversionData &conv, Metadata &properties,
const std::string &prefix = "", const std::string &prefix = std::string(),
unsigned int nest = 0) { unsigned int nest = 0) {
for (const Schema_2x3::IfcProperty &property : set) { for (const Schema_2x3::IfcProperty &property : set) {
const std::string &key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name; const std::string &key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
@ -618,7 +618,7 @@ void ProcessMetadata(const Schema_2x3::ListOf<Schema_2x3::Lazy<Schema_2x3::IfcPr
ProcessMetadata(complexProp->HasProperties, conv, properties, key, nest + 1); ProcessMetadata(complexProp->HasProperties, conv, properties, key, nest + 1);
} }
} else { } else {
properties[key] = ""; properties[key] = std::string();
} }
} }
} }
@ -856,7 +856,7 @@ void ProcessSpatialStructures(ConversionData &conv) {
if (!prod) { if (!prod) {
continue; continue;
} }
IFCImporter::LogVerboseDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : "")); IFCImporter::LogVerboseDebug("looking at spatial structure `", (prod->Name ? prod->Name.Get() : "unnamed"), "`", (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : ""));
// the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT
const STEP::DB::RefMap &refs = conv.db.GetRefs(); const STEP::DB::RefMap &refs = conv.db.GetRefs();

View File

@ -64,7 +64,7 @@ static int ConvertShadingMode(const std::string& name) {
else if (name == "PHONG") { else if (name == "PHONG") {
return aiShadingMode_Phong; return aiShadingMode_Phong;
} }
IFCImporter::LogWarn("shading mode "+name+" not recognized by Assimp, using Phong instead"); IFCImporter::LogWarn("shading mode ", name, " not recognized by Assimp, using Phong instead");
return aiShadingMode_Phong; return aiShadingMode_Phong;
} }
@ -75,7 +75,7 @@ static void FillMaterial(aiMaterial* mat,const IFC::Schema_2x3::IfcSurfaceStyle*
mat->AddProperty(&name,AI_MATKEY_NAME); mat->AddProperty(&name,AI_MATKEY_NAME);
// now see which kinds of surface information are present // now see which kinds of surface information are present
for(std::shared_ptr< const IFC::Schema_2x3::IfcSurfaceStyleElementSelect > sel2 : surf->Styles) { for (const std::shared_ptr<const IFC::Schema_2x3::IfcSurfaceStyleElementSelect> &sel2 : surf->Styles) {
if (const IFC::Schema_2x3::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyleShading>(conv.db)) { if (const IFC::Schema_2x3::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyleShading>(conv.db)) {
aiColor4D col_base,col; aiColor4D col_base,col;
@ -124,7 +124,7 @@ static void FillMaterial(aiMaterial* mat,const IFC::Schema_2x3::IfcSurfaceStyle*
} }
} }
} }
} }
} }
} }
@ -134,7 +134,7 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat
for(;range.first != range.second; ++range.first) { for(;range.first != range.second; ++range.first) {
if(const IFC::Schema_2x3::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr<IFC::Schema_2x3::IfcStyledItem>()) { if(const IFC::Schema_2x3::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr<IFC::Schema_2x3::IfcStyledItem>()) {
for(const IFC::Schema_2x3::IfcPresentationStyleAssignment& as : styled->Styles) { for(const IFC::Schema_2x3::IfcPresentationStyleAssignment& as : styled->Styles) {
for(std::shared_ptr<const IFC::Schema_2x3::IfcPresentationStyleSelect> sel : as.Styles) { for (const std::shared_ptr<const IFC::Schema_2x3::IfcPresentationStyleSelect> &sel : as.Styles) {
if( const IFC::Schema_2x3::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyle>(conv.db) ) { if( const IFC::Schema_2x3::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyle>(conv.db) ) {
// try to satisfy from cache // try to satisfy from cache
@ -145,7 +145,7 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat
// not found, create new material // not found, create new material
const std::string side = static_cast<std::string>(surf->Side); const std::string side = static_cast<std::string>(surf->Side);
if( side != "BOTH" ) { if( side != "BOTH" ) {
IFCImporter::LogWarn("ignoring surface side marker on IFC::IfcSurfaceStyle: " + side); IFCImporter::LogWarn("ignoring surface side marker on IFC::IfcSurfaceStyle: ", side);
} }
std::unique_ptr<aiMaterial> mat(new aiMaterial()); std::unique_ptr<aiMaterial> mat(new aiMaterial());

View File

@ -68,7 +68,7 @@ bool ProcessCurve(const Schema_2x3::IfcCurve& curve, TempMesh& meshout, Convers
{ {
std::unique_ptr<const Curve> cv(Curve::Convert(curve,conv)); std::unique_ptr<const Curve> cv(Curve::Convert(curve,conv));
if (!cv) { if (!cv) {
IFCImporter::LogWarn("skipping unknown IfcCurve entity, type is " + curve.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcCurve entity, type is ", curve.GetClassName());
return false; return false;
} }
@ -78,7 +78,7 @@ bool ProcessCurve(const Schema_2x3::IfcCurve& curve, TempMesh& meshout, Convers
bc->SampleDiscrete(meshout); bc->SampleDiscrete(meshout);
} }
catch(const CurveError& cv) { catch(const CurveError& cv) {
IFCImporter::LogError(cv.mStr + " (error occurred while processing curve)"); IFCImporter::LogError(cv.mStr, " (error occurred while processing curve)");
return false; return false;
} }
meshout.mVertcnt.push_back(static_cast<unsigned int>(meshout.mVerts.size())); meshout.mVertcnt.push_back(static_cast<unsigned int>(meshout.mVerts.size()));
@ -152,7 +152,7 @@ void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& de
meshout.mVertcnt.push_back(12); meshout.mVertcnt.push_back(12);
} }
else { else {
IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is " + def.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is ", def.GetClassName());
return; return;
} }
@ -174,7 +174,7 @@ bool ProcessProfile(const Schema_2x3::IfcProfileDef& prof, TempMesh& meshout, Co
ProcessParametrizedProfile(*cparam,meshout,conv); ProcessParametrizedProfile(*cparam,meshout,conv);
} }
else { else {
IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is " + prof.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is ", prof.GetClassName());
return false; return false;
} }
meshout.RemoveAdjacentDuplicates(); meshout.RemoveAdjacentDuplicates();

View File

@ -506,7 +506,7 @@ IfcFloat ConvertSIPrefix(const std::string& prefix)
return 1e-18f; return 1e-18f;
} }
else { else {
IFCImporter::LogError("Unrecognized SI prefix: " + prefix); IFCImporter::LogError("Unrecognized SI prefix: ", prefix);
return 1; return 1;
} }
} }

View File

@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <utility>
struct aiNode; struct aiNode;
namespace Assimp { namespace Assimp {
@ -137,14 +139,10 @@ struct TempOpening
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
TempOpening(const IFC::Schema_2x3::IfcSolidModel* solid,IfcVector3 extrusionDir, TempOpening(const IFC::Schema_2x3::IfcSolidModel *solid, IfcVector3 extrusionDir,
std::shared_ptr<TempMesh> profileMesh, std::shared_ptr<TempMesh> profileMesh,
std::shared_ptr<TempMesh> profileMesh2D) std::shared_ptr<TempMesh> profileMesh2D) :
: solid(solid) solid(solid), extrusionDir(extrusionDir), profileMesh(std::move(profileMesh)), profileMesh2D(std::move(profileMesh2D)) {
, extrusionDir(extrusionDir)
, profileMesh(profileMesh)
, profileMesh2D(profileMesh2D)
{
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------

View File

@ -639,7 +639,7 @@ void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
// graph we're currently building // graph we're currently building
aiScene *localScene = batch.GetImport(root->id); aiScene *localScene = batch.GetImport(root->id);
if (!localScene) { if (!localScene) {
ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath); ASSIMP_LOG_ERROR("IRR: Unable to load external file: ", root->meshPath);
break; break;
} }
attach.push_back(AttachmentInfo(localScene, rootOut)); attach.push_back(AttachmentInfo(localScene, rootOut));
@ -859,13 +859,13 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open IRR file " + pFile + ""); throw DeadlyImportError("Failed to open IRR file ", pFile);
} }
// Construct the irrXML parser // Construct the irrXML parser
XmlParser st; XmlParser st;
if (!st.parse( file.get() )) { if (!st.parse( file.get() )) {
return; throw DeadlyImportError("XML parse error while loading IRR file ", pFile);
} }
pugi::xml_node rootElement = st.getRootNode(); pugi::xml_node rootElement = st.getRootNode();
@ -963,7 +963,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp"); ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp");
nd = new Node(Node::DUMMY); nd = new Node(Node::DUMMY);
} else { } else {
ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(attrib.name())); ASSIMP_LOG_WARN("IRR: Found unknown node: ", attrib.name());
/* We skip the contents of nodes we don't know. /* We skip the contents of nodes we don't know.
* We parse the transformation and all animators * We parse the transformation and all animators
@ -1181,7 +1181,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
lights.pop_back(); lights.pop_back();
curNode->type = Node::DUMMY; curNode->type = Node::DUMMY;
ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value); ASSIMP_LOG_ERROR("Ignoring light of unknown type: ", prop.value);
} }
} else if ((prop.name == "Mesh" && Node::MESH == curNode->type) || } else if ((prop.name == "Mesh" && Node::MESH == curNode->type) ||
Node::ANIMMESH == curNode->type) { Node::ANIMMESH == curNode->type) {
@ -1225,7 +1225,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} else if (prop.value == "followSpline") { } else if (prop.value == "followSpline") {
curAnim->type = Animator::FOLLOW_SPLINE; curAnim->type = Animator::FOLLOW_SPLINE;
} else { } else {
ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: " + prop.value); ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: ", prop.value);
curAnim->type = Animator::UNKNOWN; curAnim->type = Animator::UNKNOWN;
} }

View File

@ -135,12 +135,12 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == NULL) if (file.get() == NULL)
throw DeadlyImportError("Failed to open IRRMESH file " + pFile + ""); throw DeadlyImportError("Failed to open IRRMESH file ", pFile);
// Construct the irrXML parser // Construct the irrXML parser
XmlParser parser; XmlParser parser;
if (!parser.parse( file.get() )) { if (!parser.parse( file.get() )) {
return; throw DeadlyImportError("XML parse error while loading IRRMESH file ", pFile);
} }
XmlNode root = parser.getRootNode(); XmlNode root = parser.getRootNode();

View File

@ -260,7 +260,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags) {
prop.value == "parallaxmap_trans_add") { prop.value == "parallaxmap_trans_add") {
matFlags = AI_IRRMESH_MAT_normalmap_ta; matFlags = AI_IRRMESH_MAT_normalmap_ta;
} else { } else {
ASSIMP_LOG_WARN("IRRMat: Unrecognized material type: " + prop.value); ASSIMP_LOG_WARN("IRRMat: Unrecognized material type: ", prop.value);
} }
} }

View File

@ -242,7 +242,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i
else else
{ {
// procedural or gradient, not supported // procedural or gradient, not supported
ASSIMP_LOG_ERROR_F("LWOB: Unsupported legacy texture: ", type); ASSIMP_LOG_ERROR("LWOB: Unsupported legacy texture: ", type);
} }
return tex; return tex;

View File

@ -502,7 +502,7 @@ struct Surface {
Surface() : Surface() :
mColor(0.78431f, 0.78431f, 0.78431f), bDoubleSided(false), mDiffuseValue(1.f), mSpecularValue(0.f), mTransparency(0.f), mGlossiness(0.4f), mLuminosity(0.f), mColorHighlights(0.f), mMaximumSmoothAngle(0.f) // 0 == not specified, no smoothing mColor(0.78431f, 0.78431f, 0.78431f), bDoubleSided(false), mDiffuseValue(1.f), mSpecularValue(0.f), mTransparency(0.f), mGlossiness(0.4f), mLuminosity(0.f), mColorHighlights(0.f), mMaximumSmoothAngle(0.f) // 0 == not specified, no smoothing
, ,
mVCMap(""), mVCMap(),
mVCMapType(AI_LWO_RGBA), mVCMapType(AI_LWO_RGBA),
mIOR(1.f) // vakuum mIOR(1.f) // vakuum
, ,

View File

@ -961,7 +961,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) {
switch (type) { switch (type) {
case AI_LWO_TXUV: case AI_LWO_TXUV:
if (dims != 2) { if (dims != 2) {
ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'" + name + "\' with !2 components"); ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'", name, "\' with !2 components");
return; return;
} }
base = FindEntry(mCurLayer->mUVChannels, name, perPoly); base = FindEntry(mCurLayer->mUVChannels, name, perPoly);
@ -969,7 +969,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) {
case AI_LWO_WGHT: case AI_LWO_WGHT:
case AI_LWO_MNVW: case AI_LWO_MNVW:
if (dims != 1) { if (dims != 1) {
ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'" + name + "\' with !1 components"); ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'", name, "\' with !1 components");
return; return;
} }
base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels : mCurLayer->mSWeightChannels), name, perPoly); base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels : mCurLayer->mSWeightChannels), name, perPoly);
@ -977,7 +977,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) {
case AI_LWO_RGB: case AI_LWO_RGB:
case AI_LWO_RGBA: case AI_LWO_RGBA:
if (dims != 3 && dims != 4) { if (dims != 3 && dims != 4) {
ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'" + name + "\' with a dimension > 4 or < 3"); ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'", name, "\' with a dimension > 4 or < 3");
return; return;
} }
base = FindEntry(mCurLayer->mVColorChannels, name, perPoly); base = FindEntry(mCurLayer->mVColorChannels, name, perPoly);
@ -1006,7 +1006,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) {
if (name == "APS.Level") { if (name == "APS.Level") {
// XXX handle this (seems to be subdivision-related). // XXX handle this (seems to be subdivision-related).
} }
ASSIMP_LOG_WARN_F("LWO2: Skipping unknown VMAP/VMAD channel \'", name, "\'"); ASSIMP_LOG_WARN("LWO2: Skipping unknown VMAP/VMAD channel \'", name, "\'");
return; return;
}; };
base->Allocate((unsigned int)mCurLayer->mTempPoints.size()); base->Allocate((unsigned int)mCurLayer->mTempPoints.size());
@ -1026,7 +1026,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) {
unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs; unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs;
if (idx >= numPoints) { if (idx >= numPoints) {
ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAP/VMAD entry \'", name, "\', vertex index is out of range"); ASSIMP_LOG_WARN("LWO2: Failure evaluating VMAP/VMAD entry \'", name, "\', vertex index is out of range");
mFileBuffer += base->dims << 2u; mFileBuffer += base->dims << 2u;
continue; continue;
} }
@ -1036,7 +1036,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) {
// we have already a VMAP entry for this vertex - thus // we have already a VMAP entry for this vertex - thus
// we need to duplicate the corresponding polygon. // we need to duplicate the corresponding polygon.
if (polyIdx >= numFaces) { if (polyIdx >= numFaces) {
ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', polygon index is out of range"); ASSIMP_LOG_WARN("LWO2: Failure evaluating VMAD entry \'", name, "\', polygon index is out of range");
mFileBuffer += base->dims << 2u; mFileBuffer += base->dims << 2u;
continue; continue;
} }
@ -1076,7 +1076,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) {
CreateNewEntry(mCurLayer->mNormals, srcIdx); CreateNewEntry(mCurLayer->mNormals, srcIdx);
} }
if (!had) { if (!had) {
ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', vertex index wasn't found in that polygon"); ASSIMP_LOG_WARN("LWO2: Failure evaluating VMAD entry \'", name, "\', vertex index wasn't found in that polygon");
ai_assert(had); ai_assert(had);
} }
} }

View File

@ -335,7 +335,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat) {
m = aiShadingMode_Fresnel; m = aiShadingMode_Fresnel;
break; break;
} else { } else {
ASSIMP_LOG_WARN_F("LWO2: Unknown surface shader: ", shader.functionName); ASSIMP_LOG_WARN("LWO2: Unknown surface shader: ", shader.functionName);
} }
} }
if (surf.mMaximumSmoothAngle <= 0.0) if (surf.mMaximumSmoothAngle <= 0.0)
@ -711,7 +711,7 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) {
} }
} }
if (derived.size()) { if (derived.size()) {
ASSIMP_LOG_WARN("LWO2: Unable to find source surface: " + derived); ASSIMP_LOG_WARN("LWO2: Unable to find source surface: ", derived);
} }
} }

View File

@ -318,7 +318,7 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
} else { } else {
++s; ++s;
} }
std::string::size_type t = src.path.substr(s).find_last_of("."); std::string::size_type t = src.path.substr(s).find_last_of('.');
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined); nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
return; return;
@ -346,7 +346,7 @@ void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vector<Attachm
if (src.path.length()) { if (src.path.length()) {
obj = batch.GetImport(src.id); obj = batch.GetImport(src.id);
if (!obj) { if (!obj) {
ASSIMP_LOG_ERROR("LWS: Failed to read external file " + src.path); ASSIMP_LOG_ERROR("LWS: Failed to read external file ", src.path);
} else { } else {
if (obj->mRootNode->mNumChildren == 1) { if (obj->mRootNode->mNumChildren == 1) {
@ -538,7 +538,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// get file format version and print to log // get file format version and print to log
++it; ++it;
unsigned int version = strtoul10((*it).tokens[0].c_str()); unsigned int version = strtoul10((*it).tokens[0].c_str());
ASSIMP_LOG_INFO("LWS file format version is " + (*it).tokens[0]); ASSIMP_LOG_INFO("LWS file format version is ", (*it).tokens[0]);
first = 0.; first = 0.;
last = 60.; last = 60.;
fps = 25.; // seems to be a good default frame rate fps = 25.; // seems to be a good default frame rate

View File

@ -88,7 +88,7 @@ struct NodeDesc {
id(), id(),
number(0), number(0),
parent(0), parent(0),
name(""), name(),
isPivotSet(false), isPivotSet(false),
lightColor(1.f, 1.f, 1.f), lightColor(1.f, 1.f, 1.f),
lightIntensity(1.f), lightIntensity(1.f),

View File

@ -294,21 +294,17 @@ void ExportSceneM3D(
// Worker function for exporting a scene to ASCII A3D. // Worker function for exporting a scene to ASCII A3D.
// Prototyped and registered in Exporter.cpp // Prototyped and registered in Exporter.cpp
void ExportSceneM3DA( void ExportSceneM3DA(
const char *, const char *pFile,
IOSystem *, IOSystem *pIOSystem,
const aiScene *, const aiScene *pScene,
const ExportProperties * const ExportProperties *pProperties
) { ) {
#ifdef M3D_ASCII
// initialize the exporter // initialize the exporter
M3DExporter exporter(pScene, pProperties); M3DExporter exporter(pScene, pProperties);
// perform ascii export // perform ascii export
exporter.doExport(pFile, pIOSystem, true); exporter.doExport(pFile, pIOSystem, true);
#else
throw DeadlyExportError("Assimp configured without M3D_ASCII support");
#endif
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -95,11 +95,7 @@ static const aiImporterDesc desc = {
0, 0,
0, 0,
0, 0,
#ifdef M3D_ASCII
"m3d a3d" "m3d a3d"
#else
"m3d"
#endif
}; };
namespace Assimp { namespace Assimp {
@ -119,9 +115,7 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
const std::string extension = GetExtension(pFile); const std::string extension = GetExtension(pFile);
if (extension == "m3d" if (extension == "m3d"
#ifdef M3D_ASCII
|| extension == "a3d" || extension == "a3d"
#endif
) )
return true; return true;
else if (!extension.length() || checkSig) { else if (!extension.length() || checkSig) {
@ -137,13 +131,11 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
*/ */
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb")); std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb"));
unsigned char data[4]; unsigned char data[4];
if (4 != pStream->Read(data, 1, 4)) { if (!pStream || 4 != pStream->Read(data, 1, 4)) {
return false; return false;
} }
return !memcmp(data, "3DMO", 4) /* bin */ return !memcmp(data, "3DMO", 4) /* bin */
#ifdef M3D_ASCII
|| !memcmp(data, "3dmo", 4) /* ASCII */ || !memcmp(data, "3dmo", 4) /* ASCII */
#endif
; ;
} }
return false; return false;
@ -176,12 +168,10 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
if (!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) { if (!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) {
throw DeadlyImportError("Bad binary header in file ", file, "."); throw DeadlyImportError("Bad binary header in file ", file, ".");
} }
#ifdef M3D_ASCII
// make sure there's a terminator zero character, as input must be ASCIIZ // make sure there's a terminator zero character, as input must be ASCIIZ
if (!memcmp(buffer.data(), "3dmo", 4)) { if (!memcmp(buffer.data(), "3dmo", 4)) {
buffer.push_back(0); buffer.push_back(0);
} }
#endif
// Get the path for external assets // Get the path for external assets
std::string folderName("./"); std::string folderName("./");
@ -194,7 +184,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
} }
//DefaultLogger::create("/dev/stderr", Logger::VERBOSE); //DefaultLogger::create("/dev/stderr", Logger::VERBOSE);
ASSIMP_LOG_DEBUG_F("M3D: loading ", file); ASSIMP_LOG_DEBUG("M3D: loading ", file);
// let the C SDK do the hard work for us // let the C SDK do the hard work for us
M3DWrapper m3d(pIOHandler, buffer); M3DWrapper m3d(pIOHandler, buffer);
@ -210,7 +200,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
pScene->mRootNode->mNumChildren = 0; pScene->mRootNode->mNumChildren = 0;
mScene = pScene; mScene = pScene;
ASSIMP_LOG_DEBUG("M3D: root node " + m3d.Name()); ASSIMP_LOG_DEBUG("M3D: root node ", m3d.Name());
// now we just have to fill up the Assimp structures in pScene // now we just have to fill up the Assimp structures in pScene
importMaterials(m3d); importMaterials(m3d);
@ -240,7 +230,7 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) {
mScene->mNumMaterials = m3d->nummaterial + 1; mScene->mNumMaterials = m3d->nummaterial + 1;
mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials); ASSIMP_LOG_DEBUG("M3D: importMaterials ", mScene->mNumMaterials);
// add a default material as first // add a default material as first
aiMaterial *mat = new aiMaterial; aiMaterial *mat = new aiMaterial;
@ -335,7 +325,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) {
ai_assert(m3d); ai_assert(m3d);
mScene->mNumTextures = m3d->numtexture; mScene->mNumTextures = m3d->numtexture;
ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); ASSIMP_LOG_DEBUG("M3D: importTextures ", mScene->mNumTextures);
if (!m3d->numtexture || !m3d->texture) { if (!m3d->numtexture || !m3d->texture) {
return; return;
@ -390,7 +380,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) {
// individually. In assimp there're per mesh vertex and UV lists, and they must be // individually. In assimp there're per mesh vertex and UV lists, and they must be
// indexed simultaneously. // indexed simultaneously.
void M3DImporter::importMeshes(const M3DWrapper &m3d) { void M3DImporter::importMeshes(const M3DWrapper &m3d) {
ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); ASSIMP_LOG_DEBUG("M3D: importMeshes ", m3d->numface);
if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) {
return; return;
@ -509,7 +499,7 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo
ai_assert(mScene != nullptr); ai_assert(mScene != nullptr);
ai_assert(m3d); ai_assert(m3d);
ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); ASSIMP_LOG_DEBUG("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid);
if (!m3d->numbone || !m3d->bone) { if (!m3d->numbone || !m3d->bone) {
return; return;
@ -550,7 +540,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) {
mScene->mNumAnimations = m3d->numaction; mScene->mNumAnimations = m3d->numaction;
ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); ASSIMP_LOG_DEBUG("M3D: importAnimations ", mScene->mNumAnimations);
if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) { if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) {
return; return;
@ -665,7 +655,7 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// find a node by name // find a node by name
aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) { aiNode *M3DImporter::findNode(aiNode *pNode, const aiString &name) {
ai_assert(pNode != nullptr); ai_assert(pNode != nullptr);
ai_assert(mScene != nullptr); ai_assert(mScene != nullptr);
@ -713,7 +703,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector
ai_assert(vertexids != nullptr); ai_assert(vertexids != nullptr);
ai_assert(m3d); ai_assert(m3d);
ASSIMP_LOG_DEBUG_F("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(), ASSIMP_LOG_DEBUG("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(),
" numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone); " numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone);
if (vertices->size() && faces->size()) { if (vertices->size() && faces->size()) {

View File

@ -89,8 +89,8 @@ private:
// helper functions // helper functions
aiColor4D mkColor(uint32_t c); aiColor4D mkColor(uint32_t c);
void convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid); void convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid);
aiNode *findNode(aiNode *pNode, aiString name); aiNode *findNode(aiNode *pNode, const aiString &name);
void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m); void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m);
void populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector<aiFace> *faces, std::vector<aiVector3D> *verteces, void populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector<aiFace> *faces, std::vector<aiVector3D> *verteces,
std::vector<aiVector3D> *normals, std::vector<aiVector3D> *texcoords, std::vector<aiColor4D> *colors, std::vector<aiVector3D> *normals, std::vector<aiVector3D> *texcoords, std::vector<aiColor4D> *colors,
std::vector<unsigned int> *vertexids); std::vector<unsigned int> *vertexids);

View File

@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef AI_M3DWRAPPER_H_INC #ifndef AI_M3DWRAPPER_H_INC
#define AI_M3DWRAPPER_H_INC #define AI_M3DWRAPPER_H_INC
#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER #if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER
#include <memory> #include <memory>
@ -54,46 +55,76 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Assimp specific M3D configuration. Comment out these defines to remove functionality // Assimp specific M3D configuration. Comment out these defines to remove functionality
//#define ASSIMP_USE_M3D_READFILECB //#define ASSIMP_USE_M3D_READFILECB
//#define M3D_ASCII
// Share stb_image's PNG loader with other importers/exporters instead of bringing our own copy.
#define STBI_ONLY_PNG
#include <stb/stb_image.h>
#include "m3d.h" #include "m3d.h"
namespace Assimp { namespace Assimp {
class IOSystem; class IOSystem;
/// brief The M3D-Wrapper, provudes c++ access to the data.
class M3DWrapper { class M3DWrapper {
m3d_t *m3d_ = nullptr;
unsigned char *saved_output_ = nullptr;
public: public:
// Construct an empty M3D model /// Construct an empty M3D model
explicit M3DWrapper(); explicit M3DWrapper();
// Construct an M3D model from provided buffer /// Construct an M3D model from provided buffer
// NOTE: The m3d.h SDK function does not mark the data as const. Have assumed it does not write. /// @note The m3d.h SDK function does not mark the data as const. Have assumed it does not write.
// BUG: SECURITY: The m3d.h SDK cannot be informed of the buffer size. BUFFER OVERFLOW IS CERTAIN /// BUG: SECURITY: The m3d.h SDK cannot be informed of the buffer size. BUFFER OVERFLOW IS CERTAIN
explicit M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer); explicit M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer);
~M3DWrapper(); /// Theclasss destructor.
~M3DWrapper();
void reset(); /// Will reset the wrapper, all data will become nullptr.
void reset();
// Name // The Name access, empty string returned when no m3d instance.
inline std::string Name() const { std::string Name() const;
if (m3d_) return std::string(m3d_->name);
return std::string();
}
// Execute a save /// Executes a save.
unsigned char *Save(int quality, int flags, unsigned int &size); unsigned char *Save(int quality, int flags, unsigned int &size);
/// Clearer
void ClearSave(); void ClearSave();
inline explicit operator bool() const { return m3d_ != nullptr; } /// True for m3d instance exists.
explicit operator bool() const;
// Allow direct access to M3D API // Allow direct access to M3D API
inline m3d_t *operator->() const { return m3d_; } m3d_t *operator->() const;
inline m3d_t *M3D() const { return m3d_; } m3d_t *M3D() const;
private:
m3d_t *m3d_ = nullptr;
unsigned char *saved_output_ = nullptr;
}; };
inline std::string M3DWrapper::Name() const {
if (nullptr != m3d_) {
if (nullptr != m3d_->name) {
return std::string(m3d_->name);
}
}
return std::string();
}
inline M3DWrapper::operator bool() const {
return m3d_ != nullptr;
}
inline m3d_t *M3DWrapper::operator->() const {
return m3d_;
}
inline m3d_t *M3DWrapper::M3D() const {
return m3d_;
}
} // namespace Assimp } // namespace Assimp
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/StringUtils.h>
#include <memory> #include <memory>
@ -148,46 +149,39 @@ void MD2Importer::ValidateHeader( )
if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE && if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE &&
m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE) m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE)
{ {
char szBuffer[5]; throw DeadlyImportError("Invalid MD2 magic word: expected IDP2, found ",
szBuffer[0] = ((char*)&m_pcHeader->magic)[0]; ai_str_toprintable((char *)&m_pcHeader->magic, 4));
szBuffer[1] = ((char*)&m_pcHeader->magic)[1];
szBuffer[2] = ((char*)&m_pcHeader->magic)[2];
szBuffer[3] = ((char*)&m_pcHeader->magic)[3];
szBuffer[4] = '\0';
throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the "
"magic word found is " + std::string(szBuffer));
} }
// check file format version // check file format version
if (m_pcHeader->version != 8) if (m_pcHeader->version != 8)
ASSIMP_LOG_WARN( "Unsupported md2 file version. Continuing happily ..."); ASSIMP_LOG_WARN( "Unsupported MD2 file version. Continuing happily ...");
// check some values whether they are valid // check some values whether they are valid
if (0 == m_pcHeader->numFrames) if (0 == m_pcHeader->numFrames)
throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0"); throw DeadlyImportError( "Invalid MD2 file: NUM_FRAMES is 0");
if (m_pcHeader->offsetEnd > (uint32_t)fileSize) if (m_pcHeader->offsetEnd > (uint32_t)fileSize)
throw DeadlyImportError( "Invalid md2 file: File is too small"); throw DeadlyImportError( "Invalid MD2 file: File is too small");
if (m_pcHeader->numSkins > AI_MAX_ALLOC(MD2::Skin)) { if (m_pcHeader->numSkins > AI_MAX_ALLOC(MD2::Skin)) {
throw DeadlyImportError("Invalid MD2 header: too many skins, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many skins, would overflow");
} }
if (m_pcHeader->numVertices > AI_MAX_ALLOC(MD2::Vertex)) { if (m_pcHeader->numVertices > AI_MAX_ALLOC(MD2::Vertex)) {
throw DeadlyImportError("Invalid MD2 header: too many vertices, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many vertices, would overflow");
} }
if (m_pcHeader->numTexCoords > AI_MAX_ALLOC(MD2::TexCoord)) { if (m_pcHeader->numTexCoords > AI_MAX_ALLOC(MD2::TexCoord)) {
throw DeadlyImportError("Invalid MD2 header: too many texcoords, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many texcoords, would overflow");
} }
if (m_pcHeader->numTriangles > AI_MAX_ALLOC(MD2::Triangle)) { if (m_pcHeader->numTriangles > AI_MAX_ALLOC(MD2::Triangle)) {
throw DeadlyImportError("Invalid MD2 header: too many triangles, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many triangles, would overflow");
} }
if (m_pcHeader->numFrames > AI_MAX_ALLOC(MD2::Frame)) { if (m_pcHeader->numFrames > AI_MAX_ALLOC(MD2::Frame)) {
throw DeadlyImportError("Invalid MD2 header: too many frames, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many frames, would overflow");
} }
// -1 because Frame already contains one // -1 because Frame already contains one
@ -199,7 +193,7 @@ void MD2Importer::ValidateHeader( )
m_pcHeader->offsetFrames + m_pcHeader->numFrames * frameSize >= fileSize || m_pcHeader->offsetFrames + m_pcHeader->numFrames * frameSize >= fileSize ||
m_pcHeader->offsetEnd > fileSize) m_pcHeader->offsetEnd > fileSize)
{ {
throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file"); throw DeadlyImportError("Invalid MD2 header: Some offsets are outside the file");
} }
if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS) if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
@ -210,7 +204,7 @@ void MD2Importer::ValidateHeader( )
ASSIMP_LOG_WARN("The model contains more vertices than Quake 2 supports"); ASSIMP_LOG_WARN("The model contains more vertices than Quake 2 supports");
if (m_pcHeader->numFrames <= configFrameID ) if (m_pcHeader->numFrames <= configFrameID )
throw DeadlyImportError("The requested frame is not existing the file"); throw DeadlyImportError("MD2: The requested frame (", configFrameID, ") does not exist in the file");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -433,10 +427,6 @@ void MD2Importer::InternReadFile( const std::string& pFile,
aiVector3D& vNormal = pcMesh->mNormals[iCurrent]; aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal); LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
// flip z and y to become right-handed
std::swap((float&)vNormal.z,(float&)vNormal.y);
std::swap((float&)vec.z,(float&)vec.y);
if (m_pcHeader->numTexCoords) { if (m_pcHeader->numTexCoords) {
// validate texture coordinates // validate texture coordinates
iIndex = pcTriangles[i].textureIndices[c]; iIndex = pcTriangles[i].textureIndices[c];
@ -454,7 +444,15 @@ void MD2Importer::InternReadFile( const std::string& pFile,
} }
pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
} }
// flip the face order
std::swap( pScene->mMeshes[0]->mFaces[i].mIndices[0], pScene->mMeshes[0]->mFaces[i].mIndices[2] );
} }
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(
1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f);
} }
#endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER #endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER

View File

@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MDL_NORMALTABLE_H_INC #define AI_MDL_NORMALTABLE_H_INC
float g_avNormals[162][3] = { const float g_avNormals[162][3] = {
{ -0.525731f, 0.000000f, 0.850651f }, { -0.525731f, 0.000000f, 0.850651f },
{ -0.442863f, 0.238856f, 0.864188f }, { -0.442863f, 0.238856f, 0.864188f },
{ -0.295242f, 0.000000f, 0.955423f }, { -0.295242f, 0.000000f, 0.955423f },

View File

@ -101,7 +101,7 @@ Q3Shader::BlendFunc StringToBlendFunc(const std::string &m) {
if (m == "GL_ONE_MINUS_DST_COLOR") { if (m == "GL_ONE_MINUS_DST_COLOR") {
return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR; return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR;
} }
ASSIMP_LOG_ERROR("Q3Shader: Unknown blend function: " + m); ASSIMP_LOG_ERROR("Q3Shader: Unknown blend function: ", m);
return Q3Shader::BLEND_NONE; return Q3Shader::BLEND_NONE;
} }
@ -112,7 +112,7 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem *
if (!file.get()) if (!file.get())
return false; // if we can't access the file, don't worry and return return false; // if we can't access the file, don't worry and return
ASSIMP_LOG_INFO_F("Loading Quake3 shader file ", pFile); ASSIMP_LOG_INFO("Loading Quake3 shader file ", pFile);
// read file in memory // read file in memory
const size_t s = file->FileSize(); const size_t s = file->FileSize();
@ -196,11 +196,11 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem *
// 'cull' specifies culling behaviour for the model // 'cull' specifies culling behaviour for the model
else if (TokenMatchI(buff, "cull", 4)) { else if (TokenMatchI(buff, "cull", 4)) {
SkipSpaces(&buff); SkipSpaces(&buff);
if (!ASSIMP_strincmp(buff, "back", 4)) { if (!ASSIMP_strincmp(buff, "back", 4)) { // render face's backside, does not function in Q3 engine (bug)
curData->cull = Q3Shader::CULL_CCW; curData->cull = Q3Shader::CULL_CCW;
} else if (!ASSIMP_strincmp(buff, "front", 5)) { } else if (!ASSIMP_strincmp(buff, "front", 5)) { // is not valid keyword in Q3, but occurs in shaders
curData->cull = Q3Shader::CULL_CW; curData->cull = Q3Shader::CULL_CW;
} else if (!ASSIMP_strincmp(buff, "none", 4) || !ASSIMP_strincmp(buff, "disable", 7)) { } else if (!ASSIMP_strincmp(buff, "none", 4) || !ASSIMP_strincmp(buff, "twosided", 8) || !ASSIMP_strincmp(buff, "disable", 7)) {
curData->cull = Q3Shader::CULL_NONE; curData->cull = Q3Shader::CULL_NONE;
} else { } else {
ASSIMP_LOG_ERROR("Q3Shader: Unrecognized cull mode"); ASSIMP_LOG_ERROR("Q3Shader: Unrecognized cull mode");
@ -226,7 +226,7 @@ bool Q3Shader::LoadSkin(SkinData &fill, const std::string &pFile, IOSystem *io)
if (!file.get()) if (!file.get())
return false; // if we can't access the file, don't worry and return return false; // if we can't access the file, don't worry and return
ASSIMP_LOG_INFO("Loading Quake3 skin file " + pFile); ASSIMP_LOG_INFO("Loading Quake3 skin file ", pFile);
// read file in memory // read file in memory
const size_t s = file->FileSize(); const size_t s = file->FileSize();
@ -450,6 +450,9 @@ void MD3Importer::SetupProperties(const Importer *pImp) {
// AI_CONFIG_IMPORT_MD3_SKIN_NAME // AI_CONFIG_IMPORT_MD3_SKIN_NAME
configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME, "default")); configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME, "default"));
// AI_CONFIG_IMPORT_MD3_LOAD_SHADERS
configLoadShaders = (pImp->GetPropertyBool(AI_CONFIG_IMPORT_MD3_LOAD_SHADERS, true));
// AI_CONFIG_IMPORT_MD3_SHADER_SRC // AI_CONFIG_IMPORT_MD3_SHADER_SRC
configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC, "")); configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC, ""));
@ -483,8 +486,9 @@ void MD3Importer::ReadShader(Q3Shader::ShaderData &fill) const {
// If no specific dir or file is given, use our default search behaviour // If no specific dir or file is given, use our default search behaviour
if (!configShaderFile.length()) { if (!configShaderFile.length()) {
if (!Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + model_file + ".shader", mIOHandler)) { const char sep = mIOHandler->getOsSeparator();
Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + filename + ".shader", mIOHandler); if (!Q3Shader::LoadShader(fill, path + ".." + sep + ".." + sep + ".." + sep + "scripts" + sep + model_file + ".shader", mIOHandler)) {
Q3Shader::LoadShader(fill, path + ".." + sep + ".." + sep + ".." + sep + "scripts" + sep + filename + ".shader", mIOHandler);
} }
} else { } else {
// If the given string specifies a file, load this file. // If the given string specifies a file, load this file.
@ -702,7 +706,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
filename = mFile.substr(s), path = mFile.substr(0, s); filename = mFile.substr(s), path = mFile.substr(0, s);
for (std::string::iterator it = filename.begin(); it != filename.end(); ++it) { for (std::string::iterator it = filename.begin(); it != filename.end(); ++it) {
*it = static_cast<char>(tolower(*it)); *it = static_cast<char>(tolower(static_cast<unsigned char>(*it)));
} }
// Load multi-part model file, if necessary // Load multi-part model file, if necessary
@ -780,7 +784,9 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// And check whether we can locate a shader file for this model // And check whether we can locate a shader file for this model
Q3Shader::ShaderData shaders; Q3Shader::ShaderData shaders;
ReadShader(shaders); if (configLoadShaders){
ReadShader(shaders);
}
// Adjust all texture paths in the shader // Adjust all texture paths in the shader
const char *header_name = pcHeader->NAME; const char *header_name = pcHeader->NAME;
@ -851,7 +857,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
if (it != skins.textures.end()) { if (it != skins.textures.end()) {
texture_name = &*(_texture_name = (*it).second).begin(); texture_name = &*(_texture_name = (*it).second).begin();
ASSIMP_LOG_VERBOSE_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME); ASSIMP_LOG_VERBOSE_DEBUG("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME);
(*it).resolved = true; // mark entry as resolved (*it).resolved = true; // mark entry as resolved
} }
@ -862,7 +868,12 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
std::string convertedPath; std::string convertedPath;
if (texture_name) { if (texture_name) {
ConvertPath(texture_name, header_name, convertedPath); if (configLoadShaders){
ConvertPath(texture_name, header_name, convertedPath);
}
else{
convertedPath = texture_name;
}
} }
const Q3Shader::ShaderDataBlock *shader = nullptr; const Q3Shader::ShaderDataBlock *shader = nullptr;
@ -880,9 +891,9 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
if (dit != shaders.blocks.end()) { if (dit != shaders.blocks.end()) {
// We made it! // We made it!
shader = &*dit; shader = &*dit;
ASSIMP_LOG_INFO("Found shader record for " + without_ext); ASSIMP_LOG_INFO("Found shader record for ", without_ext);
} else { } else {
ASSIMP_LOG_WARN("Unable to find shader record for " + without_ext); ASSIMP_LOG_WARN("Unable to find shader record for ", without_ext);
} }
} }
@ -985,8 +996,8 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[index].U; pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[index].U;
pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[index].V; pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[index].V;
} }
// Flip face order if necessary // Flip face order normally, unless shader is backfacing
if (!shader || shader->cull == Q3Shader::CULL_CW) { if (!(shader && shader->cull == Q3Shader::CULL_CCW)) {
std::swap(pcMesh->mFaces[i].mIndices[2], pcMesh->mFaces[i].mIndices[1]); std::swap(pcMesh->mFaces[i].mIndices[2], pcMesh->mFaces[i].mIndices[1]);
} }
++pcTriangles; ++pcTriangles;
@ -1000,7 +1011,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
for (std::list<Q3Shader::SkinData::TextureEntry>::const_iterator it = skins.textures.begin(); it != skins.textures.end(); ++it) { for (std::list<Q3Shader::SkinData::TextureEntry>::const_iterator it = skins.textures.begin(); it != skins.textures.end(); ++it) {
if (!(*it).resolved) { if (!(*it).resolved) {
ASSIMP_LOG_ERROR_F("MD3: Failed to match skin ", (*it).first, " to surface ", (*it).second); ASSIMP_LOG_ERROR("MD3: Failed to match skin ", (*it).first, " to surface ", (*it).second);
} }
} }
} }

View File

@ -297,6 +297,9 @@ protected:
/** Configuration option: name of skin file to be read */ /** Configuration option: name of skin file to be read */
std::string configSkinFile; std::string configSkinFile;
/** Configuration option: whether to load shaders */
bool configLoadShaders;
/** Configuration option: name or path of shader */ /** Configuration option: name or path of shader */
std::string configShaderFile; std::string configShaderFile;

View File

@ -345,7 +345,7 @@ void MD5Importer::LoadMD5MeshFile() {
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr || !file->FileSize()) { if (file.get() == nullptr || !file->FileSize()) {
ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + filename); ASSIMP_LOG_WARN("Failed to access MD5MESH file: ", filename);
return; return;
} }
mHadMD5Mesh = true; mHadMD5Mesh = true;
@ -567,7 +567,7 @@ void MD5Importer::LoadMD5AnimFile() {
// Check whether we can read from the file // Check whether we can read from the file
if (!file.get() || !file->FileSize()) { if (!file.get() || !file->FileSize()) {
ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile); ASSIMP_LOG_WARN("Failed to read MD5ANIM file: ", pFile);
return; return;
} }

View File

@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <assimp/StringUtils.h>
#include <memory> #include <memory>
@ -143,16 +144,8 @@ void MDCImporter::ValidateHeader() {
if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE && if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE) { pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE) {
char szBuffer[5]; throw DeadlyImportError("Invalid MDC magic word: expected IDPC, found ",
szBuffer[0] = ((char *)&pcHeader->ulIdent)[0]; ai_str_toprintable((char *)&pcHeader->ulIdent, 4));
szBuffer[1] = ((char *)&pcHeader->ulIdent)[1];
szBuffer[2] = ((char *)&pcHeader->ulIdent)[2];
szBuffer[3] = ((char *)&pcHeader->ulIdent)[3];
szBuffer[4] = '\0';
throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the "
"magic word found is " +
std::string(szBuffer));
} }
if (pcHeader->ulVersion != AI_MDC_VERSION) { if (pcHeader->ulVersion != AI_MDC_VERSION) {
@ -250,7 +243,7 @@ void MDCImporter::InternReadFile(
// get the number of valid surfaces // get the number of valid surfaces
BE_NCONST MDC::Surface *pcSurface, *pcSurface2; BE_NCONST MDC::Surface *pcSurface, *pcSurface2;
pcSurface = pcSurface2 = new (mBuffer + pcHeader->ulOffsetSurfaces) MDC::Surface; pcSurface = pcSurface2 = reinterpret_cast<BE_NCONST MDC::Surface *>(mBuffer + pcHeader->ulOffsetSurfaces);
unsigned int iNumShaders = 0; unsigned int iNumShaders = 0;
for (unsigned int i = 0; i < pcHeader->ulNumSurfaces; ++i) { for (unsigned int i = 0; i < pcHeader->ulNumSurfaces; ++i) {
// validate the surface header // validate the surface header
@ -260,7 +253,7 @@ void MDCImporter::InternReadFile(
++pScene->mNumMeshes; ++pScene->mNumMeshes;
} }
iNumShaders += pcSurface2->ulNumShaders; iNumShaders += pcSurface2->ulNumShaders;
pcSurface2 = new ((int8_t *)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface; pcSurface2 = reinterpret_cast<BE_NCONST MDC::Surface *>((BE_NCONST int8_t *)pcSurface2 + pcSurface2->ulOffsetEnd);
} }
aszShaders.reserve(iNumShaders); aszShaders.reserve(iNumShaders);
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
@ -405,7 +398,7 @@ void MDCImporter::InternReadFile(
pcFaceCur->mIndices[2] = iOutIndex + 0; pcFaceCur->mIndices[2] = iOutIndex + 0;
} }
pcSurface = new ((int8_t *)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface; pcSurface = reinterpret_cast<BE_NCONST MDC::Surface *>((BE_NCONST int8_t *)pcSurface + pcSurface->ulOffsetEnd);
} }
// create a flat node graph with a root node and one child for each surface // create a flat node graph with a root node and one child for each surface
@ -465,6 +458,13 @@ void MDCImporter::InternReadFile(
pcMat->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0)); pcMat->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
} }
} }
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(
1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f);
} }
#endif // !! ASSIMP_BUILD_NO_MDC_IMPORTER #endif // !! ASSIMP_BUILD_NO_MDC_IMPORTER

View File

@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define MDC_NORMAL_TABLE_INCLUDED #define MDC_NORMAL_TABLE_INCLUDED
/* mdc decoding normal table */ /* mdc decoding normal table */
float mdcNormals[ 256 ][ 3 ] = const float mdcNormals[ 256 ][ 3 ] =
{ {
{ 1.000000f, 0.000000f, 0.000000f }, { 1.000000f, 0.000000f, 0.000000f },
{ 0.980785f, 0.195090f, 0.000000f }, { 0.980785f, 0.195090f, 0.000000f },

View File

@ -57,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <map>
#ifdef MDL_HALFLIFE_LOG_WARN_HEADER #ifdef MDL_HALFLIFE_LOG_WARN_HEADER
#undef MDL_HALFLIFE_LOG_WARN_HEADER #undef MDL_HALFLIFE_LOG_WARN_HEADER
@ -868,7 +869,7 @@ void HL1MDLLoader::read_meshes() {
scene_mesh->mNormals[v] = bind_pose_normals[pTrivert->normindex]; scene_mesh->mNormals[v] = bind_pose_normals[pTrivert->normindex];
scene_mesh->mTextureCoords[0][v] = aiVector3D( scene_mesh->mTextureCoords[0][v] = aiVector3D(
pTrivert->s * texcoords_s_scale, pTrivert->s * texcoords_s_scale,
pTrivert->t * texcoords_t_scale, 0); pTrivert->t * -texcoords_t_scale, 0);
} }
// Add face and indices. // Add face and indices.
@ -879,9 +880,9 @@ void HL1MDLLoader::read_meshes() {
aiFace *face = &scene_mesh->mFaces[f]; aiFace *face = &scene_mesh->mFaces[f];
face->mNumIndices = 3; face->mNumIndices = 3;
face->mIndices = new unsigned int[3]; face->mIndices = new unsigned int[3];
face->mIndices[0] = mesh_faces[f].v0; face->mIndices[0] = mesh_faces[f].v2;
face->mIndices[1] = mesh_faces[f].v1; face->mIndices[1] = mesh_faces[f].v1;
face->mIndices[2] = mesh_faces[f].v2; face->mIndices[2] = mesh_faces[f].v0;
} }
// Add mesh bones. // Add mesh bones.
@ -1342,7 +1343,7 @@ bool HL1MDLLoader::get_num_blend_controllers(const int num_blend_animations, int
return true; return true;
default: default:
num_blend_controllers = 0; num_blend_controllers = 0;
ASSIMP_LOG_WARN(MDL_HALFLIFE_LOG_HEADER "Unsupported number of blend animations (" + std::to_string(num_blend_animations) + ")"); ASSIMP_LOG_WARN(MDL_HALFLIFE_LOG_HEADER "Unsupported number of blend animations (", num_blend_animations, ")");
return false; return false;
} }
} }

View File

@ -95,7 +95,7 @@ void UniqueNameGenerator::make_unique(std::vector<std::string> &names) {
auto generate_unique_name = [&](const std::string &base_name) -> std::string { auto generate_unique_name = [&](const std::string &base_name) -> std::string {
auto *duplicate_info = &names_to_duplicates[base_name]; auto *duplicate_info = &names_to_duplicates[base_name];
std::string new_name = ""; std::string new_name;
bool found_identical_name; bool found_identical_name;
bool tried_with_base_name_only = false; bool tried_with_base_name_only = false;

View File

@ -199,6 +199,7 @@ void MDLImporter::InternReadFile(const std::string &pFile,
const uint32_t iMagicWord = *((uint32_t *)mBuffer); const uint32_t iMagicWord = *((uint32_t *)mBuffer);
// Determine the file subtype and call the appropriate member function // Determine the file subtype and call the appropriate member function
bool is_half_life = false;
// Original Quake1 format // Original Quake1 format
if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) { if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) {
@ -240,6 +241,7 @@ void MDLImporter::InternReadFile(const std::string &pFile,
else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord || else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) { AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) {
iGSFileVersion = 0; iGSFileVersion = 0;
is_half_life = true;
HalfLife::HalfLifeMDLBaseHeader *pHeader = (HalfLife::HalfLifeMDLBaseHeader *)mBuffer; HalfLife::HalfLifeMDLBaseHeader *pHeader = (HalfLife::HalfLifeMDLBaseHeader *)mBuffer;
if (pHeader->version == AI_MDL_HL1_VERSION) { if (pHeader->version == AI_MDL_HL1_VERSION) {
@ -252,12 +254,22 @@ void MDLImporter::InternReadFile(const std::string &pFile,
} else { } else {
// print the magic word to the log file // print the magic word to the log file
throw DeadlyImportError("Unknown MDL subformat ", pFile, throw DeadlyImportError("Unknown MDL subformat ", pFile,
". Magic word (", std::string((char *)&iMagicWord, 4), ") is not known"); ". Magic word (", ai_str_toprintable((const char *)&iMagicWord, sizeof(iMagicWord)), ") is not known");
} }
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system if (is_half_life){
pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, // Now rotate the whole scene 90 degrees around the z and x axes to convert to internal coordinate system
0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); pScene->mRootNode->mTransformation = aiMatrix4x4(
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
-1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f);
}
else {
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
}
DeleteBufferAndCleanup(); DeleteBufferAndCleanup();
} catch (...) { } catch (...) {

View File

@ -75,7 +75,7 @@ using namespace std;
// Default constructor // Default constructor
MMDImporter::MMDImporter() : MMDImporter::MMDImporter() :
m_Buffer(), m_Buffer(),
m_strAbsPath("") { m_strAbsPath() {
DefaultIOSystem io; DefaultIOSystem io;
m_strAbsPath = io.getOsSeparator(); m_strAbsPath = io.getOsSeparator();
} }

View File

@ -91,7 +91,7 @@ namespace pmx
std::vector<char> buffer; std::vector<char> buffer;
if (size == 0) if (size == 0)
{ {
return std::string(""); return std::string();
} }
buffer.reserve(size); buffer.reserve(size);
stream->read((char*) buffer.data(), size); stream->read((char*) buffer.data(), size);
@ -478,8 +478,7 @@ namespace pmx
void PmxSoftBody::Read(std::istream * /*stream*/, PmxSetting * /*setting*/) void PmxSoftBody::Read(std::istream * /*stream*/, PmxSetting * /*setting*/)
{ {
std::cerr << "Not Implemented Exception" << std::endl; throw DeadlyImportError("MMD: Soft Body support is not implemented.");
throw DeadlyImportError("MMD: Not Implemented Exception");
} }
void PmxModel::Init() void PmxModel::Init()
@ -516,15 +515,13 @@ namespace pmx
char magic[4]; char magic[4];
stream->read((char*) magic, sizeof(char) * 4); stream->read((char*) magic, sizeof(char) * 4);
if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20) if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20)
{ {
std::cerr << "invalid magic number." << std::endl; throw DeadlyImportError("MMD: Invalid magic number.");
throw DeadlyImportError("MMD: invalid magic number.");
} }
stream->read((char*) &version, sizeof(float)); stream->read((char*) &version, sizeof(float));
if (version != 2.0f && version != 2.1f) if (version != 2.0f && version != 2.1f)
{ {
std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl; throw DeadlyImportError("MMD: Unsupported version (must be 2.0 or 2.1): ", ai_to_string(version));
throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but ", ai_to_string(version));
} }
this->setting.Read(stream); this->setting.Read(stream);

View File

@ -215,7 +215,12 @@ void MS3DImporter :: CollectChildJoints(const std::vector<TempJoint>& joints, ai
void MS3DImporter::InternReadFile( const std::string& pFile, void MS3DImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene* pScene, IOSystem* pIOHandler)
{ {
StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
auto file = pIOHandler->Open(pFile, "rb");
if (!file)
throw DeadlyImportError("MS3D: Could not open ", pFile);
StreamReaderLE stream(file);
// CanRead() should have done this already // CanRead() should have done this already
char head[10]; char head[10];
@ -382,7 +387,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
} }
const std::string& s = std::string(reinterpret_cast<char*>(stream.GetPtr()),len); const std::string& s = std::string(reinterpret_cast<char*>(stream.GetPtr()),len);
ASSIMP_LOG_DEBUG_F("MS3D: Model comment: ", s); ASSIMP_LOG_DEBUG("MS3D: Model comment: ", s);
} }
if(stream.GetRemainingSize() > 4 && inrange((stream >> subversion,subversion),1u,3u)) { if(stream.GetRemainingSize() > 4 && inrange((stream >> subversion,subversion),1u,3u)) {
@ -500,7 +505,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed"); throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
} }
TempTriangle& t = triangles[g.triangles[i]]; TempTriangle& t = triangles[g.triangles[j]];
f.mIndices = new unsigned int[f.mNumIndices=3]; f.mIndices = new unsigned int[f.mNumIndices=3];
for (unsigned int k = 0; k < 3; ++k,++n) { for (unsigned int k = 0; k < 3; ++k,++n) {
@ -508,7 +513,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed"); throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
} }
const TempVertex& v = vertices[t.indices[i]]; const TempVertex& v = vertices[t.indices[k]];
for(unsigned int a = 0; a < 4; ++a) { for(unsigned int a = 0; a < 4; ++a) {
if (v.bone_id[a] != UINT_MAX) { if (v.bone_id[a] != UINT_MAX) {
if (v.bone_id[a] >= joints.size()) { if (v.bone_id[a] >= joints.size()) {
@ -524,9 +529,9 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
// collect vertex components // collect vertex components
m->mVertices[n] = v.pos; m->mVertices[n] = v.pos;
m->mNormals[n] = t.normals[i]; m->mNormals[n] = t.normals[k];
m->mTextureCoords[0][n] = aiVector3D(t.uv[i].x,1.f-t.uv[i].y,0.0); m->mTextureCoords[0][n] = aiVector3D(t.uv[k].x,1.f-t.uv[k].y,0.0);
f.mIndices[i] = n; f.mIndices[k] = n;
} }
} }

View File

@ -116,7 +116,13 @@ void NDOImporter::SetupProperties(const Importer* /*pImp*/)
void NDOImporter::InternReadFile( const std::string& pFile, void NDOImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene* pScene, IOSystem* pIOHandler)
{ {
StreamReaderBE reader(pIOHandler->Open( pFile, "rb"));
auto file = pIOHandler->Open( pFile, "rb");
if (!file) {
throw DeadlyImportError("Nendo: Could not open ", pFile);
}
StreamReaderBE reader(file);
// first 9 bytes are nendo file format ("nendo 1.n") // first 9 bytes are nendo file format ("nendo 1.n")
const char* head = (const char*)reader.GetPtr(); const char* head = (const char*)reader.GetPtr();
@ -141,7 +147,7 @@ void NDOImporter::InternReadFile( const std::string& pFile,
ASSIMP_LOG_INFO("NDO file format is 1.2"); ASSIMP_LOG_INFO("NDO file format is 1.2");
} }
else { else {
ASSIMP_LOG_WARN_F( "Unrecognized nendo file format version, continuing happily ... :", (head+6)); ASSIMP_LOG_WARN( "Unrecognized nendo file format version, continuing happily ... :", (head+6));
} }
reader.IncPtr(2); /* skip flags */ reader.IncPtr(2); /* skip flags */

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