Compare commits

..

1 Commits

Author SHA1 Message Date
Kim Kulling 81957917a1
Create inno_setup 2024-06-15 11:43:19 +02:00
172 changed files with 1308 additions and 4594 deletions

View File

@ -7,10 +7,10 @@ on:
branches: [ master ] branches: [ master ]
permissions: permissions:
contents: write # to fetch code (actions/checkout),and release contents: read # to fetch code (actions/checkout)
jobs: jobs:
build: job:
name: ${{ matrix.name }}-build-and-test name: ${{ matrix.name }}-build-and-test
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
@ -37,9 +37,6 @@ jobs:
cc: gcc cc: gcc
steps: steps:
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
submodules: true submodules: true
@ -73,12 +70,12 @@ jobs:
- name: Set Windows specific CMake arguments - name: Set Windows specific CMake arguments
if: contains(matrix.name, 'windows') if: contains(matrix.name, 'windows')
id: windows_extra_cmake_args id: windows_extra_cmake_args
run: echo ":set-output name=args::=-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1" >> $GITHUB_OUTPUT run: echo "::set-output name=args::-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1 -DASSIMP_BUILD_ZLIB=1"
- name: Set Hunter specific CMake arguments - name: Set Hunter specific CMake arguments
if: contains(matrix.name, 'hunter') if: contains(matrix.name, 'hunter')
id: hunter_extra_cmake_args id: hunter_extra_cmake_args
run: echo "args=-DBUILD_SHARED_LIBS=OFF -DASSIMP_HUNTER_ENABLED=ON -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/cmake/polly/${{ matrix.toolchain }}.cmake" >> $GITHUB_OUTPUT run: echo "::set-output name=args::-DBUILD_SHARED_LIBS=OFF -DASSIMP_HUNTER_ENABLED=ON -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/cmake/polly/${{ matrix.toolchain }}.cmake"
- name: configure and build - name: configure and build
uses: lukka/run-cmake@v3 uses: lukka/run-cmake@v3
@ -95,7 +92,7 @@ jobs:
- name: Exclude certain tests in Hunter specific builds - name: Exclude certain tests in Hunter specific builds
if: contains(matrix.name, 'hunter') if: contains(matrix.name, 'hunter')
id: hunter_extra_test_args id: hunter_extra_test_args
run: echo "args=--gtest_filter=-utOpenGEXImportExport.Importissue1340_EmptyCameraObject:utColladaZaeImportExport.importBlenFromFileTest" >> $GITHUB_OUTPUT run: echo "::set-output name=args::--gtest_filter=-utOpenGEXImportExport.Importissue1340_EmptyCameraObject:utColladaZaeImportExport.importBlenFromFileTest"
- name: test - name: test
run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }} run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }}
@ -103,90 +100,6 @@ jobs:
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
if: matrix.name == 'windows-msvc' if: matrix.name == 'windows-msvc'
with:
name: 'assimp-bins-${{ matrix.name }}'
path: build/bin/assimp*.exe
- uses: marvinpinto/action-automatic-releases@latest
if: contains(matrix.name, 'windows-msvc-hunter')
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "master"
prerelease: true
title: "AutoRelease"
files: |
build/bin/assimp*.exe
create-release:
needs: [build]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- id: create-release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: '${{secrets.GITHUB_TOKEN}}'
with:
tag_name: '${{github.ref}}'
release_name: 'Release ${{github.ref}}'
draft: false
prerelease: true
- run: |
echo '${{steps.create-release.outputs.upload_url}}' > release_upload_url.txt
- uses: actions/upload-artifact@v4
with:
name: create-release
path: release_upload_url.txt
upload-release:
strategy:
matrix:
name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++, ubuntu-gcc-hunter, macos-clang-hunter, windows-msvc-hunter]
# For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
include:
- name: windows-latest-cl.exe
os: windows-latest
cxx: cl.exe
cc: cl.exe
- name: ubuntu-latest-clang++
os: ubuntu-latest
cxx: clang++
cc: clang
- name: macos-latest-clang++
os: macos-latest
cxx: clang++
cc: clang
- name: ubuntu-latest-g++
os: ubuntu-latest
cxx: g++
cc: gcc
- name: ubuntu-gcc-hunter
os: ubuntu-latest
toolchain: ninja-gcc-cxx17-fpic
- name: macos-clang-hunter
os: macos-latest
toolchain: ninja-clang-cxx17-fpic
- name: windows-msvc-hunter
os: windows-latest
toolchain: ninja-vs-win64-cxx17
needs: [create-release]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- uses: softprops/action-gh-release@v2
with:
name: create-release
- id: upload-url
run: |
echo "url=$(cat create-release/release_upload_url.txt)" >> $GITHUB_OUTPUT
- uses: actions/download-artifact@v4
with: with:
name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}' name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'
- uses: actions/upload-release-asset@v1 path: build/bin
env:
GITHUB_TOKEN: '${{secrets.GITHUB_TOKEN}}'
with:
files: |
*.zip

4
.gitignore vendored
View File

@ -120,7 +120,3 @@ tools/assimp_qt_viewer/ui_mainwindow.h
#Generated directory #Generated directory
generated/* generated/*
# 3rd party cloned repos/tarballs etc
# tinyusdz repo, automatically cloned via CMake
contrib/tinyusdz/autoclone

View File

@ -40,22 +40,6 @@ SET(CMAKE_POLICY_DEFAULT_CMP0092 NEW)
CMAKE_MINIMUM_REQUIRED( VERSION 3.22 ) CMAKE_MINIMUM_REQUIRED( VERSION 3.22 )
# Experimental USD importer: disabled, need to opt-in
# Note: assimp github PR automatic checks will fail the PR due to compiler warnings in
# the external, 3rd party tinyusdz code which isn't technically part of the PR since it's
# auto-cloned during build; so MUST disable the feature or the PR will be rejected
option(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off)
option(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off)
option(ASSIMP_BUILD_USE_CCACHE "Use ccache to speed up compilation." on)
if(ASSIMP_BUILD_USE_CCACHE)
find_program(CCACHE_PATH ccache)
if (CCACHE_PATH)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH})
endif()
endif()
# Disabled importers: m3d for 5.1 or later # Disabled importers: m3d for 5.1 or later
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER)
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_EXPORTER) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_EXPORTER)
@ -71,7 +55,7 @@ IF(ASSIMP_HUNTER_ENABLED)
add_definitions(-DASSIMP_USE_HUNTER) add_definitions(-DASSIMP_USE_HUNTER)
ENDIF() ENDIF()
PROJECT(Assimp VERSION 5.4.3) PROJECT(Assimp VERSION 5.4.1)
# All supported options ############################################### # All supported options ###############################################
@ -163,7 +147,7 @@ IF (WIN32)
IF(MSVC) IF(MSVC)
OPTION( ASSIMP_INSTALL_PDB OPTION( ASSIMP_INSTALL_PDB
"Create MSVC debug symbol files and add to Install target." "Install MSVC debug files."
ON ) ON )
IF(NOT (MSVC_VERSION LESS 1900)) IF(NOT (MSVC_VERSION LESS 1900))
# Multibyte character set has been deprecated since at least MSVC2015 (possibly earlier) # Multibyte character set has been deprecated since at least MSVC2015 (possibly earlier)
@ -308,15 +292,8 @@ ELSEIF(MSVC)
# supress warning for double to float conversion if Double precision is activated # supress warning for double to float conversion if Double precision is activated
ADD_COMPILE_OPTIONS(/wd4244) ADD_COMPILE_OPTIONS(/wd4244)
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")
# Allow user to disable PDBs SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
if(ASSIMP_INSTALL_PDB)
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") SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
elseif((GENERATOR_IS_MULTI_CONFIG) OR (CMAKE_BUILD_TYPE MATCHES Release))
message("-- MSVC PDB generation disabled. Release binary will not be debuggable.")
endif()
# Source code is encoded in UTF-8
ADD_COMPILE_OPTIONS(/source-charset:utf-8)
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_POSITION_INDEPENDENT_CODE ON) SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
@ -659,7 +636,7 @@ ELSE()
IF ( ASSIMP_BUILD_DRACO ) IF ( ASSIMP_BUILD_DRACO )
# Primarily for glTF v2 # Primarily for glTF v2
# Enable Draco glTF feature set # Enable Draco glTF feature set
set(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE) set(DRACO_GLTF ON CACHE BOOL "" FORCE)
# Disable unnecessary or omitted components # Disable unnecessary or omitted components
set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE) set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
set(DRACO_WASM OFF CACHE BOOL "" FORCE) set(DRACO_WASM OFF CACHE BOOL "" FORCE)

View File

@ -1,6 +1,6 @@
FROM ubuntu:22.04 FROM ubuntu:22.04
RUN apt-get update && apt-get install --no-install-recommends -y ninja-build \ RUN apt-get update && apt-get install -y ninja-build \
git cmake build-essential software-properties-common git cmake build-essential software-properties-common
RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update

View File

@ -26,11 +26,12 @@ Clone [our model database](https://github.com/assimp/assimp-mdb).
### Communities ### ### Communities ###
- Ask questions at [the Assimp Discussion Board](https://github.com/assimp/assimp/discussions). - Ask questions at [the Assimp Discussion Board](https://github.com/assimp/assimp/discussions).
- Find us on [https://discord.gg/s9KJfaem](https://discord.gg/kKazXMXDy2)
- Ask [the Assimp community on Reddit](https://www.reddit.com/r/Assimp/). - Ask [the Assimp community on Reddit](https://www.reddit.com/r/Assimp/).
- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). - Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
- Nothing has worked? File a question or an issue-report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues) - Nothing has worked? File a question or an issue-report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
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>
#### Supported file formats #### #### Supported file formats ####
See [the complete list of supported formats](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md). See [the complete list of supported formats](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md).

View File

@ -22,9 +22,38 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # 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. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# This is a gate file to Hunter package manager.
# Include this file using `include` command and add package you need, example:
#
# cmake_minimum_required(VERSION 3.2)
#
# include("cmake/HunterGate.cmake")
# HunterGate(
# URL "https://github.com/path/to/hunter/archive.tar.gz"
# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d"
# )
#
# project(MyProject)
#
# hunter_add_package(Foo)
# hunter_add_package(Boo COMPONENTS Bar Baz)
#
# Projects:
# * https://github.com/hunter-packages/gate/
# * https://github.com/ruslo/hunter
option(HUNTER_ENABLED "Enable Hunter package manager support" ON) option(HUNTER_ENABLED "Enable Hunter package manager support" ON)
if(HUNTER_ENABLED)
if(CMAKE_VERSION VERSION_LESS "3.2")
message(
FATAL_ERROR
"At least CMake version 3.2 required for Hunter dependency management."
" Update CMake or set HUNTER_ENABLED to OFF."
)
endif()
endif()
include(CMakeParseArguments) # cmake_parse_arguments include(CMakeParseArguments) # cmake_parse_arguments
option(HUNTER_STATUS_PRINT "Print working status" ON) option(HUNTER_STATUS_PRINT "Print working status" ON)

View File

@ -643,17 +643,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
} }
// Allocate storage for children // Allocate storage for children
const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size()); pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
pcOut->mNumChildren = size;
if (size == 0) {
return;
}
pcOut->mChildren = new aiNode *[pcIn->mChildren.size()]; pcOut->mChildren = new aiNode *[pcIn->mChildren.size()];
// Recursively process all children // Recursively process all children
const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
for (unsigned int i = 0; i < size; ++i) { for (unsigned int i = 0; i < size; ++i) {
pcOut->mChildren[i] = new aiNode(); pcOut->mChildren[i] = new aiNode();
pcOut->mChildren[i]->mParent = pcOut; pcOut->mChildren[i]->mParent = pcOut;
@ -715,7 +709,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
pcNode->mNumMeshes = 1; pcNode->mNumMeshes = 1;
// Build a name for the node // Build a name for the node
pcNode->mName.length = ai_snprintf(pcNode->mName.data, AI_MAXLEN, "3DSMesh_%u", i); pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u", i);
} }
// Build dummy nodes for all cameras // Build dummy nodes for all cameras

View File

@ -52,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/Exporter.hpp> #include <assimp/Exporter.hpp>
#include <assimp/Exceptional.h>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <memory> #include <memory>

View File

@ -365,13 +365,14 @@ struct Texture {
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER #endif // _MSC_VER
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing a 3ds material */ /** Helper structure representing a 3ds material */
struct Material { struct Material {
//! Default constructor has been deleted //! Default constructor has been deleted
Material() : Material() :
mName(), mName(),
mDiffuse(0.6f, 0.6f, 0.6f), mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
mSpecularExponent(ai_real(0.0)), mSpecularExponent(ai_real(0.0)),
mShininessStrength(ai_real(1.0)), mShininessStrength(ai_real(1.0)),
mShading(Discreet3DS::Gouraud), mShading(Discreet3DS::Gouraud),
@ -384,7 +385,7 @@ struct Material {
//! Constructor with explicit name //! Constructor with explicit name
explicit Material(const std::string &name) : explicit Material(const std::string &name) :
mName(name), mName(name),
mDiffuse(0.6f, 0.6f, 0.6f), mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
mSpecularExponent(ai_real(0.0)), mSpecularExponent(ai_real(0.0)),
mShininessStrength(ai_real(1.0)), mShininessStrength(ai_real(1.0)),
mShading(Discreet3DS::Gouraud), mShading(Discreet3DS::Gouraud),

View File

@ -249,10 +249,10 @@ void D3MFExporter::writeBaseMaterials() {
if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) { if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) {
hexDiffuseColor = ai_rgba2hex( hexDiffuseColor = ai_rgba2hex(
(int)(((ai_real)color.r) * 255), (int)((ai_real)color.r) * 255,
(int)(((ai_real)color.g) * 255), (int)((ai_real)color.g) * 255,
(int)(((ai_real)color.b) * 255), (int)((ai_real)color.b) * 255,
(int)(((ai_real)color.a) * 255), (int)((ai_real)color.a) * 255,
true); true);
} else { } else {

View File

@ -57,8 +57,8 @@ static constexpr size_t ColRGBA_Len = 9;
static constexpr size_t ColRGB_Len = 7; static constexpr size_t ColRGB_Len = 7;
// 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)
bool validateColorString(const std::string color) { bool validateColorString(const char *color) {
const size_t len = color.size(); const size_t len = strlen(color);
if (ColRGBA_Len != len && ColRGB_Len != len) { if (ColRGBA_Len != len && ColRGB_Len != len) {
return false; return false;
} }
@ -157,8 +157,8 @@ aiMatrix4x4 parseTransformMatrix(const std::string& matrixStr) {
return transformMatrix; return transformMatrix;
} }
bool parseColor(const std::string &color, aiColor4D &diffuse) { bool parseColor(const char *color, aiColor4D &diffuse) {
if (color.empty()) { if (nullptr == color) {
return false; return false;
} }
@ -178,7 +178,7 @@ bool parseColor(const std::string &color, aiColor4D &diffuse) {
char b[3] = { color[5], color[6], '\0' }; char b[3] = { color[5], color[6], '\0' };
diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0); diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
const size_t len = color.size(); const size_t len = strlen(color);
if (ColRGB_Len == len) { if (ColRGB_Len == len) {
return true; return true;
} }

View File

@ -193,7 +193,7 @@ bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
// Generate a default name for both the light source and the node // Generate a default name for both the light source and the node
// FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version. // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version.
light->mName.length = ::ai_snprintf(light->mName.data, AI_MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1); light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
obj.name = std::string(light->mName.data); obj.name = std::string(light->mName.data);
ASSIMP_LOG_VERBOSE_DEBUG("AC3D: Light source encountered"); ASSIMP_LOG_VERBOSE_DEBUG("AC3D: Light source encountered");
@ -696,18 +696,18 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
// generate a name depending on the type of the node // generate a name depending on the type of the node
switch (object.type) { switch (object.type) {
case Object::Group: case Object::Group:
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACGroup_%i", mGroupsCounter++); node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++);
break; break;
case Object::Poly: case Object::Poly:
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACPoly_%i", mPolysCounter++); node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++);
break; break;
case Object::Light: case Object::Light:
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACLight_%i", mLightsCounter++); node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++);
break; break;
// there shouldn't be more than one world, but we don't care // there shouldn't be more than one world, but we don't care
case Object::World: case Object::World:
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACWorld_%i", mWorldsCounter++); node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++);
break; break;
} }
} }

View File

@ -178,6 +178,28 @@ bool AMFImporter::XML_SearchNode(const std::string &nodeName) {
return nullptr != mXmlParser->findNode(nodeName); return nullptr != mXmlParser->findNode(nodeName);
} }
void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString) {
size_t instr_len;
pOutString.clear();
instr_len = strlen(pInStr);
if (!instr_len) return;
pOutString.reserve(instr_len * 3 / 2);
// check and correct floats in format ".x". Must be "x.y".
if (pInStr[0] == '.') pOutString.push_back('0');
pOutString.push_back(pInStr[0]);
for (size_t ci = 1; ci < instr_len; ci++) {
if ((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t'))) {
pOutString.push_back('0');
pOutString.push_back('.');
} else {
pOutString.push_back(pInStr[ci]);
}
}
}
static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) { static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) {
return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/')); return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/'));
} }
@ -191,10 +213,7 @@ void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std
uint8_t arr4[4], arr3[3]; uint8_t arr4[4], arr3[3];
// check input data // check input data
if (pInputBase64.size() % 4) { if (pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
}
// prepare output place // prepare output place
pOutputData.clear(); pOutputData.clear();
pOutputData.reserve(pInputBase64.size() / 4 * 3); pOutputData.reserve(pInputBase64.size() / 4 * 3);
@ -384,17 +403,17 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
for (auto &currentNode : node.children()) { for (auto &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "deltax") { if (currentName == "deltax") {
XmlParser::getValueAsReal(currentNode, als.Delta.x); XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "deltay") { } else if (currentName == "deltay") {
XmlParser::getValueAsReal(currentNode, als.Delta.y); XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "deltaz") { } else if (currentName == "deltaz") {
XmlParser::getValueAsReal(currentNode, als.Delta.z); XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} else if (currentName == "rx") { } else if (currentName == "rx") {
XmlParser::getValueAsReal(currentNode, als.Delta.x); XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "ry") { } else if (currentName == "ry") {
XmlParser::getValueAsReal(currentNode, als.Delta.y); XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "rz") { } else if (currentName == "rz") {
XmlParser::getValueAsReal(currentNode, als.Delta.z); XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();

View File

@ -168,6 +168,7 @@ public:
AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX;
void XML_CheckNode_MustHaveChildren(pugi::xml_node &node); void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
bool XML_SearchNode(const std::string &nodeName); bool XML_SearchNode(const std::string &nodeName);
void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);
AMFImporter(const AMFImporter &pScene) = delete; AMFImporter(const AMFImporter &pScene) = delete;
AMFImporter &operator=(const AMFImporter &pScene) = delete; AMFImporter &operator=(const AMFImporter &pScene) = delete;

View File

@ -167,11 +167,11 @@ void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
const std::string &currentName = ai_tolower(currentNode.name()); const std::string &currentName = ai_tolower(currentNode.name());
if (currentName == "x") { if (currentName == "x") {
XmlParser::getValueAsReal(currentNode, als.Coordinate.x); XmlParser::getValueAsFloat(currentNode, als.Coordinate.x);
} else if (currentName == "y") { } else if (currentName == "y") {
XmlParser::getValueAsReal(currentNode, als.Coordinate.y); XmlParser::getValueAsFloat(currentNode, als.Coordinate.y);
} else if (currentName == "z") { } else if (currentName == "z") {
XmlParser::getValueAsReal(currentNode, als.Coordinate.z); XmlParser::getValueAsFloat(currentNode, als.Coordinate.z);
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();

View File

@ -263,25 +263,26 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
const std::string &name = currentNode.name(); const std::string &name = currentNode.name();
if (name == "utex1") { if (name == "utex1") {
read_flag[0] = true; read_flag[0] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[0].x); XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].x);
} else if (name == "utex2") { } else if (name == "utex2") {
read_flag[1] = true; read_flag[1] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[1].x); XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].x);
} else if (name == "utex3") { } else if (name == "utex3") {
read_flag[2] = true; read_flag[2] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[2].x); XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].x);
} else if (name == "vtex1") { } else if (name == "vtex1") {
read_flag[3] = true; read_flag[3] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[0].y); XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].y);
} else if (name == "vtex2") { } else if (name == "vtex2") {
read_flag[4] = true; read_flag[4] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[1].y); XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].y);
} else if (name == "vtex3") { } else if (name == "vtex3") {
read_flag[5] = true; read_flag[5] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[2].y); XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].y);
} }
} }
ParseHelper_Node_Exit(); 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

