Merge branch 'master' into patch-1

pull/5432/head
Kim Kulling 2024-07-23 10:42:52 +02:00 committed by GitHub
commit 1820cc5550
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
252 changed files with 18510 additions and 6504 deletions

51
.github/workflows/inno_setup vendored 100644
View File

@ -0,0 +1,51 @@
name: Build Windows Installer
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
name: Build the Inno Setup Installer
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: lukka/get-cmake@latest
- uses: ilammy/msvc-dev-cmd@v1
- name: Cache DX SDK
id: dxcache
uses: actions/cache@v4
with:
path: '${{ github.workspace }}/DX_SDK'
key: ${{ runner.os }}-DX_SDK
restore-keys: |
${{ runner.os }}-DX_SDK
- name: Download DXSetup
run: |
curl -s -o DXSDK_Jun10.exe --location https://download.microsoft.com/download/A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe
cmd.exe /c start /wait .\DXSDK_Jun10.exe /U /O /F /S /P "${{ github.workspace }}\DX_SDK"
- name: Set Windows specific CMake arguments
id: windows_extra_cmake_args
run: echo "::set-output name=args::-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1 -DASSIMP_BUILD_ZLIB=1"
- name: configure and build
uses: lukka/run-cmake@v3
env:
DXSDK_DIR: '${{ github.workspace }}/DX_SDK'
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release ${{ steps.windows_extra_cmake_args.outputs.args }} ${{ steps.hunter_extra_cmake_args.outputs.args }}'
buildWithCMakeArgs: '--parallel 24 -v'
buildDirectory: '${{ github.workspace }}/build/'
- name: Compile .ISS to .EXE Installer
uses: Minionguyjpro/Inno-Setup-Action@v1.2.2
with:
path: packaging/windows-innosetup/script_x64.iss
options: /O+

4
.gitignore vendored
View File

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

View File

@ -38,9 +38,16 @@ SET(CMAKE_POLICY_DEFAULT_CMP0012 NEW)
SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW)
SET(CMAKE_POLICY_DEFAULT_CMP0092 NEW)
CMAKE_MINIMUM_REQUIRED( VERSION 3.10 )
CMAKE_MINIMUM_REQUIRED( VERSION 3.22 )
# Disabled importers: m3d for 5.1
# 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)
# Disabled importers: m3d for 5.1 or later
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER)
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_EXPORTER)
# Toggles the use of the hunter package manager
@ -49,13 +56,13 @@ option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
IF(ASSIMP_HUNTER_ENABLED)
include("cmake-modules/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.25.3.tar.gz"
SHA1 "3319fe6a3b08090df7df98dee75134d68e2ef5a3"
URL "https://github.com/cpp-pm/hunter/archive/v0.25.5.tar.gz"
SHA1 "a20151e4c0740ee7d0f9994476856d813cdead29"
)
add_definitions(-DASSIMP_USE_HUNTER)
ENDIF()
PROJECT(Assimp VERSION 5.3.0)
PROJECT(Assimp VERSION 5.4.1)
# All supported options ###############################################
@ -131,18 +138,18 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH
IF (WIN32)
OPTION( ASSIMP_BUILD_ZLIB
"Build your own zlib"
"Build your zlib"
ON
)
ELSE()
OPTION( ASSIMP_BUILD_ZLIB
"Build your own zlib"
"Build your zlib"
OFF
)
ENDIF()
IF (WIN32)
# Use subset of Windows.h
# Use a subset of Windows.h
ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
IF(MSVC)
@ -150,16 +157,16 @@ IF (WIN32)
"Install MSVC debug files."
ON )
IF(NOT (MSVC_VERSION LESS 1900))
# Multibyte character set is deprecated since at least MSVC2015 (possibly earlier)
# Multibyte character set has been deprecated since at least MSVC2015 (possibly earlier)
ADD_DEFINITIONS( -DUNICODE -D_UNICODE )
ENDIF()
# Link statically against c/c++ lib to avoid missing redistriburable such as
# Link statically against c/c++ lib to avoid missing redistributable such as
# "VCRUNTIME140.dll not found. Try reinstalling the app.", but give users
# a choice to opt for the shared runtime if they want.
option(USE_STATIC_CRT "Link against the static runtime libraries." OFF)
# The CMAKE_CXX_FLAGS vars can be overriden by some Visual Studio generators, so we use an alternative
# The CMAKE_CXX_FLAGS vars can be overridden by some Visual Studio generators, so we use an alternative
# global method here:
if (${USE_STATIC_CRT})
add_compile_options(
@ -249,9 +256,9 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
IF( UNIX )
# Use GNUInstallDirs for Unix predefined directories
INCLUDE(GNUInstallDirs)
# Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
# Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit Linux
IF(NOT ${OPERATING_SYSTEM} MATCHES "Android")
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit Linux
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
ENDIF()
ENDIF()
@ -262,7 +269,7 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU)
IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
ENDIF()
IF(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 13)
MESSAGE(STATUS "GCC13 detected disabling \"-Wdangling-reference\" in Cpp files as it appears to be a false positive")
ADD_COMPILE_OPTIONS("$<$<COMPILE_LANGUAGE:CXX>:-Wno-dangling-reference>")
@ -284,13 +291,13 @@ ELSEIF(MSVC)
ELSE() # msvc
ADD_COMPILE_OPTIONS(/MP /bigobj)
ENDIF()
# disable "elements of array '' will be default initialized" warning on MSVC2013
IF(MSVC12)
ADD_COMPILE_OPTIONS(/wd4351)
ADD_COMPILE_OPTIONS(/wd4351)
ENDIF()
# supress warning for double to float conversion if Double precission is activated
ADD_COMPILE_OPTIONS(/wd4244)
# supress warning for double to float conversion if Double precision is activated
ADD_COMPILE_OPTIONS(/wd4244)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
@ -330,7 +337,7 @@ ENDIF()
IF (ASSIMP_COVERALLS)
MESSAGE(STATUS "Coveralls enabled")
INCLUDE(Coveralls)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
@ -338,7 +345,7 @@ ENDIF()
IF (ASSIMP_ASAN)
MESSAGE(STATUS "AddressSanitizer enabled")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
ENDIF()
@ -452,18 +459,20 @@ configure_package_config_file(
INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
)
install(
FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
)
if(ASSIMP_INSTALL)
install(
FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
)
install(
EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${NAMESPACE}"
DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
)
install(
EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${NAMESPACE}"
DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
)
endif()
IF( ASSIMP_BUILD_DOCS )
ADD_SUBDIRECTORY(doc)
@ -481,7 +490,7 @@ IF(ASSIMP_HUNTER_ENABLED)
set(ASSIMP_BUILD_MINIZIP TRUE)
ELSE()
# If the zlib is already found outside, add an export in case assimpTargets can't find it.
IF( ZLIB_FOUND )
IF( ZLIB_FOUND AND ASSIMP_INSTALL)
INSTALL( TARGETS zlib zlibstatic
EXPORT "${TARGETS_EXPORT_NAME}")
ENDIF()
@ -563,9 +572,9 @@ SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
)
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
IF ( MSVC )
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
IF (WIN32)
# pick the correct prebuilt library
IF(MSVC143)
SET(C4D_LIB_POSTFIX "_2022")
@ -583,7 +592,7 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
SET(C4D_LIB_POSTFIX "_2010")
ELSE()
MESSAGE( FATAL_ERROR
"C4D is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3"
"C4D for Windows is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3"
)
ENDIF()
@ -601,15 +610,30 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
# winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because
# it can be used to communicate with a running Cinema 4D instance
SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
ELSEIF (APPLE)
SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/osx")
SET(C4D_DEBUG_LIBRARIES
"${C4D_LIB_BASE_PATH}/debug/libcinewarelib.a"
"${C4D_LIB_BASE_PATH}/debug/libjpeglib.a"
)
SET(C4D_RELEASE_LIBRARIES
"${C4D_LIB_BASE_PATH}/release/libcinewarelib.a"
"${C4D_LIB_BASE_PATH}/release/libjpeglib.a"
)
ELSE ()
MESSAGE( FATAL_ERROR
"C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware"
"C4D is currently only available on Windows and macOS with Cineware SDK installed in contrib/Cineware"
)
ENDIF ()
ELSE ()
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
ENDIF ()
if(ASSIMP_BUILD_DRACO_STATIC)
set(ASSIMP_BUILD_DRACO ON)
endif()
# Draco requires cmake 3.12
IF (DEFINED CMAKE_VERSION AND "${CMAKE_VERSION}" VERSION_LESS "3.12")
message(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled")
@ -645,22 +669,29 @@ ELSE()
"-Wno-sign-compare"
"-Wno-unused-local-typedefs"
)
# Draco 1.4.1 does not explicitly export any symbols under GCC/clang
list(APPEND DRACO_CXX_FLAGS
"-fvisibility=default"
)
if(NOT ASSIMP_BUILD_DRACO_STATIC)
# Draco 1.4.1 does not explicitly export any symbols under GCC/clang
list(APPEND DRACO_CXX_FLAGS
"-fvisibility=default"
)
endif()
ENDIF()
# Don't build or install all of Draco by default
ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL )
if(ASSIMP_BUILD_DRACO_STATIC)
set_property(DIRECTORY "contrib/draco" PROPERTY BUILD_SHARED_LIBS OFF)
endif()
if(MSVC OR WIN32)
set(draco_LIBRARIES "draco")
else()
if(BUILD_SHARED_LIBS)
set(draco_LIBRARIES "draco_shared")
else()
if(ASSIMP_BUILD_DRACO_STATIC)
set(draco_LIBRARIES "draco_static")
else()
set(draco_LIBRARIES "draco_shared")
endif()
endif()
@ -683,15 +714,17 @@ ELSE()
set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
# This is probably wrong
INSTALL( TARGETS ${draco_LIBRARIES}
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION include
)
if (ASSIMP_INSTALL)
INSTALL( TARGETS ${draco_LIBRARIES}
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION include
)
endif()
ENDIF()
ENDIF()
ENDIF()
@ -735,8 +768,8 @@ IF ( ASSIMP_INSTALL )
ENDIF()
CONFIGURE_FILE(
${CMAKE_CURRENT_LIST_DIR}/revision.h.in
${CMAKE_CURRENT_BINARY_DIR}/revision.h
${CMAKE_CURRENT_LIST_DIR}/include/assimp/revision.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/assimp/revision.h
)
CONFIGURE_FILE(

View File

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

View File

@ -26,12 +26,11 @@ Clone [our model database](https://github.com/assimp/assimp-mdb).
### Communities ###
- 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 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)
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 ####
See [the complete list of supported formats](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md).

View File

@ -22,38 +22,9 @@
# 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.
# 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)
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
option(HUNTER_STATUS_PRINT "Print working status" ON)

View File

@ -709,7 +709,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
pcNode->mNumMeshes = 1;
// Build a name for the node
pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u", i);
pcNode->mName.length = ai_snprintf(pcNode->mName.data, AI_MAXLEN, "3DSMesh_%u", i);
}
// Build dummy nodes for all cameras

