Compare commits
52
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30b20e07e7 | ||
|
|
fa18d3dde6 | ||
|
|
709fe3c3d0 | ||
|
|
489c8d565b | ||
|
|
0581ed5f11 | ||
|
|
5c568616ec | ||
|
|
45cb880835 | ||
|
|
dd98d4aea3 | ||
|
|
01ac320de8 | ||
|
|
a815a78433 | ||
|
|
69f8eb21fd | ||
|
|
72b9939b9f | ||
|
|
4c8a3bd39c | ||
|
|
8ef3838beb | ||
|
|
441884387f | ||
|
|
f7bbf6dc15 | ||
|
|
aadd49311a | ||
|
|
3f107bebf2 | ||
|
|
a38ec50fd3 | ||
|
|
4c42db1805 | ||
|
|
26e2372882 | ||
|
|
36b004e286 | ||
|
|
3a0ee8792f | ||
|
|
e3f9cf5564 | ||
|
|
6d7ea78792 | ||
|
|
13316790aa | ||
|
|
9255412906 | ||
|
|
8355e0c4bc | ||
|
|
6fa9d09a97 | ||
|
|
9f4e7c6d8d | ||
|
|
59bc03d931 | ||
|
|
edcb350129 | ||
|
|
a79dc358cf | ||
|
|
db0bde758e | ||
|
|
b447485c06 | ||
|
|
4c61ca3af5 | ||
|
|
4b6cc8c28a | ||
|
|
d99f9bd2f7 | ||
|
|
b2afe717d3 | ||
|
|
ad6e8e210a | ||
|
|
fb375dd8c0 | ||
|
|
a95addfc4a | ||
|
|
2d8c09b60f | ||
|
|
357b5baabb | ||
|
|
269987085f | ||
|
|
5be336779d | ||
|
|
177797c77b | ||
|
|
c1d6226c06 | ||
|
|
8621d52430 | ||
|
|
5d39661751 | ||
|
|
a98ffe6c6f | ||
|
|
b3a47a68fa |
@@ -16,9 +16,13 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++]
|
||||
name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, windows-latest-clang.exe, ubuntu-latest-clang++]
|
||||
# For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
|
||||
include:
|
||||
- name: windows-latest-clang.exe
|
||||
os: windows-latest
|
||||
cxx: clang++.exe
|
||||
cc: clang.exe
|
||||
- name: windows-latest-cl.exe
|
||||
os: windows-latest
|
||||
cxx: cl.exe
|
||||
@@ -44,7 +48,7 @@ jobs:
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -69,13 +73,13 @@ jobs:
|
||||
${{ runner.os }}-DX_SDK
|
||||
|
||||
- name: Download DXSetup
|
||||
if: contains(matrix.name, 'windows') && steps.dxcache.outputs.cache-hit != 'true'
|
||||
if: contains(matrix.name, 'windows-latest-cl.exe') && steps.dxcache.outputs.cache-hit != 'true'
|
||||
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
|
||||
if: contains(matrix.name, 'windows')
|
||||
if: contains(matrix.name, 'windows-latest-cl.exe')
|
||||
id: windows_extra_cmake_args
|
||||
run: echo ":set-output name=args::=-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1" >> $GITHUB_OUTPUT
|
||||
|
||||
@@ -184,7 +188,7 @@ jobs:
|
||||
- id: upload-url
|
||||
run: |
|
||||
echo "url=$(cat create-release/release_upload_url.txt)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'
|
||||
- uses: actions/upload-release-asset@v1
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: lukka/get-cmake@latest
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
name: adress-sanitizer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: lukka/get-cmake@latest
|
||||
- uses: lukka/set-shell-env@v1
|
||||
with:
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
name: undefined-behavior-sanitizer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: lukka/get-cmake@latest
|
||||
- uses: lukka/set-shell-env@v1
|
||||
with:
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
name: printf-sanitizer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: run scan_printf script
|
||||
run: ./scripts/scan_printf.sh
|
||||
|
||||
@@ -67,7 +67,7 @@ The cmake-build-environment provides options to configure the build. The followi
|
||||
- **ASSIMP_NO_EXPORT (default OFF)**: Disable Assimp's export functionality.
|
||||
- **ASSIMP_BUILD_ZLIB (default OFF)**: Build our own zlib.
|
||||
- **ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all exporters enabled.
|
||||
- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all importers enabled.
|
||||
- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with (most) importers enabled. Currently, USD importer is not included. See ASSIMP_BUILD_USD_IMPORTER.
|
||||
- **ASSIMP_BUILD_ASSIMP_TOOLS (default OFF)**: If the supplementary tools for Assimp are built in addition to the library.
|
||||
- **ASSIMP_BUILD_SAMPLES (default OFF)**: If the official samples are built as well (needs Glut).
|
||||
- **ASSIMP_BUILD_TESTS (default ON)**: If the test suite for Assimp is built in addition to the library.
|
||||
@@ -83,6 +83,7 @@ The cmake-build-environment provides options to configure the build. The followi
|
||||
- **USE_STATIC_CRT (default OFF)**: Link against the static MSVC runtime libraries.
|
||||
- **ASSIMP_BUILD_DRACO (default OFF)**: Build Draco libraries. Primarily for glTF.
|
||||
- **ASSIMP_BUILD_ASSIMP_VIEW (default ON, if DirectX found, OFF otherwise)**: Build Assimp view tool (requires DirectX).
|
||||
- **ASSIMP_BUILD_USD_IMPORTER (default OFF, requires ASSIMP_WARNINGS_AS_ERRORS to be OFF)**: Build USD importer, defaults to off for CI purposes
|
||||
|
||||
### Install prebuild binaries
|
||||
## Install on all platforms using vcpkg
|
||||
@@ -109,5 +110,5 @@ You need to have pip installed:
|
||||
pip install pyassimp
|
||||
```
|
||||
|
||||
### Get the SDK from itchi.io
|
||||
Just check [itchi.io](https://kimkulling.itch.io/the-asset-importer-lib)
|
||||
### Get the SDK from itch.io
|
||||
Just check [itch.io](https://kimkulling.itch.io/the-asset-importer-lib)
|
||||
|
||||
+85
-71
@@ -50,20 +50,21 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.22 )
|
||||
# M3D format import support (assimp integration no longer supported by M3D format author)
|
||||
# User may override these in their CMake script to provide M3D import/export support
|
||||
# (M3D importer/exporter was disabled for assimp release 5.1 or later)
|
||||
option(ASSIMP_BUILD_M3D_IMPORTER "Enable M3D file import" off)
|
||||
option(ASSIMP_BUILD_M3D_EXPORTER "Enable M3D file export" off)
|
||||
OPTION(ASSIMP_BUILD_M3D_IMPORTER "Enable M3D file import" off)
|
||||
OPTION(ASSIMP_BUILD_M3D_EXPORTER "Enable M3D file export" off)
|
||||
|
||||
# Experimental USD importer: disabled, need to opt-in
|
||||
# Note: assimp github PR automatic checks will fail the PR due to compiler warnings in
|
||||
# the external, 3rd party tinyusdz code which isn't technically part of the PR since it's
|
||||
# auto-cloned during build; so MUST disable the feature or the PR will be rejected
|
||||
option(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off)
|
||||
option(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off)
|
||||
OPTION(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off)
|
||||
OPTION(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off)
|
||||
|
||||
# VRML (.wrl/.x3dv) file import support by leveraging X3D importer and 3rd party file
|
||||
# format converter to convert .wrl/.x3dv files to X3D-compatible .xml
|
||||
# (Need to make this opt-in because 3rd party code triggers lots of CI code quality warnings)
|
||||
option(ASSIMP_BUILD_VRML_IMPORTER "Enable VRML (.wrl/.x3dv) file import" off)
|
||||
OPTION(ASSIMP_BUILD_VRML_IMPORTER "Enable VRML (.wrl/.x3dv) file import" off)
|
||||
|
||||
#--------------------------------------------------------------------------------#
|
||||
# Internal impl for optional model formats
|
||||
#--------------------------------------------------------------------------------#
|
||||
@@ -83,13 +84,13 @@ endif () # if (not ASSIMP_BUILD_VRML_IMPORTER)
|
||||
|
||||
option(ASSIMP_BUILD_USE_CCACHE "Use ccache to speed up compilation." on)
|
||||
|
||||
if(ASSIMP_BUILD_USE_CCACHE)
|
||||
IF(ASSIMP_BUILD_USE_CCACHE)
|
||||
find_program(CCACHE_PATH ccache)
|
||||
if (CCACHE_PATH)
|
||||
IF (CCACHE_PATH)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH})
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH})
|
||||
endif()
|
||||
endif()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Toggles the use of the hunter package manager
|
||||
option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
|
||||
@@ -100,10 +101,13 @@ IF(ASSIMP_HUNTER_ENABLED)
|
||||
URL "https://github.com/cpp-pm/hunter/archive/v0.25.8.tar.gz"
|
||||
SHA1 "26c79d587883ec910bce168e25f6ac4595f97033"
|
||||
)
|
||||
add_definitions(-DASSIMP_USE_HUNTER)
|
||||
ADD_DEFINITIONS(-DASSIMP_USE_HUNTER)
|
||||
ENDIF()
|
||||
|
||||
PROJECT(Assimp VERSION 5.4.3)
|
||||
PROJECT(Assimp VERSION 6.0.2
|
||||
LANGUAGES C CXX
|
||||
DESCRIPTION "Open Asset Import Library (Assimp) is a library to import various well-known 3D model formats in a uniform manner."
|
||||
)
|
||||
|
||||
# All supported options ###############################################
|
||||
|
||||
@@ -245,7 +249,7 @@ SET (ASSIMP_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||
SET (ASSIMP_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
||||
SET (ASSIMP_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
||||
SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
|
||||
SET (ASSIMP_SOVERSION 5)
|
||||
SET (ASSIMP_SOVERSION 6)
|
||||
|
||||
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
@@ -305,6 +309,17 @@ IF( UNIX )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND WIN32)
|
||||
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
|
||||
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
|
||||
ENDIF()
|
||||
|
||||
IF( MSVC OR "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") # clang with MSVC ABI
|
||||
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
|
||||
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
|
||||
endif ()
|
||||
|
||||
|
||||
# Grouped compiler settings ########################################
|
||||
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU)
|
||||
IF(NOT ASSIMP_HUNTER_ENABLED)
|
||||
@@ -350,14 +365,13 @@ ELSEIF(MSVC)
|
||||
if(NOT /utf-8 IN_LIST CMAKE_CXX_FLAGS)
|
||||
# Source code is encoded in UTF-8
|
||||
ADD_COMPILE_OPTIONS(/source-charset:utf-8)
|
||||
endif ()
|
||||
|
||||
endif()
|
||||
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||
IF(NOT ASSIMP_HUNTER_ENABLED)
|
||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
ENDIF()
|
||||
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
|
||||
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS "-Wno-deprecated-non-prototype -fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
|
||||
SET(CMAKE_C_FLAGS "-Wno-deprecated-non-prototype -fno-strict-aliasing ${CMAKE_C_FLAGS}")
|
||||
ELSEIF( MINGW )
|
||||
IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
|
||||
message(FATAL_ERROR "MinGW is too old to be supported. Please update MinGW and try again.")
|
||||
@@ -480,20 +494,20 @@ ENDIF()
|
||||
set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
|
||||
IF(ASSIMP_HUNTER_ENABLED)
|
||||
set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
|
||||
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in")
|
||||
set(NAMESPACE "${PROJECT_NAME}::")
|
||||
set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
|
||||
set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
|
||||
SET(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
|
||||
SET(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in")
|
||||
SET(NAMESPACE "${PROJECT_NAME}::")
|
||||
SET(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
|
||||
SET(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
SET(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
|
||||
ELSE()
|
||||
set(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
|
||||
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in")
|
||||
SET(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
|
||||
SET(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in")
|
||||
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)
|
||||
set(NAMESPACE "${PROJECT_NAME_LOWERCASE}::")
|
||||
set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets")
|
||||
set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}ConfigVersion.cmake")
|
||||
set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}Config.cmake")
|
||||
SET(NAMESPACE "${PROJECT_NAME_LOWERCASE}::")
|
||||
SET(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets")
|
||||
SET(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}ConfigVersion.cmake")
|
||||
SET(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}Config.cmake")
|
||||
ENDIF()
|
||||
|
||||
set(INCLUDE_INSTALL_DIR "include")
|
||||
@@ -510,20 +524,20 @@ configure_package_config_file(
|
||||
INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
|
||||
)
|
||||
|
||||
if(ASSIMP_INSTALL)
|
||||
install(
|
||||
IF(ASSIMP_INSTALL)
|
||||
INSTALL(
|
||||
FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
|
||||
DESTINATION "${CONFIG_INSTALL_DIR}"
|
||||
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
|
||||
)
|
||||
|
||||
install(
|
||||
INSTALL(
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
NAMESPACE "${NAMESPACE}"
|
||||
DESTINATION "${CONFIG_INSTALL_DIR}"
|
||||
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
|
||||
)
|
||||
endif()
|
||||
ENDIF()
|
||||
|
||||
IF( ASSIMP_BUILD_DOCS )
|
||||
ADD_SUBDIRECTORY(doc)
|
||||
@@ -536,9 +550,9 @@ IF(ASSIMP_HUNTER_ENABLED)
|
||||
find_package(ZLIB CONFIG REQUIRED)
|
||||
|
||||
add_definitions(-DASSIMP_BUILD_NO_OWN_ZLIB)
|
||||
set(ZLIB_FOUND TRUE)
|
||||
set(ZLIB_LIBRARIES ZLIB::zlib)
|
||||
set(ASSIMP_BUILD_MINIZIP TRUE)
|
||||
SET(ZLIB_FOUND TRUE)
|
||||
SET(ZLIB_LIBRARIES ZLIB::zlib)
|
||||
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 AND ASSIMP_INSTALL)
|
||||
@@ -565,8 +579,8 @@ ELSE()
|
||||
# https://github.com/madler/zlib/issues/41#issuecomment-125848075
|
||||
# Also prevents these options from "polluting" the cmake options if assimp is being
|
||||
# included as a submodule.
|
||||
set( ASM686 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
|
||||
set( AMD64 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
|
||||
SET(ASM686 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
|
||||
SET(AMD64 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
|
||||
|
||||
# compile from sources
|
||||
ADD_SUBDIRECTORY(contrib/zlib)
|
||||
@@ -577,7 +591,7 @@ ELSE()
|
||||
SET(ASSIMP_BUILD_MINIZIP 1)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
|
||||
SET(ZLIB_LIBRARIES_LINKED -lz)
|
||||
SET(ZLIB_LIBRARIES_LINKED -l${ZLIB_LIBRARIES})
|
||||
ENDIF()
|
||||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
|
||||
ENDIF()
|
||||
@@ -589,7 +603,7 @@ IF( NOT IOS )
|
||||
ELSE ()
|
||||
IF( NOT BUILD_SHARED_LIBS )
|
||||
IF( NOT ASSIMP_BUILD_MINIZIP )
|
||||
use_pkgconfig(UNZIP minizip)
|
||||
USE_PKGCONFIG(UNZIP minizip)
|
||||
ENDIF()
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
@@ -672,48 +686,48 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||
"${C4D_LIB_BASE_PATH}/release/libcinewarelib.a"
|
||||
"${C4D_LIB_BASE_PATH}/release/libjpeglib.a"
|
||||
)
|
||||
ELSE ()
|
||||
ELSE()
|
||||
MESSAGE( FATAL_ERROR
|
||||
"C4D is currently only available on Windows and macOS with Cineware SDK installed in contrib/Cineware"
|
||||
)
|
||||
ENDIF ()
|
||||
ENDIF()
|
||||
ELSE ()
|
||||
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
|
||||
ENDIF ()
|
||||
|
||||
if(ASSIMP_BUILD_DRACO_STATIC)
|
||||
set(ASSIMP_BUILD_DRACO ON)
|
||||
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")
|
||||
MESSAGE(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled")
|
||||
SET ( ASSIMP_BUILD_DRACO OFF CACHE BOOL "Disabled: Draco requires newer cmake" FORCE )
|
||||
ELSE()
|
||||
OPTION ( ASSIMP_BUILD_DRACO "If the Draco libraries are to be built. Primarily for glTF" OFF )
|
||||
IF ( ASSIMP_BUILD_DRACO )
|
||||
# Primarily for glTF v2
|
||||
# Enable Draco glTF feature set
|
||||
set(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE)
|
||||
SET(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE)
|
||||
# Disable unnecessary or omitted components
|
||||
set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
|
||||
set(DRACO_WASM OFF CACHE BOOL "" FORCE)
|
||||
set(DRACO_MAYA_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(DRACO_UNITY_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(DRACO_TESTS OFF CACHE BOOL "" FORCE)
|
||||
SET(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
|
||||
SET(DRACO_WASM OFF CACHE BOOL "" FORCE)
|
||||
SET(DRACO_MAYA_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
SET(DRACO_UNITY_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
SET(DRACO_TESTS OFF CACHE BOOL "" FORCE)
|
||||
|
||||
IF(ASSIMP_HUNTER_ENABLED)
|
||||
hunter_add_package(draco)
|
||||
find_package(draco CONFIG REQUIRED)
|
||||
set(draco_LIBRARIES draco::draco)
|
||||
SET(draco_LIBRARIES draco::draco)
|
||||
ELSE()
|
||||
# Draco 1.4.1 has many warnings and will not build with /WX or -Werror
|
||||
# See https://github.com/google/draco/issues/672
|
||||
# and https://github.com/google/draco/issues/673
|
||||
IF(MSVC)
|
||||
set(DRACO_CXX_FLAGS "/W0")
|
||||
SET(DRACO_CXX_FLAGS "/W0")
|
||||
ELSE()
|
||||
list(APPEND DRACO_CXX_FLAGS
|
||||
LIST(APPEND DRACO_CXX_FLAGS
|
||||
"-Wno-bool-compare"
|
||||
"-Wno-comment"
|
||||
"-Wno-maybe-uninitialized"
|
||||
@@ -721,30 +735,30 @@ ELSE()
|
||||
"-Wno-unused-local-typedefs"
|
||||
)
|
||||
|
||||
if(NOT ASSIMP_BUILD_DRACO_STATIC)
|
||||
IF(NOT ASSIMP_BUILD_DRACO_STATIC)
|
||||
# Draco 1.4.1 does not explicitly export any symbols under GCC/clang
|
||||
list(APPEND DRACO_CXX_FLAGS
|
||||
LIST(APPEND DRACO_CXX_FLAGS
|
||||
"-fvisibility=default"
|
||||
)
|
||||
endif()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Don't build or install all of Draco by default
|
||||
ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL )
|
||||
|
||||
if(ASSIMP_BUILD_DRACO_STATIC)
|
||||
IF(ASSIMP_BUILD_DRACO_STATIC)
|
||||
set_property(DIRECTORY "contrib/draco" PROPERTY BUILD_SHARED_LIBS OFF)
|
||||
endif()
|
||||
ENDIF()
|
||||
|
||||
if(MSVC OR WIN32)
|
||||
set(draco_LIBRARIES "draco")
|
||||
else()
|
||||
if(ASSIMP_BUILD_DRACO_STATIC)
|
||||
set(draco_LIBRARIES "draco_static")
|
||||
else()
|
||||
set(draco_LIBRARIES "draco_shared")
|
||||
endif()
|
||||
endif()
|
||||
IF(MSVC OR WIN32)
|
||||
SET(draco_LIBRARIES "draco")
|
||||
ELSE()
|
||||
IF(ASSIMP_BUILD_DRACO_STATIC)
|
||||
SET(draco_LIBRARIES "draco_static")
|
||||
ELSE()
|
||||
SET(draco_LIBRARIES "draco_shared")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Don't build the draco command-line tools by default
|
||||
set_target_properties(draco_encoder draco_decoder PROPERTIES
|
||||
@@ -762,10 +776,10 @@ ELSE()
|
||||
TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_encoder)
|
||||
TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_decoder)
|
||||
|
||||
set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
|
||||
SET(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
|
||||
|
||||
# This is probably wrong
|
||||
if (ASSIMP_INSTALL)
|
||||
IF (ASSIMP_INSTALL)
|
||||
INSTALL( TARGETS ${draco_LIBRARIES}
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
|
||||
@@ -775,7 +789,7 @@ ELSE()
|
||||
COMPONENT ${LIBASSIMP_COMPONENT}
|
||||
INCLUDES DESTINATION include
|
||||
)
|
||||
endif()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 20,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "assimp_with_tools",
|
||||
"binaryDir": "${sourceDir}",
|
||||
"cacheVariables": {
|
||||
"ASSIMP_BUILD_ASSIMP_TOOLS" : "ON"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
FROM gcc:latest
|
||||
FROM gcc:1.5.1.0
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y ninja-build cmake
|
||||
RUN apt-get update \
|
||||
apt-get install --no-install-recommends -y ninja-build cmake zlib1g-dev
|
||||
|
||||
WORKDIR /app
|
||||
RUN apt install zlib1g-dev
|
||||
|
||||
COPY . .
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2021, assimp team
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
||||
@@ -20,17 +20,17 @@ Additionally, assimp features various __mesh post-processing tools__: normals an
|
||||

|
||||
|
||||
### Documentation ###
|
||||
Read [our latest documentation](https://assimp-docs.readthedocs.io/en/latest/).
|
||||
Read [our latest documentation](https://the-asset-importer-lib-documentation.readthedocs.io/en/latest/).
|
||||
|
||||
### Pre-built binaries ###
|
||||
Download binaries from [our Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib).
|
||||
Download binaries from [our Itch Projectspace](https://kimkulling.itch.io/the-asset-importer-lib).
|
||||
|
||||
### Test data ###
|
||||
Clone [our model database](https://github.com/assimp/assimp-mdb).
|
||||
Clone [our model database for testing purposes](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)
|
||||
- Find us on [discord](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)
|
||||
@@ -83,7 +83,7 @@ The source code is organized in the following way:
|
||||
code/AssetLib/<FormatName> Implementation for import and export of the format
|
||||
|
||||
### Contributing ###
|
||||
I would greatly appreciate contributing to assimp. The easiest way to get involved is to submit
|
||||
We would greatly appreciate for you to contribute to assimp. The easiest way to get involved is to submit
|
||||
a pull request with your changes against the main repository's `master` branch.
|
||||
|
||||
## Contributors
|
||||
|
||||
+2
-3
@@ -2,12 +2,11 @@
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
The current version of Assimp that's being supported with security updates:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 5.2.4 | :white_check_mark: |
|
||||
| 6.0.2 | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ void Discreet3DSImporter::ConvertMaterial(Material &oldMat, aiMaterial &mat) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Split meshes by their materials and generate output aiMesh'es
|
||||
void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
|
||||
std::vector<aiMesh *> avOutMeshes;
|
||||
MeshArray avOutMeshes;
|
||||
avOutMeshes.reserve(mScene->mMeshes.size() * 2);
|
||||
|
||||
unsigned int iFaceCnt = 0, num = 0;
|
||||
|
||||
@@ -157,7 +157,7 @@ struct Component {
|
||||
|
||||
class Object : public Resource {
|
||||
public:
|
||||
std::vector<aiMesh *> mMeshes;
|
||||
MeshArray mMeshes;
|
||||
std::vector<unsigned int> mMeshIndex;
|
||||
std::vector<Component> mComponents;
|
||||
std::string mName;
|
||||
|
||||
@@ -58,9 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Assimp::D3MF {
|
||||
|
||||
namespace D3MF {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
|
||||
@@ -132,9 +131,11 @@ static bool IsEmbeddedTexture( const std::string &filename ) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
||||
mRootStream(nullptr),
|
||||
mZipArchive() {
|
||||
mZipArchive(nullptr) {
|
||||
mZipArchive = new ZipArchiveIOSystem(pIOHandler, rFile);
|
||||
if (!mZipArchive->isOpen()) {
|
||||
delete mZipArchive;
|
||||
mZipArchive = nullptr;
|
||||
throw DeadlyImportError("Failed to open file ", rFile, ".");
|
||||
}
|
||||
|
||||
@@ -184,7 +185,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
||||
}
|
||||
|
||||
D3MFOpcPackage::~D3MFOpcPackage() {
|
||||
mZipArchive->Close(mRootStream);
|
||||
if (mRootStream && mZipArchive) {
|
||||
mZipArchive->Close(mRootStream);
|
||||
}
|
||||
delete mZipArchive;
|
||||
}
|
||||
|
||||
@@ -250,7 +253,6 @@ void D3MFOpcPackage::LoadEmbeddedTextures(IOStream *fileStream, const std::strin
|
||||
mEmbeddedTextures.emplace_back(texture);
|
||||
}
|
||||
|
||||
} // Namespace D3MF
|
||||
} // Namespace Assimp
|
||||
} // Namespace Assimp::D3MF
|
||||
|
||||
#endif //ASSIMP_BUILD_NO_3MF_IMPORTER
|
||||
|
||||
@@ -495,13 +495,16 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||
}
|
||||
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
|
||||
for (unsigned int vertex_index = 0; vertex_index < mesh->mNumVertices; vertex_index++) {
|
||||
mesh->mTextureCoords[0][vertex_index].z = IdNotSet;//mark not set
|
||||
mesh->mTextureCoords[0][vertex_index].z = IdNotSet; //mark not set
|
||||
}
|
||||
}
|
||||
|
||||
auto update_texture = [&](int idx) {
|
||||
if (pindex[idx] != IdNotSet) {
|
||||
size_t vertex_index = face.mIndices[idx];
|
||||
if (vertex_index >= mesh->mNumVertices) {
|
||||
return;
|
||||
}
|
||||
mesh->mTextureCoords[0][vertex_index] =
|
||||
aiVector3D(group->mTex2dCoords[pindex[idx]].x, group->mTex2dCoords[pindex[idx]].y, 0.0f);
|
||||
}
|
||||
@@ -521,6 +524,9 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||
auto update_color = [&](int idx) {
|
||||
if (pindex[idx] != IdNotSet) {
|
||||
size_t vertex_index = face.mIndices[idx];
|
||||
if (vertex_index >= mesh->mNumVertices) {
|
||||
return;
|
||||
}
|
||||
mesh->mColors[0][vertex_index] = group->mColors[pindex[idx]];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,6 +75,8 @@ static constexpr aiImporterDesc desc = {
|
||||
"ac acc ac3d"
|
||||
};
|
||||
|
||||
static constexpr auto ACDoubleSidedFlag = 0x20;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// skip to the next token
|
||||
inline const char *AcSkipToNextToken(const char *buffer, const char *end) {
|
||||
@@ -123,12 +125,36 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *end,
|
||||
}
|
||||
for (unsigned int _i = 0; _i < num; ++_i) {
|
||||
buffer = AcSkipToNextToken(buffer, end);
|
||||
buffer = fast_atoreal_move<float>(buffer, ((float *)out)[_i]);
|
||||
buffer = fast_atoreal_move(buffer, ((float *)out)[_i]);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Reverses vertex indices in a face.
|
||||
static void flipWindingOrder(aiFace &f) {
|
||||
std::reverse(f.mIndices, f.mIndices + f.mNumIndices);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Duplicates a face and inverts it. Also duplicates all vertices (so the new face gets its own
|
||||
// set of normals and isn’t smoothed against the original).
|
||||
static void buildBacksideOfFace(const aiFace &origFace, aiFace *&outFaces, aiVector3D *&outVertices, const aiVector3D *allVertices,
|
||||
aiVector3D *&outUV, const aiVector3D *allUV, unsigned &curIdx) {
|
||||
auto &newFace = *outFaces++;
|
||||
newFace = origFace;
|
||||
flipWindingOrder(newFace);
|
||||
for (unsigned f = 0; f < newFace.mNumIndices; ++f) {
|
||||
*outVertices++ = allVertices[newFace.mIndices[f]];
|
||||
if (outUV) {
|
||||
*outUV = allUV[newFace.mIndices[f]];
|
||||
outUV++;
|
||||
}
|
||||
newFace.mIndices[f] = curIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
AC3DImporter::AC3DImporter() :
|
||||
@@ -392,7 +418,7 @@ void AC3DImporter::ConvertMaterial(const Object &object,
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts the loaded data to the internal verbose representation
|
||||
aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
std::vector<aiMesh *> &meshes,
|
||||
MeshArray &meshes,
|
||||
std::vector<aiMaterial *> &outMaterials,
|
||||
const std::vector<Material> &materials,
|
||||
aiNode *parent) {
|
||||
@@ -451,6 +477,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
if ((*it).entries.empty()) {
|
||||
ASSIMP_LOG_WARN("AC3D: surface has zero vertex references");
|
||||
}
|
||||
const bool isDoubleSided = ACDoubleSidedFlag == (it->flags & ACDoubleSidedFlag);
|
||||
const int doubleSidedFactor = isDoubleSided ? 2 : 1;
|
||||
|
||||
// validate all vertex indices to make sure we won't crash here
|
||||
for (it2 = (*it).entries.begin(),
|
||||
@@ -480,8 +508,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
|
||||
// triangle strip
|
||||
case Surface::TriangleStrip:
|
||||
needMat[idx].first += (unsigned int)(*it).entries.size() - 2;
|
||||
needMat[idx].second += ((unsigned int)(*it).entries.size() - 2) * 3;
|
||||
needMat[idx].first += static_cast<unsigned int>(it->entries.size() - 2) * doubleSidedFactor;
|
||||
needMat[idx].second += static_cast<unsigned int>(it->entries.size() - 2) * 3 * doubleSidedFactor;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -494,8 +522,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
case Surface::Polygon:
|
||||
// the number of faces increments by one, the number
|
||||
// of vertices by surface.numref.
|
||||
needMat[idx].first++;
|
||||
needMat[idx].second += (unsigned int)(*it).entries.size();
|
||||
needMat[idx].first += doubleSidedFactor;
|
||||
needMat[idx].second += static_cast<unsigned int>(it->entries.size()) * doubleSidedFactor;
|
||||
};
|
||||
}
|
||||
unsigned int *pip = node->mMeshes = new unsigned int[node->mNumMeshes];
|
||||
@@ -545,6 +573,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
for (it = object.surfaces.begin(); it != end; ++it) {
|
||||
if (mat == (*it).mat) {
|
||||
const Surface &src = *it;
|
||||
const bool isDoubleSided = ACDoubleSidedFlag == (src.flags & ACDoubleSidedFlag);
|
||||
|
||||
// closed polygon
|
||||
uint8_t type = (*it).GetType();
|
||||
@@ -570,6 +599,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
++uv;
|
||||
}
|
||||
}
|
||||
if(isDoubleSided) // Need a backface?
|
||||
buildBacksideOfFace(faces[-1], faces, vertices, mesh->mVertices, uv, mesh->mTextureCoords[0], cur);
|
||||
}
|
||||
} else if (type == Surface::TriangleStrip) {
|
||||
for (unsigned int i = 0; i < (unsigned int)src.entries.size() - 2; ++i) {
|
||||
@@ -619,6 +650,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
uv->y = entry3.second.y;
|
||||
++uv;
|
||||
}
|
||||
if(isDoubleSided) // Need a backface?
|
||||
buildBacksideOfFace(faces[-1], faces, vertices, mesh->mVertices, uv, mesh->mTextureCoords[0], cur);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -677,7 +710,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
|
||||
ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: ", object.name);
|
||||
|
||||
std::vector<aiMesh *> cpy(meshes.size() - oldm, nullptr);
|
||||
MeshArray cpy(meshes.size() - oldm, nullptr);
|
||||
div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true);
|
||||
std::copy(cpy.begin(), cpy.end(), meshes.begin() + oldm);
|
||||
|
||||
@@ -813,7 +846,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
|
||||
}
|
||||
|
||||
mNumMeshes += (mNumMeshes >> 2u) + 1;
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
meshes.reserve(mNumMeshes);
|
||||
|
||||
std::vector<aiMaterial *> omaterials;
|
||||
|
||||
@@ -226,7 +226,7 @@ private:
|
||||
* @param materials Material list
|
||||
* @param Scenegraph node for the object */
|
||||
aiNode *ConvertObjectSection(Object &object,
|
||||
std::vector<aiMesh *> &meshes,
|
||||
MeshArray &meshes,
|
||||
std::vector<aiMaterial *> &outMaterials,
|
||||
const std::vector<Material> &materials,
|
||||
aiNode *parent = nullptr);
|
||||
|
||||
@@ -99,8 +99,6 @@ namespace Assimp {
|
||||
///
|
||||
class AMFImporter : public BaseImporter {
|
||||
using AMFMetaDataArray = std::vector<AMFMetadata *>;
|
||||
using MeshArray = std::vector<aiMesh *>;
|
||||
using NodeArray = std::vector<aiNode *>;
|
||||
|
||||
public:
|
||||
struct SPP_Material;
|
||||
|
||||
@@ -162,7 +162,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
|
||||
|
||||
// process all meshes
|
||||
bool tookNormals = false;
|
||||
std::vector<aiMesh *> avOutMeshes;
|
||||
MeshArray avOutMeshes;
|
||||
avOutMeshes.reserve(mParser->m_vMeshes.size() * 2);
|
||||
for (std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin(); i != mParser->m_vMeshes.end(); ++i) {
|
||||
if ((*i).bSkip) {
|
||||
@@ -187,7 +187,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
|
||||
// Now build the output mesh list. Remove dummies
|
||||
pScene->mNumMeshes = (unsigned int)avOutMeshes.size();
|
||||
aiMesh **pp = pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
||||
for (std::vector<aiMesh *>::const_iterator i = avOutMeshes.begin(); i != avOutMeshes.end(); ++i) {
|
||||
for (MeshArray::const_iterator i = avOutMeshes.begin(); i != avOutMeshes.end(); ++i) {
|
||||
if (!(*i)->mNumFaces) {
|
||||
continue;
|
||||
}
|
||||
@@ -902,7 +902,7 @@ void ASEImporter::ConvertMaterial(ASE::Material &mat) {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build output meshes
|
||||
void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, std::vector<aiMesh *> &avOutMeshes) {
|
||||
void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, MeshArray &avOutMeshes) {
|
||||
// validate the material index of the mesh
|
||||
if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) {
|
||||
mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size() - 1;
|
||||
|
||||
@@ -1427,7 +1427,7 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes
|
||||
|
||||
// then parse the vertex weight
|
||||
if (!SkipSpaces(&mFilePtr, mEnd)) break;
|
||||
mFilePtr = fast_atoreal_move<float>(mFilePtr, pairOut.second);
|
||||
mFilePtr = fast_atoreal_move(mFilePtr, pairOut.second);
|
||||
|
||||
// -1 marks unused entries
|
||||
if (-1 != pairOut.first) {
|
||||
@@ -1893,7 +1893,7 @@ void Parser::ParseLV4MeshReal(ai_real &fOut) {
|
||||
return;
|
||||
}
|
||||
// parse the first float
|
||||
mFilePtr = fast_atoreal_move<ai_real>(mFilePtr, fOut);
|
||||
mFilePtr = fast_atoreal_move(mFilePtr, fOut);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Parser::ParseLV4MeshFloat(float &fOut) {
|
||||
@@ -1906,7 +1906,7 @@ void Parser::ParseLV4MeshFloat(float &fOut) {
|
||||
return;
|
||||
}
|
||||
// parse the first float
|
||||
mFilePtr = fast_atoreal_move<float>(mFilePtr, fOut);
|
||||
mFilePtr = fast_atoreal_move(mFilePtr, fOut);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Parser::ParseLV4MeshLong(unsigned int &iOut) {
|
||||
|
||||
@@ -385,7 +385,7 @@ float BVHLoader::GetNextTokenAsFloat() {
|
||||
// check if the float is valid by testing if the atof() function consumed every char of the token
|
||||
const char *ctoken = token.c_str();
|
||||
float result = 0.0f;
|
||||
ctoken = fast_atoreal_move<float>(ctoken, result);
|
||||
ctoken = fast_atoreal_move(ctoken, result);
|
||||
|
||||
if (ctoken != token.c_str() + token.length())
|
||||
ThrowException("Expected a floating point number, but found \"", token, "\".");
|
||||
|
||||
@@ -961,7 +961,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
|
||||
if (mesh->totface > static_cast<int>(mesh->mtface.size())) {
|
||||
ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)");
|
||||
}
|
||||
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
for (MeshArray::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
ai_assert(0 != (*it)->mNumVertices);
|
||||
ai_assert(0 != (*it)->mNumFaces);
|
||||
const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
|
||||
@@ -1030,7 +1030,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
|
||||
if (mesh->totface > static_cast<int>(mesh->tface.size())) {
|
||||
ThrowException("Number of faces is larger than the corresponding UV face array (#2)");
|
||||
}
|
||||
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
for (MeshArray::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
ai_assert(0 != (*it)->mNumVertices);
|
||||
ai_assert(0 != (*it)->mNumFaces);
|
||||
|
||||
@@ -1057,7 +1057,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
|
||||
if (mesh->totface > static_cast<int>((mesh->mcol.size() / 4))) {
|
||||
ThrowException("Number of faces is larger than the corresponding color face array");
|
||||
}
|
||||
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
for (MeshArray::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
ai_assert(0 != (*it)->mNumVertices);
|
||||
ai_assert(0 != (*it)->mNumFaces);
|
||||
|
||||
|
||||
@@ -166,10 +166,10 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
||||
// copy meshes over
|
||||
pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
|
||||
std::copy(meshes.begin(), meshes.end(), pScene->mMeshes);
|
||||
std::copy(mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
|
||||
|
||||
// copy materials over, adding a default material if necessary
|
||||
unsigned int mat_count = static_cast<unsigned int>(materials.size());
|
||||
unsigned int mat_count = static_cast<unsigned int>(mMaterials.size());
|
||||
for(aiMesh* mesh : meshes) {
|
||||
ai_assert(mesh->mMaterialIndex <= mat_count);
|
||||
if(mesh->mMaterialIndex >= mat_count) {
|
||||
@@ -179,14 +179,14 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
||||
const aiString name(AI_DEFAULT_MATERIAL_NAME);
|
||||
def_material->AddProperty(&name, AI_MATKEY_NAME);
|
||||
|
||||
materials.push_back(def_material.release());
|
||||
mMaterials.push_back(def_material.release());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pScene->mNumMaterials = static_cast<unsigned int>(materials.size());
|
||||
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
|
||||
std::copy(materials.begin(), materials.end(), pScene->mMaterials);
|
||||
std::copy(mMaterials.begin(), mMaterials.end(), pScene->mMaterials);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -251,8 +251,8 @@ void C4DImporter::ReadMaterials(BaseMaterial* mat) {
|
||||
while (mat) {
|
||||
if (mat->GetType() == Mmaterial) {
|
||||
aiMaterial* out = new aiMaterial();
|
||||
material_mapping[mat] = static_cast<unsigned int>(materials.size());
|
||||
materials.push_back(out);
|
||||
mMaterialMapping[mat] = static_cast<unsigned int>(mMaterials.size());
|
||||
mMaterials.push_back(out);
|
||||
|
||||
auto const ai_name = aiStringFrom(mat->GetName());
|
||||
out->AddProperty(&ai_name, AI_MATKEY_NAME);
|
||||
@@ -289,7 +289,7 @@ void C4DImporter::ReadMaterials(BaseMaterial* mat) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
|
||||
ai_assert(parent != nullptr );
|
||||
std::vector<aiNode*> nodes;
|
||||
NodeArray nodes;
|
||||
|
||||
// based on Cineware sample code
|
||||
while (object) {
|
||||
@@ -577,7 +577,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
|
||||
unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) {
|
||||
ai_assert(obj != nullptr);
|
||||
|
||||
const unsigned int mat_count = static_cast<unsigned int>(materials.size());
|
||||
const unsigned int mat_count = static_cast<unsigned int>(mMaterials.size());
|
||||
|
||||
BaseTag* tag = obj->GetTag(Ttexture);
|
||||
if(tag == nullptr) {
|
||||
|
||||
@@ -97,11 +97,12 @@ private:
|
||||
|
||||
bool ReadShader(aiMaterial* out, cineware::BaseShader* shader);
|
||||
|
||||
std::vector<aiMesh*> meshes;
|
||||
std::vector<aiMaterial*> materials;
|
||||
private:
|
||||
MeshArray mMeshes;
|
||||
MaterialArray materials;
|
||||
|
||||
typedef std::map<cineware::BaseMaterial*, unsigned int> MaterialMap;
|
||||
MaterialMap material_mapping;
|
||||
using MaterialMap = std::map<cineware::BaseMaterial*, unsigned int> ;
|
||||
MaterialMap mMaterialMapping;
|
||||
|
||||
}; // !class C4DImporter
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
|
||||
else if (TokenMatchI(buffer,"rate",4)) {
|
||||
SkipSpaces(&buffer, end);
|
||||
float d = { 0.0f };
|
||||
buffer = fast_atoreal_move<float>(buffer,d);
|
||||
buffer = fast_atoreal_move(buffer,d);
|
||||
anim->mTicksPerSecond = d;
|
||||
}
|
||||
else if (TokenMatchI(buffer,"order",5)) {
|
||||
@@ -176,9 +176,17 @@ void CSMImporter::InternReadFile( const std::string& pFile,
|
||||
// If we know how many frames we'll read, we can preallocate some storage
|
||||
unsigned int alloc = 100;
|
||||
if (last != 0x00ffffff) {
|
||||
// re-init if the file has last frame data
|
||||
alloc = last-first;
|
||||
alloc += alloc>>2u; // + 25%
|
||||
for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
|
||||
if (anim->mChannels[i]->mPositionKeys != nullptr) delete[] anim->mChannels[i]->mPositionKeys;
|
||||
anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
|
||||
}
|
||||
} else {
|
||||
// default init
|
||||
for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
|
||||
if (anim->mChannels[i]->mPositionKeys != nullptr) continue;
|
||||
anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
|
||||
}
|
||||
}
|
||||
@@ -202,7 +210,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
|
||||
if (s->mNumPositionKeys == alloc) {
|
||||
// need to reallocate?
|
||||
aiVectorKey* old = s->mPositionKeys;
|
||||
s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
|
||||
s->mPositionKeys = new aiVectorKey[alloc*2];
|
||||
::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
|
||||
delete[] old;
|
||||
}
|
||||
@@ -218,17 +226,17 @@ void CSMImporter::InternReadFile( const std::string& pFile,
|
||||
} else {
|
||||
aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
|
||||
sub->mTime = (double)frame;
|
||||
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
|
||||
buffer = fast_atoreal_move(buffer, sub->mValue.x);
|
||||
|
||||
if (!SkipSpacesAndLineEnd(&buffer, end)) {
|
||||
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample y coord");
|
||||
}
|
||||
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
|
||||
buffer = fast_atoreal_move(buffer, sub->mValue.y);
|
||||
|
||||
if (!SkipSpacesAndLineEnd(&buffer, end)) {
|
||||
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample z coord");
|
||||
}
|
||||
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
|
||||
buffer = fast_atoreal_move(buffer, sub->mValue.z);
|
||||
|
||||
++s->mNumPositionKeys;
|
||||
}
|
||||
@@ -271,7 +279,13 @@ void CSMImporter::InternReadFile( const std::string& pFile,
|
||||
nd->mName = anim->mChannels[i]->mNodeName;
|
||||
nd->mParent = pScene->mRootNode;
|
||||
|
||||
aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
|
||||
if (na->mPositionKeys != nullptr && na->mNumPositionKeys > 0) {
|
||||
aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
|
||||
} else {
|
||||
// Use identity matrix if no valid position data is available
|
||||
nd->mTransformation = aiMatrix4x4();
|
||||
DefaultLogger::get()->warn("CSM: No position keys available for node - using identity transformation");
|
||||
}
|
||||
}
|
||||
|
||||
// Store the one and only animation in the scene
|
||||
|
||||
@@ -668,7 +668,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
|
||||
}
|
||||
|
||||
// create morph target meshes if any
|
||||
std::vector<aiMesh *> targetMeshes;
|
||||
MeshArray targetMeshes;
|
||||
std::vector<float> targetWeights;
|
||||
Collada::MorphMethod method = Normalized;
|
||||
|
||||
|
||||
@@ -206,10 +206,10 @@ private:
|
||||
std::map<std::string, size_t> mMaterialIndexByName;
|
||||
|
||||
/** Accumulated meshes for the target scene */
|
||||
std::vector<aiMesh *> mMeshes;
|
||||
MeshArray mMeshes;
|
||||
|
||||
/** Accumulated morph target meshes */
|
||||
std::vector<aiMesh *> mTargetMeshes;
|
||||
MeshArray mTargetMeshes;
|
||||
|
||||
/** Temporary material list */
|
||||
std::vector<std::pair<Collada::Effect *, aiMaterial *>> newMats;
|
||||
|
||||
@@ -129,7 +129,7 @@ static void ReadNodeTransformation(XmlNode &node, Node *pNode, TransformType pTy
|
||||
// skip whitespace before the number
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
// read a number
|
||||
content = fast_atoreal_move<ai_real>(content, tf.f[a]);
|
||||
content = fast_atoreal_move(content, tf.f[a]);
|
||||
}
|
||||
|
||||
// place the transformation at the queue of the node
|
||||
@@ -346,13 +346,13 @@ static void ReadLight(XmlNode &node, Light &pLight) {
|
||||
const char *content = v.c_str();
|
||||
const char *end = content + v.size();
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.r);
|
||||
content = fast_atoreal_move(content, pLight.mColor.r);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.g);
|
||||
content = fast_atoreal_move(content, pLight.mColor.g);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b);
|
||||
content = fast_atoreal_move(content, pLight.mColor.b);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
} else if (currentName == "constant_attenuation") {
|
||||
XmlParser::getValueAsReal(currentNode, pLight.mAttConstant);
|
||||
@@ -631,7 +631,7 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
|
||||
std::string tUnitSizeString;
|
||||
if (XmlParser::getStdStrAttribute(currentNode, "meter", tUnitSizeString)) {
|
||||
try {
|
||||
fast_atoreal_move<ai_real>(tUnitSizeString.data(), mUnitSize);
|
||||
fast_atoreal_move(tUnitSizeString.data(), mUnitSize);
|
||||
} catch (const DeadlyImportError& die) {
|
||||
std::string warning("Collada: Failed to parse meter parameter to real number. Exception:\n");
|
||||
warning.append(die.what());
|
||||
@@ -886,10 +886,10 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
|
||||
XmlParser::getValueAsString(currentNode, v);
|
||||
const char *content = v.c_str();
|
||||
const char *end = content + v.size();
|
||||
for (float & a : controller.mBindShapeMatrix) {
|
||||
for (auto & a : controller.mBindShapeMatrix) {
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
// read a number
|
||||
content = fast_atoreal_move<ai_real>(content, a);
|
||||
content = fast_atoreal_move(content, a);
|
||||
// skip whitespace after it
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
}
|
||||
@@ -1262,16 +1262,16 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
|
||||
const char *content = v.c_str();
|
||||
const char *end = v.c_str() + v.size() + 1;
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.r);
|
||||
content = fast_atoreal_move(content, pColor.r);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.g);
|
||||
content = fast_atoreal_move(content, pColor.g);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.b);
|
||||
content = fast_atoreal_move(content, pColor.b);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.a);
|
||||
content = fast_atoreal_move(content, pColor.a);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
} else if (currentName == "texture") {
|
||||
// get name of source texture/sampler
|
||||
@@ -1494,7 +1494,7 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
|
||||
|
||||
// read a number
|
||||
ai_real value;
|
||||
content = fast_atoreal_move<ai_real>(content, value);
|
||||
content = fast_atoreal_move(content, value);
|
||||
data.mValues.push_back(value);
|
||||
// skip whitespace after it
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
@@ -91,7 +91,9 @@ AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
size_t Offset(const char* begin, const char* cursor) {
|
||||
ai_assert(begin <= cursor);
|
||||
if (begin > cursor) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cursor - begin;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace FBX {
|
||||
|
||||
using namespace Util;
|
||||
|
||||
#define MAGIC_NODE_TAG "_$AssimpFbx$"
|
||||
static constexpr char MAGIC_NODE_TAG[] = "_$AssimpFbx$";
|
||||
|
||||
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL
|
||||
|
||||
@@ -125,21 +125,10 @@ static void correctRootTransform(const aiScene *scene) {
|
||||
|
||||
FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) :
|
||||
defaultMaterialIndex(),
|
||||
mMeshes(),
|
||||
lights(),
|
||||
cameras(),
|
||||
textures(),
|
||||
materials_converted(),
|
||||
textures_converted(),
|
||||
meshes_converted(),
|
||||
node_anim_chain_bits(),
|
||||
mNodeNames(),
|
||||
anim_fps(),
|
||||
mSceneOut(out),
|
||||
doc(doc),
|
||||
mRemoveEmptyBones(removeEmptyBones) {
|
||||
|
||||
|
||||
// animations need to be converted first since this will
|
||||
// populate the node_anim_chain_bits map, which is needed
|
||||
// to determine which nodes need to be generated.
|
||||
@@ -162,7 +151,7 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
|
||||
continue;
|
||||
}
|
||||
|
||||
const Material *mat = dynamic_cast<const Material *>(ob);
|
||||
auto mat = dynamic_cast<const Material *>(ob);
|
||||
if (mat) {
|
||||
|
||||
if (materials_converted.find(mat) == materials_converted.end()) {
|
||||
@@ -222,7 +211,6 @@ static std::string getAncestorBaseName(const aiNode *node) {
|
||||
return std::string(nodeName, length);
|
||||
}
|
||||
|
||||
// Make unique name
|
||||
std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiNode &parent) {
|
||||
std::string original_name = FixNodeName(model->Name());
|
||||
if (original_name.empty()) {
|
||||
@@ -236,9 +224,18 @@ std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiN
|
||||
/// This struct manages nodes which may or may not end up in the node hierarchy.
|
||||
/// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
|
||||
struct FBXConverter::PotentialNode {
|
||||
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
|
||||
PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
|
||||
aiNode* operator->() { return mNode; }
|
||||
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {
|
||||
// empty
|
||||
}
|
||||
|
||||
explicit PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {
|
||||
// empty
|
||||
}
|
||||
|
||||
aiNode* operator->() {
|
||||
return mNode;
|
||||
}
|
||||
|
||||
std::unique_ptr<aiNode> mOwnership;
|
||||
aiNode* mNode;
|
||||
};
|
||||
@@ -1092,14 +1089,14 @@ aiMesh *FBXConverter::SetupEmptyMesh(const Geometry &mesh, aiNode *parent) {
|
||||
}
|
||||
|
||||
static aiSkeleton *createAiSkeleton(SkeletonBoneContainer &sbc) {
|
||||
if (sbc.MeshArray.empty() || sbc.SkeletonBoneToMeshLookup.empty()) {
|
||||
if (sbc.meshArray.empty() || sbc.skeletonBoneToMeshLookup.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
aiSkeleton *skeleton = new aiSkeleton;
|
||||
for (auto *mesh : sbc.MeshArray) {
|
||||
auto it = sbc.SkeletonBoneToMeshLookup.find(mesh);
|
||||
if (it == sbc.SkeletonBoneToMeshLookup.end()) {
|
||||
for (auto *mesh : sbc.meshArray) {
|
||||
auto it = sbc.skeletonBoneToMeshLookup.find(mesh);
|
||||
if (it == sbc.skeletonBoneToMeshLookup.end()) {
|
||||
continue;
|
||||
}
|
||||
SkeletonBoneArray *ba = it->second;
|
||||
@@ -1547,12 +1544,12 @@ static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *s
|
||||
void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent, unsigned int materialIndex,
|
||||
std::vector<unsigned int> *outputVertStartIndices, SkeletonBoneContainer &skeletonContainer) {
|
||||
|
||||
if (skeletonContainer.SkeletonBoneToMeshLookup.find(out) != skeletonContainer.SkeletonBoneToMeshLookup.end()) {
|
||||
if (skeletonContainer.skeletonBoneToMeshLookup.find(out) != skeletonContainer.skeletonBoneToMeshLookup.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConvertWeights(out, geo, absolute_transform, parent, materialIndex, outputVertStartIndices);
|
||||
skeletonContainer.MeshArray.emplace_back(out);
|
||||
skeletonContainer.meshArray.emplace_back(out);
|
||||
SkeletonBoneArray *ba = new SkeletonBoneArray;
|
||||
for (size_t i = 0; i < out->mNumBones; ++i) {
|
||||
aiBone *bone = out->mBones[i];
|
||||
@@ -1563,7 +1560,7 @@ void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo
|
||||
copyBoneToSkeletonBone(out, bone, skeletonBone);
|
||||
ba->emplace_back(skeletonBone);
|
||||
}
|
||||
skeletonContainer.SkeletonBoneToMeshLookup[out] = ba;
|
||||
skeletonContainer.skeletonBoneToMeshLookup[out] = ba;
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
|
||||
@@ -1571,8 +1568,6 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
|
||||
std::vector<unsigned int> *outputVertStartIndices) {
|
||||
ai_assert(geo.DeformerSkin());
|
||||
|
||||
std::vector<size_t> out_indices, index_out_indices, count_out_indices;
|
||||
|
||||
const Skin &sk = *geo.DeformerSkin();
|
||||
|
||||
std::vector<aiBone*> bones;
|
||||
@@ -1580,6 +1575,10 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
|
||||
ai_assert(no_mat_check || outputVertStartIndices);
|
||||
|
||||
try {
|
||||
std::vector<size_t> count_out_indices;
|
||||
std::vector<size_t> index_out_indices;
|
||||
std::vector<size_t> out_indices;
|
||||
|
||||
// iterate over the sub deformers
|
||||
for (const Cluster *cluster : sk.Clusters()) {
|
||||
ai_assert(cluster);
|
||||
@@ -1751,10 +1750,10 @@ unsigned int FBXConverter::GetDefaultMaterial() {
|
||||
return defaultMaterialIndex - 1;
|
||||
}
|
||||
|
||||
aiMaterial *out_mat = new aiMaterial();
|
||||
auto out_mat = new aiMaterial();
|
||||
materials.push_back(out_mat);
|
||||
|
||||
const aiColor3D diffuse = aiColor3D(0.8f, 0.8f, 0.8f);
|
||||
const auto diffuse = aiColor3D(0.8f, 0.8f, 0.8f);
|
||||
out_mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
|
||||
aiString s;
|
||||
@@ -1770,7 +1769,7 @@ unsigned int FBXConverter::ConvertMaterial(const Material &material, const MeshG
|
||||
const PropertyTable &props = material.Props();
|
||||
|
||||
// generate empty output material
|
||||
aiMaterial *out_mat = new aiMaterial();
|
||||
auto out_mat = new aiMaterial();
|
||||
materials_converted[&material] = static_cast<unsigned int>(materials.size());
|
||||
|
||||
materials.push_back(out_mat);
|
||||
@@ -1809,7 +1808,7 @@ unsigned int FBXConverter::ConvertMaterial(const Material &material, const MeshG
|
||||
|
||||
unsigned int FBXConverter::ConvertVideo(const Video &video) {
|
||||
// generate empty output texture
|
||||
aiTexture *out_tex = new aiTexture();
|
||||
auto out_tex = new aiTexture();
|
||||
textures.push_back(out_tex);
|
||||
|
||||
// assuming the texture is compressed
|
||||
|
||||
@@ -80,8 +80,8 @@ using SkeletonBoneArray = std::vector<aiSkeletonBone *>;
|
||||
using SkeletonBoneToMesh = std::map<aiMesh*, SkeletonBoneArray*>;
|
||||
|
||||
struct SkeletonBoneContainer {
|
||||
std::vector<aiMesh *> MeshArray;
|
||||
SkeletonBoneToMesh SkeletonBoneToMeshLookup;
|
||||
MeshArray meshArray;
|
||||
SkeletonBoneToMesh skeletonBoneToMeshLookup;
|
||||
};
|
||||
|
||||
class Document;
|
||||
|
||||
@@ -1043,6 +1043,10 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) {
|
||||
}
|
||||
|
||||
inline int64_t to_ktime(double ticks, const aiAnimation* anim) {
|
||||
if (FP_ZERO == std::fpclassify(anim->mTicksPerSecond)) {
|
||||
return static_cast<int64_t>(ticks * FBX::SECOND);
|
||||
}
|
||||
|
||||
// Defensive: handle zero or near-zero mTicksPerSecond
|
||||
double tps = anim->mTicksPerSecond;
|
||||
double timeVal;
|
||||
@@ -1062,7 +1066,7 @@ inline int64_t to_ktime(double ticks, const aiAnimation* anim) {
|
||||
if (timeVal < kMin) {
|
||||
return INT64_MIN;
|
||||
}
|
||||
return static_cast<int64_t>(timeVal * FBX::SECOND);
|
||||
return static_cast<int64_t>((ticks / anim->mTicksPerSecond) * FBX::SECOND);
|
||||
}
|
||||
|
||||
inline int64_t to_ktime(double time) {
|
||||
@@ -1094,6 +1098,7 @@ void FBXExporter::WriteObjects () {
|
||||
bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true);
|
||||
// save vertex_indices as it is needed later
|
||||
std::vector<std::vector<int32_t>> vVertexIndice(mScene->mNumMeshes);
|
||||
std::vector<uint32_t> uniq_v_before_mi;
|
||||
|
||||
const auto bTransparencyFactorReferencedToOpacity = mProperties->GetPropertyBool(AI_CONFIG_EXPORT_FBX_TRANSPARENCY_FACTOR_REFER_TO_OPACITY, false);
|
||||
|
||||
@@ -1140,6 +1145,7 @@ void FBXExporter::WriteObjects () {
|
||||
const aiMesh *m = mScene->mMeshes[mi];
|
||||
|
||||
size_t v_offset = vertex_indices.size();
|
||||
size_t uniq_v_before = flattened_vertices.size() / 3;
|
||||
|
||||
// map of vertex value to its index in the data vector
|
||||
std::map<aiVector3D,size_t> index_by_vertex_value;
|
||||
@@ -1182,11 +1188,17 @@ void FBXExporter::WriteObjects () {
|
||||
if (f.mNumIndices == 0) continue;
|
||||
size_t pvi = 0;
|
||||
for (; pvi < f.mNumIndices - 1; pvi++) {
|
||||
polygon_data.push_back(vertex_indices[v_offset + f.mIndices[pvi]]);
|
||||
polygon_data.push_back(
|
||||
static_cast<int32_t>(uniq_v_before + vertex_indices[v_offset + f.mIndices[pvi]])
|
||||
);
|
||||
}
|
||||
polygon_data.push_back(-1 - vertex_indices[v_offset+f.mIndices[pvi]]);
|
||||
polygon_data.push_back(
|
||||
static_cast<int32_t>(-1 ^ (uniq_v_before + vertex_indices[v_offset+f.mIndices[pvi]]))
|
||||
);
|
||||
}
|
||||
|
||||
uniq_v_before_mi.push_back(static_cast<uint32_t>(uniq_v_before));
|
||||
|
||||
if (m->HasNormals()) {
|
||||
normal_data.reserve(3 * polygon_data.size());
|
||||
for (size_t fi = 0; fi < m->mNumFaces; fi++) {
|
||||
@@ -1329,14 +1341,13 @@ void FBXExporter::WriteObjects () {
|
||||
} else {
|
||||
mat.AddChild("MappingInformationType", "ByPolygon");
|
||||
mat.AddChild("ReferenceInformationType", "IndexToDirect");
|
||||
std::vector<int32_t> mat_indices(polygon_data.size());
|
||||
uint32_t curr_offset = 0;
|
||||
for (uint32_t mi = 0; mi < node->mNumMeshes; mi++) {
|
||||
uint32_t num_faces = mScene->mMeshes[node->mMeshes[mi]]->mNumFaces;
|
||||
for (uint32_t fi = 0; fi < num_faces; fi++) {
|
||||
mat_indices[curr_offset + fi] = mi;
|
||||
std::vector<int32_t> mat_indices;
|
||||
for (uint32_t n_mi = 0; n_mi < node->mNumMeshes; n_mi++) {
|
||||
const auto mi = node->mMeshes[n_mi];
|
||||
const auto *const m = mScene->mMeshes[mi];
|
||||
for (size_t fi = 0; fi < m->mNumFaces; fi++) {
|
||||
mat_indices.push_back(n_mi);
|
||||
}
|
||||
curr_offset += num_faces;
|
||||
}
|
||||
mat.AddChild("Materials", mat_indices);
|
||||
}
|
||||
@@ -2059,7 +2070,8 @@ void FBXExporter::WriteObjects () {
|
||||
ASSIMP_LOG_ERROR("UNREAL: Skipping vertex index to prevent buffer overflow.");
|
||||
continue;
|
||||
}
|
||||
int32_t vi = vVertexIndice[mi][b->mWeights[wi].mVertexId];
|
||||
int32_t vi = vVertexIndice[mi][b->mWeights[wi].mVertexId]
|
||||
+ uniq_v_before_mi[mi];
|
||||
bool bIsWeightedAlready = (setWeightedVertex.find(vi) != setWeightedVertex.end());
|
||||
if (vi == last_index || bIsWeightedAlready) {
|
||||
// only for vertices we exported to fbx
|
||||
|
||||
@@ -365,10 +365,14 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
|
||||
}
|
||||
|
||||
if (data[0] == 'F') {
|
||||
return SafeParse<float>(data+1, t.end());
|
||||
BE_NCONST float id = SafeParse<float>(data+1, t.end());
|
||||
AI_SWAP4(id);
|
||||
return id;
|
||||
}
|
||||
else {
|
||||
return static_cast<float>( SafeParse<double>(data+1, t.end()) );
|
||||
BE_NCONST double id = SafeParse<double>(data+1, t.end());
|
||||
AI_SWAP8(id);
|
||||
return static_cast<float>(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,9 +641,15 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
|
||||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count3; ++i, d += 3) {
|
||||
out.emplace_back(static_cast<ai_real>(d[0]),
|
||||
static_cast<ai_real>(d[1]),
|
||||
static_cast<ai_real>(d[2]));
|
||||
BE_NCONST double val1 = d[0];
|
||||
BE_NCONST double val2 = d[1];
|
||||
BE_NCONST double val3 = d[2];
|
||||
AI_SWAP8(val1);
|
||||
AI_SWAP8(val2);
|
||||
AI_SWAP8(val3);
|
||||
out.emplace_back(static_cast<ai_real>(val1),
|
||||
static_cast<ai_real>(val2),
|
||||
static_cast<ai_real>(val3));
|
||||
}
|
||||
// for debugging
|
||||
/*for ( size_t i = 0; i < out.size(); i++ ) {
|
||||
@@ -652,7 +662,13 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
|
||||
else if (type == 'f') {
|
||||
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count3; ++i, f += 3) {
|
||||
out.emplace_back(f[0],f[1],f[2]);
|
||||
BE_NCONST float val1 = f[0];
|
||||
BE_NCONST float val2 = f[1];
|
||||
BE_NCONST float val3 = f[2];
|
||||
AI_SWAP4(val1);
|
||||
AI_SWAP4(val2);
|
||||
AI_SWAP4(val3);
|
||||
out.emplace_back(val1,val2,val3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -726,16 +742,32 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
|
||||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count4; ++i, d += 4) {
|
||||
out.emplace_back(static_cast<float>(d[0]),
|
||||
static_cast<float>(d[1]),
|
||||
static_cast<float>(d[2]),
|
||||
static_cast<float>(d[3]));
|
||||
BE_NCONST double val1 = d[0];
|
||||
BE_NCONST double val2 = d[1];
|
||||
BE_NCONST double val3 = d[2];
|
||||
BE_NCONST double val4 = d[3];
|
||||
AI_SWAP8(val1);
|
||||
AI_SWAP8(val2);
|
||||
AI_SWAP8(val3);
|
||||
AI_SWAP8(val4);
|
||||
out.emplace_back(static_cast<float>(val1),
|
||||
static_cast<float>(val2),
|
||||
static_cast<float>(val3),
|
||||
static_cast<float>(val4));
|
||||
}
|
||||
}
|
||||
else if (type == 'f') {
|
||||
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count4; ++i, f += 4) {
|
||||
out.emplace_back(f[0],f[1],f[2],f[3]);
|
||||
BE_NCONST float val1 = f[0];
|
||||
BE_NCONST float val2 = f[1];
|
||||
BE_NCONST float val3 = f[2];
|
||||
BE_NCONST float val4 = f[3];
|
||||
AI_SWAP4(val1);
|
||||
AI_SWAP4(val2);
|
||||
AI_SWAP4(val3);
|
||||
AI_SWAP4(val4);
|
||||
out.emplace_back(val1,val2,val3,val4);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -807,13 +839,21 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el) {
|
||||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count2; ++i, d += 2) {
|
||||
out.emplace_back(static_cast<float>(d[0]),
|
||||
static_cast<float>(d[1]));
|
||||
BE_NCONST double val1 = d[0];
|
||||
BE_NCONST double val2 = d[1];
|
||||
AI_SWAP8(val1);
|
||||
AI_SWAP8(val2);
|
||||
out.emplace_back(static_cast<float>(val1),
|
||||
static_cast<float>(val2));
|
||||
}
|
||||
} else if (type == 'f') {
|
||||
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count2; ++i, f += 2) {
|
||||
out.emplace_back(f[0],f[1]);
|
||||
BE_NCONST float val1 = f[0];
|
||||
BE_NCONST float val2 = f[1];
|
||||
AI_SWAP4(val1);
|
||||
AI_SWAP4(val2);
|
||||
out.emplace_back(val1,val2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -938,13 +978,17 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
|
||||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count; ++i, ++d) {
|
||||
out.push_back(static_cast<float>(*d));
|
||||
BE_NCONST double val = *d;
|
||||
AI_SWAP8(val);
|
||||
out.push_back(static_cast<float>(val));
|
||||
}
|
||||
}
|
||||
else if (type == 'f') {
|
||||
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count; ++i, ++f) {
|
||||
out.push_back(*f);
|
||||
BE_NCONST float val = *f;
|
||||
AI_SWAP4(val);
|
||||
out.push_back(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ aiMesh *IRRImporter::BuildSingleQuadMesh(const SkyboxVertex &v1,
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void IRRImporter::BuildSkybox(std::vector<aiMesh *> &meshes, std::vector<aiMaterial *> materials) {
|
||||
void IRRImporter::BuildSkybox(MeshArray &meshes, std::vector<aiMaterial *> materials) {
|
||||
// Update the material of the skybox - replace the name and disable shading for skyboxes.
|
||||
for (unsigned int i = 0; i < 6; ++i) {
|
||||
aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i)));
|
||||
@@ -602,7 +602,7 @@ void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
|
||||
BatchLoader &batch,
|
||||
std::vector<aiMesh *> &meshes,
|
||||
MeshArray &meshes,
|
||||
std::vector<aiNodeAnim *> &anims,
|
||||
std::vector<AttachmentInfo> &attach,
|
||||
std::vector<aiMaterial *> &materials,
|
||||
@@ -1283,7 +1283,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
std::vector<aiNodeAnim *> anims;
|
||||
std::vector<aiMaterial *> materials;
|
||||
std::vector<AttachmentInfo> attach;
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
|
||||
// try to guess how much storage we'll need
|
||||
anims.reserve(guessedAnimCnt + (guessedAnimCnt >> 2));
|
||||
|
||||
@@ -229,7 +229,7 @@ private:
|
||||
/// Fill the scene-graph recursively
|
||||
void GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
|
||||
BatchLoader &batch,
|
||||
std::vector<aiMesh *> &meshes,
|
||||
MeshArray &meshes,
|
||||
std::vector<aiNodeAnim *> &anims,
|
||||
std::vector<AttachmentInfo> &attach,
|
||||
std::vector<aiMaterial *> &materials,
|
||||
@@ -248,7 +248,7 @@ private:
|
||||
/// @param meshes Receives 6 output meshes
|
||||
/// @param materials The last 6 materials are assigned to the newly
|
||||
/// created meshes. The names of the materials are adjusted.
|
||||
void BuildSkybox(std::vector<aiMesh *> &meshes,
|
||||
void BuildSkybox(MeshArray &meshes,
|
||||
std::vector<aiMaterial *> materials);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@@ -121,7 +121,7 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
|
||||
|
||||
// final data
|
||||
std::vector<aiMaterial *> materials;
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
materials.reserve(5);
|
||||
meshes.reserve(5);
|
||||
|
||||
@@ -433,24 +433,24 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, const char *end, Verte
|
||||
aiColor4D c;
|
||||
|
||||
// Read the vertex position
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.z);
|
||||
sz = fast_atoreal_move(sz, temp.z);
|
||||
SkipSpaces(&sz, end);
|
||||
vertices.push_back(temp);
|
||||
|
||||
// Read the vertex normals
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.z);
|
||||
sz = fast_atoreal_move(sz, temp.z);
|
||||
SkipSpaces(&sz, end);
|
||||
normals.push_back(temp);
|
||||
|
||||
@@ -466,10 +466,10 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, const char *end, Verte
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
// read the first UV coordinate set
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
temp.z = 0.f;
|
||||
temp.y = 1.f - temp.y; // DX to OGL
|
||||
@@ -479,35 +479,35 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, const char *end, Verte
|
||||
// So by definition, all buffers have either UV2 or tangents or neither
|
||||
// read the (optional) second UV coordinate set
|
||||
if (vertexFormat == VertexFormat::t2coord) {
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
temp.y = 1.f - temp.y; // DX to OGL
|
||||
UV2s.push_back(temp);
|
||||
}
|
||||
// read optional tangent and bitangent vectors
|
||||
else if (vertexFormat == VertexFormat::tangent) {
|
||||
// tangents
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.z);
|
||||
sz = fast_atoreal_move(sz, temp.z);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
temp.y *= -1.0f;
|
||||
tangents.push_back(temp);
|
||||
|
||||
// bitangents
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.z);
|
||||
sz = fast_atoreal_move(sz, temp.z);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
temp.y *= -1.0f;
|
||||
bitangents.push_back(temp);
|
||||
|
||||
@@ -139,21 +139,21 @@ void IrrlichtBase::ReadVectorProperty(VectorProperty &out, pugi::xml_node& vecto
|
||||
const char *end = ptr + len;
|
||||
|
||||
SkipSpaces(&ptr, end);
|
||||
ptr = fast_atoreal_move<float>(ptr, (float &)out.value.x);
|
||||
ptr = fast_atoreal_move(ptr, out.value.x);
|
||||
SkipSpaces(&ptr, end);
|
||||
if (',' != *ptr) {
|
||||
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
|
||||
} else {
|
||||
SkipSpaces(ptr + 1, &ptr, end);
|
||||
}
|
||||
ptr = fast_atoreal_move<float>(ptr, (float &)out.value.y);
|
||||
ptr = fast_atoreal_move(ptr, out.value.y);
|
||||
SkipSpaces(&ptr, end);
|
||||
if (',' != *ptr) {
|
||||
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
|
||||
} else {
|
||||
SkipSpaces(ptr + 1, &ptr, end);
|
||||
}
|
||||
ptr = fast_atoreal_move<float>(ptr, (float &)out.value.z);
|
||||
ptr = fast_atoreal_move(ptr, out.value.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ void AnimResolver::UpdateAnimRangeSetup() {
|
||||
unsigned int tt = 1;
|
||||
for (const double tmp = delta * (num + 1); cur_minus <= tmp; cur_minus += delta, ++tt) {
|
||||
m = (delta == tmp ? (*it).keys.begin() : n - (old_size + 1));
|
||||
for (; m != n; --n) {
|
||||
for (; m < n; --n) {
|
||||
(*n).time -= cur_minus;
|
||||
|
||||
// offset repeat? add delta offset to key value
|
||||
|
||||
@@ -239,7 +239,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
|
||||
ResolveClips();
|
||||
|
||||
// now process all layers and build meshes and nodes
|
||||
std::vector<aiMesh *> apcMeshes;
|
||||
MeshArray apcMeshes;
|
||||
std::map<uint16_t, aiNode *> apcNodes;
|
||||
|
||||
apcMeshes.reserve(mLayers->size() * std::min(((unsigned int)mSurfaces->size() / 2u), 1u));
|
||||
|
||||
@@ -208,9 +208,9 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
|
||||
|
||||
float f;
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, key.value);
|
||||
c = fast_atoreal_move(c, key.value);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, f);
|
||||
c = fast_atoreal_move(c, f);
|
||||
|
||||
key.time = f;
|
||||
|
||||
@@ -242,7 +242,7 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
|
||||
}
|
||||
for (unsigned int i = 0; i < num; ++i) {
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, key.params[i]);
|
||||
c = fast_atoreal_move(c, key.params[i]);
|
||||
}
|
||||
} else if ((*it).tokens[0] == "Behaviors") {
|
||||
SkipSpaces(&c, end);
|
||||
@@ -284,11 +284,11 @@ void LWSImporter::ReadEnvelope_Old(std::list<LWS::Element>::const_iterator &it,c
|
||||
|
||||
// parse value and time, skip the rest for the moment.
|
||||
LWO::Key key;
|
||||
const char *c = fast_atoreal_move<float>((*it).tokens[0].c_str(), key.value);
|
||||
const char *c = fast_atoreal_move((*it).tokens[0].c_str(), key.value);
|
||||
const char *end = c + (*it).tokens[0].size();
|
||||
SkipSpaces(&c, end);
|
||||
float f;
|
||||
fast_atoreal_move<float>((*it).tokens[0].c_str(), f);
|
||||
fast_atoreal_move((*it).tokens[0].c_str(), f);
|
||||
key.time = f;
|
||||
|
||||
envl.keys.emplace_back(key);
|
||||
@@ -775,7 +775,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
ASSIMP_LOG_ERROR("LWS: envelopes for LightIntensity not supported, set to 1.0");
|
||||
nodes.back().lightIntensity = (ai_real)1.0;
|
||||
} else {
|
||||
fast_atoreal_move<float>(c, nodes.back().lightIntensity);
|
||||
fast_atoreal_move(c, nodes.back().lightIntensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -816,11 +816,11 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) {
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'");
|
||||
} else {
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.r);
|
||||
c = fast_atoreal_move(c, nodes.back().lightColor.r);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.g);
|
||||
c = fast_atoreal_move(c, nodes.back().lightColor.g);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.b);
|
||||
c = fast_atoreal_move(c, nodes.back().lightColor.b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,11 +829,11 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (nodes.empty()) {
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'");
|
||||
} else {
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.x);
|
||||
c = fast_atoreal_move(c, nodes.back().pivotPos.x);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.y);
|
||||
c = fast_atoreal_move(c, nodes.back().pivotPos.y);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.z);
|
||||
c = fast_atoreal_move(c, nodes.back().pivotPos.z);
|
||||
// Mark pivotPos as set
|
||||
nodes.back().isPivotSet = true;
|
||||
}
|
||||
|
||||
@@ -246,11 +246,11 @@ inline void AI_MD5_READ_TRIPLE(aiVector3D &vec, const char **sz, const char *buf
|
||||
return;
|
||||
++*sz;
|
||||
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
|
||||
*sz = fast_atoreal_move<float>(*sz, (float &)vec.x);
|
||||
*sz = fast_atoreal_move(*sz, vec.x);
|
||||
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
|
||||
*sz = fast_atoreal_move<float>(*sz, (float &)vec.y);
|
||||
*sz = fast_atoreal_move(*sz, vec.y);
|
||||
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
|
||||
*sz = fast_atoreal_move<float>(*sz, (float &)vec.z);
|
||||
*sz = fast_atoreal_move(*sz, vec.z);
|
||||
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
|
||||
if (')' != **sz) {
|
||||
MD5Parser::ReportWarning("Unexpected token: ) was expected", linenumber);
|
||||
@@ -277,6 +277,8 @@ inline bool AI_MD5_PARSE_STRING(const char **sz, const char *bufferEnd, aiString
|
||||
}
|
||||
}
|
||||
out.length = (ai_uint32)(szEnd - szStart);
|
||||
if (out.length >= AI_MAXLEN)
|
||||
out.length = AI_MAXLEN - 1;
|
||||
::memcpy(out.data, szStart, out.length);
|
||||
out.data[out.length] = '\0';
|
||||
|
||||
@@ -299,6 +301,8 @@ inline void AI_MD5_PARSE_STRING_IN_QUOTATION(const char **sz, const char *buffer
|
||||
const char *szEnd = *sz;
|
||||
++*sz;
|
||||
out.length = (ai_uint32)(szEnd - szStart);
|
||||
if (out.length >= AI_MAXLEN)
|
||||
out.length = AI_MAXLEN - 1;
|
||||
::memcpy(out.data, szStart, out.length);
|
||||
}
|
||||
}
|
||||
@@ -373,9 +377,9 @@ MD5MeshParser::MD5MeshParser(SectionArray &mSections) {
|
||||
if ('(' != *sz++)
|
||||
MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber);
|
||||
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
|
||||
sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.x);
|
||||
sz = fast_atoreal_move(sz, vert.mUV.x);
|
||||
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
|
||||
sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.y);
|
||||
sz = fast_atoreal_move(sz, vert.mUV.y);
|
||||
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
|
||||
if (')' != *sz++)
|
||||
MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber);
|
||||
@@ -411,7 +415,7 @@ MD5MeshParser::MD5MeshParser(SectionArray &mSections) {
|
||||
WeightDesc &weight = desc.mWeights[idx];
|
||||
weight.mBone = strtoul10(sz, &sz);
|
||||
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
|
||||
sz = fast_atoreal_move<float>(sz, weight.mWeight);
|
||||
sz = fast_atoreal_move(sz, weight.mWeight);
|
||||
AI_MD5_READ_TRIPLE(weight.vOffsetPosition, &sz, elem.end, elem.iLineNumber);
|
||||
}
|
||||
}
|
||||
@@ -482,7 +486,7 @@ MD5AnimParser::MD5AnimParser(SectionArray &mSections) {
|
||||
const char *sz = elem.szStart;
|
||||
while (SkipSpacesAndLineEnd(&sz, elem.end)) {
|
||||
float f;
|
||||
sz = fast_atoreal_move<float>(sz, f);
|
||||
sz = fast_atoreal_move(sz, f);
|
||||
desc.mValues.push_back(f);
|
||||
}
|
||||
}
|
||||
@@ -499,7 +503,7 @@ MD5AnimParser::MD5AnimParser(SectionArray &mSections) {
|
||||
} else if ((*iter).mName == "numAnimatedComponents") {
|
||||
mAnimatedBones.reserve(strtoul10((*iter).mGlobalValue.c_str()));
|
||||
} else if ((*iter).mName == "frameRate") {
|
||||
fast_atoreal_move<float>((*iter).mGlobalValue.c_str(), fFrameRate);
|
||||
fast_atoreal_move((*iter).mGlobalValue.c_str(), fFrameRate);
|
||||
}
|
||||
}
|
||||
ASSIMP_LOG_DEBUG("MD5AnimParser end");
|
||||
|
||||
@@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "MDLLoader.h"
|
||||
#include "AssetLib/MD2/MD2FileData.h"
|
||||
#include "HalfLife/HL1MDLLoader.h"
|
||||
#include "HalfLife/HL1FileData.h"
|
||||
#include "MDLDefaultColorMap.h"
|
||||
|
||||
#include <assimp/StringUtils.h>
|
||||
@@ -1404,10 +1405,10 @@ void MDLImporter::InternReadFile_3DGS_MDL7() {
|
||||
sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
|
||||
|
||||
// vector to held all created meshes
|
||||
std::vector<aiMesh *> *avOutList;
|
||||
MeshArray *avOutList;
|
||||
|
||||
// 3 meshes per group - that should be OK for most models
|
||||
avOutList = new std::vector<aiMesh *>[pcHeader->groups_num];
|
||||
avOutList = new MeshArray[pcHeader->groups_num];
|
||||
for (uint32_t i = 0; i < pcHeader->groups_num; ++i)
|
||||
avOutList[i].reserve(3);
|
||||
|
||||
@@ -1980,6 +1981,11 @@ void MDLImporter::InternReadFile_HL1(const std::string &pFile, const uint32_t iM
|
||||
if (iMagicWord == AI_MDL_MAGIC_NUMBER_BE_HL2b || iMagicWord == AI_MDL_MAGIC_NUMBER_LE_HL2b)
|
||||
throw DeadlyImportError("Impossible to properly load a model from an MDL sequence file.");
|
||||
|
||||
// Check if the buffer is large enough to hold the header
|
||||
if (iFileSize < sizeof(HalfLife::Header_HL1)) {
|
||||
throw DeadlyImportError("HL1 MDL file is too small to contain header.");
|
||||
}
|
||||
|
||||
// Read the MDL file.
|
||||
HalfLife::HL1MDLLoader loader(
|
||||
pScene,
|
||||
|
||||
@@ -86,7 +86,7 @@ const aiImporterDesc *NFFImporter::GetInfo() const {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#define AI_NFF_PARSE_FLOAT(f) \
|
||||
SkipSpaces(&sz, lineEnd); \
|
||||
if (!IsLineEnd(*sz)) sz = fast_atoreal_move<ai_real>(sz, (ai_real &)f);
|
||||
if (!IsLineEnd(*sz)) sz = fast_atoreal_move(sz, (ai_real &)f);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#define AI_NFF_PARSE_TRIPLE(v) \
|
||||
|
||||
@@ -212,14 +212,14 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
// stop at dimensions: this allows loading 1D or 2D coordinate vertices
|
||||
for (unsigned int dim = 0; dim < dimensions; ++dim) {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, *vec[dim]);
|
||||
sz = fast_atoreal_move(sz, *vec[dim]);
|
||||
}
|
||||
|
||||
// if has homogeneous coordinate, divide others by this one
|
||||
if (hasHomogenous) {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
ai_real w = 1.;
|
||||
sz = fast_atoreal_move<ai_real>(sz, w);
|
||||
sz = fast_atoreal_move(sz, w);
|
||||
for (unsigned int dim = 0; dim < dimensions; ++dim) {
|
||||
*(vec[dim]) /= w;
|
||||
}
|
||||
@@ -229,11 +229,11 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (hasNormals) {
|
||||
aiVector3D &n = mesh->mNormals[i];
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.x);
|
||||
sz = fast_atoreal_move(sz, n.x);
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.y);
|
||||
sz = fast_atoreal_move(sz, n.y);
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
fast_atoreal_move<ai_real>(sz, (ai_real &)n.z);
|
||||
fast_atoreal_move(sz, n.z);
|
||||
}
|
||||
|
||||
// reading colors is a pain because the specification says it can be
|
||||
@@ -243,22 +243,22 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (hasColors) {
|
||||
aiColor4D &c = mesh->mColors[0][i];
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.r);
|
||||
sz = fast_atoreal_move(sz, c.r);
|
||||
if (*sz != '#' && *sz != '\n' && *sz != '\r') {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.g);
|
||||
sz = fast_atoreal_move(sz, c.g);
|
||||
} else {
|
||||
c.g = 0.;
|
||||
}
|
||||
if (*sz != '#' && *sz != '\n' && *sz != '\r') {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.b);
|
||||
sz = fast_atoreal_move(sz, c.b);
|
||||
} else {
|
||||
c.b = 0.;
|
||||
}
|
||||
if (*sz != '#' && *sz != '\n' && *sz != '\r') {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.a);
|
||||
sz = fast_atoreal_move(sz, c.a);
|
||||
} else {
|
||||
c.a = 1.;
|
||||
}
|
||||
@@ -266,9 +266,9 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (hasTexCoord) {
|
||||
aiVector3D &t = mesh->mTextureCoords[0][i];
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)t.x);
|
||||
sz = fast_atoreal_move(sz, t.x);
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
fast_atoreal_move<ai_real>(sz, (ai_real &)t.y);
|
||||
fast_atoreal_move(sz, t.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -396,9 +395,12 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices) {
|
||||
if (nd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
|
||||
|
||||
aiMesh *cm( nullptr );
|
||||
aiMesh *cm{nullptr};
|
||||
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
|
||||
cm = pScene->mMeshes[nd->mMeshes[i]];
|
||||
if (nullptr != cm) {
|
||||
|
||||
@@ -165,21 +165,23 @@ struct Material {
|
||||
//! Ambient color
|
||||
aiColor3D ambient;
|
||||
//! Diffuse color
|
||||
aiColor3D diffuse;
|
||||
aiColor3D diffuse = aiColor3D(0.6f, 0.6f, 0.6f);
|
||||
//! Specular color
|
||||
aiColor3D specular;
|
||||
//! Emissive color
|
||||
aiColor3D emissive;
|
||||
//! Alpha value
|
||||
ai_real alpha;
|
||||
ai_real alpha = ai_real(1.0);
|
||||
//! Shineness factor
|
||||
ai_real shineness;
|
||||
ai_real shineness = ai_real(0.0);
|
||||
//! Illumination model
|
||||
int illumination_model;
|
||||
int illumination_model = 1;
|
||||
//! Index of refraction
|
||||
ai_real ior;
|
||||
ai_real ior = ai_real(1.0);
|
||||
//! Transparency color
|
||||
aiColor3D transparent;
|
||||
aiColor3D transparent = aiColor3D(1.0f, 1.0f, 1.0f);
|
||||
//! Ambient occlusion
|
||||
Maybe<ai_real> ambient_occlusion;
|
||||
|
||||
//! PBR Roughness
|
||||
Maybe<ai_real> roughness;
|
||||
@@ -187,31 +189,33 @@ struct Material {
|
||||
Maybe<ai_real> metallic;
|
||||
//! PBR Metallic
|
||||
Maybe<aiColor3D> sheen;
|
||||
//! PBR Sheen: an additional grazing component, primarily intended for cloth.
|
||||
Maybe<ai_real> sheen_grazing;
|
||||
//! PBR Sheen Tint: amount to tint sheen towards base color.
|
||||
Maybe<ai_real> sheen_tint;
|
||||
//! PBR Clearcoat
|
||||
Maybe<ai_real> clearcoat;
|
||||
//! PBR Clearcoat Thickness
|
||||
Maybe<ai_real> clearcoat_thickness;
|
||||
//! PBR Clearcoat Rougness
|
||||
Maybe<ai_real> clearcoat_roughness;
|
||||
//! PBR clearcoatGloss: controls clearcoat glossiness (0 = a “satin” appearance, 1 = a “gloss” appearance).
|
||||
Maybe<ai_real> clearcoat_gloss;
|
||||
//! PBR Anisotropy
|
||||
ai_real anisotropy;
|
||||
ai_real anisotropy = ai_real(0.0);
|
||||
//! PBR Anisotropy Rotation
|
||||
Maybe<ai_real> anisotropy_rotation;
|
||||
//! PBR Subsurface Scattering
|
||||
Maybe<ai_real> subsurface_scattering;
|
||||
//! PBR Specular Tint: a concession for artistic control that tints incident specular towards the base color.
|
||||
Maybe<ai_real> specular_tint;
|
||||
// See: https://disneyanimation.com/publications/physically-based-shading-at-disney/
|
||||
|
||||
//! bump map multipler (normal map scalar)(-bm)
|
||||
ai_real bump_multiplier;
|
||||
//! bump map multiplier (normal map scalar)(-bm)
|
||||
ai_real bump_multiplier = ai_real(1.0);
|
||||
|
||||
//! Constructor
|
||||
Material() :
|
||||
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(1.0f, 1.0, 1.0),
|
||||
roughness(),
|
||||
metallic(),
|
||||
sheen(),
|
||||
clearcoat_thickness(),
|
||||
clearcoat_roughness(),
|
||||
anisotropy(ai_real(0.0)),
|
||||
bump_multiplier(ai_real(1.0)) {
|
||||
Material() {
|
||||
std::fill_n(clamp, static_cast<unsigned int>(TextureTypeCount), false);
|
||||
}
|
||||
|
||||
|
||||
@@ -235,24 +235,64 @@ void ObjFileMtlImporter::load() {
|
||||
++m_DataIt;
|
||||
if (m_pModel->mCurrentMaterial != nullptr)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->clearcoat_roughness);
|
||||
} else {
|
||||
} else if (*m_DataIt == 't') {
|
||||
++m_DataIt;
|
||||
if (m_pModel->mCurrentMaterial != nullptr)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->clearcoat_thickness);
|
||||
} else {
|
||||
if (m_pModel->mCurrentMaterial != nullptr)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->clearcoat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm': // Texture or metallic
|
||||
{
|
||||
// Save start of token (after 'm')
|
||||
auto tokenStart = m_DataIt; // points to 'm'
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd); // move iterator to end of token
|
||||
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd; // advance iterator
|
||||
|
||||
if (keyword.compare(0, 3, "map") == 0) {
|
||||
// starts with "map", treat as texture map
|
||||
m_DataIt = tokenStart;
|
||||
getTexture();
|
||||
} else if (keyword == "metallic" || keyword == "metal" || keyword == "metalness") {
|
||||
// parse metallic float value instead of texture
|
||||
getFloatIfMaterialValid(&ObjFile::Material::metallic);
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'm': // Texture
|
||||
case 'b': // quick'n'dirty - for 'bump' sections
|
||||
case 'r': // quick'n'dirty - for 'refl' sections
|
||||
{
|
||||
getTexture();
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'r': // refl (map) or roughness (float)
|
||||
{
|
||||
auto tokenStart = m_DataIt; // points to 'r'
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd);
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd;
|
||||
|
||||
if (keyword == "roughness" || keyword == "rough") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::roughness);
|
||||
} else if (keyword == "refl" || keyword == "reflection") {
|
||||
m_DataIt = tokenStart;
|
||||
getTexture();
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'i': // Illumination model
|
||||
{
|
||||
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||
@@ -261,11 +301,60 @@ void ObjFileMtlImporter::load() {
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'a': // Anisotropy
|
||||
{
|
||||
++m_DataIt;
|
||||
if (m_pModel->mCurrentMaterial != nullptr)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->anisotropy);
|
||||
case 'a': {
|
||||
auto tokenStart = m_DataIt;
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd);
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd;
|
||||
|
||||
if (keyword == "aniso" || keyword == "anisotropy") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::anisotropy);
|
||||
} else if (keyword == "ao") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::ambient_occlusion);
|
||||
} else if (keyword == "anisor" || ai_stdStrToLower(keyword) == "anisotropicrotation") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::anisotropy_rotation);
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("Unhandled keyword: ", keyword );
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 's': {
|
||||
auto tokenStart = m_DataIt;
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd);
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd;
|
||||
|
||||
if (keyword == "subsurface" || keyword == "scattering") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::subsurface_scattering);
|
||||
} else if (ai_stdStrToLower(keyword) == "speculartint") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::specular_tint);
|
||||
} else if (keyword == "sheen") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::sheen_grazing);
|
||||
} else if (ai_stdStrToLower(keyword) == "sheentint") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::sheen_tint);
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("Unhandled keyword: ", keyword );
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'c': {
|
||||
auto tokenStart = m_DataIt;
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd);
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd;
|
||||
|
||||
if (ai_stdStrToLower(keyword) == "clearcoat") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::clearcoat);
|
||||
} else if (ai_stdStrToLower(keyword) == "clearcoatgloss") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::clearcoat_gloss);
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("Unhandled keyword: ", keyword );
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
@@ -332,6 +421,23 @@ void ObjFileMtlImporter::getFloatValue(Maybe<ai_real> &value) {
|
||||
value = Maybe<ai_real>();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Writes a loaded single float value if material not null
|
||||
void ObjFileMtlImporter::getFloatIfMaterialValid(ai_real ObjFile::Material::*member) {
|
||||
if (m_pModel != nullptr && m_pModel->mCurrentMaterial != nullptr) {
|
||||
// This will call getFloatValue(ai_real&)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->*member);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void ObjFileMtlImporter::getFloatIfMaterialValid(Maybe<ai_real> ObjFile::Material::*member) {
|
||||
// It can directly access `m_pModel` because it's part of the class
|
||||
if (m_pModel != nullptr && m_pModel->mCurrentMaterial != nullptr) {
|
||||
getFloatValue(m_pModel->mCurrentMaterial->*member);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Creates a material from loaded data.
|
||||
void ObjFileMtlImporter::createMaterial() {
|
||||
|
||||
@@ -87,6 +87,8 @@ private:
|
||||
/// Gets a float value from data.
|
||||
void getFloatValue(ai_real &value);
|
||||
void getFloatValue(Maybe<ai_real> &value);
|
||||
void getFloatIfMaterialValid(ai_real ObjFile::Material::*member);
|
||||
void getFloatIfMaterialValid(Maybe<ai_real> ObjFile::Material::*member);
|
||||
/// Creates a new material from loaded data.
|
||||
void createMaterial();
|
||||
/// Get texture name from loaded data.
|
||||
|
||||
@@ -121,6 +121,13 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
|
||||
m_DataItEnd = buffer.end();
|
||||
mEnd = &buffer[buffer.size() - 1] + 1;
|
||||
|
||||
if (processed == 0 && std::distance(m_DataIt, m_DataItEnd) >= 3 &&
|
||||
static_cast<unsigned char>(*m_DataIt) == 0xEF &&
|
||||
static_cast<unsigned char>(*(m_DataIt + 1)) == 0xBB &&
|
||||
static_cast<unsigned char>(*(m_DataIt + 2)) == 0xBF) {
|
||||
m_DataIt += 3; // skip BOM
|
||||
}
|
||||
|
||||
// Handle progress reporting
|
||||
const size_t filePos(streamBuffer.getFilePos());
|
||||
if (lastFilePos < filePos) {
|
||||
|
||||
@@ -828,13 +828,13 @@ bool PLY::PropertyInstance::ParseValue(const char *&pCur,
|
||||
// technically this should cast to float, but people tend to use float descriptors for double data
|
||||
// this is the best way to not risk losing precision on import and it doesn't hurt to do this
|
||||
ai_real f;
|
||||
pCur = fast_atoreal_move<ai_real>(pCur, f);
|
||||
pCur = fast_atoreal_move(pCur, f);
|
||||
out->fFloat = (ai_real)f;
|
||||
break;
|
||||
|
||||
case EDT_Double:
|
||||
double d;
|
||||
pCur = fast_atoreal_move<double>(pCur, d);
|
||||
pCur = fast_atoreal_move(pCur, d);
|
||||
out->fDouble = (double)d;
|
||||
break;
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ void Q3BSPFileImporter::CreateNodes(const Q3BSP::Q3BSPModel *pModel, aiScene *pS
|
||||
}
|
||||
|
||||
unsigned int matIdx(0);
|
||||
std::vector<aiMesh *> MeshArray;
|
||||
MeshArray MeshArray;
|
||||
std::vector<aiNode *> NodeArray;
|
||||
for (FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) {
|
||||
std::vector<Q3BSP::sQ3BSPFace *> *pArray = (*it).second;
|
||||
|
||||
@@ -136,7 +136,7 @@ void RAWImporter::InternReadFile(const std::string &pFile,
|
||||
unsigned int num;
|
||||
for (num = 0; num < 12; ++num) {
|
||||
if (!SkipSpaces(&sz, end) || !IsNumeric(*sz)) break;
|
||||
sz = fast_atoreal_move<float>(sz, data[num]);
|
||||
sz = fast_atoreal_move(sz, data[num]);
|
||||
}
|
||||
if (num != 12 && num != 9) {
|
||||
ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture");
|
||||
|
||||
@@ -116,7 +116,7 @@ struct SIBObject {
|
||||
|
||||
struct SIB {
|
||||
std::vector<aiMaterial *> mtls;
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
std::vector<aiLight *> lights;
|
||||
std::vector<SIBObject> objs, insts;
|
||||
};
|
||||
|
||||
@@ -982,7 +982,7 @@ bool SMDImporter::ParseFloat(const char *szCurrent, const char **szCurrentOut, c
|
||||
return false;
|
||||
}
|
||||
|
||||
*szCurrentOut = fast_atoreal_move<float>(szCurrent,out);
|
||||
*szCurrentOut = fast_atoreal_move(szCurrent,out);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -404,7 +404,7 @@ std::shared_ptr<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*& i
|
||||
for(;*cur && *cur != ',' && *cur != ')' && !IsSpace(*cur);++cur) {
|
||||
if (*cur == '.') {
|
||||
double f;
|
||||
inout = fast_atoreal_move<double>(start,f);
|
||||
inout = fast_atoreal_move(start,f);
|
||||
return std::make_shared<EXPRESS::REAL>(f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Read an ASCII STL file
|
||||
void STLImporter::LoadASCIIFile(aiNode *root) {
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
std::vector<aiNode *> nodes;
|
||||
const char *sz = mBuffer;
|
||||
const char *bufferEnd = mBuffer + mFileSize;
|
||||
@@ -294,11 +294,11 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
|
||||
aiVector3D vn;
|
||||
sz += 7;
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.x);
|
||||
sz = fast_atoreal_move(sz, vn.x);
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.y);
|
||||
sz = fast_atoreal_move(sz, vn.y);
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.z);
|
||||
sz = fast_atoreal_move(sz, vn.z);
|
||||
normalBuffer.emplace_back(vn);
|
||||
normalBuffer.emplace_back(vn);
|
||||
normalBuffer.emplace_back(vn);
|
||||
@@ -315,11 +315,11 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
positionBuffer.emplace_back();
|
||||
aiVector3D *vn = &positionBuffer.back();
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->x);
|
||||
sz = fast_atoreal_move(sz, vn->x);
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->y);
|
||||
sz = fast_atoreal_move(sz, vn->y);
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->z);
|
||||
sz = fast_atoreal_move(sz, vn->z);
|
||||
faceVertexCounter++;
|
||||
}
|
||||
} else if (!::strncmp(sz, "endsolid", 8)) {
|
||||
|
||||
@@ -383,11 +383,11 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
|
||||
|
||||
for (; !IsLineEnd(*data); ++data) {
|
||||
if (data[0] == 'X' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.a1);
|
||||
data = fast_atoreal_move(data + 2, nd->mTransformation.a1);
|
||||
} else if (data[0] == 'Y' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.b2);
|
||||
data = fast_atoreal_move(data + 2, nd->mTransformation.b2);
|
||||
} else if (data[0] == 'Z' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.c3);
|
||||
data = fast_atoreal_move(data + 2, nd->mTransformation.c3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ void XFileImporter::CreateMeshes(aiScene *pScene, aiNode *pNode, const std::vect
|
||||
}
|
||||
|
||||
// create a mesh for each mesh-material combination in the source node
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
for (unsigned int a = 0; a < pMeshes.size(); ++a) {
|
||||
XFile::Mesh *sourceMesh = pMeshes[a];
|
||||
if (nullptr == sourceMesh) {
|
||||
|
||||
@@ -1277,7 +1277,7 @@ ai_real XFileParser::ReadFloat() {
|
||||
}
|
||||
|
||||
ai_real result = 0.0;
|
||||
mP = fast_atoreal_move<ai_real>(mP, result);
|
||||
mP = fast_atoreal_move(mP, result);
|
||||
|
||||
CheckForSeparator();
|
||||
|
||||
|
||||
@@ -128,13 +128,17 @@ void X3DGeoHelper::rect_parallel_epiped(const aiVector3D &pSize, std::list<aiVec
|
||||
|
||||
#undef MESH_RectParallelepiped_CREATE_VERT
|
||||
|
||||
static constexpr int InvalidIndex = -1;
|
||||
|
||||
void X3DGeoHelper::coordIdx_str2faces_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces, unsigned int &pPrimitiveTypes) {
|
||||
std::vector<int32_t> f_data(pCoordIdx);
|
||||
std::vector<unsigned int> inds;
|
||||
unsigned int prim_type = 0;
|
||||
|
||||
if (f_data.back() != (-1)) {
|
||||
f_data.push_back(-1);
|
||||
if (!f_data.empty()) {
|
||||
if (f_data.back() != InvalidIndex) {
|
||||
f_data.push_back(InvalidIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// reserve average size.
|
||||
@@ -191,8 +195,10 @@ mg_m_err:
|
||||
void X3DGeoHelper::coordIdx_str2lines_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces) {
|
||||
std::vector<int32_t> f_data(pCoordIdx);
|
||||
|
||||
if (f_data.back() != (-1)) {
|
||||
f_data.push_back(-1);
|
||||
if (!f_data.empty()) {
|
||||
if (f_data.back() != InvalidIndex) {
|
||||
f_data.push_back(InvalidIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// reserve average size.
|
||||
|
||||
@@ -139,7 +139,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
ReadWorld(*worldNode, scope);
|
||||
}
|
||||
|
||||
std::vector<aiMesh *> &meshes = scope.meshes_linear;
|
||||
MeshArray &meshes = scope.meshes_linear;
|
||||
std::vector<aiMaterial *> &materials = scope.materials_linear;
|
||||
if (meshes.empty() || materials.empty()) {
|
||||
ThrowException("failed to extract data from XGL file, no meshes loaded");
|
||||
|
||||
@@ -192,7 +192,7 @@ static bool CheckValidFacesIndices(const aiFace *faces, unsigned nFaces, unsigne
|
||||
}
|
||||
|
||||
void glTFImporter::ImportMeshes(Asset &r) {
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
|
||||
unsigned int k = 0;
|
||||
meshOffsets.clear();
|
||||
@@ -515,7 +515,7 @@ void glTFImporter::ImportLights(Asset &r) {
|
||||
CopyValue(l.color, ail->mColorSpecular);
|
||||
|
||||
ail->mAngleOuterCone = l.falloffAngle;
|
||||
ail->mAngleInnerCone = l.falloffExponent; // TODO fix this, it does not look right at all
|
||||
ail->mAngleInnerCone = l.falloffAngle * (1.0f - 1.0f / (1.0f + l.falloffExponent));
|
||||
|
||||
ail->mAttenuationConstant = l.constantAttenuation;
|
||||
ail->mAttenuationLinear = l.linearAttenuation;
|
||||
|
||||
@@ -59,6 +59,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Header files, standard library.
|
||||
#include <cinttypes>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
@@ -1238,13 +1239,25 @@ void glTF2Exporter::ExportMeshes() {
|
||||
}
|
||||
|
||||
/******************** Tangents ********************/
|
||||
if (nullptr != aim->mTangents) {
|
||||
if (nullptr != aim->mTangents && nullptr != aim->mBitangents) {
|
||||
// Find the handedness by calculating the bitangent without the handedness factor,
|
||||
// the use a dot product to find out if the original bitangent was inverted (multiplied
|
||||
// by a factor of -1.0) or not (multiplied by 1.0)
|
||||
std::vector<ai_real> tangentsWithHandedness(aim->mNumVertices * 4);
|
||||
for (uint32_t i = 0; i < aim->mNumVertices; ++i) {
|
||||
aiVector3D calculatedBitangent = aim->mNormals[i] ^ aim->mTangents[i];
|
||||
ai_real bitangentDotProduct = calculatedBitangent * aim->mBitangents[i];
|
||||
ai_real handedness = std::copysign(1.0, bitangentDotProduct);
|
||||
aim->mTangents[i].NormalizeSafe();
|
||||
tangentsWithHandedness[i * 4] = aim->mTangents[i][0];
|
||||
tangentsWithHandedness[i * 4 + 1] = aim->mTangents[i][1];
|
||||
tangentsWithHandedness[i * 4 + 2] = aim->mTangents[i][2];
|
||||
tangentsWithHandedness[i * 4 + 3] = handedness;
|
||||
}
|
||||
|
||||
Ref<Accessor> t = ExportData(
|
||||
*mAsset, meshId, b, aim->mNumVertices, aim->mTangents, AttribType::VEC3,
|
||||
AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER
|
||||
*mAsset, meshId, b, aim->mNumVertices, &tangentsWithHandedness[0], AttribType::VEC4,
|
||||
AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER
|
||||
);
|
||||
if (t) {
|
||||
p.attributes.tangent.push_back(t);
|
||||
|
||||
@@ -347,6 +347,21 @@ struct ReadHelper<int64_t> {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
// On Mac size_t and uint64_t are not the same, so we need a specialized version
|
||||
// here to properly parse byteOffset and other parameters > 2^31
|
||||
// On Windows and Linux the types match andno additional specialization is required
|
||||
|
||||
template <>
|
||||
struct ReadHelper<size_t> {
|
||||
static bool Read(Value &val, size_t &out) {
|
||||
return val.IsInt64() ? out = val.GetInt64(), true : false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline static bool ReadValue(Value &val, T &out) {
|
||||
return ReadHelper<T>::Read(val, out);
|
||||
|
||||
+2
-7
@@ -1122,6 +1122,7 @@ IF(ASSIMP_HUNTER_ENABLED)
|
||||
ELSEIF(NOT TARGET pugixml::pugixml)
|
||||
SET( Pugixml_SRCS
|
||||
../contrib/pugixml/src/pugiconfig.hpp
|
||||
../contrib/pugixml/src/pugixml.cpp
|
||||
../contrib/pugixml/src/pugixml.hpp
|
||||
)
|
||||
INCLUDE_DIRECTORIES("../contrib/pugixml/src")
|
||||
@@ -1317,11 +1318,6 @@ if(MSVC10)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
IF( MSVC OR "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") # clang with MSVC ABI
|
||||
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
|
||||
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
|
||||
endif ()
|
||||
|
||||
IF(NOT ASSIMP_HUNTER_ENABLED)
|
||||
if (UNZIP_FOUND)
|
||||
SET (unzip_compile_SRCS "")
|
||||
@@ -1414,7 +1410,6 @@ add_compile_options(
|
||||
IF (ASSIMP_WARNINGS_AS_ERRORS)
|
||||
MESSAGE(STATUS "Treating all warnings as errors (for assimp library only)")
|
||||
IF (MSVC)
|
||||
|
||||
IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
|
||||
TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror
|
||||
-Wno-microsoft-enum-value
|
||||
@@ -1465,7 +1460,7 @@ IF (ASSIMP_WARNINGS_AS_ERRORS)
|
||||
-Wno-undefined-func-template
|
||||
-Wno-declaration-after-statement
|
||||
-Wno-deprecated-declarations
|
||||
-Wno-deprecated-non-prototype
|
||||
-Wno-deprecated-non-prototype
|
||||
)
|
||||
ELSE()
|
||||
TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX)
|
||||
|
||||
@@ -120,10 +120,10 @@ static std::mutex gLogStreamMutex;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Custom LogStream implementation for the C-API
|
||||
class LogToCallbackRedirector : public LogStream {
|
||||
class LogToCallbackRedirector final : public LogStream {
|
||||
public:
|
||||
explicit LogToCallbackRedirector(const aiLogStream &s) :
|
||||
stream(s) {
|
||||
mStream(s) {
|
||||
ai_assert(nullptr != s.callback);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public:
|
||||
// might cause strange problems, but the chance is quite low.
|
||||
|
||||
PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
|
||||
gPredefinedStreams.end(), (Assimp::LogStream *)stream.user);
|
||||
gPredefinedStreams.end(), (Assimp::LogStream *)mStream.user);
|
||||
|
||||
if (it != gPredefinedStreams.end()) {
|
||||
delete *it;
|
||||
@@ -147,11 +147,11 @@ public:
|
||||
|
||||
/** @copydoc LogStream::write */
|
||||
void write(const char *message) {
|
||||
stream.callback(message, stream.user);
|
||||
mStream.callback(message, mStream.user);
|
||||
}
|
||||
|
||||
private:
|
||||
aiLogStream stream;
|
||||
const aiLogStream &mStream;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -678,8 +678,8 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build a list of unique bones
|
||||
void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash> &asBones,
|
||||
std::vector<aiMesh *>::const_iterator it,
|
||||
std::vector<aiMesh *>::const_iterator end) {
|
||||
MeshArray::const_iterator it,
|
||||
MeshArray::const_iterator end) {
|
||||
unsigned int iOffset = 0;
|
||||
for (; it != end; ++it) {
|
||||
for (unsigned int l = 0; l < (*it)->mNumBones; ++l) {
|
||||
@@ -712,8 +712,7 @@ void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash> &asBones,
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Merge a list of bones
|
||||
void SceneCombiner::MergeBones(aiMesh *out, std::vector<aiMesh *>::const_iterator it,
|
||||
std::vector<aiMesh *>::const_iterator end) {
|
||||
void SceneCombiner::MergeBones(aiMesh *out, MeshArray::const_iterator it, MeshArray::const_iterator end) {
|
||||
if (nullptr == out || out->mNumBones == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -771,8 +770,8 @@ void SceneCombiner::MergeBones(aiMesh *out, std::vector<aiMesh *>::const_iterato
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Merge a list of meshes
|
||||
void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
std::vector<aiMesh *>::const_iterator begin,
|
||||
std::vector<aiMesh *>::const_iterator end) {
|
||||
MeshArray::const_iterator begin,
|
||||
MeshArray::const_iterator end) {
|
||||
if (nullptr == _out) {
|
||||
return;
|
||||
}
|
||||
@@ -788,7 +787,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
|
||||
std::string name;
|
||||
// Find out how much output storage we'll need
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
const char *meshName((*it)->mName.C_Str());
|
||||
name += std::string(meshName);
|
||||
if (it != end - 1) {
|
||||
@@ -810,7 +809,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
if ((**begin).HasPositions()) {
|
||||
|
||||
pv2 = out->mVertices = new aiVector3D[out->mNumVertices];
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mVertices) {
|
||||
::memcpy(pv2, (*it)->mVertices, (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
} else
|
||||
@@ -822,7 +821,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
if ((**begin).HasNormals()) {
|
||||
|
||||
pv2 = out->mNormals = new aiVector3D[out->mNumVertices];
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mNormals) {
|
||||
::memcpy(pv2, (*it)->mNormals, (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
} else {
|
||||
@@ -837,7 +836,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
pv2 = out->mTangents = new aiVector3D[out->mNumVertices];
|
||||
aiVector3D *pv2b = out->mBitangents = new aiVector3D[out->mNumVertices];
|
||||
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mTangents) {
|
||||
::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
::memcpy(pv2b, (*it)->mBitangents, (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
@@ -854,7 +853,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n];
|
||||
|
||||
pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices];
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mTextureCoords[n]) {
|
||||
::memcpy(pv2, (*it)->mTextureCoords[n], (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
} else {
|
||||
@@ -868,7 +867,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
n = 0;
|
||||
while ((**begin).HasVertexColors(n)) {
|
||||
aiColor4D *pVec2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mColors[n]) {
|
||||
::memcpy(pVec2, (*it)->mColors[n], (*it)->mNumVertices * sizeof(aiColor4D));
|
||||
} else {
|
||||
@@ -887,7 +886,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
aiFace *pf2 = out->mFaces;
|
||||
|
||||
unsigned int ofs = 0;
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
for (unsigned int m = 0; m < (*it)->mNumFaces; ++m, ++pf2) {
|
||||
aiFace &face = (*it)->mFaces[m];
|
||||
pf2->mNumIndices = face.mNumIndices;
|
||||
@@ -910,7 +909,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
MergeBones(out, begin, end);
|
||||
|
||||
// delete all source meshes
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it)
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
|
||||
@@ -158,8 +158,8 @@ void CatmullClarkSubdivider::Subdivide(
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<aiMesh *> inmeshes;
|
||||
std::vector<aiMesh *> outmeshes;
|
||||
MeshArray inmeshes;
|
||||
MeshArray outmeshes;
|
||||
std::vector<unsigned int> maptbl;
|
||||
|
||||
inmeshes.reserve(nmesh);
|
||||
@@ -577,7 +577,7 @@ void CatmullClarkSubdivider::InternSubdivide(
|
||||
// 7. Apply the next subdivision step.
|
||||
// ---------------------------------------------------------------------
|
||||
if (num != 1) {
|
||||
std::vector<aiMesh *> tmp(nmesh);
|
||||
MeshArray tmp(nmesh);
|
||||
InternSubdivide(out, nmesh, &tmp.front(), num - 1);
|
||||
for (size_t i = 0; i < nmesh; ++i) {
|
||||
delete out[i];
|
||||
|
||||
@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
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-2024, Assimp team\n"
|
||||
"(c) 2006-2025, Assimp team\n"
|
||||
"License under the terms and conditions of the 3-clause BSD license\n"
|
||||
"https://www.assimp.org\n";
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ namespace Assimp {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ai_real GeometryUtils::heron( ai_real a, ai_real b, ai_real c ) {
|
||||
const ai_real s = (a + b + c) / 2;
|
||||
const ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 );
|
||||
const ai_real s = (a + b + c) * 0.5;
|
||||
const ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), static_cast<ai_real>(0.5));
|
||||
return area;
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ ai_real GeometryUtils::distance3D( const aiVector3D &vA, const aiVector3D &vB )
|
||||
const ai_real lx = ( vB.x - vA.x );
|
||||
const ai_real ly = ( vB.y - vA.y );
|
||||
const ai_real lz = ( vB.z - vA.z );
|
||||
const ai_real a = lx*lx + ly*ly + lz*lz;
|
||||
const ai_real d = pow( a, (ai_real)0.5 );
|
||||
const ai_real a = lx*lx + ly*ly + lz*lz;
|
||||
const ai_real d = pow( a, static_cast<ai_real>(0.5));
|
||||
|
||||
return d;
|
||||
}
|
||||
@@ -66,6 +66,9 @@ ai_real GeometryUtils::distance3D( const aiVector3D &vA, const aiVector3D &vB )
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ai_real GeometryUtils::calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
|
||||
ai_real area = 0;
|
||||
if (mesh == nullptr) {
|
||||
return area;
|
||||
}
|
||||
|
||||
const aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] );
|
||||
const aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] );
|
||||
@@ -81,8 +84,7 @@ ai_real GeometryUtils::calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Check whether a ray intersects a plane and find the intersection point
|
||||
bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
|
||||
const aiVector3D& planeNormal, aiVector3D& pos) {
|
||||
bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, const aiVector3D& planeNormal, aiVector3D& pos) {
|
||||
const ai_real b = planeNormal * (planePos - ray.pos);
|
||||
ai_real h = ray.dir * planeNormal;
|
||||
if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0)
|
||||
@@ -93,11 +95,14 @@ bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut,
|
||||
size_t numVectors) {
|
||||
void GeometryUtils::normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors) {
|
||||
if (vectorArrayIn == nullptr || vectorArrayOut == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i=0; i<numVectors; ++i) {
|
||||
vectorArrayOut[i] = vectorArrayIn[i].Normalize();
|
||||
}
|
||||
vectorArrayOut[i] = vectorArrayIn[i].Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
@@ -83,13 +83,17 @@ aiReturn aiGetMaterialProperty(const aiMaterial *pMat,
|
||||
return AI_FAILURE;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get an array of floating-point values from the material.
|
||||
aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
|
||||
// Implementation of functions "aiGetMaterialFloatArray" and "aiGetMaterialFloatFloatArray".
|
||||
template <class TReal>
|
||||
aiReturn GetMaterialFloatArray(const aiMaterial *pMat,
|
||||
const char *pKey,
|
||||
unsigned int type,
|
||||
unsigned int index,
|
||||
ai_real *pOut,
|
||||
TReal *pOut,
|
||||
unsigned int *pMax) {
|
||||
ai_assert(pOut != nullptr);
|
||||
ai_assert(pMat != nullptr);
|
||||
@@ -100,7 +104,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
|
||||
return AI_FAILURE;
|
||||
}
|
||||
|
||||
// data is given in floats, convert to ai_real
|
||||
// data is given in floats, convert to TReal
|
||||
unsigned int iWrite = 0;
|
||||
if (aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) {
|
||||
iWrite = prop->mDataLength / sizeof(float);
|
||||
@@ -110,14 +114,14 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
|
||||
}
|
||||
|
||||
for (unsigned int a = 0; a < iWrite; ++a) {
|
||||
pOut[a] = static_cast<ai_real>(reinterpret_cast<float *>(prop->mData)[a]);
|
||||
pOut[a] = static_cast<TReal>(reinterpret_cast<float *>(prop->mData)[a]);
|
||||
}
|
||||
|
||||
if (pMax) {
|
||||
*pMax = iWrite;
|
||||
}
|
||||
}
|
||||
// data is given in doubles, convert to float
|
||||
// data is given in doubles, convert to TReal
|
||||
else if (aiPTI_Double == prop->mType) {
|
||||
iWrite = prop->mDataLength / sizeof(double);
|
||||
if (pMax) {
|
||||
@@ -125,13 +129,13 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
|
||||
;
|
||||
}
|
||||
for (unsigned int a = 0; a < iWrite; ++a) {
|
||||
pOut[a] = static_cast<ai_real>(reinterpret_cast<double *>(prop->mData)[a]);
|
||||
pOut[a] = static_cast<TReal>(reinterpret_cast<double *>(prop->mData)[a]);
|
||||
}
|
||||
if (pMax) {
|
||||
*pMax = iWrite;
|
||||
}
|
||||
}
|
||||
// data is given in ints, convert to float
|
||||
// data is given in ints, convert to TReal
|
||||
else if (aiPTI_Integer == prop->mType) {
|
||||
iWrite = prop->mDataLength / sizeof(int32_t);
|
||||
if (pMax) {
|
||||
@@ -139,7 +143,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
|
||||
;
|
||||
}
|
||||
for (unsigned int a = 0; a < iWrite; ++a) {
|
||||
pOut[a] = static_cast<ai_real>(reinterpret_cast<int32_t *>(prop->mData)[a]);
|
||||
pOut[a] = static_cast<TReal>(reinterpret_cast<int32_t *>(prop->mData)[a]);
|
||||
}
|
||||
if (pMax) {
|
||||
*pMax = iWrite;
|
||||
@@ -155,7 +159,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
|
||||
ai_assert(prop->mDataLength >= 5);
|
||||
ai_assert(!prop->mData[prop->mDataLength - 1]);
|
||||
for (unsigned int a = 0;; ++a) {
|
||||
cur = fast_atoreal_move<ai_real>(cur, pOut[a]);
|
||||
cur = fast_atoreal_move(cur, pOut[a]);
|
||||
if (a == iWrite - 1) {
|
||||
break;
|
||||
}
|
||||
@@ -174,92 +178,27 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get an array of floating-point values from the material.
|
||||
aiReturn aiGetMaterialDoubleArray(const aiMaterial *pMat,
|
||||
// Get an array of float typed float values from the material.
|
||||
aiReturn aiGetMaterialFloatFloatArray(const aiMaterial *pMat,
|
||||
const char *pKey,
|
||||
unsigned int type,
|
||||
unsigned int index,
|
||||
double *pOut,
|
||||
float *pOut,
|
||||
unsigned int *pMax) {
|
||||
ai_assert(pOut != nullptr);
|
||||
ai_assert(pMat != nullptr);
|
||||
return ::GetMaterialFloatArray(pMat, pKey, type, index, pOut, pMax);
|
||||
}
|
||||
|
||||
const aiMaterialProperty *prop;
|
||||
aiGetMaterialProperty(pMat, pKey, type, index, (const aiMaterialProperty **)&prop);
|
||||
if (nullptr == prop) {
|
||||
return AI_FAILURE;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// 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 of floating-point values from the material.
|
||||
aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat,
|
||||
const char *pKey,
|
||||
unsigned int type,
|
||||
unsigned int index,
|
||||
ai_real *pOut,
|
||||
unsigned int *pMax) {
|
||||
return ::GetMaterialFloatArray(pMat, pKey, type, index, pOut, pMax);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -348,7 +287,7 @@ aiReturn aiGetMaterialColor(const aiMaterial *pMat,
|
||||
unsigned int index,
|
||||
aiColor4D *pOut) {
|
||||
unsigned int iMax = 4;
|
||||
const aiReturn eRet = aiGetMaterialFloatArray(pMat, pKey, type, index, (ai_real *)pOut, &iMax);
|
||||
const aiReturn eRet = aiGetMaterialFloatFloatArray(pMat, pKey, type, index, (float *)pOut, &iMax);
|
||||
|
||||
// if no alpha channel is defined: set it to 1.0
|
||||
if (3 == iMax) {
|
||||
|
||||
@@ -100,6 +100,65 @@ void JoinVerticesProcess::Execute( aiScene* pScene) {
|
||||
|
||||
namespace {
|
||||
|
||||
struct CompareVerticesAlmostEqual {
|
||||
bool operator () (const Vertex & a, const Vertex & b) const {
|
||||
static const float epsilon = 1e-5f;
|
||||
static const float squareEpsilon = epsilon * epsilon;
|
||||
|
||||
if ((a.position - b.position).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We just test the other attributes even if they're not present in the mesh.
|
||||
// In this case they're initialized to 0 so the comparison succeeds.
|
||||
// By this method the non-present attributes are effectively ignored in the comparison.
|
||||
|
||||
if ((a.normal - b.normal).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a.tangent - b.tangent).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a.bitangent - b.bitangent).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i ++) {
|
||||
if ((a.texcoords[i] - b.texcoords[i]).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; i ++) {
|
||||
if (GetColorDifference(a.colors[i], b.colors[i]) > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If reached this point, they are ~equal
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct HashVertex {
|
||||
inline void hash_combine(std::size_t& seed, const ai_real& v) const {
|
||||
std::hash<ai_real> hasher;
|
||||
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
|
||||
size_t operator () (const Vertex & v) const {
|
||||
size_t hash = 0;
|
||||
|
||||
hash_combine(hash, v.position.x);
|
||||
hash_combine(hash, v.position.y);
|
||||
hash_combine(hash, v.position.z);
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
template<class XMesh>
|
||||
void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) {
|
||||
// replace vertex data with the unique data sets
|
||||
@@ -208,7 +267,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) {
|
||||
}
|
||||
}
|
||||
// a map that maps a vertex to its new index
|
||||
std::map<Vertex, int> vertex2Index = {};
|
||||
std::unordered_map<Vertex, int, HashVertex, CompareVerticesAlmostEqual> vertex2Index = {};
|
||||
// we can not end up with more vertices than we started with
|
||||
// Now check each vertex if it brings something new to the table
|
||||
int newIndex = 0;
|
||||
|
||||
@@ -332,7 +332,7 @@ void PretransformVertices::ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Simple routine to build meshes in worldspace, no further optimization
|
||||
void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh *> &out, aiMesh **in,
|
||||
void PretransformVertices::BuildWCSMeshes(MeshArray &out, aiMesh **in,
|
||||
unsigned int numIn, aiNode *node) const {
|
||||
// NOTE:
|
||||
// aiMesh::mNumBones store original source mesh, or UINT_MAX if not a copy
|
||||
@@ -459,7 +459,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
|
||||
}
|
||||
|
||||
// now build a list of output meshes
|
||||
std::vector<aiMesh *> apcOutMeshes;
|
||||
MeshArray apcOutMeshes;
|
||||
|
||||
// Keep scene hierarchy? It's an easy job in this case ...
|
||||
// we go on and transform all meshes, if one is referenced by nodes
|
||||
|
||||
@@ -139,7 +139,7 @@ private:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Simple routine to build meshes in worldspace, no further optimization
|
||||
void BuildWCSMeshes(std::vector<aiMesh *> &out, aiMesh **in,
|
||||
void BuildWCSMeshes(MeshArray &out, aiMesh **in,
|
||||
unsigned int numIn, aiNode *node) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@@ -126,7 +126,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
|
||||
|
||||
unsigned int aiNumMeshesPerPType[4] = { 0, 0, 0, 0 };
|
||||
|
||||
std::vector<aiMesh *> outMeshes;
|
||||
MeshArray outMeshes;
|
||||
outMeshes.reserve(static_cast<size_t>(pScene->mNumMeshes) << 1u);
|
||||
|
||||
bool bAnyChanges = false;
|
||||
@@ -165,6 +165,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
|
||||
if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) {
|
||||
*meshIdx = static_cast<unsigned int>(outMeshes.size());
|
||||
outMeshes.emplace_back(mesh);
|
||||
pScene->mMeshes[i] = nullptr; // Indicate ownership transfer
|
||||
} else {
|
||||
delete mesh;
|
||||
pScene->mMeshes[i] = nullptr;
|
||||
@@ -188,12 +189,15 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
|
||||
|
||||
unsigned int numPolyVerts = 0;
|
||||
for (; pFirstFace != pLastFace; ++pFirstFace) {
|
||||
if (pFirstFace->mNumIndices <= 3)
|
||||
if (pFirstFace->mNumIndices >= 1 && pFirstFace->mNumIndices <= 3)
|
||||
++aiNumPerPType[pFirstFace->mNumIndices - 1];
|
||||
else {
|
||||
++aiNumPerPType[3];
|
||||
numPolyVerts += pFirstFace->mNumIndices;
|
||||
}
|
||||
if (pFirstFace->mNumIndices == 0) {
|
||||
ASSIMP_LOG_WARN("Face with 0 indices treated as polygon");
|
||||
}
|
||||
}
|
||||
|
||||
VertexWeightTable *avw = ComputeVertexBoneWeightTable(mesh);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
All rights reserved.
|
||||
@@ -35,27 +34,20 @@ 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 A helper class that processes texture transformations */
|
||||
|
||||
#include "TextureTransform.h"
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
#include "TextureTransform.h"
|
||||
#include <assimp/StringUtils.h>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
TextureTransformStep::TextureTransformStep() : configFlags() {
|
||||
// nothing to do here
|
||||
}
|
||||
namespace Assimp {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
@@ -202,7 +194,6 @@ inline static const char* MappingModeToChar(aiTextureMapMode map) {
|
||||
void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
ASSIMP_LOG_DEBUG("TransformUVCoordsProcess begin");
|
||||
|
||||
|
||||
/* We build a per-mesh list of texture transformations we'll need
|
||||
* to apply. To achieve this, we iterate through all materials,
|
||||
* find all textures and get their transformations and UV indices.
|
||||
@@ -426,7 +417,6 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
// it shouldn't be too worse if we remove them.
|
||||
unsigned int size = (unsigned int)trafo.size();
|
||||
if (size > AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
||||
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_ERROR(static_cast<unsigned int>(trafo.size()), " UV channels required but just ",
|
||||
AI_MAX_NUMBER_OF_TEXTURECOORDS, " available");
|
||||
@@ -434,7 +424,6 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
size = AI_MAX_NUMBER_OF_TEXTURECOORDS;
|
||||
}
|
||||
|
||||
|
||||
aiVector3D* old[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
|
||||
old[n] = mesh->mTextureCoords[n];
|
||||
@@ -443,14 +432,13 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
// that we're not going to need later can be overridden.
|
||||
it = trafo.begin();
|
||||
for (unsigned int n = 0; n < trafo.size();++n,++it) {
|
||||
|
||||
if (n >= size) {
|
||||
// Try to use an untransformed channel for all channels we threw over board
|
||||
UpdateUVIndex((*it).updateList,untransformed);
|
||||
continue;
|
||||
}
|
||||
|
||||
outChannels++;
|
||||
++outChannels;
|
||||
|
||||
// Write to the log
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
@@ -470,15 +458,18 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
// Check whether we need a new buffer here
|
||||
if (mesh->mTextureCoords[n]) {
|
||||
|
||||
it2 = it;++it2;
|
||||
it2 = it;
|
||||
++it2;
|
||||
for (unsigned int m = n+1; m < size;++m, ++it2) {
|
||||
|
||||
if ((*it2).uvIndex == n){
|
||||
it2 = trafo.begin();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it2 == trafo.begin()){
|
||||
if (it2 == trafo.begin()) {
|
||||
{
|
||||
std::unique_ptr<aiVector3D[]> oldTextureCoords(mesh->mTextureCoords[n]);
|
||||
}
|
||||
mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
|
||||
}
|
||||
}
|
||||
@@ -536,13 +527,12 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
|
||||
// Print some detailed statistics into the log
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
|
||||
if (transformedChannels) {
|
||||
ASSIMP_LOG_INFO("TransformUVCoordsProcess end: ", outChannels, " output channels (in: ", inChannels, ", modified: ", transformedChannels,")");
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("TransformUVCoordsProcess finished");
|
||||
ASSIMP_LOG_INFO("TransformUVCoordsProcess finished");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
All rights reserved.
|
||||
@@ -43,9 +42,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef AI_TEXTURE_TRANSFORM_H_INCLUDED
|
||||
#define AI_TEXTURE_TRANSFORM_H_INCLUDED
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include "Common/BaseProcess.h"
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/material.h>
|
||||
#include <list>
|
||||
|
||||
@@ -56,129 +55,103 @@ namespace Assimp {
|
||||
|
||||
#define AI_TT_UV_IDX_LOCK_TBD 0xffffffff
|
||||
#define AI_TT_UV_IDX_LOCK_NONE 0xeeeeeeee
|
||||
|
||||
|
||||
#define AI_TT_ROTATION_EPSILON ((float)AI_DEG_TO_RAD(0.5))
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Small helper structure representing a shortcut into the material list
|
||||
* to be able to update some values quickly.
|
||||
*/
|
||||
/**
|
||||
* @brief Small helper structure representing a shortcut into the material list
|
||||
* to be able to update some values quickly.
|
||||
*/
|
||||
struct TTUpdateInfo {
|
||||
TTUpdateInfo() AI_NO_EXCEPT
|
||||
: directShortcut(nullptr)
|
||||
, mat(nullptr)
|
||||
, semantic(0)
|
||||
, index(0) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Direct shortcut, if available
|
||||
unsigned int* directShortcut;
|
||||
unsigned int* directShortcut = nullptr;
|
||||
|
||||
//! Material
|
||||
aiMaterial *mat;
|
||||
aiMaterial *mat = nullptr;
|
||||
|
||||
//! Texture type and index
|
||||
unsigned int semantic, index;
|
||||
//! Texture type
|
||||
unsigned int semantic = 0;
|
||||
|
||||
//! Texture index
|
||||
unsigned int index = 0;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper class representing texture coordinate transformations
|
||||
*/
|
||||
/**
|
||||
* @brief Helper class representing texture coordinate transformations
|
||||
*/
|
||||
struct STransformVecInfo : public aiUVTransform {
|
||||
STransformVecInfo() AI_NO_EXCEPT
|
||||
: uvIndex(0)
|
||||
, mapU(aiTextureMapMode_Wrap)
|
||||
, mapV(aiTextureMapMode_Wrap)
|
||||
, lockedPos(AI_TT_UV_IDX_LOCK_NONE) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Source texture coordinate index
|
||||
unsigned int uvIndex;
|
||||
unsigned int uvIndex = 0;
|
||||
|
||||
//! Texture mapping mode in the u, v direction
|
||||
aiTextureMapMode mapU,mapV;
|
||||
//! Texture mapping mode in the u direction
|
||||
aiTextureMapMode mapU = aiTextureMapMode_Wrap;
|
||||
|
||||
//! Texture mapping mode in the v direction
|
||||
aiTextureMapMode mapV = aiTextureMapMode_Wrap;
|
||||
|
||||
//! Locked destination UV index
|
||||
//! AI_TT_UV_IDX_LOCK_TBD - to be determined
|
||||
//! AI_TT_UV_IDX_LOCK_NONE - none (default)
|
||||
unsigned int lockedPos;
|
||||
unsigned int lockedPos = AI_TT_UV_IDX_LOCK_NONE;
|
||||
|
||||
//! Update info - shortcuts into all materials
|
||||
//! that are referencing this transform setup
|
||||
std::list<TTUpdateInfo> updateList;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Compare two transform setups
|
||||
*/
|
||||
inline bool operator== (const STransformVecInfo& other) const
|
||||
{
|
||||
inline bool operator== (const STransformVecInfo& other) const {
|
||||
// We use a small epsilon here
|
||||
const static float epsilon = 0.05f;
|
||||
|
||||
if (std::fabs( mTranslation.x - other.mTranslation.x ) > epsilon ||
|
||||
std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon)
|
||||
{
|
||||
std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::fabs( mScaling.x - other.mScaling.x ) > epsilon ||
|
||||
std::fabs( mScaling.y - other.mScaling.y ) > epsilon)
|
||||
{
|
||||
std::fabs( mScaling.y - other.mScaling.y ) > epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::fabs( mRotation - other.mRotation) > epsilon)
|
||||
{
|
||||
if (std::fabs( mRotation - other.mRotation) > epsilon) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator!= (const STransformVecInfo& other) const
|
||||
{
|
||||
inline bool operator!= (const STransformVecInfo& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether this is an untransformed texture coordinate set
|
||||
*/
|
||||
inline bool IsUntransformed() const
|
||||
{
|
||||
/**
|
||||
* @brief Returns whether this is an untransformed texture coordinate set
|
||||
*/
|
||||
inline bool IsUntransformed() const {
|
||||
return (1.0f == mScaling.x && 1.f == mScaling.y &&
|
||||
!mTranslation.x && !mTranslation.y &&
|
||||
mRotation < AI_TT_ROTATION_EPSILON);
|
||||
!mTranslation.x && !mTranslation.y && mRotation < AI_TT_ROTATION_EPSILON);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Build a 3x3 matrix from the transformations
|
||||
*/
|
||||
inline void GetMatrix(aiMatrix3x3& mOut)
|
||||
{
|
||||
/**
|
||||
* @brief Build a 3x3 matrix from the transformations
|
||||
*/
|
||||
inline void GetMatrix(aiMatrix3x3& mOut) {
|
||||
mOut = aiMatrix3x3();
|
||||
|
||||
if (1.0f != mScaling.x || 1.0f != mScaling.y)
|
||||
{
|
||||
if (1.0f != mScaling.x || 1.0f != mScaling.y) {
|
||||
aiMatrix3x3 mScale;
|
||||
mScale.a1 = mScaling.x;
|
||||
mScale.b2 = mScaling.y;
|
||||
mOut = mScale;
|
||||
}
|
||||
if (mRotation)
|
||||
{
|
||||
if (mRotation) {
|
||||
aiMatrix3x3 mRot;
|
||||
mRot.a1 = mRot.b2 = std::cos(mRotation);
|
||||
mRot.a2 = mRot.b1 = std::sin(mRotation);
|
||||
mRot.a2 = -mRot.a2;
|
||||
mOut *= mRot;
|
||||
}
|
||||
if (mTranslation.x || mTranslation.y)
|
||||
{
|
||||
if (mTranslation.x || mTranslation.y) {
|
||||
aiMatrix3x3 mTrans;
|
||||
mTrans.a3 = mTranslation.x;
|
||||
mTrans.b3 = mTranslation.y;
|
||||
@@ -187,16 +160,18 @@ struct STransformVecInfo : public aiUVTransform {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper step to compute final UV coordinate sets if there are scalings
|
||||
/**
|
||||
* @brief Helper step to compute final UV coordinate sets if there are scalings
|
||||
* or rotations in the original data read from the file.
|
||||
*/
|
||||
class TextureTransformStep : public BaseProcess {
|
||||
*/
|
||||
class TextureTransformStep final : public BaseProcess {
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
/// The default class constructor / destructor.
|
||||
TextureTransformStep();
|
||||
/// The default class constructor. /
|
||||
TextureTransformStep() = default;
|
||||
|
||||
/// The default class destructor.
|
||||
~TextureTransformStep() override = default;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@@ -210,10 +185,11 @@ public:
|
||||
|
||||
protected:
|
||||
// -------------------------------------------------------------------
|
||||
/** Preprocess a specific UV transformation setup
|
||||
/**
|
||||
* @brief Preprocess a specific UV transformation setup
|
||||
*
|
||||
* @param info Transformation setup to be preprocessed.
|
||||
*/
|
||||
*/
|
||||
void PreProcessUVTransform(STransformVecInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
@@ -583,6 +583,9 @@ char *OpenDDLParser::parsePrimitiveDataType(char *in, char *end, Value::ValueTyp
|
||||
size_t prim_len(0);
|
||||
for (size_t i = 0; i < (size_t) Value::ValueType::ddl_types_max; i++) {
|
||||
prim_len = strlen(Grammar::PrimitiveTypeToken[i]);
|
||||
if (static_cast<size_t>(end - in) < prim_len) {
|
||||
continue;
|
||||
}
|
||||
if (0 == strncmp(in, Grammar::PrimitiveTypeToken[i], prim_len)) {
|
||||
type = static_cast<Value::ValueType>(i);
|
||||
break;
|
||||
@@ -595,6 +598,9 @@ char *OpenDDLParser::parsePrimitiveDataType(char *in, char *end, Value::ValueTyp
|
||||
} else {
|
||||
in += prim_len;
|
||||
}
|
||||
if (in >= end) {
|
||||
return in;
|
||||
}
|
||||
|
||||
bool ok(true);
|
||||
if (*in == Grammar::OpenArrayToken[0]) {
|
||||
@@ -602,13 +608,13 @@ char *OpenDDLParser::parsePrimitiveDataType(char *in, char *end, Value::ValueTyp
|
||||
++in;
|
||||
char *start(in);
|
||||
while (in != end) {
|
||||
++in;
|
||||
if (*in == Grammar::CloseArrayToken[0]) {
|
||||
len = ::atoi(start);
|
||||
ok = true;
|
||||
++in;
|
||||
break;
|
||||
}
|
||||
++in;
|
||||
}
|
||||
} else {
|
||||
len = 1;
|
||||
@@ -630,9 +636,9 @@ char *OpenDDLParser::parseReference(char *in, char *end, std::vector<Name *> &na
|
||||
if (nextName) {
|
||||
names.push_back(nextName);
|
||||
}
|
||||
while (Grammar::CommaSeparator[0] == *in) {
|
||||
while (in != end && Grammar::CommaSeparator[0] == *in) {
|
||||
in = getNextSeparator(in, end);
|
||||
if (Grammar::CommaSeparator[0] == *in) {
|
||||
if (in != end && Grammar::CommaSeparator[0] == *in) {
|
||||
in = parseName(in, end, &nextName);
|
||||
if (nextName) {
|
||||
names.push_back(nextName);
|
||||
@@ -655,7 +661,7 @@ char *OpenDDLParser::parseBooleanLiteral(char *in, char *end, Value **boolean) {
|
||||
char *start(in);
|
||||
|
||||
size_t len(0);
|
||||
while (!isSeparator(*in) && in != end) {
|
||||
while (in != end && !isSeparator(*in)) {
|
||||
++in;
|
||||
++len;
|
||||
}
|
||||
@@ -688,7 +694,7 @@ char *OpenDDLParser::parseIntegerLiteral(char *in, char *end, Value **integer, V
|
||||
|
||||
in = lookForNextToken(in, end);
|
||||
char *start(in);
|
||||
while (!isSeparator(*in) && in != end) {
|
||||
while (in != end && !isSeparator(*in)) {
|
||||
++in;
|
||||
}
|
||||
|
||||
@@ -831,7 +837,7 @@ char *OpenDDLParser::parseHexaLiteral(char *in, char *end, Value **data) {
|
||||
bool ok(true);
|
||||
char *start(in);
|
||||
int pos(0);
|
||||
while (!isSeparator(*in) && in != end) {
|
||||
while (in != end && !isSeparator(*in)) {
|
||||
if ((*in < '0' && *in > '9') || (*in < 'a' && *in > 'f') || (*in < 'A' && *in > 'F')) {
|
||||
ok = false;
|
||||
break;
|
||||
|
||||
+279
-69
@@ -1,87 +1,297 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.10...3.30)
|
||||
|
||||
project(pugixml)
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
|
||||
option(BUILD_TESTS "Build tests" OFF)
|
||||
option(BUILD_PKGCONFIG "Build in PKGCONFIG mode" OFF)
|
||||
|
||||
set(BUILD_DEFINES "" CACHE STRING "Build defines")
|
||||
|
||||
if(MSVC)
|
||||
option(STATIC_CRT "Use static CRT libraries" OFF)
|
||||
|
||||
# Rewrite command line flags to use /MT if necessary
|
||||
if(STATIC_CRT)
|
||||
foreach(flag_var
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
if(${flag_var} MATCHES "/MD")
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
endif(${flag_var} MATCHES "/MD")
|
||||
endforeach(flag_var)
|
||||
endif()
|
||||
# Policy configuration; this *MUST* be specified before project is defined
|
||||
if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW) # Enables use of MSVC_RUNTIME_LIBRARY
|
||||
endif()
|
||||
|
||||
# Pre-defines standard install locations on *nix systems.
|
||||
project(pugixml VERSION 1.15 LANGUAGES CXX)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(CMakeDependentOption)
|
||||
include(GNUInstallDirs)
|
||||
mark_as_advanced(CLEAR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR)
|
||||
|
||||
set(HEADERS src/pugixml.hpp src/pugiconfig.hpp)
|
||||
set(SOURCES src/pugixml.cpp)
|
||||
cmake_dependent_option(PUGIXML_USE_VERSIONED_LIBDIR
|
||||
"Use a private subdirectory to install the headers and libraries" OFF
|
||||
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
|
||||
if(DEFINED BUILD_DEFINES)
|
||||
foreach(DEFINE ${BUILD_DEFINES})
|
||||
add_definitions("-D" ${DEFINE})
|
||||
endforeach()
|
||||
endif()
|
||||
#message(pugixml" "${BUILD_SHARED_LIBS})
|
||||
#if(BUILD_SHARED_LIBS)
|
||||
# add_library(pugixml SHARED ${HEADERS} ${SOURCES})
|
||||
#else()
|
||||
add_library(pugixml STATIC ${HEADERS} ${SOURCES})
|
||||
#endif()
|
||||
cmake_dependent_option(PUGIXML_USE_POSTFIX
|
||||
"Use separate postfix for each configuration to make sure you can install multiple build outputs" OFF
|
||||
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
|
||||
# Export symbols for shared library builds
|
||||
if(BUILD_SHARED_LIBS AND MSVC)
|
||||
target_compile_definitions(pugixml PRIVATE "PUGIXML_API=__declspec(dllexport)")
|
||||
cmake_dependent_option(PUGIXML_STATIC_CRT
|
||||
"Use static MSVC RT libraries" OFF
|
||||
"MSVC" OFF)
|
||||
|
||||
cmake_dependent_option(PUGIXML_BUILD_TESTS
|
||||
"Build pugixml tests" OFF
|
||||
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
|
||||
# Custom build defines
|
||||
set(PUGIXML_BUILD_DEFINES CACHE STRING "Build defines for custom options")
|
||||
separate_arguments(PUGIXML_BUILD_DEFINES)
|
||||
|
||||
# Technically not needed for this file. This is builtin CMAKE global variable.
|
||||
option(BUILD_SHARED_LIBS "Build shared instead of static library")
|
||||
|
||||
# Expose option to build PUGIXML as static as well when the global BUILD_SHARED_LIBS variable is set
|
||||
cmake_dependent_option(PUGIXML_BUILD_SHARED_AND_STATIC_LIBS
|
||||
"Build both shared and static libraries" OFF
|
||||
"BUILD_SHARED_LIBS" OFF)
|
||||
|
||||
# Expose options from the pugiconfig.hpp
|
||||
option(PUGIXML_WCHAR_MODE "Enable wchar_t mode" OFF)
|
||||
option(PUGIXML_COMPACT "Enable compact mode" OFF)
|
||||
option(PUGIXML_INSTALL "Enable installation rules" ON)
|
||||
|
||||
# Advanced options from pugiconfig.hpp
|
||||
option(PUGIXML_NO_XPATH "Disable XPath" OFF)
|
||||
option(PUGIXML_NO_STL "Disable STL" OFF)
|
||||
option(PUGIXML_NO_EXCEPTIONS "Disable Exceptions" OFF)
|
||||
mark_as_advanced(PUGIXML_NO_XPATH PUGIXML_NO_STL PUGIXML_NO_EXCEPTIONS)
|
||||
|
||||
if (APPLE)
|
||||
option(PUGIXML_BUILD_APPLE_FRAMEWORK "Build as Apple Frameworks" OFF)
|
||||
endif()
|
||||
|
||||
# Enable C++11 long long for compilers that are capable of it
|
||||
if(NOT ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} STRLESS 3.1 AND ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_long_long_type;")
|
||||
target_compile_features(pugixml PUBLIC cxx_long_long_type)
|
||||
set(PUGIXML_PUBLIC_DEFINITIONS
|
||||
$<$<BOOL:${PUGIXML_WCHAR_MODE}>:PUGIXML_WCHAR_MODE>
|
||||
$<$<BOOL:${PUGIXML_COMPACT}>:PUGIXML_COMPACT>
|
||||
$<$<BOOL:${PUGIXML_NO_XPATH}>:PUGIXML_NO_XPATH>
|
||||
$<$<BOOL:${PUGIXML_NO_STL}>:PUGIXML_NO_STL>
|
||||
$<$<BOOL:${PUGIXML_NO_EXCEPTIONS}>:PUGIXML_NO_EXCEPTIONS>
|
||||
)
|
||||
|
||||
# This is used to backport a CMake 3.15 feature, but is also forwards compatible
|
||||
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
MultiThreaded$<$<CONFIG:Debug>:Debug>$<$<NOT:$<BOOL:${PUGIXML_STATIC_CRT}>>:DLL>)
|
||||
endif()
|
||||
|
||||
set_target_properties(pugixml PROPERTIES VERSION 1.9 SOVERSION 1)
|
||||
get_target_property(PUGIXML_VERSION_STRING pugixml VERSION)
|
||||
# Set the default C++ standard to C++17 if not set; CMake will automatically downgrade this if the compiler does not support it
|
||||
# When CMAKE_CXX_STANDARD_REQUIRED is set, we fall back to C++11 to avoid breaking older compilers
|
||||
if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED AND NOT DEFINED CMAKE_CXX_STANDARD AND NOT CMAKE_VERSION VERSION_LESS 3.8)
|
||||
|
||||
if(BUILD_PKGCONFIG)
|
||||
# Install library into its own directory under LIBDIR
|
||||
set(INSTALL_SUFFIX /pugixml-${PUGIXML_VERSION_STRING})
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED OFF)
|
||||
elseif (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
|
||||
target_include_directories(pugixml PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/src>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}${INSTALL_SUFFIX}>)
|
||||
|
||||
install(TARGETS pugixml EXPORT pugixml-config
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}${INSTALL_SUFFIX}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}${INSTALL_SUFFIX}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}${INSTALL_SUFFIX})
|
||||
install(EXPORT pugixml-config DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml)
|
||||
|
||||
if(BUILD_PKGCONFIG)
|
||||
configure_file(scripts/pugixml.pc.in ${PROJECT_BINARY_DIR}/pugixml.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/pugixml.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
|
||||
if (PUGIXML_USE_POSTFIX)
|
||||
set(CMAKE_RELWITHDEBINFO_POSTFIX _r)
|
||||
set(CMAKE_MINSIZEREL_POSTFIX _m)
|
||||
set(CMAKE_DEBUG_POSTFIX _d)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTS)
|
||||
file(GLOB TEST_SOURCES tests/*.cpp)
|
||||
file(GLOB FUZZ_SOURCES tests/fuzz_*.cpp)
|
||||
list(REMOVE_ITEM TEST_SOURCES ${FUZZ_SOURCES})
|
||||
if (CMAKE_VERSION VERSION_LESS 3.15)
|
||||
set(msvc-rt $<TARGET_PROPERTY:MSVC_RUNTIME_LIBRARY>)
|
||||
|
||||
add_executable(check ${TEST_SOURCES})
|
||||
target_link_libraries(check pugixml)
|
||||
add_custom_command(TARGET check POST_BUILD COMMAND check WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
set(msvc-rt-mtd-shared $<STREQUAL:${msvc-rt},MultiThreadedDebugDLL>)
|
||||
set(msvc-rt-mtd-static $<STREQUAL:${msvc-rt},MultiThreadedDebug>)
|
||||
set(msvc-rt-mt-shared $<STREQUAL:${msvc-rt},MultiThreadedDLL>)
|
||||
set(msvc-rt-mt-static $<STREQUAL:${msvc-rt},MultiThreaded>)
|
||||
unset(msvc-rt)
|
||||
|
||||
set(msvc-rt-mtd-shared $<${msvc-rt-mtd-shared}:-MDd>)
|
||||
set(msvc-rt-mtd-static $<${msvc-rt-mtd-static}:-MTd>)
|
||||
set(msvc-rt-mt-shared $<${msvc-rt-mt-shared}:-MD>)
|
||||
set(msvc-rt-mt-static $<${msvc-rt-mt-static}:-MT>)
|
||||
endif()
|
||||
|
||||
set(versioned-dir $<$<BOOL:${PUGIXML_USE_VERSIONED_LIBDIR}>:/pugixml-${PROJECT_VERSION}>)
|
||||
|
||||
set(libs)
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
add_library(pugixml-shared SHARED
|
||||
${PROJECT_SOURCE_DIR}/scripts/pugixml_dll.rc
|
||||
${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
|
||||
add_library(pugixml::shared ALIAS pugixml-shared)
|
||||
list(APPEND libs pugixml-shared)
|
||||
string(CONCAT pugixml.msvc $<OR:
|
||||
$<STREQUAL:${CMAKE_CXX_COMPILER_FRONTEND_VARIANT},MSVC>,
|
||||
$<CXX_COMPILER_ID:MSVC>
|
||||
>)
|
||||
|
||||
set_property(TARGET pugixml-shared PROPERTY EXPORT_NAME shared)
|
||||
target_include_directories(pugixml-shared
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
target_compile_definitions(pugixml-shared
|
||||
PUBLIC
|
||||
${PUGIXML_BUILD_DEFINES}
|
||||
${PUGIXML_PUBLIC_DEFINITIONS}
|
||||
PRIVATE
|
||||
PUGIXML_API=$<IF:${pugixml.msvc},__declspec\(dllexport\),__attribute__\(\(visibility\("default"\)\)\)>
|
||||
)
|
||||
target_compile_options(pugixml-shared
|
||||
PRIVATE
|
||||
${msvc-rt-mtd-shared}
|
||||
${msvc-rt-mtd-static}
|
||||
${msvc-rt-mt-shared}
|
||||
${msvc-rt-mt-static})
|
||||
endif()
|
||||
|
||||
if (NOT BUILD_SHARED_LIBS OR PUGIXML_BUILD_SHARED_AND_STATIC_LIBS)
|
||||
add_library(pugixml-static STATIC
|
||||
${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
|
||||
add_library(pugixml::static ALIAS pugixml-static)
|
||||
list(APPEND libs pugixml-static)
|
||||
|
||||
set_property(TARGET pugixml-static PROPERTY EXPORT_NAME static)
|
||||
target_include_directories(pugixml-static
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
target_compile_definitions(pugixml-static
|
||||
PUBLIC
|
||||
${PUGIXML_BUILD_DEFINES}
|
||||
${PUGIXML_PUBLIC_DEFINITIONS})
|
||||
target_compile_options(pugixml-static
|
||||
PRIVATE
|
||||
${msvc-rt-mtd-shared}
|
||||
${msvc-rt-mtd-static}
|
||||
${msvc-rt-mt-shared}
|
||||
${msvc-rt-mt-static})
|
||||
endif()
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set(pugixml-alias pugixml-shared)
|
||||
else()
|
||||
set(pugixml-alias pugixml-static)
|
||||
endif()
|
||||
add_library(pugixml INTERFACE)
|
||||
target_link_libraries(pugixml INTERFACE ${pugixml-alias})
|
||||
add_library(pugixml::pugixml ALIAS pugixml)
|
||||
|
||||
set_target_properties(${libs}
|
||||
PROPERTIES
|
||||
MSVC_RUNTIME_LIBRARY ${CMAKE_MSVC_RUNTIME_LIBRARY}
|
||||
EXCLUDE_FROM_ALL ON
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
VERSION ${PROJECT_VERSION}
|
||||
OUTPUT_NAME pugixml)
|
||||
|
||||
set_target_properties(${libs}
|
||||
PROPERTIES
|
||||
EXCLUDE_FROM_ALL OFF)
|
||||
set(install-targets pugixml ${libs})
|
||||
|
||||
if (PUGIXML_BUILD_APPLE_FRAMEWORK)
|
||||
set_target_properties(${libs} PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
FRAMEWORK_VERSION ${PROJECT_VERSION}
|
||||
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.zeux.pugixml
|
||||
MACOSX_FRAMEWORK_IDENTIFIER com.zeux.pugixml
|
||||
MACOSX_FRAMEWORK_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR})
|
||||
endif()
|
||||
|
||||
configure_package_config_file(
|
||||
"${PROJECT_SOURCE_DIR}/scripts/pugixml-config.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/pugixml-config.cmake"
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||
NO_SET_AND_CHECK_MACRO)
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${PROJECT_BINARY_DIR}/pugixml-config-version.cmake"
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
if (PUGIXML_USE_POSTFIX)
|
||||
if(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
|
||||
set(LIB_POSTFIX ${CMAKE_RELWITHDEBINFO_POSTFIX})
|
||||
elseif(CMAKE_BUILD_TYPE MATCHES MinSizeRel)
|
||||
set(LIB_POSTFIX ${CMAKE_MINSIZEREL_POSTFIX})
|
||||
elseif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(LIB_POSTFIX ${CMAKE_DEBUG_POSTFIX})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Handle both relative and absolute paths (e.g. NixOS) for a relocatable package
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(PUGIXML_PC_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
else()
|
||||
set(PUGIXML_PC_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
endif()
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
|
||||
set(PUGIXML_PC_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
|
||||
else()
|
||||
set(PUGIXML_PC_LIBDIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
configure_file(scripts/pugixml.pc.in pugixml.pc @ONLY)
|
||||
|
||||
export(TARGETS ${install-targets}
|
||||
NAMESPACE pugixml::
|
||||
FILE pugixml-targets.cmake)
|
||||
|
||||
if(PUGIXML_INSTALL)
|
||||
if (NOT DEFINED PUGIXML_RUNTIME_COMPONENT)
|
||||
set(PUGIXML_RUNTIME_COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED PUGIXML_LIBRARY_COMPONENT)
|
||||
set(PUGIXML_LIBRARY_COMPONENT Library)
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED PUGIXML_DEVELOPMENT_COMPONENT)
|
||||
set(PUGIXML_DEVELOPMENT_COMPONENT Development)
|
||||
endif()
|
||||
|
||||
set(namelink-component)
|
||||
if (NOT CMAKE_VERSION VERSION_LESS 3.12)
|
||||
set(namelink-component NAMELINK_COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
|
||||
endif()
|
||||
install(TARGETS ${install-targets}
|
||||
EXPORT pugixml-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${PUGIXML_RUNTIME_COMPONENT}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${PUGIXML_LIBRARY_COMPONENT} ${namelink-component}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir}
|
||||
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime OPTIONAL)
|
||||
|
||||
install(EXPORT pugixml-targets
|
||||
NAMESPACE pugixml::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
|
||||
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/pugixml-config-version.cmake"
|
||||
"${PROJECT_BINARY_DIR}/pugixml-config.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
|
||||
|
||||
install(FILES ${PROJECT_BINARY_DIR}/pugixml.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
|
||||
|
||||
install(
|
||||
FILES
|
||||
"${PROJECT_SOURCE_DIR}/src/pugiconfig.hpp"
|
||||
"${PROJECT_SOURCE_DIR}/src/pugixml.hpp"
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir} COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
|
||||
endif()
|
||||
|
||||
if (PUGIXML_BUILD_TESTS)
|
||||
include(CTest)
|
||||
set(fuzz-pattern "tests/fuzz_*.cpp")
|
||||
set(test-pattern "tests/*.cpp")
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.11)
|
||||
list(INSERT fuzz-pattern 0 CONFIGURE_DEPENDS)
|
||||
list(INSERT test-pattern 0 CONFIGURE_DEPENDS)
|
||||
endif()
|
||||
file(GLOB test-sources ${test-pattern})
|
||||
file(GLOB fuzz-sources ${fuzz-pattern})
|
||||
list(REMOVE_ITEM test-sources ${fuzz-sources})
|
||||
|
||||
add_custom_target(check
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure)
|
||||
|
||||
add_executable(pugixml-check ${test-sources})
|
||||
add_test(NAME pugixml::test
|
||||
COMMAND pugixml-check
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||
add_dependencies(check pugixml-check)
|
||||
target_link_libraries(pugixml-check
|
||||
PRIVATE
|
||||
pugixml::pugixml)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2006-2025 Arseny Kapoulkine
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,6 +1,6 @@
|
||||
pugixml 1.13 - an XML processing library
|
||||
pugixml 1.15 - an XML processing library
|
||||
|
||||
Copyright (c) 2006-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
Copyright (C) 2006-2025, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
Report bugs and download new versions at https://pugixml.org/
|
||||
|
||||
This is the distribution of pugixml, which is a C++ XML processing library,
|
||||
@@ -26,7 +26,7 @@ The distribution contains the following folders:
|
||||
|
||||
This library is distributed under the MIT License:
|
||||
|
||||
Copyright (c) 2006-2024 Arseny Kapoulkine
|
||||
Copyright (c) 2006-2025 Arseny Kapoulkine
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* pugixml parser - version 1.13
|
||||
* pugixml parser - version 1.15
|
||||
* --------------------------------------------------------
|
||||
* Copyright (c) 2006-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
* Copyright (C) 2006-2025, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
* Report bugs and download new versions at https://pugixml.org/
|
||||
*
|
||||
* This library is distributed under the MIT License. See notice at the end
|
||||
@@ -30,9 +30,14 @@
|
||||
// #define PUGIXML_NO_EXCEPTIONS
|
||||
|
||||
// Set this to control attributes for public classes/functions, i.e.:
|
||||
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
|
||||
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
|
||||
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
|
||||
#ifdef _WIN32
|
||||
# define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
|
||||
#else
|
||||
# define PUGIXML_API __attribute__((visibility("default")))
|
||||
#endif // _WIN32
|
||||
#
|
||||
//define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
|
||||
//#define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
|
||||
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
|
||||
|
||||
// Tune these constants to adjust memory-related behavior
|
||||
@@ -44,15 +49,18 @@
|
||||
// #define PUGIXML_XPATH_DEPTH_LIMIT 1024
|
||||
|
||||
// Uncomment this to switch to header-only version
|
||||
#define PUGIXML_HEADER_ONLY
|
||||
// #define PUGIXML_HEADER_ONLY
|
||||
|
||||
// Uncomment this to enable long long support
|
||||
// Uncomment this to enable long long support (usually enabled automatically)
|
||||
// #define PUGIXML_HAS_LONG_LONG
|
||||
|
||||
// Uncomment this to enable support for std::string_view (usually enabled automatically)
|
||||
// #define PUGIXML_HAS_STRING_VIEW
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Copyright (c) 2006-2024 Arseny Kapoulkine
|
||||
* Copyright (c) 2006-2025 Arseny Kapoulkine
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
|
||||
+1480
-1085
File diff suppressed because it is too large
Load Diff
+109
-30
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* pugixml parser - version 1.13
|
||||
* pugixml parser - version 1.15
|
||||
* --------------------------------------------------------
|
||||
* Copyright (c) 2006-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
* Copyright (C) 2006-2025, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
* Report bugs and download new versions at https://pugixml.org/
|
||||
*
|
||||
* This library is distributed under the MIT License. See notice at the end
|
||||
@@ -14,7 +14,7 @@
|
||||
// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons
|
||||
// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits
|
||||
#ifndef PUGIXML_VERSION
|
||||
# define PUGIXML_VERSION 1130 // 1.13
|
||||
# define PUGIXML_VERSION 1150 // 1.15
|
||||
#endif
|
||||
|
||||
// Include user configuration file (this can define various configuration macros)
|
||||
@@ -38,6 +38,20 @@
|
||||
# include <string>
|
||||
#endif
|
||||
|
||||
// Check if std::string_view is available
|
||||
#if !defined(PUGIXML_HAS_STRING_VIEW) && !defined(PUGIXML_NO_STL)
|
||||
# if __cplusplus >= 201703L
|
||||
# define PUGIXML_HAS_STRING_VIEW
|
||||
# elif defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
|
||||
# define PUGIXML_HAS_STRING_VIEW
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Include string_view if appropriate
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
# include <string_view>
|
||||
#endif
|
||||
|
||||
// Macro for deprecated features
|
||||
#ifndef PUGIXML_DEPRECATED
|
||||
# if defined(__GNUC__)
|
||||
@@ -82,14 +96,14 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// If C++ is 2011 or higher, add 'noexcept' specifiers
|
||||
// If C++ is 2011 or higher, use 'noexcept' specifiers
|
||||
#ifndef PUGIXML_NOEXCEPT
|
||||
# if __cplusplus >= 201103
|
||||
# define PUGIXML_NOEXCEPT noexcept
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
# define PUGIXML_NOEXCEPT noexcept
|
||||
# else
|
||||
# define PUGIXML_NOEXCEPT
|
||||
# define PUGIXML_NOEXCEPT throw()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -138,7 +152,12 @@ namespace pugi
|
||||
|
||||
#ifndef PUGIXML_NO_STL
|
||||
// String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE
|
||||
typedef std::basic_string<PUGIXML_CHAR, std::char_traits<PUGIXML_CHAR>, std::allocator<PUGIXML_CHAR> > string_t;
|
||||
typedef std::basic_string<PUGIXML_CHAR> string_t;
|
||||
#endif
|
||||
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
// String view type used for operations that can work with a length delimited string; depends on PUGIXML_WCHAR_MODE
|
||||
typedef std::basic_string_view<PUGIXML_CHAR> string_view_t;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -213,6 +232,10 @@ namespace pugi
|
||||
// This flag is off by default.
|
||||
const unsigned int parse_embed_pcdata = 0x2000;
|
||||
|
||||
// This flag determines whether determines whether the the two pcdata should be merged or not, if no intermediatory data are parsed in the document.
|
||||
// This flag is off by default.
|
||||
const unsigned int parse_merge_pcdata = 0x4000;
|
||||
|
||||
// The default parsing mode.
|
||||
// Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded,
|
||||
// End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules.
|
||||
@@ -324,7 +347,7 @@ namespace pugi
|
||||
class PUGIXML_CLASS xml_writer
|
||||
{
|
||||
public:
|
||||
virtual ~xml_writer() {}
|
||||
virtual ~xml_writer();
|
||||
|
||||
// Write memory chunk into stream/file/whatever
|
||||
virtual void write(const void* data, size_t size) = 0;
|
||||
@@ -349,14 +372,14 @@ namespace pugi
|
||||
{
|
||||
public:
|
||||
// Construct writer from an output stream object
|
||||
xml_writer_stream(std::basic_ostream<char, std::char_traits<char> >& stream);
|
||||
xml_writer_stream(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream);
|
||||
xml_writer_stream(std::basic_ostream<char>& stream);
|
||||
xml_writer_stream(std::basic_ostream<wchar_t>& stream);
|
||||
|
||||
virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE;
|
||||
|
||||
private:
|
||||
std::basic_ostream<char, std::char_traits<char> >* narrow_stream;
|
||||
std::basic_ostream<wchar_t, std::char_traits<wchar_t> >* wide_stream;
|
||||
std::basic_ostream<char>* narrow_stream;
|
||||
std::basic_ostream<wchar_t>* wide_stream;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -392,7 +415,7 @@ namespace pugi
|
||||
bool operator<=(const xml_attribute& r) const;
|
||||
bool operator>=(const xml_attribute& r) const;
|
||||
|
||||
// Check if attribute is empty
|
||||
// Check if attribute is empty (null)
|
||||
bool empty() const;
|
||||
|
||||
// Get attribute name/value, or "" if attribute is empty
|
||||
@@ -418,8 +441,15 @@ namespace pugi
|
||||
|
||||
// Set attribute name/value (returns false if attribute is empty or there is not enough memory)
|
||||
bool set_name(const char_t* rhs);
|
||||
bool set_value(const char_t* rhs, size_t sz);
|
||||
bool set_name(const char_t* rhs, size_t size);
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
bool set_name(string_view_t rhs);
|
||||
#endif
|
||||
bool set_value(const char_t* rhs);
|
||||
bool set_value(const char_t* rhs, size_t size);
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
bool set_value(string_view_t rhs);
|
||||
#endif
|
||||
|
||||
// Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
|
||||
bool set_value(int rhs);
|
||||
@@ -447,6 +477,10 @@ namespace pugi
|
||||
xml_attribute& operator=(float rhs);
|
||||
xml_attribute& operator=(bool rhs);
|
||||
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
xml_attribute& operator=(string_view_t rhs);
|
||||
#endif
|
||||
|
||||
#ifdef PUGIXML_HAS_LONG_LONG
|
||||
xml_attribute& operator=(long long rhs);
|
||||
xml_attribute& operator=(unsigned long long rhs);
|
||||
@@ -502,7 +536,7 @@ namespace pugi
|
||||
bool operator<=(const xml_node& r) const;
|
||||
bool operator>=(const xml_node& r) const;
|
||||
|
||||
// Check if node is empty.
|
||||
// Check if node is empty (null)
|
||||
bool empty() const;
|
||||
|
||||
// Get node type
|
||||
@@ -541,9 +575,18 @@ namespace pugi
|
||||
xml_attribute attribute(const char_t* name) const;
|
||||
xml_node next_sibling(const char_t* name) const;
|
||||
xml_node previous_sibling(const char_t* name) const;
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
xml_node child(string_view_t name) const;
|
||||
xml_attribute attribute(string_view_t name) const;
|
||||
xml_node next_sibling(string_view_t name) const;
|
||||
xml_node previous_sibling(string_view_t name) const;
|
||||
#endif
|
||||
|
||||
// Get attribute, starting the search from a hint (and updating hint so that searching for a sequence of attributes is fast)
|
||||
xml_attribute attribute(const char_t* name, xml_attribute& hint) const;
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
xml_attribute attribute(string_view_t name, xml_attribute& hint) const;
|
||||
#endif
|
||||
|
||||
// Get child value of current node; that is, value of the first child node of type PCDATA/CDATA
|
||||
const char_t* child_value() const;
|
||||
@@ -553,14 +596,27 @@ namespace pugi
|
||||
|
||||
// Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value)
|
||||
bool set_name(const char_t* rhs);
|
||||
bool set_value(const char_t* rhs, size_t sz);
|
||||
bool set_name(const char_t* rhs, size_t size);
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
bool set_name(string_view_t rhs);
|
||||
#endif
|
||||
bool set_value(const char_t* rhs);
|
||||
bool set_value(const char_t* rhs, size_t size);
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
bool set_value(string_view_t rhs);
|
||||
#endif
|
||||
|
||||
// Add attribute with specified name. Returns added attribute, or empty attribute on errors.
|
||||
xml_attribute append_attribute(const char_t* name);
|
||||
xml_attribute prepend_attribute(const char_t* name);
|
||||
xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr);
|
||||
xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr);
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
xml_attribute append_attribute(string_view_t name);
|
||||
xml_attribute prepend_attribute(string_view_t name);
|
||||
xml_attribute insert_attribute_after(string_view_t name, const xml_attribute& attr);
|
||||
xml_attribute insert_attribute_before(string_view_t name, const xml_attribute& attr);
|
||||
#endif
|
||||
|
||||
// Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors.
|
||||
xml_attribute append_copy(const xml_attribute& proto);
|
||||
@@ -579,6 +635,12 @@ namespace pugi
|
||||
xml_node prepend_child(const char_t* name);
|
||||
xml_node insert_child_after(const char_t* name, const xml_node& node);
|
||||
xml_node insert_child_before(const char_t* name, const xml_node& node);
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
xml_node append_child(string_view_t name);
|
||||
xml_node prepend_child(string_view_t name);
|
||||
xml_node insert_child_after(string_view_t, const xml_node& node);
|
||||
xml_node insert_child_before(string_view_t name, const xml_node& node);
|
||||
#endif
|
||||
|
||||
// Add a copy of the specified node as a child. Returns added node, or empty node on errors.
|
||||
xml_node append_copy(const xml_node& proto);
|
||||
@@ -595,6 +657,9 @@ namespace pugi
|
||||
// Remove specified attribute
|
||||
bool remove_attribute(const xml_attribute& a);
|
||||
bool remove_attribute(const char_t* name);
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
bool remove_attribute(string_view_t name);
|
||||
#endif
|
||||
|
||||
// Remove all attributes
|
||||
bool remove_attributes();
|
||||
@@ -602,6 +667,9 @@ namespace pugi
|
||||
// Remove specified child
|
||||
bool remove_child(const xml_node& n);
|
||||
bool remove_child(const char_t* name);
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
bool remove_child(string_view_t name);
|
||||
#endif
|
||||
|
||||
// Remove all children
|
||||
bool remove_children();
|
||||
@@ -694,8 +762,8 @@ namespace pugi
|
||||
|
||||
#ifndef PUGIXML_NO_STL
|
||||
// Print subtree to stream
|
||||
void print(std::basic_ostream<char, std::char_traits<char> >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
|
||||
void print(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const;
|
||||
void print(std::basic_ostream<char>& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
|
||||
void print(std::basic_ostream<wchar_t>& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const;
|
||||
#endif
|
||||
|
||||
// Child nodes iterators
|
||||
@@ -712,9 +780,12 @@ namespace pugi
|
||||
|
||||
// Range-based for support
|
||||
xml_object_range<xml_node_iterator> children() const;
|
||||
xml_object_range<xml_named_node_iterator> children(const char_t* name) const;
|
||||
xml_object_range<xml_attribute_iterator> attributes() const;
|
||||
|
||||
// Range-based for support for all children with the specified name
|
||||
// Note: name pointer must have a longer lifetime than the returned object; be careful with passing temporaries!
|
||||
xml_object_range<xml_named_node_iterator> children(const char_t* name) const;
|
||||
|
||||
// Get node offset in parsed file/string (in char_t units) for debugging purposes
|
||||
ptrdiff_t offset_debug() const;
|
||||
|
||||
@@ -755,7 +826,7 @@ namespace pugi
|
||||
// Borland C++ workaround
|
||||
bool operator!() const;
|
||||
|
||||
// Check if text object is empty
|
||||
// Check if text object is empty (null)
|
||||
bool empty() const;
|
||||
|
||||
// Get text, or "" if object is empty
|
||||
@@ -779,8 +850,11 @@ namespace pugi
|
||||
bool as_bool(bool def = false) const;
|
||||
|
||||
// Set text (returns false if object is empty or there is not enough memory)
|
||||
bool set(const char_t* rhs, size_t sz);
|
||||
bool set(const char_t* rhs);
|
||||
bool set(const char_t* rhs, size_t size);
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
bool set(string_view_t rhs);
|
||||
#endif
|
||||
|
||||
// Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
|
||||
bool set(int rhs);
|
||||
@@ -808,6 +882,10 @@ namespace pugi
|
||||
xml_text& operator=(float rhs);
|
||||
xml_text& operator=(bool rhs);
|
||||
|
||||
#ifdef PUGIXML_HAS_STRING_VIEW
|
||||
xml_text& operator=(string_view_t rhs);
|
||||
#endif
|
||||
|
||||
#ifdef PUGIXML_HAS_LONG_LONG
|
||||
xml_text& operator=(long long rhs);
|
||||
xml_text& operator=(unsigned long long rhs);
|
||||
@@ -927,6 +1005,7 @@ namespace pugi
|
||||
xml_named_node_iterator();
|
||||
|
||||
// Construct an iterator which points to the specified node
|
||||
// Note: name pointer is stored in the iterator and must have a longer lifetime than iterator itself
|
||||
xml_named_node_iterator(const xml_node& node, const char_t* name);
|
||||
|
||||
// Iterator operators
|
||||
@@ -1062,8 +1141,8 @@ namespace pugi
|
||||
|
||||
#ifndef PUGIXML_NO_STL
|
||||
// Load document from stream.
|
||||
xml_parse_result load(std::basic_istream<char, std::char_traits<char> >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
|
||||
xml_parse_result load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& stream, unsigned int options = parse_default);
|
||||
xml_parse_result load(std::basic_istream<char>& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
|
||||
xml_parse_result load(std::basic_istream<wchar_t>& stream, unsigned int options = parse_default);
|
||||
#endif
|
||||
|
||||
// (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied.
|
||||
@@ -1092,8 +1171,8 @@ namespace pugi
|
||||
|
||||
#ifndef PUGIXML_NO_STL
|
||||
// Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details).
|
||||
void save(std::basic_ostream<char, std::char_traits<char> >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
|
||||
void save(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const;
|
||||
void save(std::basic_ostream<char>& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
|
||||
void save(std::basic_ostream<wchar_t>& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const;
|
||||
#endif
|
||||
|
||||
// Save XML to file
|
||||
@@ -1304,7 +1383,7 @@ namespace pugi
|
||||
explicit xpath_exception(const xpath_parse_result& result);
|
||||
|
||||
// Get error message
|
||||
virtual const char* what() const throw() PUGIXML_OVERRIDE;
|
||||
virtual const char* what() const PUGIXML_NOEXCEPT PUGIXML_OVERRIDE;
|
||||
|
||||
// Get parse result
|
||||
const xpath_parse_result& result() const;
|
||||
@@ -1429,12 +1508,12 @@ namespace pugi
|
||||
|
||||
#ifndef PUGIXML_NO_STL
|
||||
// Convert wide string to UTF8
|
||||
std::basic_string<char, std::char_traits<char>, std::allocator<char> > PUGIXML_FUNCTION as_utf8(const wchar_t* str);
|
||||
std::basic_string<char, std::char_traits<char>, std::allocator<char> > PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >& str);
|
||||
std::basic_string<char> PUGIXML_FUNCTION as_utf8(const wchar_t* str);
|
||||
std::basic_string<char> PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t>& str);
|
||||
|
||||
// Convert UTF8 to wide string
|
||||
std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > PUGIXML_FUNCTION as_wide(const char* str);
|
||||
std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > PUGIXML_FUNCTION as_wide(const std::basic_string<char, std::char_traits<char>, std::allocator<char> >& str);
|
||||
std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const char* str);
|
||||
std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const std::basic_string<char>& str);
|
||||
#endif
|
||||
|
||||
// Memory allocation function interface; returns pointer to allocated memory or NULL on failure
|
||||
@@ -1481,7 +1560,7 @@ namespace std
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Copyright (c) 2006-2024 Arseny Kapoulkine
|
||||
* Copyright (c) 2006-2025 Arseny Kapoulkine
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
|
||||
@@ -12,6 +12,15 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef _CRT_SECURE_NO_WARNINGS
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
# endif // _CRT_SECURE_NO_WARNINGS
|
||||
# ifndef _CRT_NONSTDC_NO_DEPRECATE
|
||||
# define _CRT_NONSTDC_NO_DEPRECATE
|
||||
# endif // _CRT_NONSTDC_NO_DEPRECATE
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef _CRT_NONSTDC_NO_DEPRECATE
|
||||
# define _CRT_NONSTDC_NO_DEPRECATE
|
||||
# endif
|
||||
# ifndef _CRT_SECURE_NO_WARNINGS
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
# endif //_CRT_SECURE_NO_WARNINGS
|
||||
#endif // _WIN32
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__BORLANDC__)
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef _CRT_SECURE_NO_WARNINGS
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
# endif // _CRT_SECURE_NO_WARNINGS
|
||||
# ifndef _CRT_NONSTDC_NO_DEPRECATE
|
||||
# define _CRT_NONSTDC_NO_DEPRECATE
|
||||
# endif // _CRT_NONSTDC_NO_DEPRECATE
|
||||
#endif // _WIN32
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Copyright (C) 2004-2019 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
|
||||
@@ -23,7 +23,6 @@ z_const char * const z_errmsg[10] = {
|
||||
(z_const char *)""
|
||||
};
|
||||
|
||||
|
||||
const char * ZEXPORT zlibVersion()
|
||||
{
|
||||
return ZLIB_VERSION;
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <assimp/types.h>
|
||||
|
||||
#include <exception>
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
// =======================================================================
|
||||
@@ -67,6 +68,7 @@ class IOStream;
|
||||
class IOSystem;
|
||||
class ProgressHandler;
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Plugin development
|
||||
//
|
||||
@@ -108,6 +110,10 @@ namespace Assimp {
|
||||
* allocations and may take some time, so it's better to reuse them as often as
|
||||
* possible.
|
||||
*
|
||||
* If you want to let assimp deal with OutOfMemory-exception make sure that
|
||||
* ASSIMP_CATCH_GLOBAL_EXCEPTIONS is set.
|
||||
* If this is not the case you need to catch the exception by yourself.
|
||||
*
|
||||
* If you need the Importer to do custom file handling to access the files,
|
||||
* implement IOSystem and IOStream and supply an instance of your custom
|
||||
* IOSystem implementation by calling SetIOHandler() before calling ReadFile().
|
||||
|
||||
@@ -240,8 +240,8 @@ public:
|
||||
* @param end Points to the mesh after the last mesh to be processed
|
||||
*/
|
||||
static void MergeMeshes(aiMesh **dest, unsigned int flags,
|
||||
std::vector<aiMesh *>::const_iterator begin,
|
||||
std::vector<aiMesh *>::const_iterator end);
|
||||
MeshArray::const_iterator begin,
|
||||
MeshArray::const_iterator end);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Merges two or more bones
|
||||
@@ -251,8 +251,8 @@ public:
|
||||
* @param begin First mesh to be processed
|
||||
* @param end Points to the mesh after the last mesh to be processed
|
||||
*/
|
||||
static void MergeBones(aiMesh *out, std::vector<aiMesh *>::const_iterator it,
|
||||
std::vector<aiMesh *>::const_iterator end);
|
||||
static void MergeBones(aiMesh *out, MeshArray::const_iterator it,
|
||||
MeshArray::const_iterator end);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Merges two or more materials
|
||||
@@ -277,8 +277,8 @@ public:
|
||||
* @param end Last mesh to be processed
|
||||
*/
|
||||
static void BuildUniqueBoneList(std::list<BoneWithHash> &asBones,
|
||||
std::vector<aiMesh *>::const_iterator it,
|
||||
std::vector<aiMesh *>::const_iterator end);
|
||||
MeshArray::const_iterator it,
|
||||
MeshArray::const_iterator end);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Add a name prefix to all nodes in a scene.
|
||||
|
||||
@@ -183,29 +183,6 @@ struct Vertex {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator < (const Vertex & o) const {
|
||||
if (position < o.position) return true;
|
||||
if (position != o.position) return false;
|
||||
|
||||
if (normal < o.normal) return true;
|
||||
if (normal != o.normal) return false;
|
||||
|
||||
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i ++) {
|
||||
if (texcoords[i] < o.texcoords[i]) return true;
|
||||
if (texcoords[i] != o.texcoords[i]) return false;
|
||||
}
|
||||
|
||||
// note that tangent/bitangent are not checked since they are optional
|
||||
|
||||
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; i ++) {
|
||||
if (colors[i] < o.colors[i]) return true;
|
||||
if (colors[i] != o.colors[i]) return false;
|
||||
}
|
||||
|
||||
// if reached this point, they are equal
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/// Convert back to non-interleaved storage
|
||||
void SortBack(aiMesh* out, unsigned int idx) const {
|
||||
|
||||
@@ -70,9 +70,15 @@ union _IEEESingle {
|
||||
float Float;
|
||||
struct
|
||||
{
|
||||
#if (defined AI_BUILD_BIG_ENDIAN)
|
||||
uint32_t Sign : 1;
|
||||
uint32_t Exp : 8;
|
||||
uint32_t Frac : 23;
|
||||
#else
|
||||
uint32_t Frac : 23;
|
||||
uint32_t Exp : 8;
|
||||
uint32_t Sign : 1;
|
||||
#endif
|
||||
} IEEE;
|
||||
};
|
||||
|
||||
@@ -83,9 +89,15 @@ union _IEEEDouble {
|
||||
double Double;
|
||||
struct
|
||||
{
|
||||
#if (defined AI_BUILD_BIG_ENDIAN)
|
||||
uint64_t Sign : 1;
|
||||
uint64_t Exp : 11;
|
||||
uint64_t Frac : 52;
|
||||
#else
|
||||
uint64_t Frac : 52;
|
||||
uint64_t Exp : 11;
|
||||
uint64_t Sign : 1;
|
||||
#endif
|
||||
} IEEE;
|
||||
};
|
||||
|
||||
|
||||
+12
-1
@@ -77,6 +77,17 @@ typedef uint32_t ai_uint32;
|
||||
#include <new> // for std::nothrow_t
|
||||
#include <string> // for aiString::Set(const std::string&)
|
||||
|
||||
struct aiNode;
|
||||
struct aiMesh;
|
||||
struct aiMaterial;
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
using MeshArray = std::vector<aiMesh *>;
|
||||
using NodeArray = std::vector<aiNode *>;
|
||||
using MaterialArray = std::vector<aiMaterial*>;
|
||||
|
||||
namespace Assimp {
|
||||
//! @cond never
|
||||
namespace Intern {
|
||||
@@ -118,7 +129,7 @@ extern "C" {
|
||||
|
||||
/** Maximum dimension for strings, ASSIMP strings are zero terminated. */
|
||||
#ifdef __cplusplus
|
||||
static const size_t AI_MAXLEN = 1024;
|
||||
static constexpr size_t AI_MAXLEN = 1024;
|
||||
#else
|
||||
#define AI_MAXLEN 1024
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[Setup]
|
||||
AppName=Open Asset Import Library - SDK
|
||||
AppVerName=Open Asset Import Library - SDK (v5.4.3)
|
||||
AppVerName=Open Asset Import Library - SDK (v6.0.2)
|
||||
DefaultDirName={pf}\Assimp
|
||||
DefaultGroupName=Assimp
|
||||
UninstallDisplayIcon={app}\bin\x64\assimp.exe
|
||||
@@ -12,9 +12,9 @@ SetupIconFile=..\..\tools\shared\assimp_tools_icon.ico
|
||||
WizardImageFile=..\..\tools\shared\assimp_tools_icon.bmp
|
||||
WizardSmallImageFile=..\..\tools\shared\assimp_tools_icon.bmp
|
||||
LicenseFile=License.rtf
|
||||
OutputBaseFileName=assimp-sdk-5.4.3-setup
|
||||
VersionInfoVersion=5.4.3.0
|
||||
VersionInfoTextVersion=5.4.3
|
||||
OutputBaseFileName=assimp-sdk-6.0.2-setup
|
||||
VersionInfoVersion=6.0.2.0
|
||||
VersionInfoTextVersion=6.0.2
|
||||
VersionInfoCompany=Assimp Development Team
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
|
||||
@@ -43,7 +43,7 @@ Source: "vc_redist.x64.exe"; DestDir: "{app}\stub\"; Check: IsWin64
|
||||
; Common stuff
|
||||
Source: "..\..\CREDITS"; DestDir: "{app}"
|
||||
Source: "..\..\LICENSE"; DestDir: "{app}"
|
||||
Source: "..\..\README"; DestDir: "{app}"
|
||||
Source: "..\..\README.md"; DestDir: "{app}"
|
||||
Source: "WEB"; DestDir: "{app}"
|
||||
|
||||
Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs
|
||||
|
||||
@@ -36,13 +36,21 @@ aiProcess_JoinIdenticalVertices = 0x2
|
||||
#
|
||||
aiProcess_MakeLeftHanded = 0x4
|
||||
|
||||
## <hr>Triangulates all faces of all meshes.
|
||||
## <hr>Triangulates all faces of all meshes.
|
||||
#
|
||||
# By default the imported mesh data might contain faces with more than 3
|
||||
# indices. For rendering you'll usually want all faces to be triangles.
|
||||
# This post processing stepaiProcess_ForceGenNormals
|
||||
## <hr>Removes some parts of the data structure (animations, materials,
|
||||
# light sources, cameras, textures, vertex components).
|
||||
# indices. For rendering you'll usually want all faces to be triangles.
|
||||
# This post processing step splits up faces with more than 3 indices into
|
||||
# triangles. Line and point primitives are *not* modified! If you want
|
||||
# 'triangles only' with no other kinds of primitives, try the following
|
||||
# solution:
|
||||
# - Specify both #aiProcess_Triangulate and #aiProcess_SortByPType
|
||||
# - Ignore all point and line meshes when you process assimp's output
|
||||
#
|
||||
aiProcess_Triangulate = 0x8
|
||||
|
||||
# <hr>Removes some parts of the data structure (animations, materials,
|
||||
# light sources, cameras, textures, vertex components).
|
||||
#
|
||||
# The components to be removed are specified in a separate
|
||||
# configuration option, <tt>#AI_CONFIG_PP_RVC_FLAGS<tt>. This is quite useful
|
||||
|
||||
@@ -314,7 +314,7 @@ public final class AiMesh {
|
||||
* @return true if tangents and bitangents are available
|
||||
*/
|
||||
public boolean hasTangentsAndBitangents() {
|
||||
return m_tangents != null && m_tangents != null;
|
||||
return m_tangents != null && m_bitangents != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+8
-2
@@ -59,6 +59,10 @@ endif()
|
||||
# Assimp library can be found, even if it is not installed system-wide yet.
|
||||
LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib )
|
||||
|
||||
SET(TOOLS
|
||||
unit/Tools/TestTools.h
|
||||
)
|
||||
|
||||
SET( COMMON
|
||||
unit/utSimd.cpp
|
||||
unit/utIOSystem.cpp
|
||||
@@ -219,6 +223,7 @@ SOURCE_GROUP( UnitTests\\GeometryTools FILES ${Geometry} )
|
||||
SOURCE_GROUP( UnitTests\\ImportExport FILES ${IMPORTERS} )
|
||||
SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} )
|
||||
SOURCE_GROUP( UnitTests\\Math FILES ${MATH} )
|
||||
SOURCE_GROUP( UnitTests\\Tools FILES ${TOOLS} )
|
||||
SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES})
|
||||
|
||||
add_executable( unit
|
||||
@@ -227,11 +232,12 @@ add_executable( unit
|
||||
../code/Common/Version.cpp
|
||||
../code/Common/Base64.cpp
|
||||
${COMMON}
|
||||
${Geometry}
|
||||
${Geometry}
|
||||
${IMPORTERS}
|
||||
${MATERIAL}
|
||||
${MATH}
|
||||
${POST_PROCESSES}
|
||||
${POST_PROCESSES}
|
||||
${TOOLS}
|
||||
)
|
||||
|
||||
if(ASSIMP_HUNTER_ENABLED)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
AC3Db
|
||||
MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0
|
||||
OBJECT world
|
||||
kids 1
|
||||
OBJECT poly
|
||||
name "rect"
|
||||
loc 1 0.5 0
|
||||
numvert 4
|
||||
-1 0.5 0
|
||||
1 0.5 0
|
||||
1 -0.5 0
|
||||
-1 -0.5 0
|
||||
numsurf 1
|
||||
SURF 0x20
|
||||
mat 0
|
||||
refs 4
|
||||
3 0 0
|
||||
2 1 0
|
||||
1 1 1
|
||||
0 0 1
|
||||
kids 0
|
||||
@@ -60,7 +60,7 @@ TEST_F(utParsingUtils, parseFloatsStringTest) {
|
||||
for (float i : floatArray) {
|
||||
float value = 0.0f;
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
content = fast_atoreal_move<ai_real>(content, value);
|
||||
content = fast_atoreal_move(content, value);
|
||||
EXPECT_FLOAT_EQ(value, i);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user