@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <vector> #include <vector>
/// \class CAMFImporter_NodeElement
/// Base class for elements of nodes. /// Base class for elements of nodes.
class AMFNodeElementBase { class AMFNodeElementBase {
public: public:
@ -105,6 +106,7 @@ protected:
} }
}; // class IAMFImporter_NodeElement }; // class IAMFImporter_NodeElement
/// \struct CAMFImporter_NodeElement_Constellation
/// A collection of objects or constellations with specific relative locations. /// A collection of objects or constellations with specific relative locations.
struct AMFConstellation : public AMFNodeElementBase { struct AMFConstellation : public AMFNodeElementBase {
/// Constructor. /// Constructor.
@ -114,6 +116,7 @@ struct AMFConstellation : public AMFNodeElementBase {
}; // struct CAMFImporter_NodeElement_Constellation }; // struct CAMFImporter_NodeElement_Constellation
/// \struct CAMFImporter_NodeElement_Instance
/// Part of constellation. /// Part of constellation.
struct AMFInstance : public AMFNodeElementBase { struct AMFInstance : public AMFNodeElementBase {
@ -132,6 +135,7 @@ struct AMFInstance : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Instance, pParent) {} AMFNodeElementBase(ENET_Instance, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Metadata
/// Structure that define metadata node. /// Structure that define metadata node.
struct AMFMetadata : public AMFNodeElementBase { struct AMFMetadata : public AMFNodeElementBase {
@ -144,6 +148,7 @@ struct AMFMetadata : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Metadata, pParent) {} AMFNodeElementBase(ENET_Metadata, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Root
/// Structure that define root node. /// Structure that define root node.
struct AMFRoot : public AMFNodeElementBase { struct AMFRoot : public AMFNodeElementBase {
@ -156,6 +161,7 @@ struct AMFRoot : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Root, pParent) {} AMFNodeElementBase(ENET_Root, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Color
/// Structure that define object node. /// Structure that define object node.
struct AMFColor : public AMFNodeElementBase { struct AMFColor : public AMFNodeElementBase {
bool Composed; ///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color. bool Composed; ///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color.
@ -171,6 +177,7 @@ struct AMFColor : public AMFNodeElementBase {
} }
}; };
/// \struct CAMFImporter_NodeElement_Material
/// Structure that define material node. /// Structure that define material node.
struct AMFMaterial : public AMFNodeElementBase { struct AMFMaterial : public AMFNodeElementBase {
@ -180,6 +187,7 @@ struct AMFMaterial : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Material, pParent) {} AMFNodeElementBase(ENET_Material, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Object
/// Structure that define object node. /// Structure that define object node.
struct AMFObject : public AMFNodeElementBase { struct AMFObject : public AMFNodeElementBase {
@ -198,6 +206,7 @@ struct AMFMesh : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Mesh, pParent) {} AMFNodeElementBase(ENET_Mesh, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Vertex
/// Structure that define vertex node. /// Structure that define vertex node.
struct AMFVertex : public AMFNodeElementBase { struct AMFVertex : public AMFNodeElementBase {
/// Constructor. /// Constructor.
@ -206,6 +215,7 @@ struct AMFVertex : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Vertex, pParent) {} AMFNodeElementBase(ENET_Vertex, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Edge
/// Structure that define edge node. /// Structure that define edge node.
struct AMFEdge : public AMFNodeElementBase { struct AMFEdge : public AMFNodeElementBase {
/// Constructor. /// Constructor.
@ -214,6 +224,7 @@ struct AMFEdge : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Edge, pParent) {} AMFNodeElementBase(ENET_Edge, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Vertices
/// Structure that define vertices node. /// Structure that define vertices node.
struct AMFVertices : public AMFNodeElementBase { struct AMFVertices : public AMFNodeElementBase {
/// Constructor. /// Constructor.
@ -222,6 +233,7 @@ struct AMFVertices : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Vertices, pParent) {} AMFNodeElementBase(ENET_Vertices, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Volume
/// Structure that define volume node. /// Structure that define volume node.
struct AMFVolume : public AMFNodeElementBase { struct AMFVolume : public AMFNodeElementBase {
std::string MaterialID; ///< Which material to use. std::string MaterialID; ///< Which material to use.
@ -233,6 +245,7 @@ struct AMFVolume : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Volume, pParent) {} AMFNodeElementBase(ENET_Volume, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Coordinates
/// Structure that define coordinates node. /// Structure that define coordinates node.
struct AMFCoordinates : public AMFNodeElementBase { struct AMFCoordinates : public AMFNodeElementBase {
aiVector3D Coordinate; ///< Coordinate. aiVector3D Coordinate; ///< Coordinate.
@ -243,6 +256,7 @@ struct AMFCoordinates : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Coordinates, pParent) {} AMFNodeElementBase(ENET_Coordinates, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_TexMap
/// Structure that define texture coordinates node. /// Structure that define texture coordinates node.
struct AMFTexMap : public AMFNodeElementBase { struct AMFTexMap : public AMFNodeElementBase {
aiVector3D TextureCoordinate[3]; ///< Texture coordinates. aiVector3D TextureCoordinate[3]; ///< Texture coordinates.
@ -259,6 +273,7 @@ struct AMFTexMap : public AMFNodeElementBase {
} }
}; };
/// \struct CAMFImporter_NodeElement_Triangle
/// Structure that define triangle node. /// Structure that define triangle node.
struct AMFTriangle : public AMFNodeElementBase { struct AMFTriangle : public AMFNodeElementBase {
size_t V[3]; ///< Triangle vertices. size_t V[3]; ///< Triangle vertices.

View File

@ -224,8 +224,7 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string &
} }
// Create format hint. // Create format hint.
constexpr char templateColor[] = "rgba0000"; strcpy(converted_texture.FormatHint, "rgba0000"); // copy initial string.
memcpy(converted_texture.FormatHint, templateColor, 8);
if (!r.empty()) converted_texture.FormatHint[4] = '8'; if (!r.empty()) converted_texture.FormatHint[4] = '8';
if (!g.empty()) converted_texture.FormatHint[5] = '8'; if (!g.empty()) converted_texture.FormatHint[5] = '8';
if (!b.empty()) converted_texture.FormatHint[6] = '8'; if (!b.empty()) converted_texture.FormatHint[6] = '8';
@ -868,7 +867,7 @@ nl_clean_loop:
pScene->mTextures[idx]->mHeight = static_cast<unsigned int>(tex_convd.Height); pScene->mTextures[idx]->mHeight = static_cast<unsigned int>(tex_convd.Height);
pScene->mTextures[idx]->pcData = (aiTexel *)tex_convd.Data; pScene->mTextures[idx]->pcData = (aiTexel *)tex_convd.Data;
// texture format description. // texture format description.
strncpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint, HINTMAXTEXTURELEN); strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint);
idx++; idx++;
} // for(const SPP_Texture& tex_convd: mTexture_Converted) } // for(const SPP_Texture& tex_convd: mTexture_Converted)

View File

@ -124,7 +124,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
// Allocate storage and copy the contents of the file to a memory buffer // Allocate storage and copy the contents of the file to a memory buffer
std::vector<char> mBuffer2; std::vector<char> mBuffer2;
TextFileToBuffer(file.get(), mBuffer2); TextFileToBuffer(file.get(), mBuffer2);
const size_t fileSize = mBuffer2.size();
this->mBuffer = &mBuffer2[0]; this->mBuffer = &mBuffer2[0];
this->pcScene = pScene; this->pcScene = pScene;
@ -146,7 +146,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
}; };
// Construct an ASE parser and parse the file // Construct an ASE parser and parse the file
ASE::Parser parser(mBuffer, fileSize, defaultFormat); ASE::Parser parser(mBuffer, defaultFormat);
mParser = &parser; mParser = &parser;
mParser->Parse(); mParser->Parse();
@ -446,9 +446,10 @@ void ASEImporter::BuildLights() {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name) { void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
aiNode *pcParent, const char *szName) {
aiMatrix4x4 m; aiMatrix4x4 m;
AddNodes(nodes, pcParent, name, m); AddNodes(nodes, pcParent, szName, m);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -505,9 +506,10 @@ void ASEImporter::AddMeshes(const ASE::BaseNode *snode, aiNode *node) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Add child nodes to a given parent node // Add child nodes to a given parent node
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name, void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
aiNode *pcParent, const char *szName,
const aiMatrix4x4 &mat) { const aiMatrix4x4 &mat) {
const size_t len = name.size(); const size_t len = szName ? ::strlen(szName) : 0;
ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS); ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
// Receives child nodes for the pcParent node // Receives child nodes for the pcParent node
@ -517,18 +519,16 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParen
// which has *us* as parent. // which has *us* as parent.
for (std::vector<BaseNode *>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) { for (std::vector<BaseNode *>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) {
const BaseNode *snode = *it; const BaseNode *snode = *it;
if (!name.empty()) { if (szName) {
if (len != snode->mParent.length() || name != snode->mParent.c_str()) { if (len != snode->mParent.length() || ::strcmp(szName, snode->mParent.c_str()))
continue; continue;
} } else if (snode->mParent.length())
} else if (snode->mParent.length()) {
continue; continue;
}
(*it)->mProcessed = true; (*it)->mProcessed = true;
// Allocate a new node and add it to the output data structure // Allocate a new node and add it to the output data structure
apcNodes.push_back(new aiNode); apcNodes.push_back(new aiNode());
aiNode *node = apcNodes.back(); aiNode *node = apcNodes.back();
node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node")); node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
@ -541,7 +541,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParen
// Add sub nodes - prevent stack overflow due to recursive parenting // Add sub nodes - prevent stack overflow due to recursive parenting
if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName) { if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName) {
AddNodes(nodes, node, node->mName.C_Str(), snode->mTransform); AddNodes(nodes, node, node->mName.data, snode->mTransform);
} }
// Further processing depends on the type of the node // Further processing depends on the type of the node
@ -619,8 +619,7 @@ void ASEImporter::BuildNodes(std::vector<BaseNode *> &nodes) {
} }
// add all nodes // add all nodes
static const std::string none = ""; AddNodes(nodes, ch, nullptr);
AddNodes(nodes, ch, none);
// now iterate through al nodes and find those that have not yet // now iterate through al nodes and find those that have not yet
// been added to the nodegraph (= their parent could not be recognized) // been added to the nodegraph (= their parent could not be recognized)

View File

@ -153,10 +153,10 @@ private:
* \param matrix Current transform * \param matrix Current transform
*/ */
void AddNodes(const std::vector<ASE::BaseNode*>& nodes, void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent, const std::string &name); aiNode* pcParent,const char* szName);
void AddNodes(const std::vector<ASE::BaseNode*>& nodes, void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent, const std::string &name, aiNode* pcParent,const char* szName,
const aiMatrix4x4& matrix); const aiMatrix4x4& matrix);
void AddMeshes(const ASE::BaseNode* snode,aiNode* node); void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
@ -188,4 +188,5 @@ protected:
} // end of namespace Assimp } // end of namespace Assimp
#endif // AI_3DSIMPORTER_H_INC #endif // AI_3DSIMPORTER_H_INC

File diff suppressed because it is too large Load Diff

View File

@ -391,11 +391,11 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Construct a parser from a given input file which is //! Construct a parser from a given input file which is
//! guaranteed to be terminated with zero. //! guaranteed to be terminated with zero.
//! @param file The name of the input file. //! @param szFile Input file
//! @param fileFormatDefault Assumed file format version. If the //! @param fileFormatDefault Assumed file format version. If the
//! file format is specified in the file the new value replaces //! file format is specified in the file the new value replaces
//! the default value. //! the default value.
Parser(const char *file, size_t fileLen, unsigned int fileFormatDefault); Parser(const char *szFile, unsigned int fileFormatDefault);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parses the file into the parsers internal representation //! Parses the file into the parsers internal representation
@ -553,15 +553,13 @@ private:
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats) //! \param apOut Output buffer (3 floats)
//! \param rIndexOut Output index //! \param rIndexOut Output index
void ParseLV4MeshRealTriple(ai_real *apOut, unsigned int &rIndexOut); void ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut);
void ParseLV4MeshFloatTriple(float *apOut, unsigned int &rIndexOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_VERT block in a file //! Parse a *MESH_VERT block in a file
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats) //! \param apOut Output buffer (3 floats)
void ParseLV4MeshRealTriple(ai_real *apOut); void ParseLV4MeshFloatTriple(ai_real *apOut);
void ParseLV4MeshFloatTriple(float *apOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_TFACE block in a file //! Parse a *MESH_TFACE block in a file
@ -579,8 +577,7 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a single float element //! Parse a single float element
//! \param fOut Output float //! \param fOut Output float
void ParseLV4MeshReal(ai_real &fOut); void ParseLV4MeshFloat(ai_real &fOut);
void ParseLV4MeshFloat(float &fOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a single int element //! Parse a single int element
@ -620,8 +617,11 @@ private:
bool ParseString(std::string &out, const char *szName); bool ParseString(std::string &out, const char *szName);
public: public:
const char *mFilePtr; ////< Pointer to current data //! Pointer to current data
const char *mEnd; ///< The end pointer of the file data const char *filePtr;
/// The end pointer of the file data
const char *mEnd;
//! background color to be passed to the viewer //! background color to be passed to the viewer
//! QNAN if none was found //! QNAN if none was found

View File

@ -359,7 +359,7 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
// check if the file contents are bundled with the BLEND file // check if the file contents are bundled with the BLEND file
if (img->packedfile) { if (img->packedfile) {
name.data[0] = '*'; name.data[0] = '*';
name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(AI_MAXLEN - 1), static_cast<int32_t>(conv_data.textures->size())); name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(conv_data.textures->size()));
conv_data.textures->push_back(new aiTexture()); conv_data.textures->push_back(new aiTexture());
aiTexture *curTex = conv_data.textures->back(); aiTexture *curTex = conv_data.textures->back();
@ -433,7 +433,7 @@ void BlenderImporter::AddSentinelTexture(aiMaterial *out, const Material *mat, c
(void)conv_data; (void)conv_data;
aiString name; aiString name;
name.length = ai_snprintf(name.data, AI_MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++, name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++,
GetTextureTypeDisplayString(tex->tex->type)); GetTextureTypeDisplayString(tex->tex->type));
out->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE( out->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(
conv_data.next_texture[aiTextureType_DIFFUSE]++)); conv_data.next_texture[aiTextureType_DIFFUSE]++));

View File

@ -372,12 +372,10 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
} }
// add children recursively // add children recursively
if (!root.temp_children.empty()) {
nd->mChildren = new aiNode *[root.temp_children.size()](); nd->mChildren = new aiNode *[root.temp_children.size()]();
for (const Node *n : root.temp_children) { for (const Node *n : root.temp_children) {
(nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd; (nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd;
} }
}
return nd; return nd;
} }

View File

@ -625,14 +625,16 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
} }
// same for texture coords, as many as we have // same for texture coords, as many as we have
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { // empty slots are not allowed, need to pack and adjust UV indexes accordingly
for (size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) { if (pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) {
dstMesh->mTextureCoords[a] = new aiVector3D[numVertices]; dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
for (size_t b = 0; b < numVertices; ++b) { for (size_t b = 0; b < numVertices; ++b) {
dstMesh->mTextureCoords[a][b] = pSrcMesh->mTexCoords[a][pStartVertex + b]; dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex + b];
} }
dstMesh->mNumUVComponents[a] = pSrcMesh->mNumUVComponents[a]; dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
++real;
} }
} }

View File

@ -968,34 +968,34 @@ void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b); content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b);
SkipSpacesAndLineEnd(&content, end); SkipSpacesAndLineEnd(&content, end);
} else if (currentName == "constant_attenuation") { } else if (currentName == "constant_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttConstant); XmlParser::getValueAsFloat(currentNode, pLight.mAttConstant);
} else if (currentName == "linear_attenuation") { } else if (currentName == "linear_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttLinear); XmlParser::getValueAsFloat(currentNode, pLight.mAttLinear);
} else if (currentName == "quadratic_attenuation") { } else if (currentName == "quadratic_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttQuadratic); XmlParser::getValueAsFloat(currentNode, pLight.mAttQuadratic);
} else if (currentName == "falloff_angle") { } else if (currentName == "falloff_angle") {
XmlParser::getValueAsReal(currentNode, pLight.mFalloffAngle); XmlParser::getValueAsFloat(currentNode, pLight.mFalloffAngle);
} else if (currentName == "falloff_exponent") { } else if (currentName == "falloff_exponent") {
XmlParser::getValueAsReal(currentNode, pLight.mFalloffExponent); XmlParser::getValueAsFloat(currentNode, pLight.mFalloffExponent);
} }
// FCOLLADA extensions // FCOLLADA extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "outer_cone") { else if (currentName == "outer_cone") {
XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle); XmlParser::getValueAsFloat(currentNode, pLight.mOuterAngle);
} else if (currentName == "penumbra_angle") { // this one is deprecated, now calculated using outer_cone } else if (currentName == "penumbra_angle") { // this one is deprecated, now calculated using outer_cone
XmlParser::getValueAsReal(currentNode, pLight.mPenumbraAngle); XmlParser::getValueAsFloat(currentNode, pLight.mPenumbraAngle);
} else if (currentName == "intensity") { } else if (currentName == "intensity") {
XmlParser::getValueAsReal(currentNode, pLight.mIntensity); XmlParser::getValueAsFloat(currentNode, pLight.mIntensity);
} }
else if (currentName == "falloff") { else if (currentName == "falloff") {
XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle); XmlParser::getValueAsFloat(currentNode, pLight.mOuterAngle);
} else if (currentName == "hotspot_beam") { } else if (currentName == "hotspot_beam") {
XmlParser::getValueAsReal(currentNode, pLight.mFalloffAngle); XmlParser::getValueAsFloat(currentNode, pLight.mFalloffAngle);
} }
// OpenCOLLADA extensions // OpenCOLLADA extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "decay_falloff") { else if (currentName == "decay_falloff") {
XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle); XmlParser::getValueAsFloat(currentNode, pLight.mOuterAngle);
} }
} }
} }
@ -1010,15 +1010,15 @@ void ColladaParser::ReadCamera(XmlNode &node, Collada::Camera &camera) {
if (currentName == "orthographic") { if (currentName == "orthographic") {
camera.mOrtho = true; camera.mOrtho = true;
} else if (currentName == "xfov" || currentName == "xmag") { } else if (currentName == "xfov" || currentName == "xmag") {
XmlParser::getValueAsReal(currentNode, camera.mHorFov); XmlParser::getValueAsFloat(currentNode, camera.mHorFov);
} else if (currentName == "yfov" || currentName == "ymag") { } else if (currentName == "yfov" || currentName == "ymag") {
XmlParser::getValueAsReal(currentNode, camera.mVerFov); XmlParser::getValueAsFloat(currentNode, camera.mVerFov);
} else if (currentName == "aspect_ratio") { } else if (currentName == "aspect_ratio") {
XmlParser::getValueAsReal(currentNode, camera.mAspect); XmlParser::getValueAsFloat(currentNode, camera.mAspect);
} else if (currentName == "znear") { } else if (currentName == "znear") {
XmlParser::getValueAsReal(currentNode, camera.mZNear); XmlParser::getValueAsFloat(currentNode, camera.mZNear);
} else if (currentName == "zfar") { } else if (currentName == "zfar") {
XmlParser::getValueAsReal(currentNode, camera.mZFar); XmlParser::getValueAsFloat(currentNode, camera.mZFar);
} }
} }
} }
@ -1170,15 +1170,15 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
} else if (currentName == "mirrorV") { } else if (currentName == "mirrorV") {
XmlParser::getValueAsBool(currentNode, out.mMirrorV); XmlParser::getValueAsBool(currentNode, out.mMirrorV);
} else if (currentName == "repeatU") { } else if (currentName == "repeatU") {
XmlParser::getValueAsReal(currentNode, out.mTransform.mScaling.x); XmlParser::getValueAsFloat(currentNode, out.mTransform.mScaling.x);
} else if (currentName == "repeatV") { } else if (currentName == "repeatV") {
XmlParser::getValueAsReal(currentNode, out.mTransform.mScaling.y); XmlParser::getValueAsFloat(currentNode, out.mTransform.mScaling.y);
} else if (currentName == "offsetU") { } else if (currentName == "offsetU") {
XmlParser::getValueAsReal(currentNode, out.mTransform.mTranslation.x); XmlParser::getValueAsFloat(currentNode, out.mTransform.mTranslation.x);
} else if (currentName == "offsetV") { } else if (currentName == "offsetV") {
XmlParser::getValueAsReal(currentNode, out.mTransform.mTranslation.y); XmlParser::getValueAsFloat(currentNode, out.mTransform.mTranslation.y);
} else if (currentName == "rotateUV") { } else if (currentName == "rotateUV") {
XmlParser::getValueAsReal(currentNode, out.mTransform.mRotation); XmlParser::getValueAsFloat(currentNode, out.mTransform.mRotation);
} else if (currentName == "blend_mode") { } else if (currentName == "blend_mode") {
std::string v; std::string v;
XmlParser::getValueAsString(currentNode, v); XmlParser::getValueAsString(currentNode, v);
@ -1198,14 +1198,14 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
// OKINO extensions // OKINO extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "weighting") { else if (currentName == "weighting") {
XmlParser::getValueAsReal(currentNode, out.mWeighting); XmlParser::getValueAsFloat(currentNode, out.mWeighting);
} else if (currentName == "mix_with_previous_layer") { } else if (currentName == "mix_with_previous_layer") {
XmlParser::getValueAsReal(currentNode, out.mMixWithPrevious); XmlParser::getValueAsFloat(currentNode, out.mMixWithPrevious);
} }
// MAX3D extensions // MAX3D extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "amount") { else if (currentName == "amount") {
XmlParser::getValueAsReal(currentNode, out.mWeighting); XmlParser::getValueAsFloat(currentNode, out.mWeighting);
} }
} }
} }
@ -1265,13 +1265,13 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads an effect entry containing a float // Reads an effect entry containing a float
void ColladaParser::ReadEffectFloat(XmlNode &node, ai_real &pReal) { void ColladaParser::ReadEffectFloat(XmlNode &node, ai_real &pFloat) {
pReal = 0.f; pFloat = 0.f;
XmlNode floatNode = node.child("float"); XmlNode floatNode = node.child("float");
if (floatNode.empty()) { if (floatNode.empty()) {
return; return;
} }
XmlParser::getValueAsReal(floatNode, pReal); XmlParser::getValueAsFloat(floatNode, pFloat);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -2293,9 +2293,9 @@ void ColladaParser::ReadNodeGeometry(XmlNode &node, Node *pNode) {
urlMat++; urlMat++;
s.mMatName = urlMat; s.mMatName = urlMat;
ReadMaterialVertexInputBinding(instanceMatNode, s);
// store the association // store the association
instance.mMaterials[group] = s; instance.mMaterials[group] = s;
ReadMaterialVertexInputBinding(instanceMatNode, s);
} }
} }
} }

View File

@ -181,8 +181,6 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
if (out->mNumMeshes == 0) { if (out->mNumMeshes == 0) {
out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
} else { } else {
// Apply the FBX axis metadata unless requested not to
if (!doc.Settings().ignoreUpDirection)
correctRootTransform(mSceneOut); correctRootTransform(mSceneOut);
} }
} }
@ -312,8 +310,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
child->mParent = last_parent; child->mParent = last_parent;
last_parent = child.mNode; last_parent = child.mNode;
new_abs_transform *= child->mTransformation;
} }
// attach geometry // attach geometry
@ -336,8 +332,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
postnode->mParent = last_parent; postnode->mParent = last_parent;
last_parent = postnode.mNode; last_parent = postnode.mNode;
new_abs_transform *= postnode->mTransformation;
} }
} else { } else {
// free the nodes we allocated as we don't need them // free the nodes we allocated as we don't need them
@ -363,14 +357,14 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
if (nodes.empty()) { if (nodes.empty()) {
parent->mNumChildren = 0; parent->mNumChildren = 0;
parent->mChildren = nullptr; parent->mChildren = nullptr;
} else { }
parent->mChildren = new aiNode *[nodes.size()](); parent->mChildren = new aiNode *[nodes.size()]();
parent->mNumChildren = static_cast<unsigned int>(nodes.size()); parent->mNumChildren = static_cast<unsigned int>(nodes.size());
for (unsigned int i = 0; i < nodes.size(); ++i) { for (unsigned int i = 0; i < nodes.size(); ++i) {
parent->mChildren[i] = nodes[i].mOwnership.release(); parent->mChildren[i] = nodes[i].mOwnership.release();
} }
} }
}
void FBXConverter::ConvertLights(const Model &model, const std::string &orig_name) { void FBXConverter::ConvertLights(const Model &model, const std::string &orig_name) {
const std::vector<const NodeAttribute *> &node_attrs = model.GetAttributes(); const std::vector<const NodeAttribute *> &node_attrs = model.GetAttributes();
@ -1866,7 +1860,7 @@ aiString FBXConverter::GetTexturePath(const Texture *tex) {
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
// This may occur on this case too, it has to be studied // This may occur on this case too, it has to be studied
path.data[0] = '*'; path.data[0] = '*';
path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index); path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
} }
} }
} }
@ -2134,10 +2128,6 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_
TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor", aiTextureType_EMISSION_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor", aiTextureType_EMISSION_COLOR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|metalness", aiTextureType_METALNESS, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|metalness", aiTextureType_METALNESS, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness", aiTextureType_DIFFUSE_ROUGHNESS, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|base", aiTextureType_MAYA_BASE, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|specular", aiTextureType_MAYA_SPECULAR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|specularColor", aiTextureType_MAYA_SPECULAR_COLOR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|specularRoughness", aiTextureType_MAYA_SPECULAR_ROUGHNESS, mesh);
// Maya stingray // Maya stingray
TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map", aiTextureType_BASE_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map", aiTextureType_BASE_COLOR, mesh);
@ -2450,7 +2440,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
path.data[0] = '*'; path.data[0] = '*';
path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index); path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
} }
out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0); out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0);
@ -2816,7 +2806,7 @@ void FBXConverter::ProcessMorphAnimDatas(std::map<std::string, morphAnimData *>
auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo); auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo);
auto geoIndex = static_cast<unsigned int>(std::distance(model->GetGeometry().begin(), geoIt)); auto geoIndex = static_cast<unsigned int>(std::distance(model->GetGeometry().begin(), geoIt));
auto name = aiString(FixNodeName(model->Name() + "*")); auto name = aiString(FixNodeName(model->Name() + "*"));
name.length = 1 + ASSIMP_itoa10(name.data + name.length, AI_MAXLEN - 1, geoIndex); name.length = 1 + ASSIMP_itoa10(name.data + name.length, MAXLEN - 1, geoIndex);
morphAnimData *animData; morphAnimData *animData;
auto animIt = morphAnimDatas->find(name.C_Str()); auto animIt = morphAnimDatas->find(name.C_Str());
if (animIt == morphAnimDatas->end()) { if (animIt == morphAnimDatas->end()) {

View File

@ -1051,7 +1051,7 @@ aiNode* get_node_for_mesh(unsigned int meshIndex, aiNode* node)
aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene)
{ {
std::vector<const aiNode*> node_chain; std::vector<const aiNode*> node_chain;
while (node != scene->mRootNode && node != nullptr) { while (node != scene->mRootNode) {
node_chain.push_back(node); node_chain.push_back(node);
node = node->mParent; node = node->mParent;
} }
@ -1217,8 +1217,10 @@ void FBXExporter::WriteObjects ()
} }
// colors, if any // colors, if any
for (size_t ci = 0; ci < m->GetNumColorChannels(); ++ci) { // TODO only one color channel currently
FBX::Node vertexcolors("LayerElementColor", int32_t(ci)); const int32_t colorChannelIndex = 0;
if (m->HasVertexColors(colorChannelIndex)) {
FBX::Node vertexcolors("LayerElementColor", int32_t(colorChannelIndex));
vertexcolors.Begin(outstream, binary, indent); vertexcolors.Begin(outstream, binary, indent);
vertexcolors.DumpProperties(outstream, binary, indent); vertexcolors.DumpProperties(outstream, binary, indent);
vertexcolors.EndProperties(outstream, binary, indent); vertexcolors.EndProperties(outstream, binary, indent);
@ -1228,7 +1230,7 @@ void FBXExporter::WriteObjects ()
"Version", int32_t(101), outstream, binary, indent "Version", int32_t(101), outstream, binary, indent
); );
char layerName[8]; char layerName[8];
snprintf(layerName, sizeof(layerName), "COLOR_%d", int32_t(ci)); snprintf(layerName, sizeof(layerName), "COLOR_%d", colorChannelIndex);
FBX::Node::WritePropertyNode( FBX::Node::WritePropertyNode(
"Name", (const char*)layerName, outstream, binary, indent "Name", (const char*)layerName, outstream, binary, indent
); );
@ -1245,7 +1247,7 @@ void FBXExporter::WriteObjects ()
for (size_t fi = 0; fi < m->mNumFaces; ++fi) { for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
const aiFace &f = m->mFaces[fi]; const aiFace &f = m->mFaces[fi];
for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
const aiColor4D &c = m->mColors[ci][f.mIndices[pvi]]; const aiColor4D &c = m->mColors[colorChannelIndex][f.mIndices[pvi]];
color_data.push_back(c.r); color_data.push_back(c.r);
color_data.push_back(c.g); color_data.push_back(c.g);
color_data.push_back(c.b); color_data.push_back(c.b);
@ -1352,14 +1354,11 @@ void FBXExporter::WriteObjects ()
le.AddChild("Type", "LayerElementNormal"); le.AddChild("Type", "LayerElementNormal");
le.AddChild("TypedIndex", int32_t(0)); le.AddChild("TypedIndex", int32_t(0));
layer.AddChild(le); layer.AddChild(le);
// TODO only 1 color channel currently
for (size_t ci = 0; ci < m->GetNumColorChannels(); ++ci) {
le = FBX::Node("LayerElement"); le = FBX::Node("LayerElement");
le.AddChild("Type", "LayerElementColor"); le.AddChild("Type", "LayerElementColor");
le.AddChild("TypedIndex", int32_t(ci)); le.AddChild("TypedIndex", int32_t(0));
layer.AddChild(le); layer.AddChild(le);
}
le = FBX::Node("LayerElement"); le = FBX::Node("LayerElement");
le.AddChild("Type", "LayerElementMaterial"); le.AddChild("Type", "LayerElementMaterial");
le.AddChild("TypedIndex", int32_t(0)); le.AddChild("TypedIndex", int32_t(0));
@ -1869,26 +1868,33 @@ void FBXExporter::WriteObjects ()
// one sticky point is that the number of vertices may not match, // one sticky point is that the number of vertices may not match,
// because assimp splits vertices by normal, uv, etc. // because assimp splits vertices by normal, uv, etc.
// functor for aiNode sorting
struct SortNodeByName
{
bool operator()(const aiNode *lhs, const aiNode *rhs) const
{
return strcmp(lhs->mName.C_Str(), rhs->mName.C_Str()) < 0;
}
};
// first we should mark the skeleton for each mesh. // first we should mark the skeleton for each mesh.
// the skeleton must include not only the aiBones, // the skeleton must include not only the aiBones,
// but also all their parent nodes. // but also all their parent nodes.
// anything that affects the position of any bone node must be included. // anything that affects the position of any bone node must be included.
// Use SorNodeByName to make sure the exported result will be the same across all systems
// note that we want to preserve input order as much as possible here. // Otherwise the aiNodes of the skeleton would be sorted based on the pointer address, which isn't consistent
// previously, sorting by name lead to consistent output across systems, but was not std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes);
// suitable for downstream consumption by some applications.
std::vector<std::vector<const aiNode*>> skeleton_by_mesh(mScene->mNumMeshes);
// at the same time we can build a list of all the skeleton nodes, // at the same time we can build a list of all the skeleton nodes,
// which will be used later to mark them as type "limbNode". // which will be used later to mark them as type "limbNode".
std::unordered_set<const aiNode*> limbnodes; std::unordered_set<const aiNode*> limbnodes;
//actual bone nodes in fbx, without parenting-up //actual bone nodes in fbx, without parenting-up
std::vector<std::string> allBoneNames; std::unordered_set<std::string> setAllBoneNamesInScene;
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m) { for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m)
{
aiMesh* pMesh = mScene->mMeshes[m]; aiMesh* pMesh = mScene->mMeshes[m];
for(unsigned int b = 0; b < pMesh->mNumBones; ++ b) for(unsigned int b = 0; b < pMesh->mNumBones; ++ b)
allBoneNames.push_back(pMesh->mBones[b]->mName.data); setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data);
} }
aiMatrix4x4 mxTransIdentity; aiMatrix4x4 mxTransIdentity;
@ -1896,7 +1902,7 @@ void FBXExporter::WriteObjects ()
std::map<std::string,aiNode*> node_by_bone; std::map<std::string,aiNode*> node_by_bone;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
const aiMesh* m = mScene->mMeshes[mi]; const aiMesh* m = mScene->mMeshes[mi];
std::vector<const aiNode*> skeleton; std::set<const aiNode*, SortNodeByName> skeleton;
for (size_t bi =0; bi < m->mNumBones; ++bi) { for (size_t bi =0; bi < m->mNumBones; ++bi) {
const aiBone* b = m->mBones[bi]; const aiBone* b = m->mBones[bi];
const std::string name(b->mName.C_Str()); const std::string name(b->mName.C_Str());
@ -1915,7 +1921,7 @@ void FBXExporter::WriteObjects ()
node_by_bone[name] = n; node_by_bone[name] = n;
limbnodes.insert(n); limbnodes.insert(n);
} }
skeleton.push_back(n); skeleton.insert(n);
// mark all parent nodes as skeleton as well, // mark all parent nodes as skeleton as well,
// up until we find the root node, // up until we find the root node,
// or else the node containing the mesh, // or else the node containing the mesh,
@ -1926,7 +1932,7 @@ void FBXExporter::WriteObjects ()
parent = parent->mParent parent = parent->mParent
) { ) {
// if we've already done this node we can skip it all // if we've already done this node we can skip it all
if (std::find(skeleton.begin(), skeleton.end(), parent) != skeleton.end()) { if (skeleton.count(parent)) {
break; break;
} }
// ignore fbx transform nodes as these will be collapsed later // ignore fbx transform nodes as these will be collapsed later
@ -1936,7 +1942,7 @@ void FBXExporter::WriteObjects ()
continue; continue;
} }
//not a bone in scene && no effect in transform //not a bone in scene && no effect in transform
if (std::find(allBoneNames.begin(), allBoneNames.end(), node_name) == allBoneNames.end() if(setAllBoneNamesInScene.find(node_name)==setAllBoneNamesInScene.end()
&& parent->mTransformation == mxTransIdentity) { && parent->mTransformation == mxTransIdentity) {
continue; continue;
} }
@ -2021,7 +2027,7 @@ void FBXExporter::WriteObjects ()
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene); aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
// now make a subdeformer for each bone in the skeleton // now make a subdeformer for each bone in the skeleton
const auto & skeleton= skeleton_by_mesh[mi]; const std::set<const aiNode*, SortNodeByName> skeleton= skeleton_by_mesh[mi];
for (const aiNode* bone_node : skeleton) { for (const aiNode* bone_node : skeleton) {
// if there's a bone for this node, find it // if there's a bone for this node, find it
const aiBone* b = nullptr; const aiBone* b = nullptr;
@ -2487,57 +2493,6 @@ const std::map<std::string,std::pair<std::string,char>> transform_types = {
{"GeometricScalingInverse", {"GeometricScalingInverse", 'i'}} {"GeometricScalingInverse", {"GeometricScalingInverse", 'i'}}
}; };
//add metadata to fbx property
void add_meta(FBX::Node& fbx_node, const aiNode* node){
if(node->mMetaData == nullptr) return;
aiMetadata* meta = node->mMetaData;
for (unsigned int i = 0; i < meta->mNumProperties; ++i) {
aiString key = meta->mKeys[i];
aiMetadataEntry* entry = &meta->mValues[i];
switch (entry->mType) {
case AI_BOOL:{
bool val = *static_cast<bool *>(entry->mData);
fbx_node.AddP70bool(key.C_Str(), val);
break;
}
case AI_INT32:{
int32_t val = *static_cast<int32_t *>(entry->mData);
fbx_node.AddP70int(key.C_Str(), val);
break;
}
case AI_UINT64:{
//use string to add uint64
uint64_t val = *static_cast<uint64_t *>(entry->mData);
fbx_node.AddP70string(key.C_Str(), std::to_string(val).c_str());
break;
}
case AI_FLOAT:{
float val = *static_cast<float *>(entry->mData);
fbx_node.AddP70double(key.C_Str(), val);
break;
}
case AI_DOUBLE:{
double val = *static_cast<double *>(entry->mData);
fbx_node.AddP70double(key.C_Str(), val);
break;
}
case AI_AISTRING:{
aiString val = *static_cast<aiString *>(entry->mData);
fbx_node.AddP70string(key.C_Str(), val.C_Str());
break;
}
case AI_AIMETADATA: {
//ignore
break;
}
default:
break;
}
}
}
// write a single model node to the stream // write a single model node to the stream
void FBXExporter::WriteModelNode( void FBXExporter::WriteModelNode(
StreamWriterLE& outstream, StreamWriterLE& outstream,
@ -2605,7 +2560,6 @@ void FBXExporter::WriteModelNode(
} }
} }
} }
add_meta(p, node);
m.AddChild(p); m.AddChild(p);
// not sure what these are for, // not sure what these are for,