View File

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

View File

@ -57,8 +57,8 @@ static constexpr size_t ColRGBA_Len = 9;
static constexpr size_t ColRGB_Len = 7;
// format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
bool validateColorString(const char *color) {
const size_t len = strlen(color);
bool validateColorString(const std::string color) {
const size_t len = color.size();
if (ColRGBA_Len != len && ColRGB_Len != len) {
return false;
}
@ -157,8 +157,8 @@ aiMatrix4x4 parseTransformMatrix(const std::string& matrixStr) {
return transformMatrix;
}
bool parseColor(const char *color, aiColor4D &diffuse) {
if (nullptr == color) {
bool parseColor(const std::string &color, aiColor4D &diffuse) {
if (color.empty()) {
return false;
}
@ -178,7 +178,7 @@ bool parseColor(const char *color, aiColor4D &diffuse) {
char b[3] = { color[5], color[6], '\0' };
diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
const size_t len = strlen(color);
const size_t len = color.size();
if (ColRGB_Len == len) {
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
// 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, MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
light->mName.length = ::ai_snprintf(light->mName.data, AI_MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
obj.name = std::string(light->mName.data);
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
switch (object.type) {
case Object::Group:
node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++);
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACGroup_%i", mGroupsCounter++);
break;
case Object::Poly:
node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++);
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACPoly_%i", mPolysCounter++);
break;
case Object::Light:
node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++);
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACLight_%i", mLightsCounter++);
break;
// there shouldn't be more than one world, but we don't care
case Object::World:
node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++);
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACWorld_%i", mWorldsCounter++);
break;
}
}

View File

@ -178,28 +178,6 @@ bool AMFImporter::XML_SearchNode(const std::string &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) {
return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/'));
}
@ -213,7 +191,10 @@ void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std
uint8_t arr4[4], arr3[3];
// check input data
if (pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
if (pInputBase64.size() % 4) {
throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
}
// prepare output place
pOutputData.clear();
pOutputData.reserve(pInputBase64.size() / 4 * 3);
@ -403,17 +384,17 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
for (auto &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "deltax") {
XmlParser::getValueAsFloat(currentNode, als.Delta.x);
XmlParser::getValueAsReal(currentNode, als.Delta.x);
} else if (currentName == "deltay") {
XmlParser::getValueAsFloat(currentNode, als.Delta.y);
XmlParser::getValueAsReal(currentNode, als.Delta.y);
} else if (currentName == "deltaz") {
XmlParser::getValueAsFloat(currentNode, als.Delta.z);
XmlParser::getValueAsReal(currentNode, als.Delta.z);
} else if (currentName == "rx") {
XmlParser::getValueAsFloat(currentNode, als.Delta.x);
XmlParser::getValueAsReal(currentNode, als.Delta.x);
} else if (currentName == "ry") {
XmlParser::getValueAsFloat(currentNode, als.Delta.y);
XmlParser::getValueAsReal(currentNode, als.Delta.y);
} else if (currentName == "rz") {
XmlParser::getValueAsFloat(currentNode, als.Delta.z);
XmlParser::getValueAsReal(currentNode, als.Delta.z);
}
}
ParseHelper_Node_Exit();

View File

@ -168,7 +168,6 @@ public:
AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX;
void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
bool XML_SearchNode(const std::string &nodeName);
void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);
AMFImporter(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
const std::string &currentName = ai_tolower(currentNode.name());
if (currentName == "x") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.x);
XmlParser::getValueAsReal(currentNode, als.Coordinate.x);
} else if (currentName == "y") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.y);
XmlParser::getValueAsReal(currentNode, als.Coordinate.y);
} else if (currentName == "z") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.z);
XmlParser::getValueAsReal(currentNode, als.Coordinate.z);
}
}
ParseHelper_Node_Exit();

View File

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

View File

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

View File

