Compare commits

..
Author SHA1 Message Date
Kim Kulling 30b20e07e7 Fix possible overflow 2025-09-23 21:28:54 +02:00
Kim Kulling fa18d3dde6 Fix possible overflow 2025-09-23 21:24:58 +02:00
Paul BauriegelandKim Kulling 709fe3c3d0 Add BOM skip and fix mtl parsing (#6253)
* Add BOM skip and fix mtl parsing
* Remove old code
* Fix #5635
* Add all attributes to ObjFileData
---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-09-22 11:20:24 +02:00
Matt PennyandKim Kulling 489c8d565b Restore merging of near-identical vertices for JoinIdenticalVertices (#6278)
* Restore merging of near-identical vertices for JoinIdenticalVertices

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-09-21 10:57:17 +02:00
Luca Della Vedova 0581ed5f11 Added tangent handedness to glTF export (#6322)
* Added tangent handedness to glTF export
2025-09-18 14:10:41 +02:00
fifth_lightandKim Kulling 5c568616ec Fix hasTangentsAndBitangents method in AiMesh.java (#6345)
original code m_tangents != null && m_tangents != null; triggers error prone

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-09-18 10:09:43 +02:00
AbdulRehman 45cb880835 Fixed Build.md (#6354)
* Fixed itch.io spelling from itchi.io
2025-09-18 09:34:55 +02:00
dd98d4aea3 PyAssimp: Re-add 'aiProcess_Triangulate' (#6335)
apparently, b9bfac0418 accidentally
removed a couple of lines with a botched copy'n'paste.

Co-authored-by: IOhannes m zmölnig <zmoelnig@umlautT.umlaeute.mur.at>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-09-17 10:23:37 +02:00
AbdulRehman 01ac320de8 Better README! Fixed discord link as well (#6351)
* Better README!
2025-09-17 08:16:38 +02:00
AbdulRehman a815a78433 Updated doc/Preamble.txt & SECURITY.md (#6338)
* Update LICENSE

* Update Preamble.txt

* Update SECURITY.md

* Remove GitHub's default comment
2025-09-10 13:59:00 +02:00
69f8eb21fd fix large glb reading by providing a proper helper for reading size_t type (#6307)
Co-authored-by: Vitaly Ovchinnikov <v@ovch.ru>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-09-09 14:27:17 +02:00
Kim Kulling 72b9939b9f Add null check for aiNode in AddNode method (#6348)
- Added null check for node in AddNode function.
- closes https://github.com/assimp/assimp/issues/6347
2025-09-09 14:10:07 +02:00
Steven FrenchandKim Kulling 4c8a3bd39c [CMake] -l (#6329)
- Fix zlib linkage.

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-09-04 09:32:37 +02:00
Kim Kulling 8ef3838beb FBX: Fix offset calculation by adding cursor check (#6337)
- closes https://github.com/assimp/assimp/issues/6336
2025-08-28 11:48:38 +02:00
AbdulRehman 441884387f Update LICENSE (#6327) 2025-08-27 20:16:18 +02:00
Pranav PandKim Kulling f7bbf6dc15 Fix endiannes issues regarding floats on s390x (#6276) (#6277)
* Fix endiannes issues regarding floats on s390x (#6276)

* Fix CI Warnings

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-08-26 15:34:33 +02:00
Kyungjoon KoandKim Kulling aadd49311a Fix OOB read in OpenDDLParser::parsePrimitiveDataType (#6315)
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-08-25 15:03:00 +02:00
dependabot[bot]andKim Kulling 3f107bebf2 Bump actions/download-artifact from 4 to 5 (#6319)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-08-22 20:26:58 +02:00
Sergei TrofimovichandKim Kulling a38ec50fd3 test/unit/utProfiler.cpp: fix gcc-16 build failure (#6267)
* test/unit/utProfiler.cpp: fix `gcc-16` build failure

Upcoming `gcc-16` improved detection of unused variables as:

    test/unit/utProfiler.cpp: In member function 'virtual void utProfiler_addRegion_success_Test::TestBody()':
    test/unit/utProfiler.cpp:71:22: error: variable 'j' set but not used [-Werror=unused-but-set-variable=]
       71 |         volatile int j=0;
          |                      ^

The change is intentional accoring to Andrew Pinsi and is not a faalse positive.

* Update utProfiler.cpp: Remove dead code

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-08-21 10:15:01 +02:00
Dongge LiuandKim Kulling 4c42db1805 Fixed a heap-use-after-free in SortByPTypeProcess. (#6326)
The process incorrectly deleted original meshes from the scene when cleaning up after an error if those meshes had been added to its output list (outMeshes). The fix ensures proper ownership transfer by nullifying the original mesh pointer in the scene (pScene->mMeshes[i] = nullptr;) when the mesh is moved to outMeshes. This prevents the scene destructor from attempting to delete the mesh again later, while allowing the error cleanup path in SortByPTypeProcess to correctly delete all meshes it owns (both newly created and transferred originals).

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-08-21 09:31:15 +02:00
dependabot[bot] 26e2372882 Bump actions/checkout from 4 to 5 (#6328)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-20 12:50:30 +02:00
Dongge LiuandKim Kulling 36b004e286 Fixed a heap-buffer-overflow in the Half-Life 1 MDL loader. (#6321)
The loader attempted to read the MDL header without verifying if the input buffer was large enough.
Added a check in MDLImporter::InternReadFile_HL1 to ensure the buffer size is sufficient before proceeding with loading.

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-08-18 09:29:45 +03:00
Kyungjoon KoandKim Kulling 3a0ee8792f Fix OOB read (2) in OpenDDLParser::parsePrimitiveDataType (#6316)
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-08-14 13:51:07 +03:00
Kyungjoon KoandKim Kulling e3f9cf5564 Fix OOB read in OpenDDLParser::parseReference (#6317)
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-08-10 14:48:27 +03:00
Kyungjoon Ko 6d7ea78792 Fix SEGV write in Assimp::SortByPTypeProcess::Execute (#6318)
* Fix OOB Write in Assimp::SortByPTypeProcess::Execute
2025-08-10 11:45:30 +03:00
Dongge Liu 13316790aa Fixed a container-overflow error (#6298)
* Fixed a container-overflow error in `ODDLParser::OpenDDLParser::parseIntegerLiteral` by swapping the order of conditions in a while loop to ensure the end-of-buffer check happens before dereferencing the pointer. This prevents reading past the end of the buffer when lookForNextToken returns the end pointer.

https://oss-fuzz.com/testcase-detail/4980126616780800
https://issues.oss-fuzz.com/issues/42527625

* Update OpenDDLParser.cpp
2025-08-02 21:25:40 +02:00
Kim KullingandKim Kulling 9255412906 Add CMakePreset file (#6295)
Co-authored-by: Kim Kulling <kim.kulling@draeger.com>
2025-07-30 13:53:21 +02:00
sSsA01andKim Kulling 8355e0c4bc Fix to fail in the function fast_atoreal_move when the flag ASSIMP_DOUBLE_PRESICION is enabled (#6250)
* Refix export fbx PolygonVertexIndex

* Fix the function ColladaParser::ReadEffectColor when the flag ASSIMP_DOUBLE_PRESICION is enabled

* Fix the static function ReadLight in ColladaParser when the flag ASSIMP_DOUBLE_PRESICION is enabled

* Refactor of the call of the function fast_atoreal_move to the member of aiColor3D

* Fix the call of the function fast_atoreal_move when the flag ASSIMP_DOUBLE_PRESICION is enabled and and refactor

* Fix the call of the function fast_atoreal_move when the flag ASSIMP_DOUBLE_PRESICION is enabled

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-07-29 14:19:50 +02:00
DIGITAL IMAGE DESIGNandKim Kulling 6fa9d09a97 AC: Support Double-Sided Faces (#6252)
* AC: Support Double-Sided Faces

The AC format marks double-sided SURF elements with the 0x20 flag, which Assimp ignored. This commit adds support for double-sided faces.

On encountering a double-sided face via the flag mentioned above, the front face is generated as usual but is then duplicated. The winding order of the duplicate is flipped to form a back face. Vertices are duplicated too so that back faces work correctly with normal vector generation and face smoothing.

* Add test file

* Simplify test case

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-07-29 13:09:30 +02:00
Kim KullingandKim Kulling 9f4e7c6d8d Refactoring: use using types (#6266)
* Refactoring: use using types

---------

Co-authored-by: Kim Kulling <kim.kulling@draeger.com>
2025-07-28 17:00:45 +02:00
Kim Kulling 59bc03d931 X3D: Fix invalid vector::back usage (#6283)
* X3D: Fix invalid vector::back usage
2025-07-25 15:01:16 +02:00
Panthuncia edcb350129 Update Build.md (#6273)
Update build instructions to include information about USD importer special-case to ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT, and about ASSIMP_BUILD_USD_IMPORTER.
2025-07-22 21:08:33 +02:00
a79dc358cf Add windows clang to CI (#5537)
- Add windows clang build step
- Closes https://github.com/assimp/assimp/issues/5519


Co-authored-by: Kim Kulling <kim.kulling@draeger.com>
Co-authored-by: Kim Kulling <kullingk@LDED5178.corp.draeger.global>
2025-07-16 16:43:20 +02:00
Kim Kulling db0bde758e Update Readme.md (#6245) 2025-07-02 14:35:32 +02:00
Kim Kulling b447485c06 Fix sonarcube findings (#6242)
* Fix sonarcube findings

* Fix review findings
2025-06-28 18:56:28 +02:00
sSsA01andKim Kulling 4c61ca3af5 Refix export fbx PolygonVertexIndex (#6240)
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-27 11:30:04 +02:00
HandsomeXiandKim Kulling 4b6cc8c28a bugfix: Fixed the memory leak when texture transforming (#6236) (#6237)
* bugfix: Fixed the memory leak when texture transforming (#6236)

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-26 10:53:08 +02:00
Kim Kulling d99f9bd2f7 Refactoring: Add nupptr-checks (#6241) 2025-06-26 00:09:02 +02:00
Kim Kulling b2afe717d3 Update Importer.hpp (#6235)
- Add doc for out-of-memory exception
- closes https://github.com/assimp/assimp/issues/5173
2025-06-21 13:33:15 +02:00
NSGandKim Kulling ad6e8e210a Fix: export fbx wrong to_ktime in FBXExporter.cpp (#6105)
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-17 08:23:21 +02:00
101 changed files with 950 additions and 526 deletions
+9 -5
View File
@@ -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
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
os: ubuntu-latest
steps:
- uses: actions/checkout@v4.2.2
- uses: actions/checkout@v5
- uses: lukka/get-cmake@latest
+3 -3
View File
@@ -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
+4 -3
View File
@@ -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)
+15 -5
View File
@@ -309,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)
@@ -354,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.")
@@ -581,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()
+17
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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,
+5 -5
View File
@@ -20,17 +20,17 @@ Additionally, assimp features various __mesh post-processing tools__: normals an
![Alt](https://repobeats.axiom.co/api/embed/997f84e5f9fcf772da1e687f3a4f3a8afdbf4cf0.svg "Repobeats analytics image")
### 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
+1 -2
View File
@@ -2,8 +2,7 @@
## 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 |
| ------- | ------------------ |
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
+8 -6
View File
@@ -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
+7 -1
View File
@@ -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]];
}
};
+41 -8
View File
@@ -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;
+1 -1
View File
@@ -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);
-2
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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) {
+1 -1
View File
@@ -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, "\".");
+3 -3
View File
@@ -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);
+8 -8
View File
@@ -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) {
+5 -4
View File
@@ -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
+4 -4
View File
@@ -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)) {
@@ -226,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;
}
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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;
+11 -11
View File
@@ -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());
@@ -889,7 +889,7 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
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);
+3 -1
View File
@@ -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;
}
+29 -30
View File
@@ -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
+2 -2
View File
@@ -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;
+17 -4
View File
@@ -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++) {
@@ -2058,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
+60 -16
View File
@@ -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);
}
}
+3 -3
View File
@@ -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));
+2 -2
View File
@@ -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);
// -------------------------------------------------------------------
+17 -17
View File
@@ -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);
+3 -3
View File
@@ -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);
}
}
}
+1 -1
View File
@@ -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));
+12 -12
View File
@@ -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;
}
+8 -8
View File
@@ -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);
@@ -377,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);
@@ -415,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);
}
}
@@ -486,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);
}
}
@@ -503,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");
+8 -2
View File
@@ -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,
+1 -1
View File
@@ -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) \
+11 -11
View File
@@ -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);
}
}
+5 -3
View File
@@ -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) {
+27 -23
View File
@@ -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);
}
+114 -8
View File
@@ -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() {
+2
View File
@@ -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.
+7
View File
@@ -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) {
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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");
+1 -1
View File
@@ -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;
};
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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);
}
}
+7 -7
View File
@@ -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)) {
+3 -3
View File
@@ -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);
}
}
}
+1 -1
View File
@@ -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) {
+1 -1
View File
@@ -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();
+10 -4
View File
@@ -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.
+1 -1
View File
@@ -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");
+1 -1
View File
@@ -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();
+16 -3
View File
@@ -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);
+15
View File
@@ -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);
-6
View File
@@ -1318,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 "")
@@ -1415,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
+13 -14
View File
@@ -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;
}
+3 -3
View File
@@ -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];
+15 -10
View File
@@ -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
+1 -1
View File
@@ -159,7 +159,7 @@ aiReturn GetMaterialFloatArray(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<TReal>(cur, pOut[a]);
cur = fast_atoreal_move(cur, pOut[a]);
if (a == iWrite - 1) {
break;
}
+60 -1
View File
@@ -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;
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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;
// -------------------------------------------------------------------
+6 -2
View File
@@ -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);
+12 -22
View File
@@ -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
+50 -74
View File
@@ -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:
+12 -6
View File
@@ -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;
+9
View File
@@ -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
+9
View File
@@ -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__)
+9
View File
@@ -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 */
-1
View File
@@ -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 */
-1
View File
@@ -23,7 +23,6 @@ z_const char * const z_errmsg[10] = {
(z_const char *)""
};
const char * ZEXPORT zlibVersion()
{
return ZLIB_VERSION;
+1 -1
View File
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2025, assimp team
All rights reserved.
+6
View File
@@ -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().
+6 -6
View File
@@ -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.
-23
View File
@@ -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 {
+12
View File
@@ -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
View File
@@ -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
+5 -5
View File
@@ -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
+13 -5
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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)
+21
View File
@@ -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
+5 -16
View File
@@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2025, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,20 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace ::Assimp;
class TestDefaultIOStream : public DefaultIOStream {
class TestDefaultIOStream final : public DefaultIOStream {
public:
TestDefaultIOStream()
: DefaultIOStream() {
// empty
}
TestDefaultIOStream( FILE* pFile, const std::string &strFilename )
: DefaultIOStream( pFile, strFilename ) {
// empty
}
virtual ~TestDefaultIOStream() {
// empty
}
TestDefaultIOStream() = default;
TestDefaultIOStream(FILE* pFile, const std::string &strFilename) : DefaultIOStream(pFile, strFilename) {}
~TestDefaultIOStream() override = default;
};
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include <gtest/gtest.h>
#include <cstdio>
#include <string>
namespace Assimp::Unittest {
class TestTools final {
public:
TestTools() = default;
~TestTools() = default;
static bool openFilestream(FILE **pFile, const char *filename, const char *mode);
};
inline bool TestTools::openFilestream(FILE **fs, const char *filename, const char *mode) {
#if defined(_WIN32)
errno_t err{ 0 };
err = fopen_s(fs, filename, mode);
EXPECT_EQ(err, 0);
#else
*fs = fopen(filename, mode);
#endif
return fs != nullptr;
}
} // namespace Assimp::Unittest
+31 -13
View File
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2024, assimp team
All rights reserved.
@@ -39,42 +39,60 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#pragma once
#ifdef _WIN32
# ifndef _CRT_NONSTDC_NO_DEPRECATE
# define _CRT_NONSTDC_NO_DEPRECATE
# endif // _CRT_NONSTDC_NO_DEPRECATE
# ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
# endif
#endif
#include <cstdio>
#include <cstdlib>
#include <gtest/gtest.h>
#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__)
#define TMP_PATH "./"
# define TMP_PATH "./"
#elif defined(__GNUC__) || defined(__clang__)
#define TMP_PATH "/tmp/"
# define TMP_PATH "/var/tmp/"
#endif
#if defined(_MSC_VER)
#include <io.h>
inline FILE* MakeTmpFile(char* tmplate)
{
auto pathtemplate = _mktemp(tmplate);
inline FILE* MakeTmpFile(char* tmplate, size_t len, std::string &tmpName) {
size_t tmpLen = len + 1;
char *pathtemplate = new char[tmpLen];
strcpy_s(pathtemplate, tmpLen, tmplate);
int err_code = _mktemp_s(pathtemplate, tmpLen);
EXPECT_EQ(err_code, 0);
EXPECT_NE(pathtemplate, nullptr);
if(pathtemplate == nullptr)
{
if(pathtemplate == nullptr) {
delete[] pathtemplate;
return nullptr;
}
auto* fs = std::fopen(pathtemplate, "w+");
errno_t err;
FILE *fs{nullptr};
err = fopen_s(&fs, pathtemplate, "w+");
EXPECT_EQ(0, err);
tmpName = pathtemplate;
EXPECT_NE(fs, nullptr);
delete[] pathtemplate;
return fs;
}
#elif defined(__GNUC__) || defined(__clang__)
inline FILE* MakeTmpFile(char* tmplate)
{
inline FILE *MakeTmpFile(char *tmplate, size_t len, std::string &tmpName) {
auto fd = mkstemp(tmplate);
EXPECT_NE(-1, fd);
if(fd == -1)
{
if(fd == -1) {
return nullptr;
}
auto fs = fdopen(fd, "w+");
EXPECT_NE(nullptr, fs);
tmpName += tmplate;
return fs;
}
#endif
+11
View File
@@ -141,3 +141,14 @@ TEST(utACImportExport, testFormatDetection) {
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/AC/TestFormatDetection", aiProcess_ValidateDataStructure);
ASSERT_NE(nullptr, scene);
}
TEST(utACImportExport, importDobuleSidedFaces) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/AC/doubleSidedFace.ac", aiProcess_ValidateDataStructure);
ASSERT_NE(nullptr, scene);
// The scene contains one double-sided, rectangular AC surface. It should resolve to two quads (front + back) with eight
// vertices (one per side to guarantee proper normal vectors).
ASSERT_EQ(scene->mNumMeshes, 1u);
ASSERT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
ASSERT_EQ(scene->mMeshes[0]->mNumVertices, 8u);
}
-2
View File
@@ -5,8 +5,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,
-2
View File
@@ -5,8 +5,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,
+7 -5
View File
@@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <gtest/gtest.h>
#include "TestIOStream.h"
#include "UnitTestFileGenerator.h"
#include "Tools/TestTools.h"
#include <cstdio>
#include <cstdlib>
#include <string>
@@ -60,8 +61,9 @@ TEST_F( utDefaultIOStream, FileSizeTest ) {
const auto dataSize = sizeof(data);
const auto dataCount = dataSize / sizeof(*data);
char fpath[] = { TMP_PATH"rndfp.XXXXXX" };
auto* fs = MakeTmpFile(fpath);
char fpath[] = { TMP_PATH"rndfp.XXXXXX\0" };
std::string tmpName;
auto *fs = MakeTmpFile(fpath, std::strlen(fpath), tmpName);
ASSERT_NE(nullptr, fs);
{
auto written = std::fwrite(data, sizeof(*data), dataCount, fs );
@@ -71,13 +73,13 @@ TEST_F( utDefaultIOStream, FileSizeTest ) {
ASSERT_EQ(vflush, 0);
std::fclose(fs);
fs = std::fopen(fpath, "r");
ASSERT_NE(nullptr, fs);
EXPECT_TRUE(Unittest::TestTools::openFilestream(&fs, tmpName.c_str(), "r"));
ASSERT_NE(nullptr, fs);
TestDefaultIOStream myStream( fs, fpath);
size_t size = myStream.FileSize();
EXPECT_EQ( size, dataSize);
}
remove(fpath);
remove(tmpName.c_str());
}
+23 -18
View File
@@ -5,8 +5,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,
@@ -44,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "UnitTestPCH.h"
#include <assimp/IOStreamBuffer.h>
#include "TestIOStream.h"
#include "Tools/TestTools.h"
#include "UnitTestFileGenerator.h"
class IOStreamBufferTest : public ::testing::Test {
@@ -86,18 +85,21 @@ TEST_F( IOStreamBufferTest, open_close_Test ) {
const auto dataCount = dataSize / sizeof(*data);
char fname[]={ "octest.XXXXXX" };
auto* fs = MakeTmpFile(fname);
std::string tmpName;
auto* fs = MakeTmpFile(fname, std::strlen(fname), tmpName);
ASSERT_NE(nullptr, fs);
auto written = std::fwrite( data, sizeof(*data), dataCount, fs );
auto written = std::fwrite(data, sizeof(*data), dataCount, fs);
EXPECT_NE( 0U, written );
auto flushResult = std::fflush( fs );
ASSERT_EQ(0, flushResult);
std::fclose( fs );
fs = std::fopen(fname, "r");
ASSERT_NE(nullptr, fs);
fclose(fs);
FILE *new_fs{ nullptr };
EXPECT_TRUE(Unittest::TestTools::openFilestream(&new_fs, tmpName.c_str(), "r"));
ASSERT_NE(nullptr, new_fs);
{
TestDefaultIOStream myStream( fs, fname );
TestDefaultIOStream myStream(new_fs, fname);
EXPECT_TRUE( myBuffer.open( &myStream ) );
EXPECT_FALSE( myBuffer.open( &myStream ) );
@@ -111,8 +113,9 @@ TEST_F( IOStreamBufferTest, readlineTest ) {
const auto dataSize = sizeof(data);
const auto dataCount = dataSize / sizeof(*data);
char fname[]={ "readlinetest.XXXXXX" };
auto* fs = MakeTmpFile(fname);
char fname[]={ "readlinetest.XXXXXX\0" };
std::string tmpName;
auto* fs = MakeTmpFile(fname, std::strlen(fname), tmpName);
ASSERT_NE(nullptr, fs);
auto written = std::fwrite( data, sizeof(*data), dataCount, fs );
@@ -121,23 +124,25 @@ TEST_F( IOStreamBufferTest, readlineTest ) {
auto flushResult = std::fflush(fs);
ASSERT_EQ(0, flushResult);
std::fclose(fs);
fs = std::fopen(fname, "r");
ASSERT_NE(nullptr, fs);
FILE *new_fs{ nullptr };
EXPECT_TRUE(Unittest::TestTools::openFilestream(&new_fs, tmpName.c_str(), "r"));
ASSERT_NE(nullptr, new_fs);
const auto tCacheSize = 26u;
IOStreamBuffer<char> myBuffer( tCacheSize );
EXPECT_EQ(tCacheSize, myBuffer.cacheSize() );
IOStreamBuffer<char> myBuffer(tCacheSize);
EXPECT_EQ(tCacheSize, myBuffer.cacheSize());
TestDefaultIOStream myStream( fs, fname );
TestDefaultIOStream myStream(new_fs, fname);
auto size = myStream.FileSize();
auto numBlocks = size / myBuffer.cacheSize();
if ( size % myBuffer.cacheSize() > 0 ) {
numBlocks++;
}
EXPECT_TRUE( myBuffer.open( &myStream ) );
EXPECT_EQ( numBlocks, myBuffer.getNumBlocks() );
EXPECT_TRUE( myBuffer.close() );
EXPECT_TRUE(myBuffer.open(&myStream));
EXPECT_EQ(numBlocks, myBuffer.getNumBlocks() );
EXPECT_TRUE(myBuffer.close() );
}
TEST_F( IOStreamBufferTest, accessBlockIndexTest ) {
+2 -16
View File
@@ -5,8 +5,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,
@@ -50,18 +48,7 @@ using namespace ::Assimp::Profiling;
class utProfiler : public ::testing::Test {
public:
LogStream *m_stream;
/*virtual void SetUp() {
m_stream = new UTLogStream;
DefaultLogger::create();
DefaultLogger::get()->attachStream( m_stream );
}
virtual void TearDown() {
DefaultLogger::get()->detatchStream( m_stream );
m_stream = nullptr;
}*/
LogStream *mStream = nullptr;
};
TEST_F( utProfiler, addRegion_success ) {
@@ -70,8 +57,7 @@ TEST_F( utProfiler, addRegion_success ) {
for ( int i=0; i<10; i++ ) {
volatile int j=0;
j++;
(void)j; /* avoid gcc-16 warnings about unused variable */
}
myProfiler.EndRegion( "t1" );
//UTLogStream *stream( (UTLogStream*) m_stream );
//EXPECT_FALSE( stream->m_messages.empty() );
}
+1 -1
View File
@@ -50,7 +50,7 @@ class utSceneCombiner : public ::testing::Test {
};
TEST_F(utSceneCombiner, MergeMeshes_ValidNames_Test) {
std::vector<aiMesh *> merge_list;
MeshArray merge_list;
aiMesh *mesh1 = new aiMesh;
mesh1->mName.Set("mesh_1");
merge_list.push_back(mesh1);

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