View File

@ -156,9 +156,6 @@ struct ImportSettings {
/** Set to true to perform a conversion from cm to meter after the import /** Set to true to perform a conversion from cm to meter after the import
*/ */
bool convertToMeters; bool convertToMeters;
// Set to true to ignore the axis configuration in the file
bool ignoreUpDirection = false;
}; };
} // namespace FBX } // namespace FBX

View File

@ -117,7 +117,6 @@ void FBXImporter::SetupProperties(const Importer *pImp) {
mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false); mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true); mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
mSettings.ignoreUpDirection = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION, false);
mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false); mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false);
} }

View File

@ -644,12 +644,10 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
return; return;
} }
if (source["Materials"]) {
// materials are handled separately. First of all, they are assigned per-face // materials are handled separately. First of all, they are assigned per-face
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
// has a slightly different meaning for materials. // has a slightly different meaning for materials.
ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials")); ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials"));
}
if (MappingInformationType == "AllSame") { if (MappingInformationType == "AllSame") {
// easy - same material for all faces // easy - same material for all faces

View File

@ -134,7 +134,7 @@ public:
const char* elementNameCStr = elementName.c_str(); const char* elementNameCStr = elementName.c_str();
for (auto element = elements.begin(); element != elements.end(); ++element) for (auto element = elements.begin(); element != elements.end(); ++element)
{ {
if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, AI_MAXLEN)) { if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) {
return element->second; return element->second;
} }
} }

View File

@ -220,7 +220,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
std::unique_ptr<STEP::DB> db(STEP::ReadFileHeader(std::move(stream))); std::unique_ptr<STEP::DB> db(STEP::ReadFileHeader(std::move(stream)));
const STEP::HeaderInfo &head = static_cast<const STEP::DB &>(*db).GetHeader(); const STEP::HeaderInfo &head = static_cast<const STEP::DB &>(*db).GetHeader();
if (!head.fileSchema.size() || head.fileSchema.substr(0, 4) != "IFC2") { if (!head.fileSchema.size() || head.fileSchema.substr(0, 3) != "IFC") {
ThrowException("Unrecognized file schema: " + head.fileSchema); ThrowException("Unrecognized file schema: " + head.fileSchema);
} }
@ -260,8 +260,6 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
ThrowException("missing IfcProject entity"); ThrowException("missing IfcProject entity");
} }
ConversionData conv(*db, proj->To<Schema_2x3::IfcProject>(), pScene, settings); ConversionData conv(*db, proj->To<Schema_2x3::IfcProject>(), pScene, settings);
SetUnits(conv); SetUnits(conv);
SetCoordinateSpace(conv); SetCoordinateSpace(conv);
@ -354,11 +352,6 @@ void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &co
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void SetUnits(ConversionData &conv) { void SetUnits(ConversionData &conv) {
if (conv.proj.UnitsInContext == nullptr) {
IFCImporter::LogError("Skipping conversion data, nullptr.");
return;
}
// see if we can determine the coordinate space used to express. // see if we can determine the coordinate space used to express.
for (size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i) { for (size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i) {
ConvertUnit(*conv.proj.UnitsInContext->Units[i], conv); ConvertUnit(*conv.proj.UnitsInContext->Units[i], conv);

View File

@ -168,7 +168,7 @@ void IRRImporter::BuildSkybox(std::vector<aiMesh *> &meshes, std::vector<aiMater
aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i))); aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i)));
aiString s; aiString s;
s.length = ::ai_snprintf(s.data, AI_MAXLEN, "SkyboxSide_%u", i); s.length = ::ai_snprintf(s.data, MAXLEN, "SkyboxSide_%u", i);
out->AddProperty(&s, AI_MATKEY_NAME); out->AddProperty(&s, AI_MATKEY_NAME);
int shading = aiShadingMode_NoShading; int shading = aiShadingMode_NoShading;
@ -316,7 +316,7 @@ void IRRImporter::ComputeAnimations(Node *root, aiNode *real, std::vector<aiNode
if (cur != total - 1) { if (cur != total - 1) {
// Build a new name - a prefix instead of a suffix because it is // Build a new name - a prefix instead of a suffix because it is
// easier to check against // easier to check against
anim->mNodeName.length = ::ai_snprintf(anim->mNodeName.data, AI_MAXLEN, anim->mNodeName.length = ::ai_snprintf(anim->mNodeName.data, MAXLEN,
"$INST_DUMMY_%i_%s", total - 1, "$INST_DUMMY_%i_%s", total - 1,
(root->name.length() ? root->name.c_str() : "")); (root->name.length() ? root->name.c_str() : ""));

View File

@ -78,15 +78,7 @@ static constexpr aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursive parsing of LWS files // Recursive parsing of LWS files
namespace { void LWS::Element::Parse(const char *&buffer, const char *end) {
constexpr int MAX_DEPTH = 1000; // Define the maximum depth allowed
}
void LWS::Element::Parse(const char *&buffer, const char *end, int depth) {
if (depth > MAX_DEPTH) {
throw std::runtime_error("Maximum recursion depth exceeded in LWS::Element::Parse");
}
for (; SkipSpacesAndLineEnd(&buffer, end); SkipLine(&buffer, end)) { for (; SkipSpacesAndLineEnd(&buffer, end); SkipLine(&buffer, end)) {
// begin of a new element with children // begin of a new element with children
@ -129,7 +121,7 @@ void LWS::Element::Parse(const char *&buffer, const char *end, int depth) {
// parse more elements recursively // parse more elements recursively
if (sub) { if (sub) {
children.back().Parse(buffer, end, depth + 1); children.back().Parse(buffer, end);
} }
} }
} }
@ -313,14 +305,14 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
} }
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, AI_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);
if (nd->mName.length > AI_MAXLEN) { if (nd->mName.length > MAXLEN) {
nd->mName.length = AI_MAXLEN; nd->mName.length = MAXLEN;
} }
return; return;
} }
} }
nd->mName.length = ::ai_snprintf(nd->mName.data, AI_MAXLEN, "%s_(%08X)", src.name, combined); nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.name, combined);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -76,7 +76,7 @@ public:
std::list<Element> children; std::list<Element> children;
//! Recursive parsing function //! Recursive parsing function
void Parse(const char *&buffer, const char *end, int depth = 0); void Parse(const char *&buffer, const char *end);
}; };
#define AI_LWS_MASK (0xffffffff >> 4u) #define AI_LWS_MASK (0xffffffff >> 4u)

View File

@ -724,7 +724,6 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
std::vector<unsigned char> mBuffer2(fileSize); std::vector<unsigned char> mBuffer2(fileSize);
file->Read(&mBuffer2[0], 1, fileSize); file->Read(&mBuffer2[0], 1, fileSize);
mBuffer = &mBuffer2[0]; mBuffer = &mBuffer2[0];
const unsigned char* bufferEnd = mBuffer + fileSize;
pcHeader = (BE_NCONST MD3::Header *)mBuffer; pcHeader = (BE_NCONST MD3::Header *)mBuffer;
@ -750,15 +749,9 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Navigate to the list of surfaces // Navigate to the list of surfaces
BE_NCONST MD3::Surface *pcSurfaces = (BE_NCONST MD3::Surface *)(mBuffer + pcHeader->OFS_SURFACES); BE_NCONST MD3::Surface *pcSurfaces = (BE_NCONST MD3::Surface *)(mBuffer + pcHeader->OFS_SURFACES);
if ((const unsigned char*)pcSurfaces + sizeof(MD3::Surface) * pcHeader->NUM_SURFACES > bufferEnd) {
throw DeadlyImportError("MD3 surface headers are outside the file");
}
// Navigate to the list of tags // Navigate to the list of tags
BE_NCONST MD3::Tag *pcTags = (BE_NCONST MD3::Tag *)(mBuffer + pcHeader->OFS_TAGS); BE_NCONST MD3::Tag *pcTags = (BE_NCONST MD3::Tag *)(mBuffer + pcHeader->OFS_TAGS);
if ((const unsigned char*)pcTags + sizeof(MD3::Tag) * pcHeader->NUM_TAGS > bufferEnd) {
throw DeadlyImportError("MD3 tags are outside the file");
}
// Allocate output storage // Allocate output storage
pScene->mNumMeshes = pcHeader->NUM_SURFACES; pScene->mNumMeshes = pcHeader->NUM_SURFACES;
@ -1033,10 +1026,6 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
for (unsigned int i = 0; i < pcHeader->NUM_TAGS; ++i, ++pcTags) { for (unsigned int i = 0; i < pcHeader->NUM_TAGS; ++i, ++pcTags) {
aiNode *nd = pScene->mRootNode->mChildren[i] = new aiNode(); aiNode *nd = pScene->mRootNode->mChildren[i] = new aiNode();
if ((const unsigned char*)pcTags + sizeof(MD3::Tag) > bufferEnd) {
throw DeadlyImportError("MD3 tag is outside the file");
}
nd->mName.Set((const char *)pcTags->NAME); nd->mName.Set((const char *)pcTags->NAME);
nd->mParent = pScene->mRootNode; nd->mParent = pScene->mRootNode;

View File

@ -707,7 +707,7 @@ void MD5Importer::LoadMD5CameraFile() {
for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) { for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) {
aiAnimation *anim = *tmp++ = new aiAnimation(); aiAnimation *anim = *tmp++ = new aiAnimation();
anim->mName.length = ::ai_snprintf(anim->mName.data, AI_MAXLEN, "anim%u_from_%u_to_%u", (unsigned int)(it - cuts.begin()), (*it), *(it + 1)); anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u", (unsigned int)(it - cuts.begin()), (*it), *(it + 1));
anim->mTicksPerSecond = cameraParser.fFrameRate; anim->mTicksPerSecond = cameraParser.fFrameRate;
anim->mChannels = new aiNodeAnim *[anim->mNumChannels = 1]; anim->mChannels = new aiNodeAnim *[anim->mNumChannels = 1];

View File

@ -234,12 +234,8 @@ inline void AI_MD5_READ_TRIPLE(aiVector3D &vec, const char **sz, const char *buf
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
if ('(' != **sz) { if ('(' != **sz) {
MD5Parser::ReportWarning("Unexpected token: ( was expected", linenumber); MD5Parser::ReportWarning("Unexpected token: ( was expected", linenumber);
if (*sz == bufferEnd)
return;
++*sz; ++*sz;
} }
if (*sz == bufferEnd)
return;
++*sz; ++*sz;
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
*sz = fast_atoreal_move<float>(*sz, (float &)vec.x); *sz = fast_atoreal_move<float>(*sz, (float &)vec.x);
@ -251,8 +247,6 @@ inline void AI_MD5_READ_TRIPLE(aiVector3D &vec, const char **sz, const char *buf
if (')' != **sz) { if (')' != **sz) {
MD5Parser::ReportWarning("Unexpected token: ) was expected", linenumber); MD5Parser::ReportWarning("Unexpected token: ) was expected", linenumber);
} }
if (*sz == bufferEnd)
return;
++*sz; ++*sz;
} }

View File

@ -63,8 +63,7 @@ struct HL1ImportSettings {
read_bone_controllers(false), read_bone_controllers(false),
read_hitboxes(false), read_hitboxes(false),
read_textures(false), read_textures(false),
read_misc_global_info(false), read_misc_global_info(false) {
transform_coord_system(true) {
} }
bool read_animations; bool read_animations;
@ -77,7 +76,6 @@ struct HL1ImportSettings {
bool read_hitboxes; bool read_hitboxes;
bool read_textures; bool read_textures;
bool read_misc_global_info; bool read_misc_global_info;
bool transform_coord_system;
}; };
} // namespace HalfLife } // namespace HalfLife

View File

@ -99,7 +99,7 @@ MDLImporter::MDLImporter() :
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static constexpr uint32_t tokens[] = { static const uint32_t tokens[] = {
AI_MDL_MAGIC_NUMBER_LE_HL2a, AI_MDL_MAGIC_NUMBER_LE_HL2a,
AI_MDL_MAGIC_NUMBER_LE_HL2b, AI_MDL_MAGIC_NUMBER_LE_HL2b,
AI_MDL_MAGIC_NUMBER_LE_GS7, AI_MDL_MAGIC_NUMBER_LE_GS7,
@ -138,7 +138,6 @@ void MDLImporter::SetupProperties(const Importer *pImp) {
mHL1ImportSettings.read_bone_controllers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_BONE_CONTROLLERS, true); mHL1ImportSettings.read_bone_controllers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_BONE_CONTROLLERS, true);
mHL1ImportSettings.read_hitboxes = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_HITBOXES, true); mHL1ImportSettings.read_hitboxes = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_HITBOXES, true);
mHL1ImportSettings.read_misc_global_info = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_MISC_GLOBAL_INFO, true); mHL1ImportSettings.read_misc_global_info = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_MISC_GLOBAL_INFO, true);
mHL1ImportSettings.transform_coord_system = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_TRANSFORM_COORD_SYSTEM);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -147,20 +146,6 @@ const aiImporterDesc *MDLImporter::GetInfo() const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------
static void transformCoordinateSystem(const aiScene *pScene) {
if (pScene == nullptr) {
return;
}
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
);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void MDLImporter::InternReadFile(const std::string &pFile, void MDLImporter::InternReadFile(const std::string &pFile,
@ -261,17 +246,19 @@ void MDLImporter::InternReadFile(const std::string &pFile,
". Magic word (", ai_str_toprintable((const char *)&iMagicWord, sizeof(iMagicWord)), ") is not known"); ". Magic word (", ai_str_toprintable((const char *)&iMagicWord, sizeof(iMagicWord)), ") is not known");
} }
if (is_half_life && mHL1ImportSettings.transform_coord_system) { if (is_half_life){
// Now rotate the whole scene 90 degrees around the z and x axes to convert to internal coordinate system // Now rotate the whole scene 90 degrees around the z and x axes to convert to internal coordinate system
transformCoordinateSystem(pScene);
} else {
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4( 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, -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); 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 (...) {
@ -975,7 +962,7 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones)
if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size) { if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size) {
// no real name for our poor bone is specified :-( // no real name for our poor bone is specified :-(
pcOutBone->mName.length = ai_snprintf(pcOutBone->mName.data, AI_MAXLEN, pcOutBone->mName.length = ai_snprintf(pcOutBone->mName.data, MAXLEN,
"UnnamedBone_%i", iBone); "UnnamedBone_%i", iBone);
} else { } else {
// Make sure we won't run over the buffer's end if there is no // Make sure we won't run over the buffer's end if there is no
@ -1580,7 +1567,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7() {
} else { } else {
pcNode->mName.length = (ai_uint32)::strlen(szBuffer); pcNode->mName.length = (ai_uint32)::strlen(szBuffer);
} }
::strncpy(pcNode->mName.data, szBuffer, AI_MAXLEN - 1); ::strncpy(pcNode->mName.data, szBuffer, MAXLEN - 1);
++p; ++p;
} }
} }

View File

@ -494,7 +494,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
aiString szFile; aiString szFile;
const size_t iLen = strlen((const char *)szCurrent); const size_t iLen = strlen((const char *)szCurrent);
size_t iLen2 = iLen > (AI_MAXLEN - 1) ? (AI_MAXLEN - 1) : iLen; size_t iLen2 = iLen > (MAXLEN - 1) ? (MAXLEN - 1) : iLen;
memcpy(szFile.data, (const char *)szCurrent, iLen2); memcpy(szFile.data, (const char *)szCurrent, iLen2);
szFile.data[iLen2] = '\0'; szFile.data[iLen2] = '\0';
szFile.length = static_cast<ai_uint32>(iLen2); szFile.length = static_cast<ai_uint32>(iLen2);
@ -610,7 +610,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
if (is_not_qnan(clrTexture.r)) { if (is_not_qnan(clrTexture.r)) {
clrTemp.r *= clrTexture.a; clrTemp.r *= clrTexture.a;
} }
pcMatOut->AddProperty<float>(&clrTemp.r, 1, AI_MATKEY_OPACITY); pcMatOut->AddProperty<ai_real>(&clrTemp.r, 1, AI_MATKEY_OPACITY);
// read phong power // read phong power
int iShadingMode = (int)aiShadingMode_Gouraud; int iShadingMode = (int)aiShadingMode_Gouraud;
@ -730,12 +730,10 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
// if an ASCII effect description (HLSL?) is contained in the file, // if an ASCII effect description (HLSL?) is contained in the file,
// we can simply ignore it ... // we can simply ignore it ...
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) { if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) {
VALIDATE_FILE_SIZE(szCurrent + sizeof(int32_t));
int32_t iMe = 0; int32_t iMe = 0;
::memcpy(&iMe, szCurrent, sizeof(int32_t)); ::memcpy(&iMe, szCurrent, sizeof(int32_t));
AI_SWAP4(iMe); AI_SWAP4(iMe);
szCurrent += sizeof(char) * iMe + sizeof(int32_t); szCurrent += sizeof(char) * iMe + sizeof(int32_t);
VALIDATE_FILE_SIZE(szCurrent);
} }
*szCurrentOut = szCurrent; *szCurrentOut = szCurrent;
} }

View File

@ -316,7 +316,7 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
aiMaterial *pcMat = new aiMaterial(); aiMaterial *pcMat = new aiMaterial();
aiColor4D clr(0.6f, 0.6f, 0.6f, 1.0f); aiColor4D clr(ai_real(0.6), ai_real(0.6), ai_real(0.6), ai_real(1.0));
pcMat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); pcMat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
pScene->mMaterials[0] = pcMat; pScene->mMaterials[0] = pcMat;

View File