@ -224,7 +224,8 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string &
}
// Create format hint.
strcpy(converted_texture.FormatHint, "rgba0000"); // copy initial string.
constexpr char templateColor[] = "rgba0000";
memcpy(converted_texture.FormatHint, templateColor, 8);
if (!r.empty()) converted_texture.FormatHint[4] = '8';
if (!g.empty()) converted_texture.FormatHint[5] = '8';
if (!b.empty()) converted_texture.FormatHint[6] = '8';
@ -867,7 +868,7 @@ nl_clean_loop:
pScene->mTextures[idx]->mHeight = static_cast<unsigned int>(tex_convd.Height);
pScene->mTextures[idx]->pcData = (aiTexel *)tex_convd.Data;
// texture format description.
strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint);
strncpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint, HINTMAXTEXTURELEN);
idx++;
} // 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
std::vector<char> mBuffer2;
TextFileToBuffer(file.get(), mBuffer2);
const size_t fileSize = mBuffer2.size();
this->mBuffer = &mBuffer2[0];
this->pcScene = pScene;
@ -146,7 +146,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
};
// Construct an ASE parser and parse the file
ASE::Parser parser(mBuffer, defaultFormat);
ASE::Parser parser(mBuffer, fileSize, defaultFormat);
mParser = &parser;
mParser->Parse();
@ -446,10 +446,9 @@ void ASEImporter::BuildLights() {
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
aiNode *pcParent, const char *szName) {
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name) {
aiMatrix4x4 m;
AddNodes(nodes, pcParent, szName, m);
AddNodes(nodes, pcParent, name, m);
}
// ------------------------------------------------------------------------------------------------
@ -506,10 +505,9 @@ void ASEImporter::AddMeshes(const ASE::BaseNode *snode, aiNode *node) {
// ------------------------------------------------------------------------------------------------
// Add child nodes to a given parent node
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
aiNode *pcParent, const char *szName,
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name,
const aiMatrix4x4 &mat) {
const size_t len = szName ? ::strlen(szName) : 0;
const size_t len = name.size();
ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
// Receives child nodes for the pcParent node
@ -519,16 +517,18 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
// which has *us* as parent.
for (std::vector<BaseNode *>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) {
const BaseNode *snode = *it;
if (szName) {
if (len != snode->mParent.length() || ::strcmp(szName, snode->mParent.c_str()))
if (!name.empty()) {
if (len != snode->mParent.length() || name != snode->mParent.c_str()) {
continue;
} else if (snode->mParent.length())
}
} else if (snode->mParent.length()) {
continue;
}
(*it)->mProcessed = true;
// 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();
node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
@ -541,7 +541,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
// Add sub nodes - prevent stack overflow due to recursive parenting
if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName) {
AddNodes(nodes, node, node->mName.data, snode->mTransform);
AddNodes(nodes, node, node->mName.C_Str(), snode->mTransform);
}
// Further processing depends on the type of the node
@ -619,7 +619,8 @@ void ASEImporter::BuildNodes(std::vector<BaseNode *> &nodes) {
}
// add all nodes
AddNodes(nodes, ch, nullptr);
static const std::string none = "";
AddNodes(nodes, ch, none);
// now iterate through al nodes and find those that have not yet
// been added to the nodegraph (= their parent could not be recognized)

View File

@ -153,13 +153,13 @@ private:
* \param matrix Current transform
*/
void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent,const char* szName);
aiNode* pcParent, const std::string &name);
void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent,const char* szName,
aiNode* pcParent, const std::string &name,
const aiMatrix4x4& matrix);
void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
void AddMeshes(const ASE::BaseNode* snode, aiNode* node);
// -------------------------------------------------------------------
/** Generate a default material and add it to the parser's list
@ -188,5 +188,4 @@ protected:
} // end of namespace Assimp
#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
//! guaranteed to be terminated with zero.
//! @param szFile Input file
//! @param file The name of the input file.
//! @param fileFormatDefault Assumed file format version. If the
//! file format is specified in the file the new value replaces
//! the default value.
Parser(const char *szFile, unsigned int fileFormatDefault);
Parser(const char *file, size_t fileLen, unsigned int fileFormatDefault);
// -------------------------------------------------------------------
//! Parses the file into the parsers internal representation
@ -553,13 +553,15 @@ private:
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats)
//! \param rIndexOut Output index
void ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut);
void ParseLV4MeshRealTriple(ai_real *apOut, unsigned int &rIndexOut);
void ParseLV4MeshFloatTriple(float *apOut, unsigned int &rIndexOut);
// -------------------------------------------------------------------
//! Parse a *MESH_VERT block in a file
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats)
void ParseLV4MeshFloatTriple(ai_real *apOut);
void ParseLV4MeshRealTriple(ai_real *apOut);
void ParseLV4MeshFloatTriple(float *apOut);
// -------------------------------------------------------------------
//! Parse a *MESH_TFACE block in a file
@ -577,7 +579,8 @@ private:
// -------------------------------------------------------------------
//! Parse a single float element
//! \param fOut Output float
void ParseLV4MeshFloat(ai_real &fOut);
void ParseLV4MeshReal(ai_real &fOut);
void ParseLV4MeshFloat(float &fOut);
// -------------------------------------------------------------------
//! Parse a single int element
@ -617,11 +620,8 @@ private:
bool ParseString(std::string &out, const char *szName);
public:
//! Pointer to current data
const char *filePtr;
/// The end pointer of the file data
const char *mEnd;
const char *mFilePtr; ////< Pointer to current data
const char *mEnd; ///< The end pointer of the file data
//! background color to be passed to the viewer
//! 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
if (img->packedfile) {
name.data[0] = '*';
name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(conv_data.textures->size()));
name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(AI_MAXLEN - 1), static_cast<int32_t>(conv_data.textures->size()));
conv_data.textures->push_back(new aiTexture());
aiTexture *curTex = conv_data.textures->back();
@ -433,7 +433,7 @@ void BlenderImporter::AddSentinelTexture(aiMaterial *out, const Material *mat, c
(void)conv_data;
aiString name;
name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++,
name.length = ai_snprintf(name.data, AI_MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++,
GetTextureTypeDisplayString(tex->tex->type));
out->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(
conv_data.next_texture[aiTextureType_DIFFUSE]++));

View File

@ -46,10 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// no #ifdefing here, Cinema4D support is carried out in a branch of assimp
// where it is turned on in the CMake settings.
#ifndef _MSC_VER
# error C4D support is currently MSVC only
#endif
#include "C4DImporter.h"
#include <memory>
#include <assimp/IOSystem.hpp>
@ -111,7 +107,7 @@ C4DImporter::C4DImporter() = default;
C4DImporter::~C4DImporter() = default;
// ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const {
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
const std::string& extension = GetExtension(pFile);
if (extension == "c4d") {
return true;
@ -305,7 +301,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
// based on Cineware sample code
while (object) {
const LONG type = object->GetType();
const Int32 type = object->GetType();
const Matrix& ml = object->GetMl();
aiNode* const nd = new aiNode();
@ -368,8 +364,8 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
ai_assert(polyObject != nullptr);
const LONG pointCount = polyObject->GetPointCount();
const LONG polyCount = polyObject->GetPolygonCount();
const Int32 pointCount = polyObject->GetPointCount();
const Int32 polyCount = polyObject->GetPolygonCount();
if(!polyObject || !pointCount) {
LogWarn("ignoring mesh with zero vertices or faces");
return nullptr;
@ -391,7 +387,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
unsigned int vcount = 0;
// first count vertices
for (LONG i = 0; i < polyCount; i++)
for (Int32 i = 0; i < polyCount; i++)
{
vcount += 3;
@ -434,7 +430,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
}
// copy vertices and extra channels over and populate faces
for (LONG i = 0; i < polyCount; ++i, ++face) {
for (Int32 i = 0; i < polyCount; ++i, ++face) {
ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
const Vector& pointA = points[polys[i].a];
verts->x = pointA.x;
@ -511,7 +507,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
if (tangents_src) {
for(unsigned int k = 0; k < face->mNumIndices; ++k) {
LONG l;
Int32 l;
switch(k) {
case 0:
l = polys[i].a;

View File

@ -78,6 +78,8 @@ namespace Assimp {
// -------------------------------------------------------------------------------------------
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
public:
C4DImporter();
~C4DImporter() override;
bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override;
protected:

View File

@ -247,7 +247,9 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
// add children. first the *real* ones
node->mNumChildren = static_cast<unsigned int>(pNode->mChildren.size() + instances.size());
node->mChildren = new aiNode *[node->mNumChildren];
if (node->mNumChildren != 0) {
node->mChildren = new aiNode * [node->mNumChildren];
}
for (size_t a = 0; a < pNode->mChildren.size(); ++a) {
node->mChildren[a] = BuildHierarchy(pParser, pNode->mChildren[a]);
@ -623,16 +625,14 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
}
// same for texture coords, as many as we have
// 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) {
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) {
dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
dstMesh->mTextureCoords[a] = new aiVector3D[numVertices];
for (size_t b = 0; b < numVertices; ++b) {
dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex + b];
dstMesh->mTextureCoords[a][b] = pSrcMesh->mTexCoords[a][pStartVertex + b];
}
dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
++real;
dstMesh->mNumUVComponents[a] = pSrcMesh->mNumUVComponents[a];
}
}

View File

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

View File

@ -76,6 +76,53 @@ using namespace Util;
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL
static void correctRootTransform(const aiScene *scene) {
if (scene == nullptr) {
return;
}
if (scene->mMetaData == nullptr) {
return;
}
int32_t UpAxis = 1, UpAxisSign = 1, FrontAxis = 2, FrontAxisSign = 1, CoordAxis = 0, CoordAxisSign = 1;
double UnitScaleFactor = 1.0;
for (unsigned MetadataIndex = 0; MetadataIndex < scene->mMetaData->mNumProperties; ++MetadataIndex) {
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UpAxis") == 0) {
scene->mMetaData->Get<int32_t>(MetadataIndex, UpAxis);
}
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UpAxisSign") == 0) {
scene->mMetaData->Get<int32_t>(MetadataIndex, UpAxisSign);
}
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "FrontAxis") == 0) {
scene->mMetaData->Get<int32_t>(MetadataIndex, FrontAxis);
}
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "FrontAxisSign") == 0) {
scene->mMetaData->Get<int32_t>(MetadataIndex, FrontAxisSign);
}
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "CoordAxis") == 0) {
scene->mMetaData->Get<int32_t>(MetadataIndex, CoordAxis);
}
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "CoordAxisSign") == 0) {
scene->mMetaData->Get<int32_t>(MetadataIndex, CoordAxisSign);
}
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UnitScaleFactor") == 0) {
scene->mMetaData->Get<double>(MetadataIndex, UnitScaleFactor);
}
}
aiVector3D upVec, forwardVec, rightVec;
upVec[UpAxis] = UpAxisSign * static_cast<float>(UnitScaleFactor);
forwardVec[FrontAxis] = FrontAxisSign * static_cast<float>(UnitScaleFactor);
rightVec[CoordAxis] = CoordAxisSign * (float)UnitScaleFactor;
aiMatrix4x4 mat(rightVec.x, rightVec.y, rightVec.z, 0.0f,
upVec.x, upVec.y, upVec.z, 0.0f,
forwardVec.x, forwardVec.y, forwardVec.z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
scene->mRootNode->mTransformation *= mat;
}
FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) :
defaultMaterialIndex(),
mMeshes(),
@ -133,6 +180,8 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
// need not contain geometry (i.e. camera animations, raw armatures).
if (out->mNumMeshes == 0) {
out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
} else {
correctRootTransform(mSceneOut);
}
}
@ -1811,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
// This may occur on this case too, it has to be studied
path.data[0] = '*';
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index);
}
}
}
@ -2391,7 +2440,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
path.data[0] = '*';
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index);
}
out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0);
@ -2757,7 +2806,7 @@ void FBXConverter::ProcessMorphAnimDatas(std::map<std::string, morphAnimData *>
auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo);
auto geoIndex = static_cast<unsigned int>(std::distance(model->GetGeometry().begin(), geoIt));
auto name = aiString(FixNodeName(model->Name() + "*"));
name.length = 1 + ASSIMP_itoa10(name.data + name.length, MAXLEN - 1, geoIndex);
name.length = 1 + ASSIMP_itoa10(name.data + name.length, AI_MAXLEN - 1, geoIndex);
morphAnimData *animData;
auto animIt = morphAnimDatas->find(name.C_Str());
if (animIt == morphAnimDatas->end()) {
@ -3239,9 +3288,9 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
}
if (keyframeLists[TransformationComp_Rotation].size() > 0) {
InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], AI_DEG_TO_RAD(defRotation), maxTime, minTime, rotOrder);
InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder);
} else {
aiQuaternion defQuat = EulerToQuaternion(AI_DEG_TO_RAD(defRotation), rotOrder);
aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder);
for (size_t i = 0; i < keyCount; ++i) {
outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
outRotations[i].mValue = defQuat;
@ -3263,7 +3312,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
if (ok && preRotation.SquareLength() > zero_epsilon) {
const aiQuaternion preQuat = EulerToQuaternion(AI_DEG_TO_RAD(preRotation), Model::RotOrder_EulerXYZ);
const aiQuaternion preQuat = EulerToQuaternion(preRotation, Model::RotOrder_EulerXYZ);
for (size_t i = 0; i < keyCount; ++i) {
outRotations[i].mValue = preQuat * outRotations[i].mValue;
}
@ -3271,7 +3320,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
const aiVector3D& postRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok);
if (ok && postRotation.SquareLength() > zero_epsilon) {
const aiQuaternion postQuat = EulerToQuaternion(AI_DEG_TO_RAD(postRotation), Model::RotOrder_EulerXYZ);
const aiQuaternion postQuat = EulerToQuaternion(postRotation, Model::RotOrder_EulerXYZ);
for (size_t i = 0; i < keyCount; ++i) {
outRotations[i].mValue = outRotations[i].mValue * postQuat;
}

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)
{
std::vector<const aiNode*> node_chain;
while (node != scene->mRootNode) {
while (node != scene->mRootNode && node != nullptr) {
node_chain.push_back(node);
node = node->mParent;
}
@ -1868,33 +1868,26 @@ void FBXExporter::WriteObjects ()
// one sticky point is that the number of vertices may not match,
// 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.
// the skeleton must include not only the aiBones,
// but also all their parent nodes.
// 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
// Otherwise the aiNodes of the skeleton would be sorted based on the pointer address, which isn't consistent
std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes);
// note that we want to preserve input order as much as possible here.
// previously, sorting by name lead to consistent output across systems, but was not
// 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,
// which will be used later to mark them as type "limbNode".
std::unordered_set<const aiNode*> limbnodes;
//actual bone nodes in fbx, without parenting-up
std::unordered_set<std::string> setAllBoneNamesInScene;
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m)
{
std::vector<std::string> allBoneNames;
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m) {
aiMesh* pMesh = mScene->mMeshes[m];
for(unsigned int b = 0; b < pMesh->mNumBones; ++ b)
setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data);
allBoneNames.push_back(pMesh->mBones[b]->mName.data);
}
aiMatrix4x4 mxTransIdentity;
@ -1902,7 +1895,7 @@ void FBXExporter::WriteObjects ()
std::map<std::string,aiNode*> node_by_bone;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
const aiMesh* m = mScene->mMeshes[mi];
std::set<const aiNode*, SortNodeByName> skeleton;
std::vector<const aiNode*> skeleton;
for (size_t bi =0; bi < m->mNumBones; ++bi) {
const aiBone* b = m->mBones[bi];
const std::string name(b->mName.C_Str());
@ -1921,7 +1914,7 @@ void FBXExporter::WriteObjects ()
node_by_bone[name] = n;
limbnodes.insert(n);
}
skeleton.insert(n);
skeleton.push_back(n);
// mark all parent nodes as skeleton as well,
// up until we find the root node,
// or else the node containing the mesh,
@ -1932,7 +1925,7 @@ void FBXExporter::WriteObjects ()
parent = parent->mParent
) {
// if we've already done this node we can skip it all
if (skeleton.count(parent)) {
if (std::find(skeleton.begin(), skeleton.end(), parent) != skeleton.end()) {
break;
}
// ignore fbx transform nodes as these will be collapsed later
@ -1942,7 +1935,7 @@ void FBXExporter::WriteObjects ()
continue;
}
//not a bone in scene && no effect in transform
if(setAllBoneNamesInScene.find(node_name)==setAllBoneNamesInScene.end()
if (std::find(allBoneNames.begin(), allBoneNames.end(), node_name) == allBoneNames.end()
&& parent->mTransformation == mxTransIdentity) {
continue;
}
@ -2027,7 +2020,7 @@ void FBXExporter::WriteObjects ()
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
// now make a subdeformer for each bone in the skeleton
const std::set<const aiNode*, SortNodeByName> skeleton= skeleton_by_mesh[mi];
const auto & skeleton= skeleton_by_mesh[mi];
for (const aiNode* bone_node : skeleton) {
// if there's a bone for this node, find it
const aiBone* b = nullptr;

View File

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

View File

@ -63,7 +63,6 @@ class Scope;
class Parser;
class Element;
// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
using ScopeList = std::vector<Scope*>;
using ElementMap = std::fbx_unordered_multimap< std::string, Element*>;
using ElementCollection = std::pair<ElementMap::const_iterator,ElementMap::const_iterator>;
@ -135,7 +134,7 @@ public:
const char* elementNameCStr = elementName.c_str();
for (auto element = elements.begin(); element != elements.end(); ++element)
{
if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) {
if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, AI_MAXLEN)) {
return element->second;
}
}

View File

@ -243,7 +243,6 @@ DirectPropertyMap PropertyTable::GetUnparsedProperties() const
// Read the element's value.
// Wrap the naked pointer (since the call site is required to acquire ownership)
// std::unique_ptr from C++11 would be preferred both as a wrapper and a return value.
std::shared_ptr<Property> prop = std::shared_ptr<Property>(ReadTypedProperty(*currentElement.second));
// Element could not be read. Skip it.

View File

@ -49,7 +49,7 @@ namespace HMP {
#include <assimp/Compiler/pushpack1.h>
#include <stdint.h>
// to make it easier for us, we test the magic word against both "endianesses"
// to make it easier for us, we test the magic word against both "endiannesses"
#define AI_HMP_MAGIC_NUMBER_BE_4 AI_MAKE_MAGIC("HMP4")
#define AI_HMP_MAGIC_NUMBER_LE_4 AI_MAKE_MAGIC("4PMH")

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)));
const STEP::HeaderInfo &head = static_cast<const STEP::DB &>(*db).GetHeader();
if (!head.fileSchema.size() || head.fileSchema.substr(0, 3) != "IFC") {
if (!head.fileSchema.size() || head.fileSchema.substr(0, 4) != "IFC2") {
ThrowException("Unrecognized file schema: " + head.fileSchema);
}
@ -260,6 +260,8 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
ThrowException("missing IfcProject entity");
}
ConversionData conv(*db, proj->To<Schema_2x3::IfcProject>(), pScene, settings);
SetUnits(conv);
SetCoordinateSpace(conv);
@ -352,6 +354,11 @@ void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &co
// ------------------------------------------------------------------------------------------------
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.
for (size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i) {
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)));
aiString s;
s.length = ::ai_snprintf(s.data, MAXLEN, "SkyboxSide_%u", i);
s.length = ::ai_snprintf(s.data, AI_MAXLEN, "SkyboxSide_%u", i);
out->AddProperty(&s, AI_MATKEY_NAME);
int shading = aiShadingMode_NoShading;
@ -316,7 +316,7 @@ void IRRImporter::ComputeAnimations(Node *root, aiNode *real, std::vector<aiNode
if (cur != total - 1) {
// Build a new name - a prefix instead of a suffix because it is
// easier to check against
anim->mNodeName.length = ::ai_snprintf(anim->mNodeName.data, MAXLEN,
anim->mNodeName.length = ::ai_snprintf(anim->mNodeName.data, AI_MAXLEN,
"$INST_DUMMY_%i_%s", total - 1,
(root->name.length() ? root->name.c_str() : ""));

View File

@ -305,14 +305,14 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
}
std::string::size_type t = src.path.substr(s).find_last_of('.');
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
if (nd->mName.length > MAXLEN) {
nd->mName.length = MAXLEN;
nd->mName.length = ::ai_snprintf(nd->mName.data, AI_MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
if (nd->mName.length > AI_MAXLEN) {
nd->mName.length = AI_MAXLEN;
}
return;
}
}
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.name, combined);
nd->mName.length = ::ai_snprintf(nd->mName.data, AI_MAXLEN, "%s_(%08X)", src.name, combined);
}
// ------------------------------------------------------------------------------------------------

View File

@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace MD2 {
// to make it easier for us, we test the magic word against both "endianesses"
// to make it easier for us, we test the magic word against both "endiannesses"
#define AI_MD2_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP2")
#define AI_MD2_MAGIC_NUMBER_LE AI_MAKE_MAGIC("2PDI")

View File

@ -62,7 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace MD3 {
// to make it easier for us, we test the magic word against both "endianesses"
// to make it easier for us, we test the magic word against both "endiannesses"
#define AI_MD3_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP3")
#define AI_MD3_MAGIC_NUMBER_LE AI_MAKE_MAGIC("3PDI")

View File

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

View File

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

View File

@ -61,7 +61,7 @@ http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf
namespace Assimp {
namespace MDC {
// to make it easier for us, we test the magic word against both "endianesses"
// to make it easier for us, we test the magic word against both "endiannesses"
#define AI_MDC_MAGIC_NUMBER_BE AI_MAKE_MAGIC("CPDI")
#define AI_MDC_MAGIC_NUMBER_LE AI_MAKE_MAGIC("IDPC")

View File

@ -67,7 +67,7 @@ namespace Assimp {
namespace MDL {
// -------------------------------------------------------------------------------------
// to make it easier for us, we test the magic word against both "endianesses"
// to make it easier for us, we test the magic word against both "endiannesses"
// magic bytes used in Quake 1 MDL meshes
#define AI_MDL_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDPO")

View File

@ -962,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) {
// no real name for our poor bone is specified :-(
pcOutBone->mName.length = ai_snprintf(pcOutBone->mName.data, MAXLEN,
pcOutBone->mName.length = ai_snprintf(pcOutBone->mName.data, AI_MAXLEN,
"UnnamedBone_%i", iBone);
} else {
// Make sure we won't run over the buffer's end if there is no
@ -1567,7 +1567,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7() {
} else {
pcNode->mName.length = (ai_uint32)::strlen(szBuffer);
}
::strncpy(pcNode->mName.data, szBuffer, MAXLEN - 1);
::strncpy(pcNode->mName.data, szBuffer, AI_MAXLEN - 1);
++p;
}
}

View File

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

View File

@ -59,9 +59,9 @@ namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) {
void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* props) {
// invoke the exporter
ObjExporter exporter(pFile, pScene);
ObjExporter exporter(pFile, pScene, false, props);
if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
@ -86,9 +86,9 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Wavefront OBJ without the material file. Prototyped and registered in Exporter.cpp
void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* ) {
void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* props) {
// invoke the exporter
ObjExporter exporter(pFile, pScene, true);
ObjExporter exporter(pFile, pScene, true, props);
if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
@ -111,7 +111,7 @@ void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* p
static const std::string MaterialExt = ".mtl";
// ------------------------------------------------------------------------------------------------
ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl)
ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl, const ExportProperties* props)
: filename(_filename)
, pScene(pScene)
, vn()
@ -130,7 +130,10 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt
mOutputMat.imbue(l);
mOutputMat.precision(ASSIMP_AI_REAL_TEXT_PRECISION);
WriteGeometryFile(noMtl);
WriteGeometryFile(
noMtl,
props == nullptr ? true : props->GetPropertyBool("bJoinIdenticalVertices", true)
);
if ( !noMtl ) {
WriteMaterialFile();
}
@ -255,14 +258,14 @@ void ObjExporter::WriteMaterialFile() {
}
}
void ObjExporter::WriteGeometryFile(bool noMtl) {
void ObjExporter::WriteGeometryFile(bool noMtl, bool merge_identical_vertices) {
WriteHeader(mOutput);
if (!noMtl)
mOutput << "mtllib " << GetMaterialLibName() << endl << endl;
// collect mesh geometry
aiMatrix4x4 mBase;
AddNode(pScene->mRootNode, mBase);
AddNode(pScene->mRootNode, mBase, merge_identical_vertices);
// write vertex positions with colors, if any
mVpMap.getKeys( vp );
@ -330,7 +333,7 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
}
// ------------------------------------------------------------------------------------------------
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices) {
mMeshes.emplace_back();
MeshInstance& mesh = mMeshes.back();
@ -362,13 +365,14 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
const unsigned int idx = f.mIndices[a];
const unsigned int fi = merge_identical_vertices ? 0 : idx;
aiVector3D vert = mat * m->mVertices[idx];
if ( nullptr != m->mColors[ 0 ] ) {
aiColor4D col4 = m->mColors[ 0 ][ idx ];
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b)});
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b), fi});
} else {
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0)});
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0), fi});
}
if (m->mNormals) {
@ -388,21 +392,21 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
}
// ------------------------------------------------------------------------------------------------
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) {
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices) {
const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
aiMesh *cm( nullptr );
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
cm = pScene->mMeshes[nd->mMeshes[i]];
if (nullptr != cm) {
AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs);
AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices);
} else {
AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs);
AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices);
}
}
for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
AddNode(nd->mChildren[i], mAbs);
AddNode(nd->mChildren[i], mAbs, merge_identical_vertices);
}
}

View File

@ -51,6 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <map>
#include <assimp/Exporter.hpp>
struct aiScene;
struct aiNode;
struct aiMesh;
@ -63,7 +65,7 @@ namespace Assimp {
class ObjExporter {
public:
/// Constructor for a specific scene to export
ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false);
ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false, const ExportProperties* props = nullptr);
~ObjExporter();
std::string GetMaterialLibName();
std::string GetMaterialLibFileName();
@ -97,10 +99,10 @@ private:
void WriteHeader(std::ostringstream& out);
void WriteMaterialFile();
void WriteGeometryFile(bool noMtl=false);
void WriteGeometryFile(bool noMtl=false, bool merge_identical_vertices = false);
std::string GetMaterialName(unsigned int index);
void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat);
void AddNode(const aiNode* nd, const aiMatrix4x4& mParent);
void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices);
void AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices);
private:
std::string filename;
@ -109,6 +111,7 @@ private:
struct vertexData {
aiVector3D vp;
aiColor3D vc; // OBJ does not support 4D color
uint32_t index = 0;
};
std::vector<aiVector3D> vn, vt;
@ -133,7 +136,7 @@ private:
if (a.vc.g > b.vc.g) return false;
if (a.vc.b < b.vc.b) return true;
if (a.vc.b > b.vc.b) return false;
return false;
return a.index < b.index;
}
};

View File

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

View File

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

View File

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

View File

@ -343,7 +343,7 @@ void ObjFileMtlImporter::createMaterial() {
}
}
name = trim_whitespaces(name);
name = ai_trim(name);
std::map<std::string, ObjFile::Material *>::iterator it = m_pModel->mMaterialMap.find(name);
if (m_pModel->mMaterialMap.end() == it) {

View File

@ -52,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdlib>
#include <memory>
#include <utility>
#include <string_view>
namespace Assimp {
@ -578,15 +577,17 @@ void ObjFileParser::getMaterialDesc() {
// Get name
std::string strName(pStart, &(*m_DataIt));
strName = trim_whitespaces(strName);
strName = ai_trim(strName);
if (strName.empty()) {
skip = true;
}
// If the current mesh has the same material, we simply ignore that 'usemtl' command
// If the current mesh has the same material, we will ignore that 'usemtl' command
// There is no need to create another object or even mesh here
if (m_pModel->mCurrentMaterial && m_pModel->mCurrentMaterial->MaterialName == aiString(strName)) {
skip = true;
if (!skip) {
if (m_pModel->mCurrentMaterial && m_pModel->mCurrentMaterial->MaterialName == aiString(strName)) {
skip = true;
}
}
if (!skip) {

View File

@ -247,22 +247,6 @@ inline char_t getFloat(char_t it, char_t end, ai_real &value) {
return it;
}
/**
* @brief Will remove white-spaces for a string.
* @param[in] str The string to clean
* @return The trimmed string.
*/
template <class string_type>
inline string_type trim_whitespaces(string_type str) {
while (!str.empty() && IsSpace(str[0])) {
str.erase(0);
}
while (!str.empty() && IsSpace(str[str.length() - 1])) {
str.erase(str.length() - 1);
}
return str;
}
/**
* @brief Checks for a line-end.
* @param[in] it Current iterator in string.

View File

@ -346,10 +346,22 @@ 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) {
if (m->HasVertexColors(c)) {
mOutput.write(reinterpret_cast<const char*>(&m->mColors[c][i].r), 16);
unsigned char rgba[4] = {
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 {
mOutput.write(reinterpret_cast<const char*>(&defaultColor.r), 16);
unsigned char rgba[4] = {
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

@ -564,6 +564,10 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
if (mGeneratedMesh->mFaces == nullptr) {
mGeneratedMesh->mNumFaces = pcElement->NumOccur;
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
} else {
if (mGeneratedMesh->mNumFaces < pcElement->NumOccur) {
throw DeadlyImportError("Invalid .ply file: Too many faces");
}
}
if (!bIsTriStrip) {

View File

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

View File

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

View File

@ -589,12 +589,12 @@ void SMDImporter::CreateOutputMaterials() {
pScene->mMaterials[iMat] = pcMat;
aiString szName;
szName.length = static_cast<ai_uint32>(ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat));
szName.length = static_cast<ai_uint32>(ai_snprintf(szName.data, AI_MAXLEN, "Texture_%u", iMat));
pcMat->AddProperty(&szName,AI_MATKEY_NAME);
if (aszTextures[iMat].length())
{
::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1);
::strncpy(szName.data, aszTextures[iMat].c_str(), AI_MAXLEN - 1);
szName.length = static_cast<ai_uint32>( aszTextures[iMat].length() );
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];
// the default vertex color is light gray.
mClrColorDefault.r = mClrColorDefault.g = mClrColorDefault.b = mClrColorDefault.a = (ai_real)0.6;
mClrColorDefault.r = mClrColorDefault.g = mClrColorDefault.b = mClrColorDefault.a = 0.6f;
// allocate a single node
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_SPECULAR);
clrDiffuse = aiColor4D(ai_real(0.05), ai_real(0.05), ai_real(0.05), ai_real(1.0));
clrDiffuse = aiColor4D(0.05f, 0.05f, 0.05f, 1.0f);
pcMat->AddProperty(&clrDiffuse, 1, AI_MATKEY_COLOR_AMBIENT);
mScene->mNumMaterials = 1;
@ -257,7 +257,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
size_t temp = (size_t)(sz - szMe);
// setup the name of the node
if (temp) {
if (temp >= MAXLEN) {
if (temp >= AI_MAXLEN) {
throw DeadlyImportError("STL: Node name too long");
}
std::string name(szMe, temp);

View File

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

View File

@ -4,7 +4,6 @@ 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,
@ -37,11 +36,9 @@ 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.
@author: Richard Steffen, 2015
----------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER

View File

@ -0,0 +1,124 @@
/*
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

@ -0,0 +1,78 @@
/*
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

@ -0,0 +1,749 @@
/*
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

@ -0,0 +1,155 @@
/*
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

@ -0,0 +1,151 @@
/*
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

@ -0,0 +1,70 @@
/*
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

@ -0,0 +1,116 @@
/*
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

@ -0,0 +1,60 @@
/*
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

@ -0,0 +1,50 @@
/*
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);
aiString s;
::ai_snprintf(s.data, MAXLEN, "mat%u_tx%u_", i, materials[i].tex);
::ai_snprintf(s.data, AI_MAXLEN, "mat%u_tx%u_", i, materials[i].tex);
// set the two-sided flag
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
if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) {
s.length = ::ai_snprintf(s.data, MAXLEN, "$WeaponTag$");
s.length = ::ai_snprintf(s.data, AI_MAXLEN, "$WeaponTag$");
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
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
uri.data[0] = '*';
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx);
}
mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
@ -242,7 +242,7 @@ void glTFImporter::ImportMeshes(glTF::Asset &r) {
if (mesh.primitives.size() > 1) {
ai_uint32 &len = aim->mName.length;
aim->mName.data[len] = '-';
len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(AI_MAXLEN - len - 1), p);
}
switch (prim.mode) {

View File

@ -1440,7 +1440,7 @@ inline void MaterialSheen::SetDefaults() {
inline void MaterialVolume::SetDefaults() {
//KHR_materials_volume properties
thicknessFactor = 0.f;
attenuationDistance = INFINITY;
attenuationDistance = std::numeric_limits<float>::infinity();
SetVector(attenuationColor, defaultAttenuationColor);
}

View File

@ -507,7 +507,7 @@ namespace glTF2 {
WriteTex(materialVolume, volume.thicknessTexture, "thicknessTexture", w.mAl);
if (volume.attenuationDistance != INFINITY) {
if (volume.attenuationDistance != std::numeric_limits<float>::infinity()) {
WriteFloat(materialVolume, volume.attenuationDistance, "attenuationDistance", w.mAl);
}

View File

@ -92,7 +92,7 @@ static constexpr aiImporterDesc desc = {
0,
0,
0,
"gltf glb"
"gltf glb vrm"
};
glTF2Importer::glTF2Importer() :
@ -106,7 +106,7 @@ const aiImporterDesc *glTF2Importer::GetInfo() const {
bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(filename);
if (!checkSig && (extension != "gltf") && (extension != "glb")) {
if (!checkSig && (extension != "gltf") && (extension != "glb") && (extension != "vrm")) {
return false;
}
@ -161,7 +161,7 @@ static void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
if (texIdx != -1) { // embedded
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
uri.data[0] = '*';
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx);
}
mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot));
@ -539,7 +539,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
if (mesh.primitives.size() > 1) {
ai_uint32 &len = aim->mName.length;
aim->mName.data[len] = '-';
len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(AI_MAXLEN - len - 1), p);
}
switch (prim.mode) {

View File

@ -42,7 +42,7 @@
# 3) Add libassimp using the file lists (eliminates duplication of file names between
# source groups and library command)
#
cmake_minimum_required( VERSION 3.10 )
cmake_minimum_required( VERSION 3.22 )
SET( HEADER_PATH ../include/assimp )
if(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
@ -471,6 +471,14 @@ ADD_ASSIMP_IMPORTER( MDL
AssetLib/MDL/HalfLife/UniqueNameGenerator.h
)
IF(((CMAKE_CXX_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU) AND CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 13)
message(STATUS "GCC13 detected disabling \"-Warray-bounds and -Wstringop-overflow\" for"
" AssetLib/MDL/MDLLoader.cpp as it appears to be a false positive")
set_source_files_properties(AssetLib/MDL/MDLLoader.cpp PROPERTIES
COMPILE_FLAGS "-Wno-array-bounds -Wno-stringop-overflow"
)
endif()
SET( MaterialSystem_SRCS
Material/MaterialSystem.cpp
Material/MaterialSystem.h
@ -503,6 +511,14 @@ ADD_ASSIMP_IMPORTER( OBJ
AssetLib/Obj/ObjTools.h
)
IF(((CMAKE_CXX_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU) AND CMAKE_CXX_COMPILER_VERSION EQUAL 14)
message(STATUS "GCC14 detected disabling \"-Wmaybe-uninitialized\" for"
" AssetLib/Obj/ObjFileParser.cpp as it appears to be a false positive")
set_source_files_properties(AssetLib/Obj/ObjFileParser.cpp PROPERTIES
COMPILE_FLAGS "-Wno-maybe-uninitialized"
)
endif()
ADD_ASSIMP_IMPORTER( OGRE
AssetLib/Ogre/OgreImporter.h
AssetLib/Ogre/OgreStructs.h
@ -812,6 +828,17 @@ ADD_ASSIMP_IMPORTER( 3D
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
AssetLib/X/XFileHelper.h
AssetLib/X/XFileImporter.cpp
@ -905,6 +932,123 @@ SET( 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
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(pugixml)
@ -1155,6 +1299,8 @@ SET( assimp_src
${openddl_parser_SRCS}
${open3dgc_SRCS}
${ziplib_SRCS}
${Tinyusdz_SRCS}
${Tinyusdz_DEP_SOURCES}
${Pugixml_SRCS}
${stb_SRCS}
# Necessary to show the headers in the project when using the VC++ generator:
@ -1286,7 +1432,7 @@ IF(ASSIMP_HUNTER_ENABLED)
endif()
if (ASSIMP_BUILD_DRACO)
target_link_libraries(assimp PUBLIC ${draco_LIBRARIES})
target_link_libraries(assimp PRIVATE ${draco_LIBRARIES})
endif()
ELSE()
TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES})
@ -1400,19 +1546,20 @@ IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
TARGET_LINK_LIBRARIES(assimp rt)
ENDIF ()
IF(ASSIMP_INSTALL)
INSTALL( TARGETS assimp
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP-DEV_COMPONENT}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
)
INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)
INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev)
ENDIF()
INSTALL( TARGETS assimp
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP-DEV_COMPONENT}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
)
INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)
INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev)
if (ASSIMP_ANDROID_JNIIOSYSTEM)
if (ASSIMP_ANDROID_JNIIOSYSTEM AND ASSIMP_INSTALL)
INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h
DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
COMPONENT assimp-dev)

View File

@ -233,8 +233,13 @@ const aiScene *aiImportFileFromMemoryWithProperties(
unsigned int pFlags,
const char *pHint,
const aiPropertyStore *props) {
ai_assert(nullptr != pBuffer);
ai_assert(0 != pLength);
if (pBuffer == nullptr) {
return nullptr;
}
if (pLength == 0u) {
return nullptr;
}
const aiScene *scene = nullptr;
ASSIMP_BEGIN_EXCEPTION_REGION();
@ -738,14 +743,14 @@ ASSIMP_API void aiVector2DivideByVector(
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector2Length(
ASSIMP_API ai_real aiVector2Length(
const C_STRUCT aiVector2D *v) {
ai_assert(nullptr != v);
return v->Length();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector2SquareLength(
ASSIMP_API ai_real aiVector2SquareLength(
const C_STRUCT aiVector2D *v) {
ai_assert(nullptr != v);
return v->SquareLength();
@ -759,7 +764,7 @@ ASSIMP_API void aiVector2Negate(
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector2DotProduct(
ASSIMP_API ai_real aiVector2DotProduct(
const C_STRUCT aiVector2D *a,
const C_STRUCT aiVector2D *b) {
ai_assert(nullptr != a);
@ -854,14 +859,14 @@ ASSIMP_API void aiVector3DivideByVector(
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector3Length(
ASSIMP_API ai_real aiVector3Length(
const C_STRUCT aiVector3D *v) {
ai_assert(nullptr != v);
return v->Length();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector3SquareLength(
ASSIMP_API ai_real aiVector3SquareLength(
const C_STRUCT aiVector3D *v) {
ai_assert(nullptr != v);
return v->SquareLength();
@ -875,7 +880,7 @@ ASSIMP_API void aiVector3Negate(
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiVector3DotProduct(
ASSIMP_API ai_real aiVector3DotProduct(
const C_STRUCT aiVector3D *a,
const C_STRUCT aiVector3D *b) {
ai_assert(nullptr != a);
@ -961,7 +966,7 @@ ASSIMP_API void aiMatrix3Inverse(C_STRUCT aiMatrix3x3 *mat) {
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) {
ASSIMP_API ai_real aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) {
ai_assert(nullptr != mat);
return mat->Determinant();
}
@ -1061,7 +1066,7 @@ ASSIMP_API void aiMatrix4Inverse(C_STRUCT aiMatrix4x4 *mat) {
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API float aiMatrix4Determinant(const C_STRUCT aiMatrix4x4 *mat) {
ASSIMP_API ai_real aiMatrix4Determinant(const C_STRUCT aiMatrix4x4 *mat) {
ai_assert(nullptr != mat);
return mat->Determinant();
}

View File

@ -93,10 +93,6 @@ BaseImporter::BaseImporter() AI_NO_EXCEPT
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
BaseImporter::~BaseImporter() = default;
void BaseImporter::UpdateImporterScale(Importer *pImp) {
ai_assert(pImp != nullptr);
ai_assert(importerScale != 0.0);
@ -254,9 +250,10 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
/*static*/ bool BaseImporter::SimpleExtensionCheck(const std::string &pFile,
const char *ext0,
const char *ext1,
const char *ext2) {
const char *ext2,
const char *ext3) {
std::set<std::string> extensions;
for (const char* ext : {ext0, ext1, ext2}) {
for (const char* ext : {ext0, ext1, ext2, ext3}) {
if (ext == nullptr) continue;
extensions.emplace(ext);
}

View File

@ -57,10 +57,6 @@ BaseProcess::BaseProcess() AI_NO_EXCEPT
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
BaseProcess::~BaseProcess() = default;
// ------------------------------------------------------------------------------------------------
void BaseProcess::ExecuteOnScene(Importer *pImp) {
ai_assert( nullptr != pImp );

View File

@ -179,11 +179,11 @@ class ASSIMP_API BaseProcess {
friend class Importer;
public:
/** @brief onstructor to be privately used by Importer */
/** @brief Constructor to be privately used by Importer */
BaseProcess() AI_NO_EXCEPT;
/** @brief Destructor, private as well */
virtual ~BaseProcess();
/** @brief Destructor */
virtual ~BaseProcess() = default;
// -------------------------------------------------------------------
/**

View File

@ -148,8 +148,10 @@ void Bitmap::WriteData(aiTexture *texture, IOStream *file) {
file->Write(pixel, mBytesPerPixel, 1);
}
file->Write(padding_data, padding, 1);
// When padding is 0, passing it as an argument will cause an assertion failure in DefaultIOStream::Write.
if (padding) {
file->Write(padding_data, padding, 1);
}
}
}

View File

@ -74,11 +74,11 @@ public:
typedef unsigned int KeyType;
// typedefs for our configuration maps.
typedef std::map<KeyType, int> IntPropertyMap;
typedef std::map<KeyType, ai_real> FloatPropertyMap;
typedef std::map<KeyType, std::string> StringPropertyMap;
typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
typedef std::map<KeyType, void*> PointerPropertyMap;
using IntPropertyMap = std::map<KeyType, int>;
using FloatPropertyMap = std::map<KeyType, ai_real>;
using StringPropertyMap = std::map<KeyType, std::string>;
using MatrixPropertyMap = std::map<KeyType, aiMatrix4x4>;
using PointerPropertyMap = std::map<KeyType, void*>;
/** IO handler to use for all file accesses. */
IOSystem* mIOHandler;
@ -128,10 +128,12 @@ public:
/// The default class constructor.
ImporterPimpl() AI_NO_EXCEPT;
/// The class destructor.
~ImporterPimpl() = default;
};
inline
ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT :
inline ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT :
mIOHandler( nullptr ),
mIsDefaultHandler( false ),
mProgressHandler( nullptr ),

View File

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

View File

@ -5,8 +5,6 @@ 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,
@ -50,16 +48,13 @@ the 3ds loader handling smooth groups correctly */
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
SGSpatialSort::SGSpatialSort()
{
SGSpatialSort::SGSpatialSort() {
// define the reference plane. We choose some arbitrary vector away from all basic axes
// in the hope that no model spreads all its vertices along this plane.
mPlaneNormal.Set( 0.8523f, 0.34321f, 0.5736f);
mPlaneNormal.Normalize();
}
// ------------------------------------------------------------------------------------------------
// Destructor
SGSpatialSort::~SGSpatialSort() = default;
// ------------------------------------------------------------------------------------------------
void SGSpatialSort::Add(const aiVector3D& vPosition, unsigned int index,
unsigned int smoothingGroup)

View File

@ -78,7 +78,7 @@ inline void PrefixString(aiString &string, const char *prefix, unsigned int len)
if (string.length >= 1 && string.data[0] == '$')
return;
if (len + string.length >= MAXLEN - 1) {
if (len + string.length >= AI_MAXLEN - 1) {
ASSIMP_LOG_VERBOSE_DEBUG("Can't add an unique prefix because the string is too long");
ai_assert(false);
return;
@ -408,7 +408,7 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
// where n is the index of the texture.
// 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
// MAXLEN in size.
// AI_MAXLEN in size.
aiString s(*(aiString *)prop->mData);
if ('*' == s.data[0]) {
// Offset the index and write it back ..

View File

@ -4,7 +4,6 @@ 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,
@ -56,7 +55,7 @@ class ScenePreprocessorTest;
namespace Assimp {
// ----------------------------------------------------------------------------------
/** ScenePreprocessor: Preprocess a scene before any post-processing
/** ScenePreprocessor: Pre-process a scene before any post-processing
* steps are executed.
*
* The step computes data that needn't necessarily be provided by the
@ -79,6 +78,9 @@ public:
ScenePreprocessor(aiScene *_scene) :
scene(_scene) {}
/// @brief The class destructor.
~ScenePreprocessor() = default;
// ----------------------------------------------------------------
/** Assign a (new) scene to the object.
*

View File

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

View File

@ -61,9 +61,10 @@ namespace Assimp {
class StackAllocator {
public:
/// @brief Constructs the allocator
inline StackAllocator();
StackAllocator();
/// @brief Destructs the allocator and frees all memory
inline ~StackAllocator();
~StackAllocator();
// non copyable
StackAllocator(const StackAllocator &) = delete;
@ -87,6 +88,11 @@ private:
} // 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"
#endif // include guard

View File

@ -41,11 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StackAllocator.h"
#include <assimp/ai_assert.h>
#include <algorithm>
using namespace Assimp;
inline StackAllocator::StackAllocator() {
}
inline StackAllocator::StackAllocator() : m_storageBlocks() {}
inline StackAllocator::~StackAllocator() {
FreeAll();
@ -56,7 +56,7 @@ inline void *StackAllocator::Allocate(size_t byteSize) {
{
// double block size every time, up to maximum of g_maxBytesPerBlock.
// Block size must be at least as large as byteSize, but we want to use this for small allocations anyway.
m_blockAllocationSize = std::max(std::min(m_blockAllocationSize * 2, g_maxBytesPerBlock), byteSize);
m_blockAllocationSize = std::max<std::size_t>(std::min<std::size_t>(m_blockAllocationSize * 2, g_maxBytesPerBlock), byteSize);
uint8_t *data = new uint8_t[m_blockAllocationSize];
m_storageBlocks.emplace_back(data);
m_subIndex = byteSize;

View File

@ -4,7 +4,6 @@ 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,
@ -525,7 +524,11 @@ void CatmullClarkSubdivider::InternSubdivide(
}
}
ai_assert(adj[o] - moffsets[nidx].first < mp->mNumFaces);
if (mp == nullptr) {
continue;
}
ai_assert(adj[o] - moffsets[nidx].first < mp->mNumFaces);
const aiFace &f = mp->mFaces[adj[o] - moffsets[nidx].first];
bool haveit = false;

View File

@ -4,7 +4,6 @@ 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,

View File

@ -4,7 +4,6 @@ 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,
@ -119,12 +118,16 @@ private:
* look-at target */
class TargetAnimationHelper {
public:
/// @brief The class constructor.
TargetAnimationHelper() :
targetPositions(nullptr),
objectPositions(nullptr) {
// empty
}
/// @brief The class destructor.
~TargetAnimationHelper() = default;
// ------------------------------------------------------------------
/** Sets the target animation channel
*

View File

@ -44,15 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ScenePrivate.h"
#include <assimp/scene.h>
#include <assimp/version.h>
#include "revision.h"
#include <assimp/revision.h>
// --------------------------------------------------------------------------------
// Legal information string - don't remove this.
static constexpr char LEGAL_INFORMATION[] =
"Open Asset Import Library (Assimp).\n"
"A free C/C++ library to import various 3D file formats into applications\n\n"
"(c) 2006-2023, Assimp team\n"
"(c) 2006-2024, Assimp team\n"
"License under the terms and conditions of the 3-clause BSD license\n"
"https://www.assimp.org\n";
@ -118,83 +117,3 @@ ASSIMP_API const char *aiGetBranchName() {
return GitBranch;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API aiScene::aiScene() :
mFlags(0),
mRootNode(nullptr),
mNumMeshes(0),
mMeshes(nullptr),
mNumMaterials(0),
mMaterials(nullptr),
mNumAnimations(0),
mAnimations(nullptr),
mNumTextures(0),
mTextures(nullptr),
mNumLights(0),
mLights(nullptr),
mNumCameras(0),
mCameras(nullptr),
mMetaData(nullptr),
mName(),
mNumSkeletons(0),
mSkeletons(nullptr),
mPrivate(new Assimp::ScenePrivateData()) {
// empty
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API aiScene::~aiScene() {
// delete all sub-objects recursively
delete mRootNode;
// To make sure we won't crash if the data is invalid it's
// much better to check whether both mNumXXX and mXXX are
// valid instead of relying on just one of them.
if (mNumMeshes && mMeshes) {
for (unsigned int a = 0; a < mNumMeshes; ++a) {
delete mMeshes[a];
}
}
delete[] mMeshes;
if (mNumMaterials && mMaterials) {
for (unsigned int a = 0; a < mNumMaterials; ++a) {
delete mMaterials[a];
}
}
delete[] mMaterials;
if (mNumAnimations && mAnimations) {
for (unsigned int a = 0; a < mNumAnimations; ++a) {
delete mAnimations[a];
}
}
delete[] mAnimations;
if (mNumTextures && mTextures) {
for (unsigned int a = 0; a < mNumTextures; ++a) {
delete mTextures[a];
}
}
delete[] mTextures;
if (mNumLights && mLights) {
for (unsigned int a = 0; a < mNumLights; ++a) {
delete mLights[a];
}
}
delete[] mLights;
if (mNumCameras && mCameras) {
for (unsigned int a = 0; a < mNumCameras; ++a) {
delete mCameras[a];
}
}
delete[] mCameras;
aiMetadata::Dealloc(mMetaData);
delete[] mSkeletons;
delete static_cast<Assimp::ScenePrivateData *>(mPrivate);
}

View File

@ -5,8 +5,6 @@ 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,

View File

@ -62,13 +62,13 @@ namespace Assimp {
// ----------------------------------------------------------------
// A read-only file inside a ZIP
class ZipFile : public IOStream {
class ZipFile final : public IOStream {
friend class ZipFileInfo;
explicit ZipFile(std::string &filename, size_t size);
public:
std::string m_Filename;
virtual ~ZipFile() override;
~ZipFile() override = default;
// IOStream interface
size_t Read(void *pvBuffer, size_t pSize, size_t pCount) override;
@ -89,6 +89,8 @@ private:
// Wraps an existing Assimp::IOSystem for unzip
class IOSystem2Unzip {
public:
IOSystem2Unzip() = default;
~IOSystem2Unzip() = default;
static voidpf open(voidpf opaque, const char *filename, int mode);
static voidpf opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode);
static uLong read(voidpf opaque, voidpf stream, void *buf, uLong size);
@ -100,6 +102,7 @@ public:
static zlib_filefunc_def get(IOSystem *pIOHandler);
};
// ----------------------------------------------------------------
voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) {
IOSystem *io_system = reinterpret_cast<IOSystem *>(opaque);
@ -119,6 +122,7 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) {
return (voidpf)io_system->Open(filename, mode_fopen);
}
// ----------------------------------------------------------------
voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) {
ZipFile *io_stream = (ZipFile *)stream;
voidpf ret = nullptr;
@ -141,24 +145,28 @@ voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_di
return ret;
}
// ----------------------------------------------------------------
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void *buf, uLong size) {
IOStream *io_stream = (IOStream *)stream;
return static_cast<uLong>(io_stream->Read(buf, 1, size));
}
// ----------------------------------------------------------------
uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void *buf, uLong size) {
IOStream *io_stream = (IOStream *)stream;
return static_cast<uLong>(io_stream->Write(buf, 1, size));
}
// ----------------------------------------------------------------
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
IOStream *io_stream = (IOStream *)stream;
return static_cast<long>(io_stream->Tell());
}
// ----------------------------------------------------------------
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
IOStream *io_stream = (IOStream *)stream;
@ -179,6 +187,7 @@ long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int or
return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
}
// ----------------------------------------------------------------
int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
IOSystem *io_system = (IOSystem *)opaque;
IOStream *io_stream = (IOStream *)stream;
@ -188,10 +197,12 @@ int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
return 0;
}
// ----------------------------------------------------------------
int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
return 0;
}
// ----------------------------------------------------------------
zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) {
zlib_filefunc_def mapping;
@ -213,9 +224,10 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) {
// ----------------------------------------------------------------
// Info about a read-only file inside a ZIP
class ZipFileInfo {
class ZipFileInfo final {
public:
explicit ZipFileInfo(unzFile zip_handle, size_t size);
~ZipFileInfo() = default;
// Allocate and Extract data from the ZIP
ZipFile *Extract(std::string &filename, unzFile zip_handle) const;
@ -225,6 +237,7 @@ private:
unz_file_pos_s m_ZipFilePos;
};
// ----------------------------------------------------------------
ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size) :
m_Size(size) {
ai_assert(m_Size != 0);
@ -234,6 +247,7 @@ ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size) :
unzGetFilePos(zip_handle, &(m_ZipFilePos));
}
// ----------------------------------------------------------------
ZipFile *ZipFileInfo::Extract(std::string &filename, unzFile zip_handle) const {
// Find in the ZIP. This cannot fail
unz_file_pos_s *filepos = const_cast<unz_file_pos_s *>(&(m_ZipFilePos));
@ -273,14 +287,14 @@ ZipFile *ZipFileInfo::Extract(std::string &filename, unzFile zip_handle) const {
return zip_file;
}
// ----------------------------------------------------------------
ZipFile::ZipFile(std::string &filename, size_t size) :
m_Filename(filename), m_Size(size) {
ai_assert(m_Size != 0);
m_Buffer = std::unique_ptr<uint8_t[]>(new uint8_t[m_Size]);
}
ZipFile::~ZipFile() = default;
// ----------------------------------------------------------------
size_t ZipFile::Read(void *pvBuffer, size_t pSize, size_t pCount) {
// Should be impossible
ai_assert(m_Buffer != nullptr);
@ -305,10 +319,12 @@ size_t ZipFile::Read(void *pvBuffer, size_t pSize, size_t pCount) {
return pCount;
}
// ----------------------------------------------------------------
size_t ZipFile::FileSize() const {
return m_Size;
}
// ----------------------------------------------------------------
aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) {
switch (pOrigin) {
case aiOrigin_SET: {
@ -334,6 +350,7 @@ aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) {
return aiReturn_FAILURE;
}
// ----------------------------------------------------------------
size_t ZipFile::Tell() const {
return m_SeekPtr;
}
@ -365,6 +382,7 @@ private:
ZipFileInfoMap m_ArchiveMap;
};
// ----------------------------------------------------------------
ZipArchiveIOSystem::Implement::Implement(IOSystem *pIOHandler, const char *pFilename, const char *pMode) {
ai_assert(strcmp(pMode, "r") == 0);
ai_assert(pFilename != nullptr);
@ -376,12 +394,14 @@ ZipArchiveIOSystem::Implement::Implement(IOSystem *pIOHandler, const char *pFile
m_ZipFileHandle = unzOpen2(pFilename, &mapping);
}
// ----------------------------------------------------------------
ZipArchiveIOSystem::Implement::~Implement() {
if (m_ZipFileHandle != nullptr) {
unzClose(m_ZipFileHandle);
}
}
// ----------------------------------------------------------------
void ZipArchiveIOSystem::Implement::MapArchive() {
if (m_ZipFileHandle == nullptr)
return;
@ -408,10 +428,12 @@ void ZipArchiveIOSystem::Implement::MapArchive() {
} while (unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
}
// ----------------------------------------------------------------
bool ZipArchiveIOSystem::Implement::isOpen() const {
return (m_ZipFileHandle != nullptr);
}
// ----------------------------------------------------------------
void ZipArchiveIOSystem::Implement::getFileList(std::vector<std::string> &rFileList) {
MapArchive();
rFileList.clear();
@ -421,6 +443,7 @@ void ZipArchiveIOSystem::Implement::getFileList(std::vector<std::string> &rFileL
}
}
// ----------------------------------------------------------------
void ZipArchiveIOSystem::Implement::getFileListExtension(std::vector<std::string> &rFileList, const std::string &extension) {
MapArchive();
rFileList.clear();
@ -431,6 +454,7 @@ void ZipArchiveIOSystem::Implement::getFileListExtension(std::vector<std::string
}
}
// ----------------------------------------------------------------
bool ZipArchiveIOSystem::Implement::Exists(std::string &filename) {
MapArchive();
@ -438,6 +462,7 @@ bool ZipArchiveIOSystem::Implement::Exists(std::string &filename) {
return (it != m_ArchiveMap.end());
}
// ----------------------------------------------------------------
IOStream *ZipArchiveIOSystem::Implement::OpenFile(std::string &filename) {
MapArchive();
@ -452,6 +477,7 @@ IOStream *ZipArchiveIOSystem::Implement::OpenFile(std::string &filename) {
return zip_file.Extract(filename, m_ZipFileHandle);
}
// ----------------------------------------------------------------
inline void ReplaceAll(std::string &data, const std::string &before, const std::string &after) {
size_t pos = data.find(before);
while (pos != std::string::npos) {
@ -460,6 +486,7 @@ inline void ReplaceAll(std::string &data, const std::string &before, const std::
}
}
// ----------------------------------------------------------------
inline void ReplaceAllChar(std::string &data, const char before, const char after) {
size_t pos = data.find(before);
while (pos != std::string::npos) {
@ -468,6 +495,7 @@ inline void ReplaceAllChar(std::string &data, const char before, const char afte
}
}
// ----------------------------------------------------------------
void ZipArchiveIOSystem::Implement::SimplifyFilename(std::string &filename) {
ReplaceAllChar(filename, '\\', '/');
@ -492,6 +520,7 @@ void ZipArchiveIOSystem::Implement::SimplifyFilename(std::string &filename) {
}
}
// ----------------------------------------------------------------
ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem *pIOHandler, const char *pFilename, const char *pMode) :
pImpl(new Implement(pIOHandler, pFilename, pMode)) {
}
@ -502,10 +531,12 @@ ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem *pIOHandler, const std::string &
pImpl(new Implement(pIOHandler, rFilename.c_str(), pMode)) {
}
// ----------------------------------------------------------------
ZipArchiveIOSystem::~ZipArchiveIOSystem() {
delete pImpl;
}
// ----------------------------------------------------------------
bool ZipArchiveIOSystem::Exists(const char *pFilename) const {
ai_assert(pFilename != nullptr);
@ -517,11 +548,13 @@ bool ZipArchiveIOSystem::Exists(const char *pFilename) const {
return pImpl->Exists(filename);
}
// ----------------------------------------------------------------
// This is always '/' in a ZIP
char ZipArchiveIOSystem::getOsSeparator() const {
return '/';
}
// ----------------------------------------------------------------
// Only supports Reading
IOStream *ZipArchiveIOSystem::Open(const char *pFilename, const char *pMode) {
ai_assert(pFilename != nullptr);
@ -536,22 +569,27 @@ IOStream *ZipArchiveIOSystem::Open(const char *pFilename, const char *pMode) {
return pImpl->OpenFile(filename);
}
// ----------------------------------------------------------------
void ZipArchiveIOSystem::Close(IOStream *pFile) {
delete pFile;
}
// ----------------------------------------------------------------
bool ZipArchiveIOSystem::isOpen() const {
return (pImpl->isOpen());
}
// ----------------------------------------------------------------
void ZipArchiveIOSystem::getFileList(std::vector<std::string> &rFileList) const {
return pImpl->getFileList(rFileList);
}
// ----------------------------------------------------------------
void ZipArchiveIOSystem::getFileListExtension(std::vector<std::string> &rFileList, const std::string &extension) const {
return pImpl->getFileListExtension(rFileList, extension);
}
// ----------------------------------------------------------------
bool ZipArchiveIOSystem::isZipArchive(IOSystem *pIOHandler, const char *pFilename) {
Implement tmp(pIOHandler, pFilename, "r");
return tmp.isOpen();

View File

@ -40,6 +40,87 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assimp/scene.h>
#include "ScenePrivate.h"
aiScene::aiScene() :
mFlags(0),
mRootNode(nullptr),
mNumMeshes(0),
mMeshes(nullptr),
mNumMaterials(0),
mMaterials(nullptr),
mNumAnimations(0),
mAnimations(nullptr),
mNumTextures(0),
mTextures(nullptr),
mNumLights(0),
mLights(nullptr),
mNumCameras(0),
mCameras(nullptr),
mMetaData(nullptr),
mName(),
mNumSkeletons(0),
mSkeletons(nullptr),
mPrivate(new Assimp::ScenePrivateData()) {
// empty
}
aiScene::~aiScene() {
// delete all sub-objects recursively
delete mRootNode;
// To make sure we won't crash if the data is invalid it's
// much better to check whether both mNumXXX and mXXX are
// valid instead of relying on just one of them.
if (mNumMeshes && mMeshes) {
for (unsigned int a = 0; a < mNumMeshes; ++a) {
delete mMeshes[a];
}
}
delete[] mMeshes;
if (mNumMaterials && mMaterials) {
for (unsigned int a = 0; a < mNumMaterials; ++a) {
delete mMaterials[a];
}
}
delete[] mMaterials;
if (mNumAnimations && mAnimations) {
for (unsigned int a = 0; a < mNumAnimations; ++a) {
delete mAnimations[a];
}
}
delete[] mAnimations;
if (mNumTextures && mTextures) {
for (unsigned int a = 0; a < mNumTextures; ++a) {
delete mTextures[a];
}
}
delete[] mTextures;
if (mNumLights && mLights) {
for (unsigned int a = 0; a < mNumLights; ++a) {
delete mLights[a];
}
}
delete[] mLights;
if (mNumCameras && mCameras) {
for (unsigned int a = 0; a < mNumCameras; ++a) {
delete mCameras[a];
}
}
delete[] mCameras;
aiMetadata::Dealloc(mMetaData);
delete[] mSkeletons;
delete static_cast<Assimp::ScenePrivateData *>(mPrivate);
}
aiNode::aiNode() :
mName(""),
mParent(nullptr),

View File

@ -49,6 +49,10 @@ namespace Assimp {
// ---------------------------------------------------------------------------
class ASSIMP_API GeometryUtils {
public:
/// @brief Will calculate the area of a triangle.
/// @param a The first vertex of the triangle.
/// @param b The first vertex of the triangle.
/// @param c The first vertex of the triangle.
static ai_real heron( ai_real a, ai_real b, ai_real c );
/// @brief Will compute the distance between 2 3D-vectors

View File

@ -174,6 +174,95 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
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
aiReturn aiGetMaterialIntegerArray(const aiMaterial *pMat,
@ -486,7 +575,7 @@ aiReturn aiMaterial::AddBinaryProperty(const void *pInput,
memcpy(pcNew->mData, pInput, pSizeInBytes);
pcNew->mKey.length = static_cast<ai_uint32>(::strlen(pKey));
ai_assert(MAXLEN > pcNew->mKey.length);
ai_assert(AI_MAXLEN > pcNew->mKey.length);
strcpy(pcNew->mKey.data, pKey);
if (UINT_MAX != iOutIndex) {

View File

@ -185,9 +185,9 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
tangent.y = (w.y * sy - v.y * ty) * dirCorrection;
tangent.z = (w.z * sy - v.z * ty) * dirCorrection;
bitangent.x = (- w.x * sx + v.x * tx) * dirCorrection;
bitangent.y = (- w.y * sx + v.y * tx) * dirCorrection;
bitangent.z = (- w.z * sx + v.z * tx) * dirCorrection;
bitangent.x = (w.x * sx - v.x * tx) * dirCorrection;
bitangent.y = (w.y * sx - v.y * tx) * dirCorrection;
bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
// store for every vertex of that face
for (unsigned int b = 0; b < face.mNumIndices; ++b) {
@ -195,7 +195,7 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
// project tangent and bitangent into the plane formed by the vertex' normal
aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]) - localTangent * (bitangent * localTangent);
aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
localTangent.NormalizeSafe();
localBitangent.NormalizeSafe();

View File

@ -346,16 +346,20 @@ void ComputeUVMappingProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin");
char buffer[1024];
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
}
std::list<MappingInfo> mappingStack;
/* Iterate through all materials and search for non-UV mapped textures
*/
// Iterate through all materials and search for non-UV mapped textures
for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
mappingStack.clear();
aiMaterial *mat = pScene->mMaterials[i];
if (mat == nullptr) {
ASSIMP_LOG_INFO("Material pointer in nullptr, skipping.");
continue;
}
for (unsigned int a = 0; a < mat->mNumProperties; ++a) {
aiMaterialProperty *prop = mat->mProperties[a];
if (!::strcmp(prop->mKey.data, "$tex.mapping")) {

View File

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

View File

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

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