@ -199,12 +199,12 @@ struct Material {
//! Constructor //! Constructor
Material() : Material() :
diffuse(0.6f, 0.6f, 0.6f), diffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
alpha(ai_real(1.0)), alpha(ai_real(1.0)),
shineness(ai_real(0.0)), shineness(ai_real(0.0)),
illumination_model(1), illumination_model(1),
ior(ai_real(1.0)), ior(ai_real(1.0)),
transparent(1.0f, 1.0, 1.0), transparent(ai_real(1.0), ai_real(1.0), ai_real(1.0)),
roughness(), roughness(),
metallic(), metallic(),
sheen(), sheen(),

View File

@ -193,7 +193,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
pScene->mRootNode->mChildren = new aiNode *[childCount]; pScene->mRootNode->mChildren = new aiNode *[childCount];
// Create nodes for the whole scene // Create nodes for the whole scene
std::vector<std::unique_ptr<aiMesh>> MeshArray; std::vector<aiMesh *> MeshArray;
MeshArray.reserve(meshCount); MeshArray.reserve(meshCount);
for (size_t index = 0; index < pModel->mObjects.size(); ++index) { for (size_t index = 0; index < pModel->mObjects.size(); ++index) {
createNodes(pModel, pModel->mObjects[index], pScene->mRootNode, pScene, MeshArray); createNodes(pModel, pModel->mObjects[index], pScene->mRootNode, pScene, MeshArray);
@ -205,7 +205,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
if (pScene->mNumMeshes > 0) { if (pScene->mNumMeshes > 0) {
pScene->mMeshes = new aiMesh *[MeshArray.size()]; pScene->mMeshes = new aiMesh *[MeshArray.size()];
for (size_t index = 0; index < MeshArray.size(); ++index) { for (size_t index = 0; index < MeshArray.size(); ++index) {
pScene->mMeshes[index] = MeshArray[index].release(); pScene->mMeshes[index] = MeshArray[index];
} }
} }
@ -257,7 +257,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
// Creates all nodes of the model // Creates all nodes of the model
aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject, aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject,
aiNode *pParent, aiScene *pScene, aiNode *pParent, aiScene *pScene,
std::vector<std::unique_ptr<aiMesh>> &MeshArray) { std::vector<aiMesh *> &MeshArray) {
ai_assert(nullptr != pModel); ai_assert(nullptr != pModel);
if (nullptr == pObject) { if (nullptr == pObject) {
return nullptr; return nullptr;
@ -275,10 +275,12 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) { for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
unsigned int meshId = pObject->m_Meshes[i]; unsigned int meshId = pObject->m_Meshes[i];
std::unique_ptr<aiMesh> pMesh = createTopology(pModel, pObject, meshId); aiMesh *pMesh = createTopology(pModel, pObject, meshId);
if (pMesh != nullptr) { if (pMesh != nullptr) {
if (pMesh->mNumFaces > 0) { if (pMesh->mNumFaces > 0) {
MeshArray.push_back(std::move(pMesh)); MeshArray.push_back(pMesh);
} else {
delete pMesh;
} }
} }
} }
@ -310,7 +312,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Create topology data // Create topology data
std::unique_ptr<aiMesh> ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData, unsigned int meshIndex) { aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData, unsigned int meshIndex) {
// Checking preconditions // Checking preconditions
ai_assert(nullptr != pModel); ai_assert(nullptr != pModel);
@ -392,7 +394,7 @@ std::unique_ptr<aiMesh> ObjFileImporter::createTopology(const ObjFile::Model *pM
// Create mesh vertices // Create mesh vertices
createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount); createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount);
return pMesh; return pMesh.release();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <memory>
#include <vector> #include <vector>
struct aiMesh; struct aiMesh;
@ -85,10 +84,10 @@ protected:
//! \brief Creates all nodes stored in imported content. //! \brief Creates all nodes stored in imported content.
aiNode *createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pData, aiNode *createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pData,
aiNode *pParent, aiScene *pScene, std::vector<std::unique_ptr<aiMesh>> &MeshArray); aiNode *pParent, aiScene *pScene, std::vector<aiMesh *> &MeshArray);
//! \brief Creates topology data like faces and meshes for the geometry. //! \brief Creates topology data like faces and meshes for the geometry.
std::unique_ptr<aiMesh> createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData, aiMesh *createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData,
unsigned int uiMeshIndex); unsigned int uiMeshIndex);
//! \brief Creates vertices from model. //! \brief Creates vertices from model.

View File

@ -346,22 +346,10 @@ void PlyExporter::WriteMeshVertsBinary(const aiMesh* m, unsigned int components)
for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) { for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
if (m->HasVertexColors(c)) { if (m->HasVertexColors(c)) {
unsigned char rgba[4] = { mOutput.write(reinterpret_cast<const char*>(&m->mColors[c][i].r), 16);
static_cast<unsigned char>(m->mColors[c][i].r * 255),
static_cast<unsigned char>(m->mColors[c][i].g * 255),
static_cast<unsigned char>(m->mColors[c][i].b * 255),
static_cast<unsigned char>(m->mColors[c][i].a * 255)
};
mOutput.write(reinterpret_cast<const char*>(&rgba), 4);
} }
else { else {
unsigned char rgba[4] = { mOutput.write(reinterpret_cast<const char*>(&defaultColor.r), 16);
static_cast<unsigned char>(defaultColor.r * 255),
static_cast<unsigned char>(defaultColor.g * 255),
static_cast<unsigned char>(defaultColor.b * 255),
static_cast<unsigned char>(defaultColor.a * 255)
};
mOutput.write(reinterpret_cast<const char*>(&rgba), 4);
} }
} }

View File

@ -81,27 +81,6 @@ namespace {
return props[idx]; return props[idx];
} }
// ------------------------------------------------------------------------------------------------
static bool isBigEndian(const char *szMe) {
ai_assert(nullptr != szMe);
// binary_little_endian
// binary_big_endian
bool isBigEndian{ false };
#if (defined AI_BUILD_BIG_ENDIAN)
if ('l' == *szMe || 'L' == *szMe) {
isBigEndian = true;
}
#else
if ('b' == *szMe || 'B' == *szMe) {
isBigEndian = true;
}
#endif // ! AI_BUILD_BIG_ENDIAN
return isBigEndian;
}
} // namespace } // namespace
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -113,11 +92,6 @@ PLYImporter::PLYImporter() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
PLYImporter::~PLYImporter() {
delete mGeneratedMesh;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@ -130,6 +104,26 @@ const aiImporterDesc *PLYImporter::GetInfo() const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------
static bool isBigEndian(const char *szMe) {
ai_assert(nullptr != szMe);
// binary_little_endian
// binary_big_endian
bool isBigEndian(false);
#if (defined AI_BUILD_BIG_ENDIAN)
if ('l' == *szMe || 'L' == *szMe) {
isBigEndian = true;
}
#else
if ('b' == *szMe || 'B' == *szMe) {
isBigEndian = true;
}
#endif // ! AI_BUILD_BIG_ENDIAN
return isBigEndian;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
@ -140,7 +134,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
// Get the file-size // Get the file-size
const size_t fileSize = fileStream->FileSize(); const size_t fileSize(fileStream->FileSize());
if (0 == fileSize) { if (0 == fileSize) {
throw DeadlyImportError("File ", pFile, " is empty."); throw DeadlyImportError("File ", pFile, " is empty.");
} }
@ -186,7 +180,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
} else if (!::strncmp(szMe, "binary_", 7)) { } else if (!::strncmp(szMe, "binary_", 7)) {
szMe += 7; szMe += 7;
const bool bIsBE = isBigEndian(szMe); const bool bIsBE(isBigEndian(szMe));
// skip the line, parse the rest of the header and build the DOM // skip the line, parse the rest of the header and build the DOM
if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) { if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) {
@ -248,8 +242,6 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
pScene->mNumMeshes = 1; pScene->mNumMeshes = 1;
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
pScene->mMeshes[0] = mGeneratedMesh; pScene->mMeshes[0] = mGeneratedMesh;
// Move the mesh ownership into the scene instance
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
// generate a simple node structure // generate a simple node structure
@ -262,22 +254,20 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
} }
static constexpr ai_uint NotSet = 0xFFFFFFFF;
void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementInstance *instElement, unsigned int pos) { void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementInstance *instElement, unsigned int pos) {
ai_assert(nullptr != pcElement); ai_assert(nullptr != pcElement);
ai_assert(nullptr != instElement); ai_assert(nullptr != instElement);
ai_uint aiPositions[3] = { NotSet, NotSet, NotSet }; ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char }; PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
ai_uint aiNormal[3] = { NotSet, NotSet, NotSet }; ai_uint aiNormal[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiNormalTypes[3] = { EDT_Char, EDT_Char, EDT_Char }; PLY::EDataType aiNormalTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
unsigned int aiColors[4] = { NotSet, NotSet, NotSet, NotSet }; unsigned int aiColors[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiColorsTypes[4] = { EDT_Char, EDT_Char, EDT_Char, EDT_Char }; PLY::EDataType aiColorsTypes[4] = { EDT_Char, EDT_Char, EDT_Char, EDT_Char };
unsigned int aiTexcoord[2] = { NotSet, NotSet }; unsigned int aiTexcoord[2] = { 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char }; PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char };
// now check whether which normal components are available // now check whether which normal components are available
@ -347,17 +337,17 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
if (0 != cnt) { if (0 != cnt) {
// Position // Position
aiVector3D vOut; aiVector3D vOut;
if (NotSet != aiPositions[0]) { if (0xFFFFFFFF != aiPositions[0]) {
vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>( vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]); GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]);
} }
if (NotSet != aiPositions[1]) { if (0xFFFFFFFF != aiPositions[1]) {
vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>( vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]); GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]);
} }
if (NotSet != aiPositions[2]) { if (0xFFFFFFFF != aiPositions[2]) {
vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>( vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]); GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]);
} }
@ -365,19 +355,19 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
// Normals // Normals
aiVector3D nOut; aiVector3D nOut;
bool haveNormal = false; bool haveNormal = false;
if (NotSet != aiNormal[0]) { if (0xFFFFFFFF != aiNormal[0]) {
nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>( nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]); GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]);
haveNormal = true; haveNormal = true;
} }
if (NotSet != aiNormal[1]) { if (0xFFFFFFFF != aiNormal[1]) {
nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>( nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]); GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]);
haveNormal = true; haveNormal = true;
} }
if (NotSet != aiNormal[2]) { if (0xFFFFFFFF != aiNormal[2]) {
nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>( nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]); GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]);
haveNormal = true; haveNormal = true;
@ -386,7 +376,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
// Colors // Colors
aiColor4D cOut; aiColor4D cOut;
bool haveColor = false; bool haveColor = false;
if (NotSet != aiColors[0]) { if (0xFFFFFFFF != aiColors[0]) {
cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[0]) aiColors[0])
.avList.front(), .avList.front(),
@ -394,7 +384,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
haveColor = true; haveColor = true;
} }
if (NotSet != aiColors[1]) { if (0xFFFFFFFF != aiColors[1]) {
cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[1]) aiColors[1])
.avList.front(), .avList.front(),
@ -402,7 +392,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
haveColor = true; haveColor = true;
} }
if (NotSet != aiColors[2]) { if (0xFFFFFFFF != aiColors[2]) {
cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[2]) aiColors[2])
.avList.front(), .avList.front(),
@ -411,7 +401,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
} }
// assume 1.0 for the alpha channel if it is not set // assume 1.0 for the alpha channel if it is not set
if (NotSet == aiColors[3]) { if (0xFFFFFFFF == aiColors[3]) {
cOut.a = 1.0; cOut.a = 1.0;
} else { } else {
cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties,
@ -426,13 +416,13 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
aiVector3D tOut; aiVector3D tOut;
tOut.z = 0; tOut.z = 0;
bool haveTextureCoords = false; bool haveTextureCoords = false;
if (NotSet != aiTexcoord[0]) { if (0xFFFFFFFF != aiTexcoord[0]) {
tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>( tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]); GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]);
haveTextureCoords = true; haveTextureCoords = true;
} }
if (NotSet != aiTexcoord[1]) { if (0xFFFFFFFF != aiTexcoord[1]) {
tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>( tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]); GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]);
haveTextureCoords = true; haveTextureCoords = true;
@ -448,9 +438,6 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
mGeneratedMesh->mNumVertices = pcElement->NumOccur; mGeneratedMesh->mNumVertices = pcElement->NumOccur;
mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices]; mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices];
} }
if (pos >= mGeneratedMesh->mNumVertices) {
throw DeadlyImportError("Invalid .ply file: Too many vertices");
}
mGeneratedMesh->mVertices[pos] = vOut; mGeneratedMesh->mVertices[pos] = vOut;
@ -517,12 +504,16 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
bool bOne = false; bool bOne = false;
// index of the vertex index list // index of the vertex index list
unsigned int iProperty = NotSet; unsigned int iProperty = 0xFFFFFFFF;
PLY::EDataType eType = EDT_Char; PLY::EDataType eType = EDT_Char;
bool bIsTriStrip = false; bool bIsTriStrip = false;
// index of the material index property
// unsigned int iMaterialIndex = 0xFFFFFFFF;
// PLY::EDataType eType2 = EDT_Char;
// texture coordinates // texture coordinates
unsigned int iTextureCoord = NotSet; unsigned int iTextureCoord = 0xFFFFFFFF;
PLY::EDataType eType3 = EDT_Char; PLY::EDataType eType3 = EDT_Char;
// face = unique number of vertex indices // face = unique number of vertex indices
@ -573,15 +564,11 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
if (mGeneratedMesh->mFaces == nullptr) { if (mGeneratedMesh->mFaces == nullptr) {
mGeneratedMesh->mNumFaces = pcElement->NumOccur; mGeneratedMesh->mNumFaces = pcElement->NumOccur;
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
} else {
if (mGeneratedMesh->mNumFaces < pcElement->NumOccur) {
throw DeadlyImportError("Invalid .ply file: Too many faces");
}
} }
if (!bIsTriStrip) { if (!bIsTriStrip) {
// parse the list of vertex indices // parse the list of vertex indices
if (NotSet != iProperty) { if (0xFFFFFFFF != iProperty) {
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size(); const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size();
mGeneratedMesh->mFaces[pos].mNumIndices = iNum; mGeneratedMesh->mFaces[pos].mNumIndices = iNum;
mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum]; mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
@ -594,7 +581,15 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
} }
} }
if (NotSet != iTextureCoord) { // parse the material index
// cannot be handled without processing the whole file first
/*if (0xFFFFFFFF != iMaterialIndex)
{
mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo<unsigned int>(
GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
}*/
if (0xFFFFFFFF != iTextureCoord) {
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size(); const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
// should be 6 coords // should be 6 coords
@ -680,29 +675,41 @@ void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance> &avL
aiColor4D *clrOut) { aiColor4D *clrOut) {
ai_assert(nullptr != clrOut); ai_assert(nullptr != clrOut);
if (NotSet == aiPositions[0]) { if (0xFFFFFFFF == aiPositions[0])
clrOut->r = 0.0f; clrOut->r = 0.0f;
} else { else {
clrOut->r = NormalizeColorValue(GetProperty(avList, aiPositions[0]).avList.front(), aiTypes[0]); clrOut->r = NormalizeColorValue(GetProperty(avList,
aiPositions[0])
.avList.front(),
aiTypes[0]);
} }
if (NotSet == aiPositions[1]) { if (0xFFFFFFFF == aiPositions[1])
clrOut->g = 0.0f; clrOut->g = 0.0f;
} else { else {
clrOut->g = NormalizeColorValue(GetProperty(avList, aiPositions[1]).avList.front(), aiTypes[1]); clrOut->g = NormalizeColorValue(GetProperty(avList,
aiPositions[1])
.avList.front(),
aiTypes[1]);
} }
if (NotSet == aiPositions[2]) if (0xFFFFFFFF == aiPositions[2])
clrOut->b = 0.0f; clrOut->b = 0.0f;
else { else {
clrOut->b = NormalizeColorValue(GetProperty(avList, aiPositions[2]).avList.front(), aiTypes[2]); clrOut->b = NormalizeColorValue(GetProperty(avList,
aiPositions[2])
.avList.front(),
aiTypes[2]);
} }
// assume 1.0 for the alpha channel ifit is not set // assume 1.0 for the alpha channel ifit is not set
if (NotSet == aiPositions[3]) if (0xFFFFFFFF == aiPositions[3])
clrOut->a = 1.0f; clrOut->a = 1.0f;
else { else {
clrOut->a = NormalizeColorValue(GetProperty(avList, aiPositions[3]).avList.front(), aiTypes[3]); clrOut->a = NormalizeColorValue(GetProperty(avList,
aiPositions[3])
.avList.front(),
aiTypes[3]);
} }
} }

View File

@ -62,10 +62,10 @@ using namespace PLY;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Importer class to load the stanford PLY file format /** Importer class to load the stanford PLY file format
*/ */
class PLYImporter final : public BaseImporter { class PLYImporter : public BaseImporter {
public: public:
PLYImporter(); PLYImporter();
~PLYImporter() override; ~PLYImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
@ -120,9 +120,13 @@ protected:
PLY::PropertyInstance::ValueUnion val, PLY::PropertyInstance::ValueUnion val,
PLY::EDataType eType); PLY::EDataType eType);
private: /** Buffer to hold the loaded file */
unsigned char *mBuffer; unsigned char *mBuffer;
/** Document object model representation extracted from the file */
PLY::DOM *pcDOM; PLY::DOM *pcDOM;
/** Mesh generated by loader */
aiMesh *mGeneratedMesh; aiMesh *mGeneratedMesh;
}; };

View File

@ -48,29 +48,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ByteSwapper.h> #include <assimp/ByteSwapper.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <unordered_set>
#include <utility> #include <utility>
namespace Assimp { namespace Assimp {
std::string to_string(EElementSemantic e) {
switch (e) {
case EEST_Vertex:
return std::string{ "vertex" };
case EEST_TriStrip:
return std::string{ "tristrips" };
case EEST_Edge:
return std::string{ "edge" };
case EEST_Material:
return std::string{ "material" };
case EEST_TextureFile:
return std::string{ "TextureFile" };
default:
return std::string{ "invalid" };
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) { PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) {
ai_assert(!buffer.empty()); ai_assert(!buffer.empty());
@ -300,8 +281,6 @@ bool PLY::Element::ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<
// if the exact semantic can't be determined, just store // if the exact semantic can't be determined, just store
// the original string identifier // the original string identifier
pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0]));
auto pos = pOut->szName.find_last_of(' ');
pOut->szName.erase(pos, pOut->szName.size());
} }
if (!PLY::DOM::SkipSpaces(buffer)) if (!PLY::DOM::SkipSpaces(buffer))
@ -434,7 +413,6 @@ bool PLY::DOM::SkipComments(std::vector<char> buffer) {
bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) { bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) {
ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() begin"); ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() begin");
std::unordered_set<std::string> definedAlElements;
// parse all elements // parse all elements
while (!buffer.empty()) { while (!buffer.empty()) {
// skip all comments // skip all comments
@ -443,13 +421,6 @@ bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char>
PLY::Element out; PLY::Element out;
if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) { if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) {
// add the element to the list of elements // add the element to the list of elements
const auto propertyName = (out.szName.empty()) ? to_string(out.eSemantic) : out.szName;
auto alreadyDefined = definedAlElements.find(propertyName);
if (alreadyDefined != definedAlElements.end()) {
throw DeadlyImportError("Property '" + propertyName + "' in header already defined ");
}
definedAlElements.insert(propertyName);
alElements.push_back(out); alElements.push_back(out);
} else if (TokenMatch(buffer, "end_header", 10)) { } else if (TokenMatch(buffer, "end_header", 10)) {
// we have reached the end of the header // we have reached the end of the header

View File

@ -588,7 +588,7 @@ bool Q3BSPFileImporter::importTextureFromArchive(const Q3BSP::Q3BSPModel *model,
aiString name; aiString name;
name.data[0] = '*'; name.data[0] = '*';
name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(AI_MAXLEN - 1), static_cast<int32_t>(mTextures.size())); name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
archive->Close(pTextureStream); archive->Close(pTextureStream);
@ -641,7 +641,7 @@ bool Q3BSPFileImporter::importLightmap(const Q3BSP::Q3BSPModel *pModel, aiScene
aiString name; aiString name;
name.data[0] = '*'; name.data[0] = '*';
name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(AI_MAXLEN - 1), static_cast<int32_t>(mTextures.size())); name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_LIGHTMAP(1)); pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_LIGHTMAP(1));
mTextures.push_back(pTexture); mTextures.push_back(pTexture);

View File

@ -250,7 +250,7 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
c = stream.GetI1(); c = stream.GetI1();
while (c) { while (c) {
mat.name.data[mat.name.length++] = c; mat.name.data[mat.name.length++] = c;
if (mat.name.length == AI_MAXLEN) { if (mat.name.length == MAXLEN) {
ASSIMP_LOG_ERROR("String ouverflow detected, skipped material name parsing."); ASSIMP_LOG_ERROR("String ouverflow detected, skipped material name parsing.");
break; break;
} }

View File

@ -400,10 +400,6 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) {
} }
} }
// nothing to do
if (pcNode->mNumChildren == 0)
return;
// now allocate the output array // now allocate the output array
pcNode->mChildren = new aiNode*[pcNode->mNumChildren]; pcNode->mChildren = new aiNode*[pcNode->mNumChildren];
@ -593,12 +589,12 @@ void SMDImporter::CreateOutputMaterials() {
pScene->mMaterials[iMat] = pcMat; pScene->mMaterials[iMat] = pcMat;
aiString szName; aiString szName;
szName.length = static_cast<ai_uint32>(ai_snprintf(szName.data, AI_MAXLEN, "Texture_%u", iMat)); szName.length = static_cast<ai_uint32>(ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat));
pcMat->AddProperty(&szName,AI_MATKEY_NAME); pcMat->AddProperty(&szName,AI_MATKEY_NAME);
if (aszTextures[iMat].length()) if (aszTextures[iMat].length())
{ {
::strncpy(szName.data, aszTextures[iMat].c_str(), AI_MAXLEN - 1); ::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1);
szName.length = static_cast<ai_uint32>( aszTextures[iMat].length() ); szName.length = static_cast<ai_uint32>( aszTextures[iMat].length() );
pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0)); pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
} }

View File

@ -181,7 +181,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
mBuffer = &buffer2[0]; mBuffer = &buffer2[0];
// the default vertex color is light gray. // the default vertex color is light gray.
mClrColorDefault.r = mClrColorDefault.g = mClrColorDefault.b = mClrColorDefault.a = 0.6f; mClrColorDefault.r = mClrColorDefault.g = mClrColorDefault.b = mClrColorDefault.a = (ai_real)0.6;
// allocate a single node // allocate a single node
mScene->mRootNode = new aiNode(); mScene->mRootNode = new aiNode();
@ -209,7 +209,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
pcMat->AddProperty(&clrDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); pcMat->AddProperty(&clrDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
pcMat->AddProperty(&clrDiffuse, 1, AI_MATKEY_COLOR_SPECULAR); pcMat->AddProperty(&clrDiffuse, 1, AI_MATKEY_COLOR_SPECULAR);
clrDiffuse = aiColor4D(0.05f, 0.05f, 0.05f, 1.0f); clrDiffuse = aiColor4D(ai_real(0.05), ai_real(0.05), ai_real(0.05), ai_real(1.0));
pcMat->AddProperty(&clrDiffuse, 1, AI_MATKEY_COLOR_AMBIENT); pcMat->AddProperty(&clrDiffuse, 1, AI_MATKEY_COLOR_AMBIENT);
mScene->mNumMaterials = 1; mScene->mNumMaterials = 1;
@ -257,7 +257,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
size_t temp = (size_t)(sz - szMe); size_t temp = (size_t)(sz - szMe);
// setup the name of the node // setup the name of the node
if (temp) { if (temp) {
if (temp >= AI_MAXLEN) { if (temp >= MAXLEN) {
throw DeadlyImportError("STL: Node name too long"); throw DeadlyImportError("STL: Node name too long");
} }
std::string name(szMe, temp); std::string name(szMe, temp);

View File

@ -82,6 +82,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// this is intended as stress test - by default, entities are evaluated // this is intended as stress test - by default, entities are evaluated
// lazily and therefore not unless needed. // lazily and therefore not unless needed.
//#define ASSIMP_IFC_TEST
namespace Assimp { namespace Assimp {
// ******************************************************************************** // ********************************************************************************
@ -529,7 +531,6 @@ public:
template <typename T> template <typename T>
const T &To() const { const T &To() const {
return dynamic_cast<const T &>(**this); return dynamic_cast<const T &>(**this);
} }
@ -598,30 +599,18 @@ struct Lazy {
Lazy(const LazyObject *obj = nullptr) : obj(obj) {} Lazy(const LazyObject *obj = nullptr) : obj(obj) {}
operator const T *() const { operator const T *() const {
if (obj == nullptr) {
throw TypeError("Obj type is nullptr.");
}
return obj->ToPtr<T>(); return obj->ToPtr<T>();
} }
operator const T &() const { operator const T &() const {
if (obj == nullptr) {
throw TypeError("Obj type is nullptr.");
}
return obj->To<T>(); return obj->To<T>();
} }
const T &operator*() const { const T &operator*() const {
if (obj == nullptr) {
throw TypeError("Obj type is nullptr.");
}
return obj->To<T>(); return obj->To<T>();
} }
const T *operator->() const { const T *operator->() const {
if (obj == nullptr) {
throw TypeError("Obj type is nullptr.");
}
return &obj->To<T>(); return &obj->To<T>();
} }

View File

@ -4,6 +4,7 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2024, assimp team Copyright (c) 2006-2024, 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,
@ -36,9 +37,11 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@author: Richard Steffen, 2015
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER #ifndef ASSIMP_BUILD_NO_STEP_EXPORTER

View File

@ -1,124 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, 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 USDLoader.cpp
* @brief Implementation of the USD importer class
*/
#ifndef ASSIMP_BUILD_NO_USD_IMPORTER
#include <memory>
// internal headers
#include <assimp/ai_assert.h>
#include <assimp/anim.h>
#include <assimp/DefaultIOSystem.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/fast_atof.h>
#include <assimp/Importer.hpp>
#include <assimp/importerdesc.h>
#include <assimp/IOStreamBuffer.h>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/StringUtils.h>
#include <assimp/StreamReader.h>
#include "USDLoader.h"
#include "USDLoaderUtil.h"
#include "USDPreprocessor.h"
static constexpr aiImporterDesc desc = {
"USD Object Importer",
"",
"",
"https://en.wikipedia.org/wiki/Universal_Scene_Description/",
aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
0,
0,
0,
0,
"usd usda usdc usdz"
};
namespace Assimp {
using namespace std;
// Constructor to be privately used by Importer
USDImporter::USDImporter() :
impl(USDImporterImplTinyusdz()) {
}
// ------------------------------------------------------------------------------------------------
bool USDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool) const {
// Based on token
static const uint32_t usdcTokens[] = { AI_MAKE_MAGIC("PXR-USDC") };
bool canRead = CheckMagicToken(pIOHandler, pFile, usdcTokens, AI_COUNT_OF(usdcTokens));
if (canRead) {
return canRead;
}
// Based on extension
// TODO: confirm OK to replace this w/SimpleExtensionCheck() below
canRead = isUsd(pFile) || isUsda(pFile) || isUsdc(pFile) || isUsdz(pFile);
if (canRead) {
return canRead;
}
canRead = SimpleExtensionCheck(pFile, "usd", "usda", "usdc", "usdz");
return canRead;
}
const aiImporterDesc *USDImporter::GetInfo() const {
return &desc;
}
void USDImporter::InternReadFile(
const std::string &pFile,
aiScene *pScene,
IOSystem *pIOHandler) {
impl.InternReadFile(
pFile,
pScene,
pIOHandler);
}
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_USD_IMPORTER

View File

@ -1,78 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, 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 USDLoader.h
* @brief Declaration of the USD importer class.
*/
#pragma once
#ifndef AI_USDLOADER_H_INCLUDED
#define AI_USDLOADER_H_INCLUDED
#include <assimp/BaseImporter.h>
#include <assimp/types.h>
#include <vector>
#include <cstdint>
#include "USDLoaderImplTinyusdz.h"
namespace Assimp {
class USDImporter : public BaseImporter {
public:
USDImporter();
~USDImporter() override = default;
/// \brief Returns whether the class can handle the format of the given file.
/// \remark See BaseImporter::CanRead() for details.
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
protected:
//! \brief Appends the supported extension.
const aiImporterDesc *GetInfo() const override;
void InternReadFile(
const std::string &pFile,
aiScene *pScene,
IOSystem *pIOHandler) override;
private:
USDImporterImplTinyusdz impl;
};
} // namespace Assimp
#endif // AI_USDLOADER_H_INCLUDED

View File

@ -1,749 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, 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 USDLoader.cpp
* @brief Implementation of the USD importer class
*/
#ifndef ASSIMP_BUILD_NO_USD_IMPORTER
#include <memory>
#include <sstream>
// internal headers
#include <assimp/ai_assert.h>
#include <assimp/anim.h>
#include <assimp/CreateAnimMesh.h>
#include <assimp/DefaultIOSystem.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/fast_atof.h>
#include <assimp/Importer.hpp>
#include <assimp/importerdesc.h>
#include <assimp/IOStreamBuffer.h>
#include <assimp/IOSystem.hpp>
#include <assimp/StringUtils.h>
#include <assimp/StreamReader.h>
#include "io-util.hh" // namespace tinyusdz::io
#include "tydra/scene-access.hh"
#include "tydra/shader-network.hh"
#include "USDLoaderImplTinyusdzHelper.h"
#include "USDLoaderImplTinyusdz.h"
#include "USDLoaderUtil.h"
#include "USDPreprocessor.h"
#include "../../../contrib/tinyusdz/assimp_tinyusdz_logging.inc"
namespace {
static constexpr char TAG[] = "tinyusdz loader";
}
namespace Assimp {
using namespace std;
void USDImporterImplTinyusdz::InternReadFile(
const std::string &pFile,
aiScene *pScene,
IOSystem *) {
// Grab filename for logging purposes
size_t pos = pFile.find_last_of('/');
string basePath = pFile.substr(0, pos);
string nameWExt = pFile.substr(pos + 1);
stringstream ss;
ss.str("");
ss << "InternReadFile(): model" << nameWExt;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
bool ret{ false };
tinyusdz::USDLoadOptions options;
tinyusdz::Stage stage;
std::string warn, err;
bool is_usdz{ false };
if (isUsdc(pFile)) {
ret = LoadUSDCFromFile(pFile, &stage, &warn, &err, options);
ss.str("");
ss << "InternReadFile(): LoadUSDCFromFile() result: " << ret;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
} else if (isUsda(pFile)) {
ret = LoadUSDAFromFile(pFile, &stage, &warn, &err, options);
ss.str("");
ss << "InternReadFile(): LoadUSDAFromFile() result: " << ret;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
} else if (isUsdz(pFile)) {
ret = LoadUSDZFromFile(pFile, &stage, &warn, &err, options);
is_usdz = true;
ss.str("");
ss << "InternReadFile(): LoadUSDZFromFile() result: " << ret;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
} else if (isUsd(pFile)) {
ret = LoadUSDFromFile(pFile, &stage, &warn, &err, options);
ss.str("");
ss << "InternReadFile(): LoadUSDFromFile() result: " << ret;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
}
if (warn.empty() && err.empty()) {
ss.str("");
ss << "InternReadFile(): load free of warnings/errors";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
} else {
if (!warn.empty()) {
ss.str("");
ss << "InternReadFile(): WARNING reported: " << warn;
TINYUSDZLOGW(TAG, "%s", ss.str().c_str());
}
if (!err.empty()) {
ss.str("");
ss << "InternReadFile(): ERROR reported: " << err;
TINYUSDZLOGE(TAG, "%s", ss.str().c_str());
}
}
if (!ret) {
ss.str("");
ss << "InternReadFile(): ERROR: load failed! ret: " << ret;
TINYUSDZLOGE(TAG, "%s", ss.str().c_str());
return;
}
tinyusdz::tydra::RenderScene render_scene;
tinyusdz::tydra::RenderSceneConverter converter;
tinyusdz::tydra::RenderSceneConverterEnv env(stage);
std::string usd_basedir = tinyusdz::io::GetBaseDir(pFile);
env.set_search_paths({ usd_basedir }); // {} needed to convert to vector of char
// NOTE: Pointer address of usdz_asset must be valid until the call of RenderSceneConverter::ConvertToRenderScene.
tinyusdz::USDZAsset usdz_asset;
if (is_usdz) {
if (!tinyusdz::ReadUSDZAssetInfoFromFile(pFile, &usdz_asset, &warn, &err)) {
if (!warn.empty()) {
ss.str("");
ss << "InternReadFile(): ReadUSDZAssetInfoFromFile: WARNING reported: " << warn;
TINYUSDZLOGW(TAG, "%s", ss.str().c_str());
}
if (!err.empty()) {
ss.str("");
ss << "InternReadFile(): ReadUSDZAssetInfoFromFile: ERROR reported: " << err;
TINYUSDZLOGE(TAG, "%s", ss.str().c_str());
}
ss.str("");
ss << "InternReadFile(): ReadUSDZAssetInfoFromFile: ERROR!";
TINYUSDZLOGE(TAG, "%s", ss.str().c_str());
} else {
ss.str("");
ss << "InternReadFile(): ReadUSDZAssetInfoFromFile: OK";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
}
tinyusdz::AssetResolutionResolver arr;
if (!tinyusdz::SetupUSDZAssetResolution(arr, &usdz_asset)) {
ss.str("");
ss << "InternReadFile(): SetupUSDZAssetResolution: ERROR: load failed! ret: " << ret;
TINYUSDZLOGE(TAG, "%s", ss.str().c_str());
} else {
ss.str("");
ss << "InternReadFile(): SetupUSDZAssetResolution: OK";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
env.asset_resolver = arr;
}
}
ret = converter.ConvertToRenderScene(env, &render_scene);
if (!ret) {
ss.str("");
ss << "InternReadFile(): ConvertToRenderScene() failed!";
TINYUSDZLOGE(TAG, "%s", ss.str().c_str());
return;
}
// sanityCheckNodesRecursive(pScene->mRootNode);
meshes(render_scene, pScene, nameWExt);
materials(render_scene, pScene, nameWExt);
textures(render_scene, pScene, nameWExt);
textureImages(render_scene, pScene, nameWExt);
buffers(render_scene, pScene, nameWExt);
std::map<size_t, tinyusdz::tydra::Node> meshNodes;
setupNodes(render_scene, pScene, meshNodes, nameWExt);
setupBlendShapes(render_scene, pScene, nameWExt);
}
void USDImporterImplTinyusdz::meshes(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt) {
stringstream ss;
pScene->mNumMeshes = static_cast<unsigned int>(render_scene.meshes.size());
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]();
ss.str("");
ss << "meshes(): pScene->mNumMeshes: " << pScene->mNumMeshes;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
// Export meshes
for (size_t meshIdx = 0; meshIdx < pScene->mNumMeshes; meshIdx++) {
pScene->mMeshes[meshIdx] = new aiMesh();
pScene->mMeshes[meshIdx]->mName.Set(render_scene.meshes[meshIdx].prim_name);
ss.str("");
ss << " mesh[" << meshIdx << "]: " <<
render_scene.meshes[meshIdx].joint_and_weights.jointIndices.size() << " jointIndices, " <<
render_scene.meshes[meshIdx].joint_and_weights.jointWeights.size() << " jointWeights, elementSize: " <<
render_scene.meshes[meshIdx].joint_and_weights.elementSize;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
ss.str("");
ss << " skel_id: " << render_scene.meshes[meshIdx].skel_id;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
if (render_scene.meshes[meshIdx].material_id > -1) {
pScene->mMeshes[meshIdx]->mMaterialIndex = render_scene.meshes[meshIdx].material_id;
}
verticesForMesh(render_scene, pScene, meshIdx, nameWExt);
facesForMesh(render_scene, pScene, meshIdx, nameWExt);
// Some models infer normals from faces, but others need them e.g.
// - apple "toy car" canopy normals will be wrong
// - human "untitled" model (tinyusdz issue #115) will be "splotchy"
normalsForMesh(render_scene, pScene, meshIdx, nameWExt);
materialsForMesh(render_scene, pScene, meshIdx, nameWExt);
uvsForMesh(render_scene, pScene, meshIdx, nameWExt);
}
}
void USDImporterImplTinyusdz::verticesForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt) {
UNUSED(nameWExt);
pScene->mMeshes[meshIdx]->mNumVertices = static_cast<unsigned int>(render_scene.meshes[meshIdx].points.size());
pScene->mMeshes[meshIdx]->mVertices = new aiVector3D[pScene->mMeshes[meshIdx]->mNumVertices];
for (size_t j = 0; j < pScene->mMeshes[meshIdx]->mNumVertices; ++j) {
pScene->mMeshes[meshIdx]->mVertices[j].x = render_scene.meshes[meshIdx].points[j][0];
pScene->mMeshes[meshIdx]->mVertices[j].y = render_scene.meshes[meshIdx].points[j][1];
pScene->mMeshes[meshIdx]->mVertices[j].z = render_scene.meshes[meshIdx].points[j][2];
}
}
void USDImporterImplTinyusdz::facesForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt) {
UNUSED(nameWExt);
pScene->mMeshes[meshIdx]->mNumFaces = static_cast<unsigned int>(render_scene.meshes[meshIdx].faceVertexCounts().size());
pScene->mMeshes[meshIdx]->mFaces = new aiFace[pScene->mMeshes[meshIdx]->mNumFaces]();
size_t faceVertIdxOffset = 0;
for (size_t faceIdx = 0; faceIdx < pScene->mMeshes[meshIdx]->mNumFaces; ++faceIdx) {
pScene->mMeshes[meshIdx]->mFaces[faceIdx].mNumIndices = render_scene.meshes[meshIdx].faceVertexCounts()[faceIdx];
pScene->mMeshes[meshIdx]->mFaces[faceIdx].mIndices = new unsigned int[pScene->mMeshes[meshIdx]->mFaces[faceIdx].mNumIndices];
for (size_t j = 0; j < pScene->mMeshes[meshIdx]->mFaces[faceIdx].mNumIndices; ++j) {
pScene->mMeshes[meshIdx]->mFaces[faceIdx].mIndices[j] =
render_scene.meshes[meshIdx].faceVertexIndices()[j + faceVertIdxOffset];
}
faceVertIdxOffset += pScene->mMeshes[meshIdx]->mFaces[faceIdx].mNumIndices;
}
}
void USDImporterImplTinyusdz::normalsForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt) {
UNUSED(nameWExt);
pScene->mMeshes[meshIdx]->mNormals = new aiVector3D[pScene->mMeshes[meshIdx]->mNumVertices];
const float *floatPtr = reinterpret_cast<const float *>(render_scene.meshes[meshIdx].normals.get_data().data());
for (size_t vertIdx = 0, fpj = 0; vertIdx < pScene->mMeshes[meshIdx]->mNumVertices; ++vertIdx, fpj += 3) {
pScene->mMeshes[meshIdx]->mNormals[vertIdx].x = floatPtr[fpj];
pScene->mMeshes[meshIdx]->mNormals[vertIdx].y = floatPtr[fpj + 1];
pScene->mMeshes[meshIdx]->mNormals[vertIdx].z = floatPtr[fpj + 2];
}
}
void USDImporterImplTinyusdz::materialsForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt) {
UNUSED(render_scene); UNUSED(pScene); UNUSED(meshIdx); UNUSED(nameWExt);
}
void USDImporterImplTinyusdz::uvsForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt) {
UNUSED(nameWExt);
const size_t uvSlotsCount = render_scene.meshes[meshIdx].texcoords.size();
if (uvSlotsCount < 1) {
return;
}
pScene->mMeshes[meshIdx]->mTextureCoords[0] = new aiVector3D[pScene->mMeshes[meshIdx]->mNumVertices];
pScene->mMeshes[meshIdx]->mNumUVComponents[0] = 2; // U and V stored in "x", "y" of aiVector3D.
for (unsigned int uvSlotIdx = 0; uvSlotIdx < uvSlotsCount; ++uvSlotIdx) {
const auto uvsForSlot = render_scene.meshes[meshIdx].texcoords.at(uvSlotIdx);
if (uvsForSlot.get_data().size() == 0) {
continue;
}
const float *floatPtr = reinterpret_cast<const float *>(uvsForSlot.get_data().data());
for (size_t vertIdx = 0, fpj = 0; vertIdx < pScene->mMeshes[meshIdx]->mNumVertices; ++vertIdx, fpj += 2) {
pScene->mMeshes[meshIdx]->mTextureCoords[uvSlotIdx][vertIdx].x = floatPtr[fpj];
pScene->mMeshes[meshIdx]->mTextureCoords[uvSlotIdx][vertIdx].y = floatPtr[fpj + 1];
}
}
}
static aiColor3D *ownedColorPtrFor(const std::array<float, 3> &color) {
aiColor3D *colorPtr = new aiColor3D();
colorPtr->r = color[0];
colorPtr->g = color[1];
colorPtr->b = color[2];
return colorPtr;
}
static std::string nameForTextureWithId(
const tinyusdz::tydra::RenderScene &render_scene,
const int targetId) {
stringstream ss;
std::string texName;
for (const auto &image : render_scene.images) {
if (image.buffer_id == targetId) {
texName = image.asset_identifier;
ss.str("");
ss << "nameForTextureWithId(): found texture " << texName << " with target id " << targetId;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
break;
}
}
ss.str("");
ss << "nameForTextureWithId(): ERROR! Failed to find texture with target id " << targetId;
TINYUSDZLOGE(TAG, "%s", ss.str().c_str());
return texName;
}
static void assignTexture(
const tinyusdz::tydra::RenderScene &render_scene,
const tinyusdz::tydra::RenderMaterial &material,
aiMaterial *mat,
const int textureId,
const int aiTextureType) {
UNUSED(material);
std::string name = nameForTextureWithId(render_scene, textureId);
aiString *texName = new aiString();
texName->Set(name);
stringstream ss;
ss.str("");
ss << "assignTexture(): name: " << name;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
// TODO: verify hard-coded '0' index is correct
mat->AddProperty(texName, _AI_MATKEY_TEXTURE_BASE, aiTextureType, 0);
}
void USDImporterImplTinyusdz::materials(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt) {
const size_t numMaterials{render_scene.materials.size()};
(void) numMaterials; // Ignore unused variable when -Werror enabled
stringstream ss;
ss.str("");
ss << "materials(): model" << nameWExt << ", numMaterials: " << numMaterials;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
pScene->mNumMaterials = 0;
if (render_scene.materials.empty()) {
return;
}
pScene->mMaterials = new aiMaterial *[render_scene.materials.size()];
for (const auto &material : render_scene.materials) {
ss.str("");
ss << " material[" << pScene->mNumMaterials << "]: name: |" << material.name << "|, disp name: |" << material.display_name << "|";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
aiMaterial *mat = new aiMaterial;
aiString *materialName = new aiString();
materialName->Set(material.name);
mat->AddProperty(materialName, AI_MATKEY_NAME);
mat->AddProperty(
ownedColorPtrFor(material.surfaceShader.diffuseColor.value),
1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty(
ownedColorPtrFor(material.surfaceShader.specularColor.value),
1, AI_MATKEY_COLOR_SPECULAR);
mat->AddProperty(
ownedColorPtrFor(material.surfaceShader.emissiveColor.value),
1, AI_MATKEY_COLOR_EMISSIVE);
ss.str("");
if (material.surfaceShader.diffuseColor.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.diffuseColor.texture_id, aiTextureType_DIFFUSE);
ss << " material[" << pScene->mNumMaterials << "]: diff tex id " << material.surfaceShader.diffuseColor.texture_id << "\n";
}
if (material.surfaceShader.specularColor.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.specularColor.texture_id, aiTextureType_SPECULAR);
ss << " material[" << pScene->mNumMaterials << "]: spec tex id " << material.surfaceShader.specularColor.texture_id << "\n";
}
if (material.surfaceShader.normal.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.normal.texture_id, aiTextureType_NORMALS);
ss << " material[" << pScene->mNumMaterials << "]: normal tex id " << material.surfaceShader.normal.texture_id << "\n";
}
if (material.surfaceShader.emissiveColor.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.emissiveColor.texture_id, aiTextureType_EMISSIVE);
ss << " material[" << pScene->mNumMaterials << "]: emissive tex id " << material.surfaceShader.emissiveColor.texture_id << "\n";
}
if (material.surfaceShader.occlusion.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.occlusion.texture_id, aiTextureType_LIGHTMAP);
ss << " material[" << pScene->mNumMaterials << "]: lightmap (occlusion) tex id " << material.surfaceShader.occlusion.texture_id << "\n";
}
if (material.surfaceShader.metallic.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.metallic.texture_id, aiTextureType_METALNESS);
ss << " material[" << pScene->mNumMaterials << "]: metallic tex id " << material.surfaceShader.metallic.texture_id << "\n";
}
if (material.surfaceShader.roughness.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.roughness.texture_id, aiTextureType_DIFFUSE_ROUGHNESS);
ss << " material[" << pScene->mNumMaterials << "]: roughness tex id " << material.surfaceShader.roughness.texture_id << "\n";
}
if (material.surfaceShader.clearcoat.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.clearcoat.texture_id, aiTextureType_CLEARCOAT);
ss << " material[" << pScene->mNumMaterials << "]: clearcoat tex id " << material.surfaceShader.clearcoat.texture_id << "\n";
}
if (material.surfaceShader.opacity.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.opacity.texture_id, aiTextureType_OPACITY);
ss << " material[" << pScene->mNumMaterials << "]: opacity tex id " << material.surfaceShader.opacity.texture_id << "\n";
}
if (material.surfaceShader.displacement.is_texture()) {
assignTexture(render_scene, material, mat, material.surfaceShader.displacement.texture_id, aiTextureType_DISPLACEMENT);
ss << " material[" << pScene->mNumMaterials << "]: displacement tex id " << material.surfaceShader.displacement.texture_id << "\n";
}
if (material.surfaceShader.clearcoatRoughness.is_texture()) {
ss << " material[" << pScene->mNumMaterials << "]: clearcoatRoughness tex id " << material.surfaceShader.clearcoatRoughness.texture_id << "\n";
}
if (material.surfaceShader.opacityThreshold.is_texture()) {
ss << " material[" << pScene->mNumMaterials << "]: opacityThreshold tex id " << material.surfaceShader.opacityThreshold.texture_id << "\n";
}
if (material.surfaceShader.ior.is_texture()) {
ss << " material[" << pScene->mNumMaterials << "]: ior tex id " << material.surfaceShader.ior.texture_id << "\n";
}
if (!ss.str().empty()) {
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
}
pScene->mMaterials[pScene->mNumMaterials] = mat;
++pScene->mNumMaterials;
}
}
void USDImporterImplTinyusdz::textures(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt) {
UNUSED(pScene);
const size_t numTextures{render_scene.textures.size()};
UNUSED(numTextures); // Ignore unused variable when -Werror enabled
stringstream ss;
ss.str("");
ss << "textures(): model" << nameWExt << ", numTextures: " << numTextures;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
size_t i{0};
UNUSED(i);
for (const auto &texture : render_scene.textures) {
UNUSED(texture);
ss.str("");
ss << " texture[" << i << "]: id: " << texture.texture_image_id << ", disp name: |" << texture.display_name << "|, varname_uv: " <<
texture.varname_uv << ", prim_name: |" << texture.prim_name << "|, abs_path: |" << texture.abs_path << "|";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
++i;
}
}
/**
* "owned" as in, used "new" to allocate and aiScene now responsible for "delete"
*
* @param render_scene renderScene object
* @param image textureImage object
* @param nameWExt filename w/ext (use to extract file type hint)
* @return aiTexture ptr
*/
static aiTexture *ownedEmbeddedTextureFor(
const tinyusdz::tydra::RenderScene &render_scene,
const tinyusdz::tydra::TextureImage &image,
const std::string &nameWExt) {
UNUSED(nameWExt);
stringstream ss;
aiTexture *tex = new aiTexture();
size_t pos = image.asset_identifier.find_last_of('/');
string embTexName{image.asset_identifier.substr(pos + 1)};
tex->mFilename.Set(image.asset_identifier.c_str());
tex->mHeight = image.height;
// const size_t imageBytesCount{render_scene.buffers[image.buffer_id].data.size() / image.channels};
tex->mWidth = image.width;
if (tex->mHeight == 0) {
pos = embTexName.find_last_of('.');
strncpy(tex->achFormatHint, embTexName.substr(pos + 1).c_str(), 3);
const size_t imageBytesCount{render_scene.buffers[image.buffer_id].data.size()};
tex->pcData = (aiTexel *) new char[imageBytesCount];
memcpy(tex->pcData, &render_scene.buffers[image.buffer_id].data[0], imageBytesCount);
} else {
string formatHint{"rgba8888"};
strncpy(tex->achFormatHint, formatHint.c_str(), 8);
const size_t imageTexelsCount{tex->mWidth * tex->mHeight};
tex->pcData = (aiTexel *) new char[imageTexelsCount * image.channels];
const float *floatPtr = reinterpret_cast<const float *>(&render_scene.buffers[image.buffer_id].data[0]);
ss.str("");
ss << "ownedEmbeddedTextureFor(): manual fill...";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
for (size_t i = 0, fpi = 0; i < imageTexelsCount; ++i, fpi += 4) {
tex->pcData[i].b = static_cast<uint8_t>(floatPtr[fpi] * 255);
tex->pcData[i].g = static_cast<uint8_t>(floatPtr[fpi + 1] * 255);
tex->pcData[i].r = static_cast<uint8_t>(floatPtr[fpi + 2] * 255);
tex->pcData[i].a = static_cast<uint8_t>(floatPtr[fpi + 3] * 255);
}
ss.str("");
ss << "ownedEmbeddedTextureFor(): imageTexelsCount: " << imageTexelsCount << ", channels: " << image.channels;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
}
return tex;
}
void USDImporterImplTinyusdz::textureImages(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt) {
stringstream ss;
const size_t numTextureImages{render_scene.images.size()};
UNUSED(numTextureImages); // Ignore unused variable when -Werror enabled
ss.str("");
ss << "textureImages(): model" << nameWExt << ", numTextureImages: " << numTextureImages;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
pScene->mTextures = nullptr; // Need to iterate over images before knowing if valid textures available
pScene->mNumTextures = 0;
for (const auto &image : render_scene.images) {
ss.str("");
ss << " image[" << pScene->mNumTextures << "]: |" << image.asset_identifier << "| w: " << image.width << ", h: " << image.height <<
", channels: " << image.channels << ", miplevel: " << image.miplevel << ", buffer id: " << image.buffer_id << "\n" <<
" buffers.size(): " << render_scene.buffers.size() << ", data empty? " << render_scene.buffers[image.buffer_id].data.empty();
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
if (image.buffer_id > -1 &&
image.buffer_id < static_cast<long int>(render_scene.buffers.size()) &&
!render_scene.buffers[image.buffer_id].data.empty()) {
aiTexture *tex = ownedEmbeddedTextureFor(
render_scene,
image,
nameWExt);
if (pScene->mTextures == nullptr) {
ss.str("");
ss << " Init pScene->mTextures[" << render_scene.images.size() << "]";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
pScene->mTextures = new aiTexture *[render_scene.images.size()];
}
ss.str("");
ss << " pScene->mTextures[" << pScene->mNumTextures << "] name: |" << tex->mFilename.C_Str() <<
"|, w: " << tex->mWidth << ", h: " << tex->mHeight << ", hint: " << tex->achFormatHint;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
pScene->mTextures[pScene->mNumTextures++] = tex;
}
}
}
void USDImporterImplTinyusdz::buffers(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt) {
const size_t numBuffers{render_scene.buffers.size()};
UNUSED(pScene); UNUSED(numBuffers); // Ignore unused variable when -Werror enabled
stringstream ss;
ss.str("");
ss << "buffers(): model" << nameWExt << ", numBuffers: " << numBuffers;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
size_t i = 0;
for (const auto &buffer : render_scene.buffers) {
ss.str("");
ss << " buffer[" << i << "]: count: " << buffer.data.size() << ", type: " << to_string(buffer.componentType);
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
++i;
}
}
void USDImporterImplTinyusdz::setupNodes(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes,
const std::string &nameWExt) {
stringstream ss;
pScene->mRootNode = nodes(render_scene, meshNodes, nameWExt);
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mMeshes = new unsigned int[pScene->mRootNode->mNumMeshes];
ss.str("");
ss << "setupNodes(): pScene->mNumMeshes: " << pScene->mNumMeshes;
if (pScene->mRootNode != nullptr) {
ss << ", mRootNode->mNumMeshes: " << pScene->mRootNode->mNumMeshes;
}
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
for (unsigned int meshIdx = 0; meshIdx < pScene->mNumMeshes; meshIdx++) {
pScene->mRootNode->mMeshes[meshIdx] = meshIdx;
}
}
aiNode *USDImporterImplTinyusdz::nodes(
const tinyusdz::tydra::RenderScene &render_scene,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes,
const std::string &nameWExt) {
const size_t numNodes{render_scene.nodes.size()};
(void) numNodes; // Ignore unused variable when -Werror enabled
stringstream ss;
ss.str("");
ss << "nodes(): model" << nameWExt << ", numNodes: " << numNodes;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
return nodesRecursive(nullptr, render_scene.nodes[0], meshNodes);
}
using Assimp::tinyusdzNodeTypeFor;
using Assimp::tinyUsdzMat4ToAiMat4;
using tinyusdz::tydra::NodeType;
aiNode *USDImporterImplTinyusdz::nodesRecursive(
aiNode *pNodeParent,
const tinyusdz::tydra::Node &node,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes) {
stringstream ss;
aiNode *cNode = new aiNode();
cNode->mParent = pNodeParent;
cNode->mName.Set(node.prim_name);
cNode->mTransformation = tinyUsdzMat4ToAiMat4(node.local_matrix.m);
ss.str("");
ss << "nodesRecursive(): node " << cNode->mName.C_Str() <<
" type: |" << tinyusdzNodeTypeFor(node.nodeType) <<
"|, disp " << node.display_name << ", abs " << node.abs_path;
if (cNode->mParent != nullptr) {
ss << " (parent " << cNode->mParent->mName.C_Str() << ")";
}
ss << " has " << node.children.size() << " children";
if (node.id > -1) {
ss << "\n node mesh id: " << node.id << " (node type: " << tinyusdzNodeTypeFor(node.nodeType) << ")";
meshNodes[node.id] = node;
}
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
if (!node.children.empty()) {
cNode->mNumChildren = static_cast<unsigned int>(node.children.size());
cNode->mChildren = new aiNode *[cNode->mNumChildren];
}
size_t i{0};
for (const auto &childNode: node.children) {
cNode->mChildren[i] = nodesRecursive(cNode, childNode, meshNodes);
++i;
}
return cNode;
}
void USDImporterImplTinyusdz::sanityCheckNodesRecursive(
aiNode *cNode) {
stringstream ss;
ss.str("");
ss << "sanityCheckNodesRecursive(): node " << cNode->mName.C_Str();
if (cNode->mParent != nullptr) {
ss << " (parent " << cNode->mParent->mName.C_Str() << ")";
}
ss << " has " << cNode->mNumChildren << " children";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
for (size_t i = 0; i < cNode->mNumChildren; ++i) {
sanityCheckNodesRecursive(cNode->mChildren[i]);
}
}
void USDImporterImplTinyusdz::setupBlendShapes(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt) {
stringstream ss;
ss.str("");
ss << "setupBlendShapes(): iterating over " << pScene->mNumMeshes << " meshes for model" << nameWExt;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
for (size_t meshIdx = 0; meshIdx < pScene->mNumMeshes; meshIdx++) {
blendShapesForMesh(render_scene, pScene, meshIdx, nameWExt);
}
}
void USDImporterImplTinyusdz::blendShapesForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt) {
UNUSED(nameWExt);
stringstream ss;
const unsigned int numBlendShapeTargets{static_cast<unsigned int>(render_scene.meshes[meshIdx].targets.size())};
UNUSED(numBlendShapeTargets); // Ignore unused variable when -Werror enabled
ss.str("");
ss << " blendShapesForMesh(): mesh[" << meshIdx << "], numBlendShapeTargets: " << numBlendShapeTargets;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
if (numBlendShapeTargets > 0) {
pScene->mMeshes[meshIdx]->mNumAnimMeshes = numBlendShapeTargets;
pScene->mMeshes[meshIdx]->mAnimMeshes = new aiAnimMesh *[pScene->mMeshes[meshIdx]->mNumAnimMeshes];
}
auto mapIter = render_scene.meshes[meshIdx].targets.begin();
size_t animMeshIdx{0};
for (; mapIter != render_scene.meshes[meshIdx].targets.end(); ++mapIter) {
const std::string name{mapIter->first};
const tinyusdz::tydra::ShapeTarget shapeTarget{mapIter->second};
pScene->mMeshes[meshIdx]->mAnimMeshes[animMeshIdx] = aiCreateAnimMesh(pScene->mMeshes[meshIdx]);
ss.str("");
ss << " mAnimMeshes[" << animMeshIdx << "]: mNumVertices: " << pScene->mMeshes[meshIdx]->mAnimMeshes[animMeshIdx]->mNumVertices <<
", target: " << shapeTarget.pointIndices.size() << " pointIndices, " << shapeTarget.pointOffsets.size() <<
" pointOffsets, " << shapeTarget.normalOffsets.size() << " normalOffsets";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
for (size_t iVert = 0; iVert < shapeTarget.pointOffsets.size(); ++iVert) {
pScene->mMeshes[meshIdx]->mAnimMeshes[animMeshIdx]->mVertices[shapeTarget.pointIndices[iVert]] +=
tinyUsdzScaleOrPosToAssimp(shapeTarget.pointOffsets[iVert]);
}
for (size_t iVert = 0; iVert < shapeTarget.normalOffsets.size(); ++iVert) {
pScene->mMeshes[meshIdx]->mAnimMeshes[animMeshIdx]->mNormals[shapeTarget.pointIndices[iVert]] +=
tinyUsdzScaleOrPosToAssimp(shapeTarget.normalOffsets[iVert]);
}
ss.str("");
ss << " target[" << animMeshIdx << "]: name: " << name << ", prim_name: " <<
shapeTarget.prim_name << ", abs_path: " << shapeTarget.abs_path <<
", display_name: " << shapeTarget.display_name << ", " << shapeTarget.pointIndices.size() <<
" pointIndices, " << shapeTarget.pointOffsets.size() << " pointOffsets, " <<
shapeTarget.normalOffsets.size() << " normalOffsets, " << shapeTarget.inbetweens.size() <<
" inbetweens";
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
++animMeshIdx;
}
}
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_USD_IMPORTER

View File

@ -1,155 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, 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 USDLoader.h
* @brief Declaration of the USD importer class.
*/
#pragma once
#ifndef AI_USDLOADER_IMPL_TINYUSDZ_H_INCLUDED
#define AI_USDLOADER_IMPL_TINYUSDZ_H_INCLUDED
#include <assimp/BaseImporter.h>
#include <assimp/scene.h>
#include <assimp/types.h>
#include <vector>
#include <cstdint>
#include "tinyusdz.hh"
#include "tydra/render-data.hh"
namespace Assimp {
class USDImporterImplTinyusdz {
public:
USDImporterImplTinyusdz() = default;
~USDImporterImplTinyusdz() = default;
void InternReadFile(
const std::string &pFile,
aiScene *pScene,
IOSystem *pIOHandler);
void meshes(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt);
void verticesForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt);
void facesForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt);
void normalsForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt);
void materialsForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt);
void uvsForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt);
void materials(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt);
void textures(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt);
void textureImages(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt);
void buffers(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt);
void setupNodes(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes,
const std::string &nameWExt
);
aiNode *nodes(
const tinyusdz::tydra::RenderScene &render_scene,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes,
const std::string &nameWExt);
aiNode *nodesRecursive(
aiNode *pNodeParent,
const tinyusdz::tydra::Node &node,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes);
void sanityCheckNodesRecursive(
aiNode *pNode);
void setupBlendShapes(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const std::string &nameWExt);
void blendShapesForMesh(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
size_t meshIdx,
const std::string &nameWExt);
};
} // namespace Assimp
#endif // AI_USDLOADER_IMPL_TINYUSDZ_H_INCLUDED

View File

@ -1,151 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, 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.
----------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_USD_IMPORTER
#include "USDLoaderImplTinyusdzHelper.h"
#include "../../../contrib/tinyusdz/assimp_tinyusdz_logging.inc"
namespace {
//const char *const TAG = "tinyusdz helper";
}
using ChannelType = tinyusdz::tydra::AnimationChannel::ChannelType;
std::string Assimp::tinyusdzAnimChannelTypeFor(ChannelType animChannel) {
switch (animChannel) {
case ChannelType::Transform: {
return "Transform";
}
case ChannelType::Translation: {
return "Translation";
}
case ChannelType::Rotation: {
return "Rotation";
}
case ChannelType::Scale: {
return "Scale";
}
case ChannelType::Weight: {
return "Weight";
}
default:
return "Invalid";
}
}
using tinyusdz::tydra::NodeType;
std::string Assimp::tinyusdzNodeTypeFor(NodeType type) {
switch (type) {
case NodeType::Xform: {
return "Xform";
}
case NodeType::Mesh: {
return "Mesh";
}
case NodeType::Camera: {
return "Camera";
}
case NodeType::Skeleton: {
return "Skeleton";
}
case NodeType::PointLight: {
return "PointLight";
}
case NodeType::DirectionalLight: {
return "DirectionalLight";
}
case NodeType::EnvmapLight: {
return "EnvmapLight";
}
default:
return "Invalid";
}
}
aiMatrix4x4 Assimp::tinyUsdzMat4ToAiMat4(const double matIn[4][4]) {
aiMatrix4x4 matOut;
matOut.a1 = matIn[0][0];
matOut.a2 = matIn[0][1];
matOut.a3 = matIn[0][2];
matOut.a4 = matIn[0][3];
matOut.b1 = matIn[1][0];
matOut.b2 = matIn[1][1];
matOut.b3 = matIn[1][2];
matOut.b4 = matIn[1][3];
matOut.c1 = matIn[2][0];
matOut.c2 = matIn[2][1];
matOut.c3 = matIn[2][2];
matOut.c4 = matIn[2][3];
matOut.d1 = matIn[3][0];
matOut.d2 = matIn[3][1];
matOut.d3 = matIn[3][2];
matOut.d4 = matIn[3][3];
// matOut.a1 = matIn[0][0];
// matOut.a2 = matIn[1][0];
// matOut.a3 = matIn[2][0];
// matOut.a4 = matIn[3][0];
// matOut.b1 = matIn[0][1];
// matOut.b2 = matIn[1][1];
// matOut.b3 = matIn[2][1];
// matOut.b4 = matIn[3][1];
// matOut.c1 = matIn[0][2];
// matOut.c2 = matIn[1][2];
// matOut.c3 = matIn[2][2];
// matOut.c4 = matIn[3][2];
// matOut.d1 = matIn[0][3];
// matOut.d2 = matIn[1][3];
// matOut.d3 = matIn[2][3];
// matOut.d4 = matIn[3][3];
return matOut;
}
aiVector3D Assimp::tinyUsdzScaleOrPosToAssimp(const std::array<float, 3> &scaleOrPosIn) {
return aiVector3D(scaleOrPosIn[0], scaleOrPosIn[1], scaleOrPosIn[2]);
}
aiQuaternion Assimp::tinyUsdzQuatToAiQuat(const std::array<float, 4> &quatIn) {
// tinyusdz "quat" is x,y,z,w
// aiQuaternion is w,x,y,z
return aiQuaternion(
quatIn[3], quatIn[0], quatIn[1], quatIn[2]);
}
#endif // !! ASSIMP_BUILD_NO_USD_IMPORTER

View File

@ -1,70 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, 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.
----------------------------------------------------------------------
*/
#pragma once
#ifndef AI_USDLOADER_IMPL_TINYUSDZ_HELPER_H_INCLUDED
#define AI_USDLOADER_IMPL_TINYUSDZ_HELPER_H_INCLUDED
#include <assimp/BaseImporter.h>
#include <assimp/scene.h>
#include <assimp/types.h>
#include "tinyusdz.hh"
#include "tydra/render-data.hh"
namespace Assimp {
std::string tinyusdzAnimChannelTypeFor(
tinyusdz::tydra::AnimationChannel::ChannelType animChannel);
std::string tinyusdzNodeTypeFor(tinyusdz::tydra::NodeType type);
aiMatrix4x4 tinyUsdzMat4ToAiMat4(const double matIn[4][4]);
aiVector3D tinyUsdzScaleOrPosToAssimp(const std::array<float, 3> &scaleOrPosIn);
/**
* Convert quaternion from tinyusdz "quat" to assimp "aiQuaternion" type
*
* @param quatIn tinyusdz float[4] in x,y,z,w order
* @return assimp aiQuaternion converted from input
*/
aiQuaternion tinyUsdzQuatToAiQuat(const std::array<float, 4> &quatIn);
} // namespace Assimp
#endif // AI_USDLOADER_IMPL_TINYUSDZ_HELPER_H_INCLUDED

View File

@ -1,116 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, 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 USDLoader.cpp
* @brief Implementation of the USD importer class
*/
#ifndef ASSIMP_BUILD_NO_USD_IMPORTER
#include <memory>
// internal headers
#include <assimp/ai_assert.h>
#include <assimp/anim.h>
#include <assimp/DefaultIOSystem.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/fast_atof.h>
#include <assimp/Importer.hpp>
#include <assimp/importerdesc.h>
#include <assimp/IOStreamBuffer.h>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/StringUtils.h>
#include <assimp/StreamReader.h>
#include "USDLoaderUtil.h"
namespace Assimp {
using namespace std;
bool isUsda(const std::string &pFile) {
size_t pos = pFile.find_last_of('.');
if (pos == string::npos) {
return false;
}
string ext = pFile.substr(pos + 1);
if (ext.size() != 4) {
return false;
}
return (ext[0] == 'u' || ext[0] == 'U') && (ext[1] == 's' || ext[1] == 'S') && (ext[2] == 'd' || ext[2] == 'D') && (ext[3] == 'a' || ext[3] == 'A');
}
bool isUsdc(const std::string &pFile) {
size_t pos = pFile.find_last_of('.');
if (pos == string::npos) {
return false;
}
string ext = pFile.substr(pos + 1);
if (ext.size() != 4) {
return false;
}
return (ext[0] == 'u' || ext[0] == 'U') && (ext[1] == 's' || ext[1] == 'S') && (ext[2] == 'd' || ext[2] == 'D') && (ext[3] == 'c' || ext[3] == 'C');
}
bool isUsdz(const std::string &pFile) {
size_t pos = pFile.find_last_of('.');
if (pos == string::npos) {
return false;
}
string ext = pFile.substr(pos + 1);
if (ext.size() != 4) {
return false;
}
return (ext[0] == 'u' || ext[0] == 'U') && (ext[1] == 's' || ext[1] == 'S') && (ext[2] == 'd' || ext[2] == 'D') && (ext[3] == 'z' || ext[3] == 'Z');
}
bool isUsd(const std::string &pFile) {
size_t pos = pFile.find_last_of('.');
if (pos == string::npos) {
return false;
}
string ext = pFile.substr(pos + 1);
if (ext.size() != 3) {
return false;
}
return (ext[0] == 'u' || ext[0] == 'U') && (ext[1] == 's' || ext[1] == 'S') && (ext[2] == 'd' || ext[2] == 'D');
}
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_USD_IMPORTER

View File

@ -1,60 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, 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 USDLoader.h
* @brief Declaration of the USD importer class.
*/
#pragma once
#ifndef AI_USDLOADER_UTIL_H_INCLUDED
#define AI_USDLOADER_UTIL_H_INCLUDED
#include <string>
namespace Assimp {
bool isUsda(const std::string &pFile);
bool isUsdc(const std::string &pFile);
bool isUsdz(const std::string &pFile);
bool isUsd(const std::string &pFile);
} // namespace Assimp
#endif // AI_USDLOADER_UTIL_H_INCLUDED

View File

@ -1,50 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, 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 USDLoader.h
* @brief Declaration of the USD importer class.
*/
#pragma once
#ifndef AI_USDPREPROCESSOR_H_INCLUDED
#define AI_USDPREPROCESSOR_H_INCLUDED
#define UNUSED(x) (void) x
#endif // AI_USDPREPROCESSOR_H_INCLUDED

View File

@ -452,7 +452,7 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
aiColor3D color(1.f, 1.f, 1.f); aiColor3D color(1.f, 1.f, 1.f);
aiString s; aiString s;
::ai_snprintf(s.data, AI_MAXLEN, "mat%u_tx%u_", i, materials[i].tex); ::ai_snprintf(s.data, MAXLEN, "mat%u_tx%u_", i, materials[i].tex);
// set the two-sided flag // set the two-sided flag
if (materials[i].type == Unreal::MF_NORMAL_TS) { if (materials[i].type == Unreal::MF_NORMAL_TS) {
@ -472,7 +472,7 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
// a special name for the weapon attachment point // a special name for the weapon attachment point
if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) { if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) {
s.length = ::ai_snprintf(s.data, AI_MAXLEN, "$WeaponTag$"); s.length = ::ai_snprintf(s.data, MAXLEN, "$WeaponTag$");
color = aiColor3D(0.f, 0.f, 0.f); color = aiColor3D(0.f, 0.f, 0.f);
} }

View File

@ -109,7 +109,7 @@ inline void SetMaterialColorProperty(std::vector<int> &embeddedTexIdxs, Asset &
if (texIdx != -1) { // embedded if (texIdx != -1) { // embedded
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
uri.data[0] = '*'; uri.data[0] = '*';
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx); uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
} }
mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0); mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
@ -242,7 +242,7 @@ void glTFImporter::ImportMeshes(glTF::Asset &r) {
if (mesh.primitives.size() > 1) { if (mesh.primitives.size() > 1) {
ai_uint32 &len = aim->mName.length; ai_uint32 &len = aim->mName.length;
aim->mName.data[len] = '-'; aim->mName.data[len] = '-';
len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(AI_MAXLEN - len - 1), p); len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
} }
switch (prim.mode) { switch (prim.mode) {

View File

@ -1036,10 +1036,10 @@ size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remap
outData = new T[usedCount]; outData = new T[usedCount];
if (remappingIndices != nullptr) { if (remappingIndices != nullptr) {
const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); const unsigned int maxIndex = static_cast<unsigned int>(maxSize / stride - 1);
for (size_t i = 0; i < usedCount; ++i) { for (size_t i = 0; i < usedCount; ++i) {
size_t srcIdx = (*remappingIndices)[i]; size_t srcIdx = (*remappingIndices)[i];
if (srcIdx >= maxIndexCount) { if (srcIdx > maxIndex) {
throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
} }
memcpy(outData + i, data + srcIdx * stride, elemSize); memcpy(outData + i, data + srcIdx * stride, elemSize);
@ -1440,7 +1440,7 @@ inline void MaterialSheen::SetDefaults() {
inline void MaterialVolume::SetDefaults() { inline void MaterialVolume::SetDefaults() {
//KHR_materials_volume properties //KHR_materials_volume properties
thicknessFactor = 0.f; thicknessFactor = 0.f;
attenuationDistance = std::numeric_limits<float>::infinity(); attenuationDistance = INFINITY;
SetVector(attenuationColor, defaultAttenuationColor); SetVector(attenuationColor, defaultAttenuationColor);
} }

View File

@ -507,7 +507,7 @@ namespace glTF2 {
WriteTex(materialVolume, volume.thicknessTexture, "thicknessTexture", w.mAl); WriteTex(materialVolume, volume.thicknessTexture, "thicknessTexture", w.mAl);
if (volume.attenuationDistance != std::numeric_limits<float>::infinity()) { if (volume.attenuationDistance != INFINITY) {
WriteFloat(materialVolume, volume.attenuationDistance, "attenuationDistance", w.mAl); WriteFloat(materialVolume, volume.attenuationDistance, "attenuationDistance", w.mAl);
} }
@ -940,7 +940,7 @@ namespace glTF2 {
if (outfile->Write(bodyBuffer->GetPointer(), 1, bodyBuffer->byteLength) != bodyBuffer->byteLength) { if (outfile->Write(bodyBuffer->GetPointer(), 1, bodyBuffer->byteLength) != bodyBuffer->byteLength) {
throw DeadlyExportError("Failed to write body data!"); throw DeadlyExportError("Failed to write body data!");
} }
if (curPaddingLength && outfile->Write(&padding, 1, curPaddingLength) != curPaddingLength) { if (curPaddingLength && outfile->Write(&padding, 1, paddingLength) != paddingLength) {
throw DeadlyExportError("Failed to write body data padding!"); throw DeadlyExportError("Failed to write body data padding!");
} }
} }

View File

@ -161,7 +161,7 @@ static void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
if (texIdx != -1) { // embedded if (texIdx != -1) { // embedded
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
uri.data[0] = '*'; uri.data[0] = '*';
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx); uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
} }
mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot));
@ -539,7 +539,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
if (mesh.primitives.size() > 1) { if (mesh.primitives.size() > 1) {
ai_uint32 &len = aim->mName.length; ai_uint32 &len = aim->mName.length;
aim->mName.data[len] = '-'; aim->mName.data[len] = '-';
len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(AI_MAXLEN - len - 1), p); len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
} }
switch (prim.mode) { switch (prim.mode) {

View File

@ -828,17 +828,6 @@ ADD_ASSIMP_IMPORTER( 3D
AssetLib/Unreal/UnrealLoader.h AssetLib/Unreal/UnrealLoader.h
) )
ADD_ASSIMP_IMPORTER( USD
AssetLib/USD/USDLoader.cpp
AssetLib/USD/USDLoader.h
AssetLib/USD/USDLoaderImplTinyusdz.cpp
AssetLib/USD/USDLoaderImplTinyusdz.h
AssetLib/USD/USDLoaderImplTinyusdzHelper.cpp
AssetLib/USD/USDLoaderImplTinyusdzHelper.h
AssetLib/USD/USDLoaderUtil.cpp
AssetLib/USD/USDLoaderUtil.h
)
ADD_ASSIMP_IMPORTER( X ADD_ASSIMP_IMPORTER( X
AssetLib/X/XFileHelper.h AssetLib/X/XFileHelper.h
AssetLib/X/XFileImporter.cpp AssetLib/X/XFileImporter.cpp
@ -932,128 +921,11 @@ SET( Extra_SRCS
) )
SOURCE_GROUP( Extra FILES ${Extra_SRCS}) SOURCE_GROUP( Extra FILES ${Extra_SRCS})
# USD/USDA/USDC/USDZ support
# tinyusdz
IF (ASSIMP_BUILD_USD_IMPORTER)
if (ASSIMP_BUILD_USD_VERBOSE_LOGS)
ADD_DEFINITIONS( -DASSIMP_USD_VERBOSE_LOGS)
endif ()
# Use CMAKE_CURRENT_SOURCE_DIR which provides assimp-local path (CMAKE_SOURCE_DIR is
# relative to top-level/main project)
set(Tinyusdz_BASE_ABSPATH "${CMAKE_CURRENT_SOURCE_DIR}/../contrib/tinyusdz")
set(Tinyusdz_REPO_ABSPATH "${Tinyusdz_BASE_ABSPATH}/autoclone")
# Note: ALWAYS specify a git commit hash (or tag) instead of a branch name; using a branch
# name can lead to non-deterministic (unpredictable) results since the code is potentially
# in flux
# "dev" branch, 9 Jul 2024
set(TINYUSDZ_GIT_TAG "bd2a1edbbf69f352a6c40730114db9918c384848")
message("****")
message("\n\n**** Cloning tinyusdz repo, git tag ${TINYUSDZ_GIT_TAG}\n\n")
# Patch required to build arm32 on android
set(TINYUSDZ_PATCH_CMD git apply ${Tinyusdz_BASE_ABSPATH}/patches/tinyusdz.patch)
# Note: CMake's "FetchContent" (which executes at configure time) is much better for this use case
# than "ExternalProject" (which executes at build time); we just want to clone a repo and
# block (wait) as long as necessary until cloning is complete, so we immediately have full
# access to the cloned source files
include(FetchContent)
# Only want to clone once (on Android, using SOURCE_DIR will clone per-ABI (x86, x86_64 etc))
set(FETCHCONTENT_BASE_DIR ${Tinyusdz_REPO_ABSPATH})
set(FETCHCONTENT_QUIET on) # Turn off to troubleshoot repo clone problems
set(FETCHCONTENT_UPDATES_DISCONNECTED on) # Prevent other ABIs from re-cloning/re-patching etc
FetchContent_Declare(
tinyusdz_repo
GIT_REPOSITORY "https://github.com/lighttransport/tinyusdz"
GIT_TAG ${TINYUSDZ_GIT_TAG}
PATCH_COMMAND ${TINYUSDZ_PATCH_CMD}
)
FetchContent_MakeAvailable(tinyusdz_repo)
message("**** Finished cloning tinyusdz repo")
message("****")
set(Tinyusdz_SRC_ABSPATH "${Tinyusdz_REPO_ABSPATH}/tinyusdz_repo-src/src")
set(Tinyusdz_SRCS
${Tinyusdz_SRC_ABSPATH}/ascii-parser.cc
${Tinyusdz_SRC_ABSPATH}/ascii-parser-basetype.cc
${Tinyusdz_SRC_ABSPATH}/ascii-parser-timesamples.cc
${Tinyusdz_SRC_ABSPATH}/ascii-parser-timesamples-array.cc
${Tinyusdz_SRC_ABSPATH}/asset-resolution.cc
${Tinyusdz_SRC_ABSPATH}/composition.cc
${Tinyusdz_SRC_ABSPATH}/crate-format.cc
${Tinyusdz_SRC_ABSPATH}/crate-pprint.cc
${Tinyusdz_SRC_ABSPATH}/crate-reader.cc
${Tinyusdz_SRC_ABSPATH}/image-loader.cc
${Tinyusdz_SRC_ABSPATH}/image-util.cc
${Tinyusdz_SRC_ABSPATH}/image-writer.cc
${Tinyusdz_SRC_ABSPATH}/io-util.cc
${Tinyusdz_SRC_ABSPATH}/linear-algebra.cc
${Tinyusdz_SRC_ABSPATH}/path-util.cc
${Tinyusdz_SRC_ABSPATH}/pprinter.cc
${Tinyusdz_SRC_ABSPATH}/prim-composition.cc
${Tinyusdz_SRC_ABSPATH}/prim-reconstruct.cc
${Tinyusdz_SRC_ABSPATH}/prim-types.cc
${Tinyusdz_SRC_ABSPATH}/primvar.cc
${Tinyusdz_SRC_ABSPATH}/stage.cc
${Tinyusdz_SRC_ABSPATH}/str-util.cc
${Tinyusdz_SRC_ABSPATH}/tiny-format.cc
${Tinyusdz_SRC_ABSPATH}/tinyusdz.cc
${Tinyusdz_SRC_ABSPATH}/tydra/attribute-eval.cc
${Tinyusdz_SRC_ABSPATH}/tydra/attribute-eval-typed.cc
${Tinyusdz_SRC_ABSPATH}/tydra/attribute-eval-typed-animatable.cc
${Tinyusdz_SRC_ABSPATH}/tydra/attribute-eval-typed-animatable-fallback.cc
${Tinyusdz_SRC_ABSPATH}/tydra/attribute-eval-typed-fallback.cc
${Tinyusdz_SRC_ABSPATH}/tydra/facial.cc
${Tinyusdz_SRC_ABSPATH}/tydra/prim-apply.cc
${Tinyusdz_SRC_ABSPATH}/tydra/render-data.cc
${Tinyusdz_SRC_ABSPATH}/tydra/scene-access.cc
${Tinyusdz_SRC_ABSPATH}/tydra/shader-network.cc
${Tinyusdz_SRC_ABSPATH}/usda-reader.cc
${Tinyusdz_SRC_ABSPATH}/usda-writer.cc
${Tinyusdz_SRC_ABSPATH}/usdc-reader.cc
${Tinyusdz_SRC_ABSPATH}/usdc-writer.cc
${Tinyusdz_SRC_ABSPATH}/usdGeom.cc
${Tinyusdz_SRC_ABSPATH}/usdLux.cc
${Tinyusdz_SRC_ABSPATH}/usdMtlx.cc
${Tinyusdz_SRC_ABSPATH}/usdShade.cc
${Tinyusdz_SRC_ABSPATH}/usdSkel.cc
${Tinyusdz_SRC_ABSPATH}/value-pprint.cc
${Tinyusdz_SRC_ABSPATH}/value-types.cc
${Tinyusdz_SRC_ABSPATH}/xform.cc
)
set(Tinyusdz_DEP_SOURCES
${Tinyusdz_SRC_ABSPATH}/external/fpng.cpp
#${Tinyusdz_SRC_ABSPATH}/external/staticstruct.cc
#${Tinyusdz_SRC_ABSPATH}/external/string_id/database.cpp
#${Tinyusdz_SRC_ABSPATH}/external/string_id/error.cpp
#${Tinyusdz_SRC_ABSPATH}/external/string_id/string_id.cpp
#${Tinyusdz_SRC_ABSPATH}/external/tinyxml2/tinyxml2.cpp
${Tinyusdz_SRC_ABSPATH}/integerCoding.cpp
${Tinyusdz_SRC_ABSPATH}/lz4-compression.cc
${Tinyusdz_SRC_ABSPATH}/lz4/lz4.c
)
set(tinyusdz_INCLUDE_DIRS "${Tinyusdz_SRC_ABSPATH}")
INCLUDE_DIRECTORIES(${tinyusdz_INCLUDE_DIRS})
SOURCE_GROUP( Contrib\\Tinyusdz
FILES
${Tinyusdz_SRCS}
${Tinyusdz_DEP_SOURCES}
)
MESSAGE(STATUS "tinyusdz enabled")
ELSE() # IF (ASSIMP_BUILD_USD_IMPORTER)
set(Tinyusdz_SRCS "")
set(Tinyusdz_DEP_SOURCES "")
MESSAGE(STATUS "tinyusdz disabled")
ENDIF() # IF (ASSIMP_BUILD_USD_IMPORTER)
# pugixml # pugixml
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(pugixml) hunter_add_package(pugixml)
find_package(pugixml CONFIG REQUIRED) find_package(pugixml CONFIG REQUIRED)
ELSEIF(NOT TARGET pugixml::pugixml) ELSE()
SET( Pugixml_SRCS SET( Pugixml_SRCS
../contrib/pugixml/src/pugiconfig.hpp ../contrib/pugixml/src/pugiconfig.hpp
../contrib/pugixml/src/pugixml.hpp ../contrib/pugixml/src/pugixml.hpp
@ -1299,8 +1171,6 @@ SET( assimp_src
${openddl_parser_SRCS} ${openddl_parser_SRCS}
${open3dgc_SRCS} ${open3dgc_SRCS}
${ziplib_SRCS} ${ziplib_SRCS}
${Tinyusdz_SRCS}
${Tinyusdz_DEP_SOURCES}
${Pugixml_SRCS} ${Pugixml_SRCS}
${stb_SRCS} ${stb_SRCS}
# Necessary to show the headers in the project when using the VC++ generator: # Necessary to show the headers in the project when using the VC++ generator:
@ -1334,7 +1204,7 @@ ADD_LIBRARY(assimp::assimp ALIAS assimp)
IF (BUILD_SHARED_LIBS) IF (BUILD_SHARED_LIBS)
TARGET_COMPILE_DEFINITIONS(assimp PRIVATE ASSIMP_BUILD_DLL_EXPORT) TARGET_COMPILE_DEFINITIONS(assimp PRIVATE ASSIMP_BUILD_DLL_EXPORT)
ELSE () ELSE ()
TARGET_COMPILE_DEFINITIONS(assimp PRIVATE OPENDDL_STATIC_LIBARY P2T_STATIC_EXPORTS) TARGET_COMPILE_DEFINITIONS(assimp PRIVATE OPENDDL_STATIC_LIBARY)
ENDIF () ENDIF ()
TARGET_USE_COMMON_OUTPUT_DIRECTORY(assimp) TARGET_USE_COMMON_OUTPUT_DIRECTORY(assimp)
@ -1396,7 +1266,6 @@ IF (ASSIMP_WARNINGS_AS_ERRORS)
-Wno-unused-template -Wno-unused-template
-Wno-undefined-func-template -Wno-undefined-func-template
-Wno-declaration-after-statement -Wno-declaration-after-statement
-Wno-deprecated-declarations
) )
ELSE() ELSE()
TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX) TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX)
@ -1418,7 +1287,9 @@ TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
TARGET_LINK_LIBRARIES(assimp TARGET_LINK_LIBRARIES(assimp
PUBLIC PUBLIC
#polyclipping::polyclipping
openddlparser::openddl_parser openddlparser::openddl_parser
#poly2tri::poly2tri
minizip::minizip minizip::minizip
ZLIB::zlib ZLIB::zlib
RapidJSON::rapidjson RapidJSON::rapidjson
@ -1438,9 +1309,6 @@ ELSE()
if (ASSIMP_BUILD_DRACO) if (ASSIMP_BUILD_DRACO)
target_link_libraries(assimp ${draco_LIBRARIES}) target_link_libraries(assimp ${draco_LIBRARIES})
endif() endif()
if(TARGET pugixml::pugixml)
target_link_libraries(assimp pugixml::pugixml)
endif()
ENDIF() ENDIF()
if(ASSIMP_ANDROID_JNIIOSYSTEM) if(ASSIMP_ANDROID_JNIIOSYSTEM)
@ -1577,7 +1445,7 @@ if(MSVC AND ASSIMP_INSTALL_PDB)
COMPILE_PDB_NAME_DEBUG assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX} COMPILE_PDB_NAME_DEBUG assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}
) )
IF(is_multi_config) IF(GENERATOR_IS_MULTI_CONFIG)
install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
DESTINATION ${ASSIMP_LIB_INSTALL_DIR} DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
CONFIGURATIONS Debug CONFIGURATIONS Debug

View File

@ -359,25 +359,20 @@ void CallbackToLogRedirector(const char *msg, char *dt) {
s->write(msg); s->write(msg);
} }
static LogStream *DefaultStream = nullptr;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, const char *file) { ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, const char *file) {
aiLogStream sout; aiLogStream sout;
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
if (DefaultStream == nullptr) { LogStream *stream = LogStream::createDefaultStream(pStream, file);
DefaultStream = LogStream::createDefaultStream(pStream, file); if (!stream) {
}
if (!DefaultStream) {
sout.callback = nullptr; sout.callback = nullptr;
sout.user = nullptr; sout.user = nullptr;
} else { } else {
sout.callback = &CallbackToLogRedirector; sout.callback = &CallbackToLogRedirector;
sout.user = (char *)DefaultStream; sout.user = (char *)stream;
} }
gPredefinedStreams.push_back(DefaultStream); gPredefinedStreams.push_back(stream);
ASSIMP_END_EXCEPTION_REGION(aiLogStream); ASSIMP_END_EXCEPTION_REGION(aiLogStream);
return sout; return sout;
} }
@ -517,11 +512,6 @@ void aiGetMemoryRequirements(const C_STRUCT aiScene *pIn,
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------
ASSIMP_API const C_STRUCT aiTexture *aiGetEmbeddedTexture(const C_STRUCT aiScene *pIn, const char *filename) {
return pIn->GetEmbeddedTexture(filename);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiPropertyStore *aiCreatePropertyStore(void) { ASSIMP_API aiPropertyStore *aiCreatePropertyStore(void) {
return reinterpret_cast<aiPropertyStore *>(new PropertyMap()); return reinterpret_cast<aiPropertyStore *>(new PropertyMap());
@ -753,14 +743,14 @@ ASSIMP_API void aiVector2DivideByVector(
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API ai_real aiVector2Length( ASSIMP_API float aiVector2Length(
const C_STRUCT aiVector2D *v) { const C_STRUCT aiVector2D *v) {
ai_assert(nullptr != v); ai_assert(nullptr != v);
return v->Length(); return v->Length();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API ai_real aiVector2SquareLength( ASSIMP_API float aiVector2SquareLength(
const C_STRUCT aiVector2D *v) { const C_STRUCT aiVector2D *v) {
ai_assert(nullptr != v); ai_assert(nullptr != v);
return v->SquareLength(); return v->SquareLength();
@ -774,7 +764,7 @@ ASSIMP_API void aiVector2Negate(
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API ai_real aiVector2DotProduct( ASSIMP_API float aiVector2DotProduct(
const C_STRUCT aiVector2D *a, const C_STRUCT aiVector2D *a,
const C_STRUCT aiVector2D *b) { const C_STRUCT aiVector2D *b) {
ai_assert(nullptr != a); ai_assert(nullptr != a);
@ -869,14 +859,14 @@ ASSIMP_API void aiVector3DivideByVector(
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API ai_real aiVector3Length( ASSIMP_API float aiVector3Length(
const C_STRUCT aiVector3D *v) { const C_STRUCT aiVector3D *v) {
ai_assert(nullptr != v); ai_assert(nullptr != v);
return v->Length(); return v->Length();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API ai_real aiVector3SquareLength( ASSIMP_API float aiVector3SquareLength(
const C_STRUCT aiVector3D *v) { const C_STRUCT aiVector3D *v) {
ai_assert(nullptr != v); ai_assert(nullptr != v);
return v->SquareLength(); return v->SquareLength();
@ -890,7 +880,7 @@ ASSIMP_API void aiVector3Negate(
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API ai_real aiVector3DotProduct( ASSIMP_API float aiVector3DotProduct(
const C_STRUCT aiVector3D *a, const C_STRUCT aiVector3D *a,
const C_STRUCT aiVector3D *b) { const C_STRUCT aiVector3D *b) {
ai_assert(nullptr != a); ai_assert(nullptr != a);
@ -976,7 +966,7 @@ ASSIMP_API void aiMatrix3Inverse(C_STRUCT aiMatrix3x3 *mat) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API ai_real aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) { ASSIMP_API float aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) {
ai_assert(nullptr != mat); ai_assert(nullptr != mat);
return mat->Determinant(); return mat->Determinant();
} }
@ -1076,7 +1066,7 @@ ASSIMP_API void aiMatrix4Inverse(C_STRUCT aiMatrix4x4 *mat) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API ai_real aiMatrix4Determinant(const C_STRUCT aiMatrix4x4 *mat) { ASSIMP_API float aiMatrix4Determinant(const C_STRUCT aiMatrix4x4 *mat) {
ai_assert(nullptr != mat); ai_assert(nullptr != mat);
return mat->Determinant(); return mat->Determinant();
} }
@ -1278,6 +1268,7 @@ ASSIMP_API void aiQuaternionInterpolate(
aiQuaternion::Interpolate(*dst, *start, *end, factor); aiQuaternion::Interpolate(*dst, *start, *end, factor);
} }
// stb_image is a lightweight image loader. It is shared by: // stb_image is a lightweight image loader. It is shared by:
// - M3D import // - M3D import
// - PBRT export // - PBRT export

View File

@ -250,10 +250,9 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
/*static*/ bool BaseImporter::SimpleExtensionCheck(const std::string &pFile, /*static*/ bool BaseImporter::SimpleExtensionCheck(const std::string &pFile,
const char *ext0, const char *ext0,
const char *ext1, const char *ext1,
const char *ext2, const char *ext2) {
const char *ext3) {
std::set<std::string> extensions; std::set<std::string> extensions;
for (const char* ext : {ext0, ext1, ext2, ext3}) { for (const char* ext : {ext0, ext1, ext2}) {
if (ext == nullptr) continue; if (ext == nullptr) continue;
extensions.emplace(ext); extensions.emplace(ext);
} }

View File

@ -93,10 +93,6 @@ static std::string WideToUtf8(const wchar_t *in) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Tests for the existence of a file at the given path. // Tests for the existence of a file at the given path.
bool DefaultIOSystem::Exists(const char *pFile) const { bool DefaultIOSystem::Exists(const char *pFile) const {
if (pFile == nullptr) {
return false;
}
#ifdef _WIN32 #ifdef _WIN32
struct __stat64 filestat; struct __stat64 filestat;
if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) { if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) {

View File

@ -848,7 +848,11 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
break; break;
} }
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
continue;
#endif // no validation
// If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
if (pimpl->bExtraVerbose) { if (pimpl->bExtraVerbose) {
ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures"); ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures");
@ -860,7 +864,6 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
break; break;
} }
} }
#endif // no validation
#endif // ! DEBUG #endif // ! DEBUG
} }
pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()), pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()),
@ -936,7 +939,6 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
profiler->EndRegion( "postprocess" ); profiler->EndRegion( "postprocess" );
} }
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
// If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
if ( pimpl->bExtraVerbose || requestValidation ) { if ( pimpl->bExtraVerbose || requestValidation ) {
ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" ); ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" );
@ -947,7 +949,6 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" ); ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" );
} }
} }
#endif // no validation
// clear any data allocated by post-process steps // clear any data allocated by post-process steps
pimpl->mPPShared->Clean(); pimpl->mPPShared->Clean();

View File

@ -55,9 +55,6 @@ corresponding preprocessor flag to selectively disable formats.
// Importers // Importers
// (include_new_importers_here) // (include_new_importers_here)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#if !defined(ASSIMP_BUILD_NO_USD_IMPORTER)
#include "AssetLib/USD/USDLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_X_IMPORTER #ifndef ASSIMP_BUILD_NO_X_IMPORTER
#include "AssetLib/X/XFileImporter.h" #include "AssetLib/X/XFileImporter.h"
#endif #endif
@ -233,9 +230,6 @@ void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
// (register_new_importers_here) // (register_new_importers_here)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
out.reserve(64); out.reserve(64);
#if !defined(ASSIMP_BUILD_NO_USD_IMPORTER)
out.push_back(new USDImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_X_IMPORTER) #if (!defined ASSIMP_BUILD_NO_X_IMPORTER)
out.push_back(new XFileImporter()); out.push_back(new XFileImporter());
#endif #endif

View File

@ -63,7 +63,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <stdio.h> #include <stdio.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <unordered_set>
namespace Assimp { namespace Assimp {
@ -79,7 +78,7 @@ inline void PrefixString(aiString &string, const char *prefix, unsigned int len)
if (string.length >= 1 && string.data[0] == '$') if (string.length >= 1 && string.data[0] == '$')
return; return;
if (len + string.length >= AI_MAXLEN - 1) { if (len + string.length >= MAXLEN - 1) {
ASSIMP_LOG_VERBOSE_DEBUG("Can't add an unique prefix because the string is too long"); ASSIMP_LOG_VERBOSE_DEBUG("Can't add an unique prefix because the string is too long");
ai_assert(false); ai_assert(false);
return; return;
@ -253,14 +252,6 @@ void SceneCombiner::AttachToGraph(aiScene *master, std::vector<NodeAttachmentInf
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<AttachmentInfo> &srcList, unsigned int flags) { void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<AttachmentInfo> &srcList, unsigned int flags) {
if (nullptr == _dest) { if (nullptr == _dest) {
std::unordered_set<aiScene *> uniqueScenes;
uniqueScenes.insert(master);
for (const auto &item : srcList) {
uniqueScenes.insert(item.scene);
}
for (const auto &item : uniqueScenes) {
delete item;
}
return; return;
} }
@ -268,7 +259,6 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
if (srcList.empty()) { if (srcList.empty()) {
if (*_dest) { if (*_dest) {
SceneCombiner::CopySceneFlat(_dest, master); SceneCombiner::CopySceneFlat(_dest, master);
delete master;
} else } else
*_dest = master; *_dest = master;
return; return;
@ -418,7 +408,7 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
// where n is the index of the texture. // where n is the index of the texture.
// Copy here because we overwrite the string data in-place and the buffer inside of aiString // Copy here because we overwrite the string data in-place and the buffer inside of aiString
// will be a lie if we just reinterpret from prop->mData. The size of mData is not guaranteed to be // will be a lie if we just reinterpret from prop->mData. The size of mData is not guaranteed to be
// AI_MAXLEN in size. // MAXLEN in size.
aiString s(*(aiString *)prop->mData); aiString s(*(aiString *)prop->mData);
if ('*' == s.data[0]) { if ('*' == s.data[0]) {
// Offset the index and write it back .. // Offset the index and write it back ..
@ -1067,7 +1057,7 @@ void SceneCombiner::CopyScene(aiScene **_dest, const aiScene *src, bool allocate
dest->mFlags = src->mFlags; dest->mFlags = src->mFlags;
// source private data might be nullptr if the scene is user-allocated (i.e. for use with the export API) // source private data might be nullptr if the scene is user-allocated (i.e. for use with the export API)
if (src->mPrivate != nullptr) { if (dest->mPrivate != nullptr) {
ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0; ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0;
} }
} }

View File

@ -71,6 +71,10 @@ SpatialSort::SpatialSort() :
mPlaneNormal.Normalize(); mPlaneNormal.Normalize();
} }
// ------------------------------------------------------------------------------------------------
// Destructor
SpatialSort::~SpatialSort() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void SpatialSort::Fill(const aiVector3D *pPositions, unsigned int pNumPositions, void SpatialSort::Fill(const aiVector3D *pPositions, unsigned int pNumPositions,
unsigned int pElementOffset, unsigned int pElementOffset,

View File

@ -88,11 +88,6 @@ private:
} // namespace Assimp } // namespace Assimp
/// @brief Fixes an undefined reference error when linking in certain build environments.
// May throw warnings about needing stdc++17, but should compile without issues on modern compilers.
inline const size_t Assimp::StackAllocator::g_maxBytesPerBlock;
inline const size_t Assimp::StackAllocator::g_startBytesPerBlock;
#include "StackAllocator.inl" #include "StackAllocator.inl"
#endif // include guard #endif // include guard

View File

@ -174,95 +174,6 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
return AI_SUCCESS; return AI_SUCCESS;
} }
// ------------------------------------------------------------------------------------------------
// Get an array of floating-point values from the material.
aiReturn aiGetMaterialDoubleArray(const aiMaterial *pMat,
const char *pKey,
unsigned int type,
unsigned int index,
double *pOut,
unsigned int *pMax) {
ai_assert(pOut != nullptr);
ai_assert(pMat != nullptr);
const aiMaterialProperty *prop;
aiGetMaterialProperty(pMat, pKey, type, index, (const aiMaterialProperty **)&prop);
if (nullptr == prop) {
return AI_FAILURE;
}
// data is given in floats, convert to ai_real
unsigned int iWrite = 0;
if (aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) {
iWrite = prop->mDataLength / sizeof(float);
if (pMax) {
iWrite = std::min(*pMax, iWrite);
;
}
for (unsigned int a = 0; a < iWrite; ++a) {
pOut[a] = static_cast<ai_real>(reinterpret_cast<float *>(prop->mData)[a]);
}
if (pMax) {
*pMax = iWrite;
}
}
// data is given in doubles, convert to float
else if (aiPTI_Double == prop->mType) {
iWrite = prop->mDataLength / sizeof(double);
if (pMax) {
iWrite = std::min(*pMax, iWrite);
;
}
for (unsigned int a = 0; a < iWrite; ++a) {
pOut[a] = static_cast<ai_real>(reinterpret_cast<double *>(prop->mData)[a]);
}
if (pMax) {
*pMax = iWrite;
}
}
// data is given in ints, convert to float
else if (aiPTI_Integer == prop->mType) {
iWrite = prop->mDataLength / sizeof(int32_t);
if (pMax) {
iWrite = std::min(*pMax, iWrite);
}
for (unsigned int a = 0; a < iWrite; ++a) {
pOut[a] = static_cast<ai_real>(reinterpret_cast<int32_t *>(prop->mData)[a]);
}
if (pMax) {
*pMax = iWrite;
}
}
// a string ... read floats separated by spaces
else {
if (pMax) {
iWrite = *pMax;
}
// strings are zero-terminated with a 32 bit length prefix, so this is safe
const char *cur = prop->mData + 4;
ai_assert(prop->mDataLength >= 5);
ai_assert(!prop->mData[prop->mDataLength - 1]);
for (unsigned int a = 0;; ++a) {
cur = fast_atoreal_move<double>(cur, pOut[a]);
if (a == iWrite - 1) {
break;
}
if (!IsSpace(*cur)) {
ASSIMP_LOG_ERROR("Material property", pKey,
" is a string; failed to parse a float array out of it.");
return AI_FAILURE;
}
}
if (pMax) {
*pMax = iWrite;
}
}
return AI_SUCCESS;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get an array if integers from the material // Get an array if integers from the material
aiReturn aiGetMaterialIntegerArray(const aiMaterial *pMat, aiReturn aiGetMaterialIntegerArray(const aiMaterial *pMat,
@ -575,7 +486,7 @@ aiReturn aiMaterial::AddBinaryProperty(const void *pInput,
memcpy(pcNew->mData, pInput, pSizeInBytes); memcpy(pcNew->mData, pInput, pSizeInBytes);
pcNew->mKey.length = static_cast<ai_uint32>(::strlen(pKey)); pcNew->mKey.length = static_cast<ai_uint32>(::strlen(pKey));
ai_assert(AI_MAXLEN > pcNew->mKey.length); ai_assert(MAXLEN > pcNew->mKey.length);
strcpy(pcNew->mKey.data, pKey); strcpy(pcNew->mKey.data, pKey);
if (UINT_MAX != iOutIndex) { if (UINT_MAX != iOutIndex) {

View File

@ -200,10 +200,8 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
localBitangent.NormalizeSafe(); localBitangent.NormalizeSafe();
// reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN. // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z) bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
|| (-0.5f < localTangent.x && localTangent.x < 0.5f && -0.5f < localTangent.y && localTangent.y < 0.5f && -0.5f < localTangent.z && localTangent.z < 0.5f); bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z);
bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z)
|| (-0.5f < localBitangent.x && localBitangent.x < 0.5f && -0.5f < localBitangent.y && localBitangent.y < 0.5f && -0.5f < localBitangent.z && localBitangent.z < 0.5f);
if (invalid_tangent != invalid_bitangent) { if (invalid_tangent != invalid_bitangent) {
if (invalid_tangent) { if (invalid_tangent) {
localTangent = meshNorm[p] ^ localBitangent; localTangent = meshNorm[p] ^ localBitangent;

View File

@ -143,13 +143,9 @@ bool FindDegeneratesProcess::ExecuteOnMesh(aiMesh *mesh) {
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
aiFace &face = mesh->mFaces[a]; aiFace &face = mesh->mFaces[a];
bool first = true; bool first = true;
auto vertex_in_range = [numVertices = mesh->mNumVertices](unsigned int vertex_idx) { return vertex_idx < numVertices; };
// check whether the face contains degenerated entries // check whether the face contains degenerated entries
for (unsigned int i = 0; i < face.mNumIndices; ++i) { for (unsigned int i = 0; i < face.mNumIndices; ++i) {
if (!std::all_of(face.mIndices, face.mIndices + face.mNumIndices, vertex_in_range))
continue;
// Polygons with more than 4 points are allowed to have double points, that is // Polygons with more than 4 points are allowed to have double points, that is
// simulating polygons with holes just with concave polygons. However, // simulating polygons with holes just with concave polygons. However,
// double points may not come directly after another. // double points may not come directly after another.

View File

@ -380,4 +380,3 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int mes
} }
} // namespace Assimp } // namespace Assimp

View File

@ -53,8 +53,7 @@ namespace Assimp {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
LimitBoneWeightsProcess::LimitBoneWeightsProcess() : LimitBoneWeightsProcess::LimitBoneWeightsProcess() : mMaxWeights(AI_LMW_MAX_WEIGHTS) {
mMaxWeights(AI_LMW_MAX_WEIGHTS), mRemoveEmptyBones(true) {
// empty // empty
} }

View File

@ -164,7 +164,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list<aiNode *> &n
++it; ++it;
} }
if (join_master && !join.empty()) { if (join_master && !join.empty()) {
join_master->mName.length = ::ai_snprintf(join_master->mName.data, AI_MAXLEN, "$MergedNode_%u", count_merged++); join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%u", count_merged++);
unsigned int out_meshes = 0; unsigned int out_meshes = 0;
for (std::list<aiNode *>::const_iterator it = join.cbegin(); it != join.cend(); ++it) { for (std::list<aiNode *>::const_iterator it = join.cbegin(); it != join.cend(); ++it) {

View File

@ -635,7 +635,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
aiNode *pcNode = new aiNode(); aiNode *pcNode = new aiNode();
*nodes = pcNode; *nodes = pcNode;
pcNode->mParent = pScene->mRootNode; pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ai_snprintf(pcNode->mName.data, AI_MAXLEN, "light_%u", i); pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "light_%u", i);
pScene->mLights[i]->mName = pcNode->mName; pScene->mLights[i]->mName = pcNode->mName;
} }
// generate camera nodes // generate camera nodes
@ -643,7 +643,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
aiNode *pcNode = new aiNode(); aiNode *pcNode = new aiNode();
*nodes = pcNode; *nodes = pcNode;
pcNode->mParent = pScene->mRootNode; pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ::ai_snprintf(pcNode->mName.data, AI_MAXLEN, "cam_%u", i); pcNode->mName.length = ::ai_snprintf(pcNode->mName.data, MAXLEN, "cam_%u", i);
pScene->mCameras[i]->mName = pcNode->mName; pScene->mCameras[i]->mName = pcNode->mName;
} }
} }

View File

@ -176,7 +176,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) {
if (ppcMaterials[idx]) { if (ppcMaterials[idx]) {
aiString sz; aiString sz;
if( ppcMaterials[idx]->Get(AI_MATKEY_NAME, sz) != AI_SUCCESS ) { if( ppcMaterials[idx]->Get(AI_MATKEY_NAME, sz) != AI_SUCCESS ) {
sz.length = ::ai_snprintf(sz.data, AI_MAXLEN,"JoinedMaterial_#%u",p); sz.length = ::ai_snprintf(sz.data,MAXLEN,"JoinedMaterial_#%u",p);
((aiMaterial*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME); ((aiMaterial*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME);
} }
} else { } else {

View File

@ -65,48 +65,38 @@ void SortByPTypeProcess::SetupProperties(const Importer *pImp) {
mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0); mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0);
} }
// ------------------------------------------------------------------------------------------------
static void clearMeshesInNode(aiNode *node) {
delete[] node->mMeshes;
node->mNumMeshes = 0;
node->mMeshes = nullptr;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Update changed meshes in all nodes // Update changed meshes in all nodes
void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) { void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) {
ai_assert(node != nullptr);
if (node->mNumMeshes) { if (node->mNumMeshes) {
unsigned int newSize = 0; unsigned int newSize = 0;
for (unsigned int m = 0; m < node->mNumMeshes; ++m) { for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
unsigned int add = node->mMeshes[m] << 2; unsigned int add = node->mMeshes[m] << 2;
for (unsigned int i = 0; i < 4; ++i) { for (unsigned int i = 0; i < 4; ++i) {
if (UINT_MAX != replaceMeshIndex[add + i]) { if (UINT_MAX != replaceMeshIndex[add + i]) ++newSize;
++newSize;
} }
} }
} if (!newSize) {
if (newSize == 0) { delete[] node->mMeshes;
clearMeshesInNode(node); node->mNumMeshes = 0;
return; node->mMeshes = nullptr;
} } else {
// Try to reuse the old array if possible // Try to reuse the old array if possible
unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes); unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes);
for (unsigned int m = 0; m < node->mNumMeshes; ++m) { for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
unsigned int add = node->mMeshes[m] << 2; unsigned int add = node->mMeshes[m] << 2;
for (unsigned int i = 0; i < 4; ++i) { for (unsigned int i = 0; i < 4; ++i) {
if (UINT_MAX != replaceMeshIndex[add + i]) { if (UINT_MAX != replaceMeshIndex[add + i])
*newMeshes++ = replaceMeshIndex[add + i]; *newMeshes++ = replaceMeshIndex[add + i];
} }
} }
} if (newSize > node->mNumMeshes)
if (newSize > node->mNumMeshes) { delete[] node->mMeshes;
clearMeshesInNode(node);
}
node->mMeshes = newMeshes - (node->mNumMeshes = newSize); node->mMeshes = newMeshes - (node->mNumMeshes = newSize);
} }
}
// call all subnodes recursively // call all subnodes recursively
for (unsigned int m = 0; m < node->mNumChildren; ++m) { for (unsigned int m = 0; m < node->mNumChildren; ++m) {
@ -177,10 +167,6 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
// with the largest number of primitives // with the largest number of primitives
unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 }; unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 };
aiFace *pFirstFace = mesh->mFaces; aiFace *pFirstFace = mesh->mFaces;
if (pFirstFace == nullptr) {
continue;
}
aiFace *const pLastFace = pFirstFace + mesh->mNumFaces; aiFace *const pLastFace = pFirstFace + mesh->mNumFaces;
unsigned int numPolyVerts = 0; unsigned int numPolyVerts = 0;

View File

@ -192,14 +192,14 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
const aiFace& face = pMesh->mFaces[a]; const aiFace& face = pMesh->mFaces[a];
if( face.mNumIndices != 3) { if( face.mNumIndices != 3) {
bNeed = true; bNeed = true;
} }
} }
if (!bNeed) { if (!bNeed)
return false; return false;
} }
}
else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) { else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
return false; return false;
} }
@ -213,7 +213,8 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
get_normals = false; get_normals = false;
} }
if( face.mNumIndices <= 3) { if( face.mNumIndices <= 3) {
++numOut; numOut++;
} else { } else {
numOut += face.mNumIndices-2; numOut += face.mNumIndices-2;
max_out = std::max(max_out,face.mNumIndices); max_out = std::max(max_out,face.mNumIndices);
@ -221,10 +222,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
} }
// Just another check whether aiMesh::mPrimitiveTypes is correct // Just another check whether aiMesh::mPrimitiveTypes is correct
if (numOut == pMesh->mNumFaces) { ai_assert(numOut != pMesh->mNumFaces);
ASSIMP_LOG_ERROR( "Invalidation detected in the number of indices: does not fit to the primitive type." );
return false;
}
aiVector3D *nor_out = nullptr; aiVector3D *nor_out = nullptr;

View File

@ -371,7 +371,20 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh) {
ReportWarning("There are unreferenced vertices"); ReportWarning("There are unreferenced vertices");
} }
// vertex color channel 2 may not be set if channel 1 is zero ... // texture channel 2 may not be set if channel 1 is zero ...
{
unsigned int i = 0;
for (; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (!pMesh->HasTextureCoords(i)) break;
}
for (; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i)
if (pMesh->HasTextureCoords(i)) {
ReportError("Texture coordinate channel %i exists "
"although the previous channel was nullptr.",
i);
}
}
// the same for the vertex colors
{ {
unsigned int i = 0; unsigned int i = 0;
for (; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { for (; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
@ -891,17 +904,14 @@ void ValidateDSProcess::Validate(const aiNode *pNode) {
ReportError("aiNode \"%s\" child %i \"%s\" parent is someone else: \"%s\"", pNode->mName.C_Str(), i, pChild->mName.C_Str(), parentName); ReportError("aiNode \"%s\" child %i \"%s\" parent is someone else: \"%s\"", pNode->mName.C_Str(), i, pChild->mName.C_Str(), parentName);
} }
} }
} else if (pNode->mChildren) {
ReportError("aiNode::mChildren is not nullptr for empty node %s (aiNode::mNumChildren is %i)",
nodeName, pNode->mNumChildren);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate(const aiString *pString) { void ValidateDSProcess::Validate(const aiString *pString) {
if (pString->length > AI_MAXLEN) { if (pString->length > MAXLEN) {
ReportError("aiString::length is too large (%u, maximum is %lu)", ReportError("aiString::length is too large (%u, maximum is %lu)",
pString->length, AI_MAXLEN); pString->length, MAXLEN);
} }
const char *sz = pString->data; const char *sz = pString->data;
while (true) { while (true) {
@ -910,7 +920,7 @@ void ValidateDSProcess::Validate(const aiString *pString) {
ReportError("aiString::data is invalid: the terminal zero is at a wrong offset"); ReportError("aiString::data is invalid: the terminal zero is at a wrong offset");
} }
break; break;
} else if (sz >= &pString->data[AI_MAXLEN]) { } else if (sz >= &pString->data[MAXLEN]) {
ReportError("aiString::data is invalid. There is no terminal character"); ReportError("aiString::data is invalid. There is no terminal character");
} }
++sz; ++sz;

View File

@ -1,6 +1,7 @@
Copyright (c) 2009-2018, Poly2Tri Contributors Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
All rights reserved. http://code.google.com/p/poly2tri/
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:

View File

@ -0,0 +1,51 @@
==================
INSTALLATION GUIDE
==================
------------
Dependencies
------------
Core poly2tri lib:
- Standard Template Library (STL)
Testbed:
- gcc
- OpenGL
- GLFW (http://glfw.sf.net)
- Python
Waf (http://code.google.com/p/waf/) is used to compile the testbed.
A waf script (86kb) is included in the repositoty.
----------------------------------------------
Building the Testbed
----------------------------------------------
Posix/MSYS environment:
./waf configure
./waf build
Windows command line:
python waf configure
python waf build
----------------------------------------------
Running the Examples
----------------------------------------------
Load data points from a file:
p2t <filename> <center_x> <center_y> <zoom>
Random distribution of points inside a consrained box:
p2t random <num_points> <box_radius> <zoom>
Examples:
./p2t dude.dat 300 500 2
./p2t nazca_monkey.dat 0 0 9
./p2t random 10 100 5.0
./p2t random 1000 20000 0.025

View File

@ -1,101 +0,0 @@
Since there are no Input validation of the data given for triangulation you need
to think about this. Poly2Tri does not support repeat points within epsilon.
* If you have a cyclic function that generates random points make sure you don't
add the same coordinate twice.
* If you are given input and aren't sure same point exist twice you need to
check for this yourself.
* Only simple polygons are supported. You may add holes or interior Steiner points
* Interior holes must not touch other holes, nor touch the polyline boundary
* Use the library in this order:
1. Initialize CDT with a simple polyline (this defines the constrained edges)
2. Add holes if necessary (also simple polylines)
3. Add Steiner points
4. Triangulate
Make sure you understand the preceding notice before posting an issue. If you have
an issue not covered by the above, include your data-set with the problem.
The only easy day was yesterday; have a nice day. <Mason Green>
TESTBED INSTALLATION GUIDE
==========================
Dependencies
------------
Core poly2tri lib:
* Standard Template Library (STL)
Unit tests:
* Boost (filesystem, test framework)
Testbed:
* OpenGL
* [GLFW](http://glfw.sf.net)
Build the library
-----------------
With the ninja build system installed:
```
mkdir build && cd build
cmake -GNinja ..
cmake --build .
```
Build and run with unit tests
----------------------------
With the ninja build system:
```
mkdir build && cd build
cmake -GNinja -DP2T_BUILD_TESTS=ON ..
cmake --build .
ctest --output-on-failure
```
Build with the testbed
-----------------
```
mkdir build && cd build
cmake -GNinja -DP2T_BUILD_TESTBED=ON ..
cmake --build .
```
Running the Examples
--------------------
Load data points from a file:
```
build/testbed/p2t <filename> <center_x> <center_y> <zoom>
```
Load data points from a file and automatically fit the geometry to the window:
```
build/testbed/p2t <filename>
```
Random distribution of points inside a constrained box:
```
build/testbed/p2t random <num_points> <box_radius> <zoom>
```
Examples:
```
build/testbed/p2t testbed/data/dude.dat 350 500 3
build/testbed/p2t testbed/data/nazca_monkey.dat
build/testbed/p2t random 10 100 5.0
build/testbed/p2t random 1000 20000 0.025
```
References
==========
- Domiter V. and Zalik B. (2008) Sweepline algorithm for constrained Delaunay triangulation
- FlipScan by library author Thomas Åhlén
![FlipScan](doc/FlipScan.png)

View File

@ -1,61 +0,0 @@
/*
* Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri
*
* All rights reserved.
*
* Redistribution and use 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 Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* 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.
*/
#pragma once
#if defined(_MSC_VER)
# pragma warning( disable: 4273)
# define P2T_COMPILER_DLLEXPORT __declspec(dllexport)
# define P2T_COMPILER_DLLIMPORT __declspec(dllimport)
#elif defined(__GNUC__)
# define P2T_COMPILER_DLLEXPORT __attribute__ ((visibility ("default")))
# define P2T_COMPILER_DLLIMPORT __attribute__ ((visibility ("default")))
#else
# define P2T_COMPILER_DLLEXPORT
# define P2T_COMPILER_DLLIMPORT
#endif
// We need to enable shard linkage explicitely
#ifdef ASSIMP_BUILD_DLL_EXPORT
# define P2T_SHARED_EXPORTS 1
#endif
#ifndef P2T_DLL_SYMBOL
# if defined(P2T_STATIC_EXPORTS)
# define P2T_DLL_SYMBOL
# elif defined(P2T_SHARED_EXPORTS)
# define P2T_DLL_SYMBOL P2T_COMPILER_DLLEXPORT
# elif defined(BUILD_SHARED_LIBS)
# define P2T_DLL_SYMBOL P2T_COMPILER_DLLIMPORT
# else
# define P2T_DLL_SYMBOL
# endif
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,24 +29,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "shapes.h" #include "shapes.h"
#include <cassert>
#include <iostream> #include <iostream>
namespace p2t { namespace p2t {
Point::Point(double x, double y) : x(x), y(y)
{
}
std::ostream& operator<<(std::ostream& out, const Point& point) {
return out << point.x << "," << point.y;
}
Triangle::Triangle(Point& a, Point& b, Point& c) Triangle::Triangle(Point& a, Point& b, Point& c)
{ {
points_[0] = &a; points_[1] = &b; points_[2] = &c; points_[0] = &a; points_[1] = &b; points_[2] = &c;
neighbors_[0] = nullptr; neighbors_[1] = nullptr; neighbors_[2] = nullptr; neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL;
constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false;
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
interior_ = false; interior_ = false;
@ -86,37 +76,39 @@ void Triangle::MarkNeighbor(Triangle& t)
void Triangle::Clear() void Triangle::Clear()
{ {
Triangle *t; Triangle *t;
for (auto& neighbor : neighbors_) { for( int i=0; i<3; i++ )
t = neighbor; {
if (t != nullptr) { t = neighbors_[i];
if( t != NULL )
{
t->ClearNeighbor( this ); t->ClearNeighbor( this );
} }
} }
ClearNeighbors(); ClearNeighbors();
points_[0]=points_[1]=points_[2] = nullptr; points_[0]=points_[1]=points_[2] = NULL;
} }
void Triangle::ClearNeighbor(const Triangle *triangle ) void Triangle::ClearNeighbor(const Triangle *triangle )
{ {
if( neighbors_[0] == triangle ) if( neighbors_[0] == triangle )
{ {
neighbors_[0] = nullptr; neighbors_[0] = NULL;
} }
else if( neighbors_[1] == triangle ) else if( neighbors_[1] == triangle )
{ {
neighbors_[1] = nullptr; neighbors_[1] = NULL;
} }
else else
{ {
neighbors_[2] = nullptr; neighbors_[2] = NULL;
} }
} }
void Triangle::ClearNeighbors() void Triangle::ClearNeighbors()
{ {
neighbors_[0] = nullptr; neighbors_[0] = NULL;
neighbors_[1] = nullptr; neighbors_[1] = NULL;
neighbors_[2] = nullptr; neighbors_[2] = NULL;
} }
void Triangle::ClearDelunayEdges() void Triangle::ClearDelunayEdges()
@ -228,7 +220,7 @@ Point* Triangle::PointCW(const Point& point)
return points_[1]; return points_[1];
} }
assert(0); assert(0);
return nullptr; return NULL;
} }
// The point counter-clockwise to given point // The point counter-clockwise to given point
@ -242,18 +234,7 @@ Point* Triangle::PointCCW(const Point& point)
return points_[0]; return points_[0];
} }
assert(0); assert(0);
return nullptr; return NULL;
}
// The neighbor across to given point
Triangle* Triangle::NeighborAcross(const Point& point)
{
if (&point == points_[0]) {
return neighbors_[0];
} else if (&point == points_[1]) {
return neighbors_[1];
}
return neighbors_[2];
} }
// The neighbor clockwise to given point // The neighbor clockwise to given point
@ -362,50 +343,23 @@ void Triangle::SetDelunayEdgeCW(const Point& p, bool e)
} }
} }
// The neighbor across to given point
Triangle& Triangle::NeighborAcross(const Point& opoint)
{
if (&opoint == points_[0]) {
return *neighbors_[0];
} else if (&opoint == points_[1]) {
return *neighbors_[1];
}
return *neighbors_[2];
}
void Triangle::DebugPrint() void Triangle::DebugPrint()
{ {
std::cout << *points_[0] << " " << *points_[1] << " " << *points_[2] << std::endl; using namespace std;
cout << points_[0]->x << "," << points_[0]->y << " ";
cout << points_[1]->x << "," << points_[1]->y << " ";
cout << points_[2]->x << "," << points_[2]->y << endl;
} }
bool Triangle::CircumcicleContains(const Point& point) const
{
assert(IsCounterClockwise());
const double dx = points_[0]->x - point.x;
const double dy = points_[0]->y - point.y;
const double ex = points_[1]->x - point.x;
const double ey = points_[1]->y - point.y;
const double fx = points_[2]->x - point.x;
const double fy = points_[2]->y - point.y;
const double ap = dx * dx + dy * dy;
const double bp = ex * ex + ey * ey;
const double cp = fx * fx + fy * fy;
return (dx * (fy * bp - cp * ey) - dy * (fx * bp - cp * ex) + ap * (fx * ey - fy * ex)) < 0;
} }
bool Triangle::IsCounterClockwise() const
{
return (points_[1]->x - points_[0]->x) * (points_[2]->y - points_[0]->y) -
(points_[2]->x - points_[0]->x) * (points_[1]->y - points_[0]->y) >
0;
}
bool IsDelaunay(const std::vector<p2t::Triangle*>& triangles)
{
for (const auto triangle : triangles) {
for (const auto other : triangles) {
if (triangle == other) {
continue;
}
for (int i = 0; i < 3; ++i) {
if (triangle->CircumcicleContains(*other->GetPoint(i))) {
return false;
}
}
}
}
return true;
}
} // namespace p2t

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,24 +29,22 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once // Include guard
#ifndef SHAPES_H
#define SHAPES_H
#include "dll_symbol.h" #include <vector>
#include <cmath>
#include <cstddef> #include <cstddef>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <assert.h>
#include <cmath>
#include <string>
#if defined(_WIN32)
# pragma warning( disable: 4251)
#endif
namespace p2t { namespace p2t {
struct Edge; struct Edge;
struct P2T_DLL_SYMBOL Point { struct Point {
double x, y; double x, y;
@ -61,7 +59,7 @@ struct P2T_DLL_SYMBOL Point {
std::vector<Edge*> edge_list; std::vector<Edge*> edge_list;
/// Construct using coordinates. /// Construct using coordinates.
Point(double x, double y); Point(double x, double y) : x(x), y(y) {}
/// Set this point to all zeros. /// Set this point to all zeros.
void set_zero() void set_zero()
@ -123,10 +121,8 @@ struct P2T_DLL_SYMBOL Point {
}; };
P2T_DLL_SYMBOL std::ostream& operator<<(std::ostream&, const Point&);
// Represents a simple polygon's edge // Represents a simple polygon's edge
struct P2T_DLL_SYMBOL Edge { struct Edge {
Point* p, *q; Point* p, *q;
@ -142,7 +138,9 @@ struct P2T_DLL_SYMBOL Edge {
p = &p2; p = &p2;
} else if (p1.x == p2.x) { } else if (p1.x == p2.x) {
// Repeat points // Repeat points
throw std::runtime_error("Edge::Edge: p1 == p2"); // ASSIMP_CHANGE (aramis_acg)
throw std::runtime_error(std::string("repeat points"));
//assert(false);
} }
} }
@ -153,7 +151,7 @@ struct P2T_DLL_SYMBOL Edge {
// Triangle-based data structures are know to have better performance than quad-edge structures // Triangle-based data structures are know to have better performance than quad-edge structures
// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" // See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator"
// "Triangulations in CGAL" // "Triangulations in CGAL"
class P2T_DLL_SYMBOL Triangle { class Triangle {
public: public:
/// Constructor /// Constructor
@ -180,7 +178,6 @@ void MarkConstrainedEdge(Point* p, Point* q);
int Index(const Point* p); int Index(const Point* p);
int EdgeIndex(const Point* p1, const Point* p2); int EdgeIndex(const Point* p1, const Point* p2);
Triangle* NeighborAcross(const Point& point);
Triangle* NeighborCW(const Point& point); Triangle* NeighborCW(const Point& point);
Triangle* NeighborCCW(const Point& point); Triangle* NeighborCCW(const Point& point);
bool GetConstrainedEdgeCCW(const Point& p); bool GetConstrainedEdgeCCW(const Point& p);
@ -208,14 +205,12 @@ void ClearDelunayEdges();
inline bool IsInterior(); inline bool IsInterior();
inline void IsInterior(bool b); inline void IsInterior(bool b);
Triangle& NeighborAcross(const Point& opoint);
void DebugPrint(); void DebugPrint();
bool CircumcicleContains(const Point&) const;
private: private:
bool IsCounterClockwise() const;
/// Triangle points /// Triangle points
Point* points_[3]; Point* points_[3];
/// Neighbor list /// Neighbor list
@ -263,7 +258,7 @@ inline bool operator ==(const Point& a, const Point& b)
inline bool operator !=(const Point& a, const Point& b) inline bool operator !=(const Point& a, const Point& b)
{ {
return !(a.x == b.x) || !(a.y == b.y); return !(a.x == b.x) && !(a.y == b.y);
} }
/// Peform the dot product on two vectors. /// Peform the dot product on two vectors.
@ -327,7 +322,6 @@ inline void Triangle::IsInterior(bool b)
interior_ = b; interior_ = b;
} }
/// Is this set a valid delaunay triangulation?
P2T_DLL_SYMBOL bool IsDelaunay(const std::vector<p2t::Triangle*>&);
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,15 +29,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #ifndef UTILS_H
#define UTILS_H
// Otherwise #defines like M_PI are undeclared under Visual Studio // Otherwise #defines like M_PI are undeclared under Visual Studio
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include "shapes.h"
#include <cmath>
#include <exception> #include <exception>
#include <math.h>
// C99 removes M_PI from math.h // C99 removes M_PI from math.h
#ifndef M_PI #ifndef M_PI
@ -67,11 +66,7 @@ Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc)
double detleft = (pa.x - pc.x) * (pb.y - pc.y); double detleft = (pa.x - pc.x) * (pb.y - pc.y);
double detright = (pa.y - pc.y) * (pb.x - pc.x); double detright = (pa.y - pc.y) * (pb.x - pc.x);
double val = detleft - detright; double val = detleft - detright;
if (val > -EPSILON && val < EPSILON) {
// Using a tolerance here fails on concave-by-subepsilon boundaries
// if (val > -EPSILON && val < EPSILON) {
// Using == on double makes -Wfloat-equal warnings yell at us
if (std::fpclassify(val) == FP_ZERO) {
return COLLINEAR; return COLLINEAR;
} else if (val > 0) { } else if (val > 0) {
return CCW; return CCW;
@ -128,3 +123,5 @@ bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point&
} }
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,7 +29,10 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #ifndef POLY2TRI_H
#define POLY2TRI_H
#include "common/shapes.h" #include "common/shapes.h"
#include "sweep/cdt.h" #include "sweep/cdt.h"
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -30,8 +30,6 @@
*/ */
#include "advancing_front.h" #include "advancing_front.h"
#include <cassert>
namespace p2t { namespace p2t {
AdvancingFront::AdvancingFront(Node& head, Node& tail) AdvancingFront::AdvancingFront(Node& head, Node& tail)
@ -46,21 +44,21 @@ Node* AdvancingFront::LocateNode(double x)
Node* node = search_node_; Node* node = search_node_;
if (x < node->value) { if (x < node->value) {
while ((node = node->prev) != nullptr) { while ((node = node->prev) != NULL) {
if (x >= node->value) { if (x >= node->value) {
search_node_ = node; search_node_ = node;
return node; return node;
} }
} }
} else { } else {
while ((node = node->next) != nullptr) { while ((node = node->next) != NULL) {
if (x < node->value) { if (x < node->value) {
search_node_ = node->prev; search_node_ = node->prev;
return node->prev; return node->prev;
} }
} }
} }
return nullptr; return NULL;
} }
Node* AdvancingFront::FindSearchNode(double x) Node* AdvancingFront::FindSearchNode(double x)
@ -88,13 +86,13 @@ Node* AdvancingFront::LocatePoint(const Point* point)
} }
} }
} else if (px < nx) { } else if (px < nx) {
while ((node = node->prev) != nullptr) { while ((node = node->prev) != NULL) {
if (point == node->point) { if (point == node->point) {
break; break;
} }
} }
} else { } else {
while ((node = node->next) != nullptr) { while ((node = node->next) != NULL) {
if (point == node->point) if (point == node->point)
break; break;
} }
@ -107,4 +105,4 @@ AdvancingFront::~AdvancingFront()
{ {
} }
} // namespace p2t }

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,7 +29,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #ifndef ADVANCED_FRONT_H
#define ADVANCED_FRONT_H
#include "../common/shapes.h" #include "../common/shapes.h"
@ -113,3 +114,5 @@ inline void AdvancingFront::set_search(Node* node)
} }
} }
#endif

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