Compare commits

..
Author SHA1 Message Date
Kim Kulling d403434c76 Add allocator impl 2026-03-02 16:42:45 +01:00
Kim Kulling 56414694b3 Adapt interface:wq 2025-12-18 11:12:14 +01:00
Kim Kulling 7610b184eb Add allocator prototypes 2025-12-15 23:48:34 +01:00
Paul Zander 4d197881ff Only build collada test when importer/exporter is build (#6411)
See-also: https://bugs.gentoo.org/962559

Signed-off-by: Paul Zander <negril.nx+gentoo@gmail.com>
2025-12-05 19:57:44 +01:00
Kim Kulling 10cd8982b0 Update copyright year in materialgen.py (#6410)
* Update copyright year in materialgen.py

* Update copyright year in structsgen.py
2025-12-04 14:24:42 +01:00
+18 ac0cfc8d9c Feature/pjoe fix fbx export (#6405)
* fix: texture paths issues with fbx export

* Update LICENSE (#6327)

* FBX: Fix offset calculation by adding cursor check (#6337)

- closes https://github.com/assimp/assimp/issues/6336

* [CMake] -l (#6329)

- Fix zlib linkage.

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>

* 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

* 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>

* Updated doc/Preamble.txt & SECURITY.md (#6338)

* Update LICENSE

* Update Preamble.txt

* Update SECURITY.md

* Remove GitHub's default comment

* Better README! Fixed discord link as well (#6351)

* Better README!

* 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>

* Fixed Build.md (#6354)

* Fixed itch.io spelling from itchi.io

* 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>

* Added tangent handedness to glTF export (#6322)

* Added tangent handedness to glTF export

* 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>

* 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>

* Clone meshlab/tinyusdz repos in default location (#6239)

* Leave FETCHCONTENT_BASE_DIR as default to avoid target platform generated build file conflicts

* Attempt address sonarCloud complaint about generic-looking include file (bare "Parser.h")

---------

Co-authored-by: tellypresence <info@tellypresence.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>

* Fix an invalid offsetof warning-as-error (#6359)

The code already disables the warning on clang. It's also caused on
GCC in some circumstances (particularly when building with
-D_GLIBCXX_DEBUG).

* Add unit test for subdivision modifier on Blender importer (#5345)

* Add unit test for subdivision modifier on Blender importer

Blend file is composed of default cube with subdivision modifier applied
and same cube with subdivision modifier.

* Update utBlenderImportExport.cpp

Fix compiler warning.

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>

* Change strcpy to strncpy for format hint safety (#6365)

* Update default material name handling (#6366)

* Replace strcpy by strncpy

* Bugfix/fix sonarcube findings (#6369)

* Fix sonarcube findings.
---------
Co-authored-by: Kim Kulling <kim.kulling@draeger.com>

* Update texture output format in AssxmlFileWriter (#6372)

* Update texture output format in AssxmlFileWriter

* Collada: Fix overflow in CopyVertex (#6374)

* Fix overflow in CopyVertex

* COB: fix validation for ascii header (#6376)

* COB: fix validation for ascii header

* MD5: Fix face index allocation in MD5Parser (#6380)

- Ensure face indices are properly allocated and resized.
- closes https://github.com/assimp/assimp/issues/6379

* Removed unnecessary copy constructor declaration in aiVector3t (#6384)

* Removed unnecessary copy constructor declaration in aiVector3t
* Added copy constructor back in aiVector3t
* Added explicit declaration of assignment operator in aiVector3t

* Bump actions/upload-artifact from 4 to 5 (#6383)

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-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>

* Bump actions/download-artifact from 5 to 6 (#6382)

Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  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>

* Made the README more tidy & fix Build.md (#6371)

* Update LICENSE

* Update Preamble.txt

* Update SECURITY.md

* Remove GitHub's default comment

* Better README!

* Fix discord link! Boom, that's how it's done

* Fixed itch.io spelling from itchi.io

* Make README more tidy :)

AR is back! Anyways, I'm working on my horror game & making devlogs so I don't have time to write. Here's a small summary:
- Just placed the dir structure information correctly in one place so the README looks tidy.

* Add international download link for Visual Studio

* Fix out-of-range access cause of aiProcess_GenNormals : array size inconsistency of members of mesh after process (#6332)

* Fix aiProcess_GenNormals process: copy members of mesh corresponding with additional vertices

* Fix aiProcess_GenNormals process: Refoctoring

* refactoring: fix SonarQube Issue

* Update GenFaceNormalsProcess.cpp: fix small findings

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>

* Fix Heap-buffer-overflow in Q3DImporter::InternReadFile (#6370)

Checks if multiplying texture width and height would overflow before
performing the operation. This avoids incorrect memory allocations and
potential crashes with very large textures.

Fixes #6358

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>

* Revert "Refactoring: use using types (#6266)" (#6324)

* Revert "Refactoring: use using types (#6266)"

* fix: write textures to folder of PBRT file (#6099)

* fix: write textures to folder of PBRT file

* Refactor condition checks for empty vectors (#6385)

* Refactor based on SonarCube.

* Fix sonarcube stuff (#6387)

* Fix sonarcube stuff

* Update contact email for reporting vulnerabilities (#6389)

* [PyAssimp] Create `pyproject.toml` (#6378)

* Create pyproject.toml

* glTF2: Avoid lookups for generating IDs (#6120)

* glTF2: Reduce lookups for generating IDs
- closes https://github.com/assimp/assimp/issues/5661

* Refactor string checks and variable declarations (#6392)

* Refactor string checks and variable declarations

* Change string check from contains to find

* Fix syntax error in mesh node creation loop

* Fix the doxygen documentation from public headers (#6394)

* Add documentation comments to DeboneProcess.h

* Added static cast for conversion from uLong to unsigned int for compiler error (#6393)

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>

* Reorganize code top prevent security warning. (#6395)

* Reorganize code to prevent security warning.

* Fix linkage (#6388)

* Fix linkage when all importers aren't part of the build.

* Update LineSplitter.h (#6396)

* Added missing scene extras properties for glTF2Importer (#6397)

* WiP. Passing USD prims along with render nodes to look for USD references. Save reference path to metaData['ref'] (#5807)

Signed-off-by: AMZN-Gene <genewalt@amazon.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>

* Bump actions/checkout from 5 to 6 (#6401)

Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [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/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  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>

* Update Readme.md (#6402)

* Update Readme.md

- Reorganize readme for code structure

* Update Readme.md

* Delete test/other/streamload.py (#6403)

* Update Readme.md

- Reorganize readme for code structure

* Update Readme.md

* Delete test/other/streamload.py

* Delete test/regression directory

* Update AndroidJNIIOSystem.cpp

* Update BundledAssetIOSystem.cpp

* Fixed DXFHelper using float instead of ai_real (#6404)

* Fixed DXFHelper using float instead of ai_real

* fixed cmake presets

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: AMZN-Gene <genewalt@amazon.com>
Co-authored-by: Pelle Johnsen <pelle.johnsen@gmail.com>
Co-authored-by: AbdulRehman <ardev1.deverson@proton.me>
Co-authored-by: Steven French <95558717+ZeunO8@users.noreply.github.com>
Co-authored-by: Vitaly Ovchinnikov <vitaly.ovchinnikov@gmail.com>
Co-authored-by: Vitaly Ovchinnikov <v@ovch.ru>
Co-authored-by: umläute <umlaeute@users.noreply.github.com>
Co-authored-by: IOhannes m zmölnig <zmoelnig@umlautT.umlaeute.mur.at>
Co-authored-by: fifth_light <liu-yu-jie@foxmail.com>
Co-authored-by: Luca Della Vedova <lucadv@intrinsic.ai>
Co-authored-by: Matt Penny <mwpenny@users.noreply.github.com>
Co-authored-by: Paul Bauriegel <paul.bauriegel@web.de>
Co-authored-by: Steve M <madsen.steve@yahoo.com>
Co-authored-by: tellypresence <info@tellypresence.com>
Co-authored-by: Sami Liedes <sami.liedes@iki.fi>
Co-authored-by: Alexandre Avenel <avenel.alexandre@gmail.com>
Co-authored-by: Kim Kulling <kim.kulling@draeger.com>
Co-authored-by: EddieBreeg <eddiebreeg0@protonmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: sSsA01 <59872472+Riv1s-sSsA01@users.noreply.github.com>
Co-authored-by: Jan Grulich <jgrulich@redhat.com>
Co-authored-by: Jan Honsbrok <jan.honsbrok@gmail.com>
Co-authored-by: thedestroyer4312 <trevortsai1@gmail.com>
Co-authored-by: Jerome St-Louis <jerome@ecere.com>
Co-authored-by: John Curley <johndanielcurley@gmail.com>
Co-authored-by: Orleonn <76880668+Orleonn@users.noreply.github.com>
Co-authored-by: Gene Walters <32776221+AMZN-Gene@users.noreply.github.com>
Co-authored-by: JakobPer <JakobPer@protonmail.com>
2025-12-01 14:17:45 +01:00
JakobPerandKim Kulling 11272f13bd Fixed DXFHelper using float instead of ai_real (#6404)
* Fixed DXFHelper using float instead of ai_real

* fixed cmake presets

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-11-30 22:01:11 +01:00
Kim Kulling f588492ab5 Delete test/other/streamload.py (#6403)
* Update Readme.md

- Reorganize readme for code structure

* Update Readme.md

* Delete test/other/streamload.py

* Delete test/regression directory

* Update AndroidJNIIOSystem.cpp

* Update BundledAssetIOSystem.cpp
2025-11-28 22:18:00 +01:00
Kim Kulling f635984770 Update Readme.md (#6402)
* Update Readme.md

- Reorganize readme for code structure

* Update Readme.md
2025-11-26 22:17:21 +01:00
dependabot[bot]andKim Kulling 0b30e3b343 Bump actions/checkout from 5 to 6 (#6401)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [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/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  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-11-24 23:42:57 +01:00
Gene WaltersandKim Kulling a989b30b58 WiP. Passing USD prims along with render nodes to look for USD references. Save reference path to metaData['ref'] (#5807)
Signed-off-by: AMZN-Gene <genewalt@amazon.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-11-24 21:26:46 +01:00
Orleonn ab28db52f0 Added missing scene extras properties for glTF2Importer (#6397) 2025-11-18 15:58:41 +01:00
Kim Kulling c4812fcc47 Update LineSplitter.h (#6396) 2025-11-17 08:56:49 +01:00
Kim Kulling 19108dff6a Fix linkage (#6388)
* Fix linkage when all importers aren't part of the build.
2025-11-16 20:05:50 +01:00
Kim Kulling 05a4fb57f1 Reorganize code top prevent security warning. (#6395)
* Reorganize code to prevent security warning.
2025-11-15 12:16:56 +01:00
John CurleyandKim Kulling a53807a02a Added static cast for conversion from uLong to unsigned int for compiler error (#6393)
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-11-15 08:53:24 +01:00
Kim Kulling 1cc7f2ba74 Fix the doxygen documentation from public headers (#6394)
* Add documentation comments to DeboneProcess.h
2025-11-14 22:05:08 +01:00
Kim Kulling e98ec7b2d3 Refactor string checks and variable declarations (#6392)
* Refactor string checks and variable declarations

* Change string check from contains to find

* Fix syntax error in mesh node creation loop
2025-11-14 00:18:35 +01:00
Jerome St-Louis 0be7cdd6db glTF2: Avoid lookups for generating IDs (#6120)
* glTF2: Reduce lookups for generating IDs
- closes https://github.com/assimp/assimp/issues/5661
2025-11-13 10:50:26 +01:00
thedestroyer4312 c6f997b584 [PyAssimp] Create pyproject.toml (#6378)
* Create pyproject.toml
2025-11-11 09:31:51 +01:00
Kim Kulling 3e2e3c9b12 Update contact email for reporting vulnerabilities (#6389) 2025-11-11 08:52:23 +01:00
Kim Kulling 34cda45471 Fix sonarcube stuff (#6387)
* Fix sonarcube stuff
2025-11-10 23:29:03 +01:00
Kim Kulling a4b8943533 Refactor condition checks for empty vectors (#6385)
* Refactor based on SonarCube.
2025-11-07 16:07:39 +01:00
Jan Honsbrok 0996221017 fix: write textures to folder of PBRT file (#6099)
* fix: write textures to folder of PBRT file
2025-11-05 08:24:41 +01:00
Luca Della Vedova 672594c230 Revert "Refactoring: use using types (#6266)" (#6324)
* Revert "Refactoring: use using types (#6266)"
2025-11-04 15:10:45 +01:00
Jan GrulichandKim Kulling 0978918f71 Fix Heap-buffer-overflow in Q3DImporter::InternReadFile (#6370)
Checks if multiplying texture width and height would overflow before
performing the operation. This avoids incorrect memory allocations and
potential crashes with very large textures.

Fixes #6358

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-11-04 10:09:13 +01:00
sSsA01andKim Kulling 8e35cb1a9f Fix out-of-range access cause of aiProcess_GenNormals : array size inconsistency of members of mesh after process (#6332)
* Fix aiProcess_GenNormals process: copy members of mesh corresponding with additional vertices

* Fix aiProcess_GenNormals process: Refoctoring

* refactoring: fix SonarQube Issue

* Update GenFaceNormalsProcess.cpp: fix small findings

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-11-01 21:15:17 +01:00
AR ea249be466 Made the README more tidy & fix Build.md (#6371)
* Update LICENSE

* Update Preamble.txt

* Update SECURITY.md

* Remove GitHub's default comment

* Better README!

* Fix discord link! Boom, that's how it's done

* Fixed itch.io spelling from itchi.io

* Make README more tidy :)

AR is back! Anyways, I'm working on my horror game & making devlogs so I don't have time to write. Here's a small summary:
- Just placed the dir structure information correctly in one place so the README looks tidy.

* Add international download link for Visual Studio
2025-10-31 17:12:12 +01:00
dependabot[bot] 276d3e998f Bump actions/download-artifact from 5 to 6 (#6382)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  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-10-30 11:06:22 +01:00
dependabot[bot]andKim Kulling b2d5fa201a Bump actions/upload-artifact from 4 to 5 (#6383)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-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-10-29 20:34:33 +01:00
EddieBreeg 95f09deaae Removed unnecessary copy constructor declaration in aiVector3t (#6384)
* Removed unnecessary copy constructor declaration in aiVector3t
* Added copy constructor back in aiVector3t
* Added explicit declaration of assignment operator in aiVector3t
2025-10-29 10:58:34 +01:00
Kim Kulling e778c84cd6 MD5: Fix face index allocation in MD5Parser (#6380)
- Ensure face indices are properly allocated and resized.
- closes https://github.com/assimp/assimp/issues/6379
2025-10-24 10:15:01 +02:00
Kim Kulling 5f7c06a71e COB: fix validation for ascii header (#6376)
* COB: fix validation for ascii header
2025-10-23 22:44:54 +02:00
Kim Kulling 7dcf6a8984 Collada: Fix overflow in CopyVertex (#6374)
* Fix overflow in CopyVertex
2025-10-19 23:13:59 +02:00
Kim Kulling cc6ab1408f Update texture output format in AssxmlFileWriter (#6372)
* Update texture output format in AssxmlFileWriter
2025-10-17 11:24:38 +02:00
Kim KullingandKim Kulling f544f9c217 Bugfix/fix sonarcube findings (#6369)
* Fix sonarcube findings.
---------
Co-authored-by: Kim Kulling <kim.kulling@draeger.com>
2025-10-14 00:01:50 +02:00
Kim Kulling 194da5b2fd Update default material name handling (#6366)
* Replace strcpy by strncpy
2025-10-07 20:25:24 +02:00
Kim Kulling f28a96121d Change strcpy to strncpy for format hint safety (#6365) 2025-10-02 16:31:00 +02:00
Alexandre AvenelandKim Kulling 6401aa9744 Add unit test for subdivision modifier on Blender importer (#5345)
* Add unit test for subdivision modifier on Blender importer

Blend file is composed of default cube with subdivision modifier applied
and same cube with subdivision modifier.

* Update utBlenderImportExport.cpp

Fix compiler warning.

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-09-29 21:22:56 +02:00
Sami Liedes 1894bfb22c Fix an invalid offsetof warning-as-error (#6359)
The code already disables the warning on clang. It's also caused on
GCC in some circumstances (particularly when building with
-D_GLIBCXX_DEBUG).
2025-09-28 20:30:59 +02:00
b8133b04c7 Clone meshlab/tinyusdz repos in default location (#6239)
* Leave FETCHCONTENT_BASE_DIR as default to avoid target platform generated build file conflicts

* Attempt address sonarCloud complaint about generic-looking include file (bare "Parser.h")

---------

Co-authored-by: tellypresence <info@tellypresence.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-09-23 11:34:13 +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
Kim Kulling fb375dd8c0 Prepare 6.0.2 (#6231) 2025-06-08 21:50:39 +02:00
sSsA01andKim Kulling a95addfc4a Fix the function "aiGetMaterialColor" when the flag ASSIMP_DOUBLE_PRECISION is enabled. (#6090)
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-08 14:25:47 +02:00
Kim Kulling 2d8c09b60f Update SECURITY.md (#6230)
* Update SECURITY.md

* Update SECURITY.md
2025-06-08 14:14:24 +02:00
357b5baabb fix-CVE-2025-3158: closes #6023 Fixes CVE-2025-3158: Heap-based Buffer Overflow in Assimp::LWO::AnimResolver::UpdateAnimRangeSetup (#6222)
- changed loop-condition to reflect the fact that m must be smaller than n

Co-authored-by: Vinz Spring <vinzs@amazon.de>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-08 14:02:04 +02:00
269987085f Fixes CVE-2025-2750: out of bounds write by assigning to wrong array element count tracking (closes #6011) (#6225)
description:
- The current implementation has faulty reallocation logic when parsing a CSM file
- Issue 1
    - https://github.com/assimp/assimp/blob/4ad1d2aa3086517816716a50aa122342806736f9/code/AssetLib/CSM/CSMLoader.cpp#L205
    - By assigning s->mNumPositionKeys = alloc*2 right before resizing the buffer, making s->mNumPositionKeys equivalent to the
      max number of aiVectorKey that can be stored in s->mPositionKeys
    - the code later attempts to get the next write location by doing: aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
    - this points to the end of the array, not after the last element in the array
- Issue 2
    - https://github.com/assimp/assimp/blob/4ad1d2aa3086517816716a50aa122342806736f9/code/AssetLib/CSM/CSMLoader.cpp#L178-L184
    - if the CSM file does not declare last frame data, then mPositionKeys will never be initialized

fix:
- we preserve s->mNumPositionKeys to still contain the actual number of aiVectorKeys and ensure that we will not write out of bounds
- we initialize mPositionKeys with a default value and if we find last frame info, we just re-initialize it

Co-authored-by: Vinz Spring <vinzs@amazon.de>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-08 13:46:39 +02:00
5be336779d Fixes CVE-2025-2757: Heap-based Buffer Overflow in AI_MD5_PARSE_STRING_IN_QUOTATION (closes #6019) (#6223)
description:
- heap buffer overflow in AI_MD5_PARSE_STRING_IN_QUOTATION. An attacker could potentially exploit the vulnerability to cause a remote code execution,
  if they can trick the victim into running assimp on a malformed MD5 file

fix:
- truncated the string to the maximum supported length, mitigating overflow

Co-authored-by: Vinz Spring <vinzs@amazon.de>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-08 13:38:05 +02:00
177797c77b Fixes CVE-2025-2751: Out-of-bounds Read in Assimp::CSMImporter::InternReadFile (closes #6012) (#6224)
description:
issue:
- https://github.com/assimp/assimp/blob/4ad1d2aa3086517816716a50aa122342806736f9/code/AssetLib/CSM/CSMLoader.cpp#L274C1-L275C1
- sometimes the code tried to construct a new 4x4 matrix from a nullptr, thus reading out of bounds

fix:
- added nullptr check
- added array count check
- added default fallback init to identity matrix

Co-authored-by: Vinz Spring <vinzs@amazon.de>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-08 12:10:12 +02:00
c1d6226c06 Update/update pugi xml (#6229)
* update pugixml

Improvements:

Many xml_attribute:: and xml_node:: functions now transparently support std::string_view and std::string when C++17 support is detected.
CMake improvements:

Improve pkg-config file generation for NixOS
PUGIXML_BUILD_APPLE_FRAMEWORK CMake option can be used to build pugixml as .xcframework
PUGIXML_INSTALL CMake option can be used to disable installation targets
Compatibility improvements:

Fix clang/gcc warnings -Wzero-as-null-pointer-constant, -Wuseless-cast, -Wshorten-64-to-32
Fix unreferenced function warnings in PUGIXML_NO_STL configuration
Fix CMake 3.31 deprecation warnings
Stop using deprecated throw() when noexcept is available

Improvements:

xml_attribute::set_name and xml_node::set_name now have overloads that accept pointer to non-null-terminated string and size
Implement parse_merge_pcdata parsing mode in which PCDATA contents is merged into a single node when original document had comments that were skipped during parsing
xml_document::load_file now returns a more consistent error status when given a path to a folder
Bug fixes:

Fix assertion in XPath number→string conversion when using non-English locales
Fix PUGIXML_STATIC_CRT CMake option to correctly select static CRT when using MSVC and recent CMake
Compatibility improvements:

Fix GCC 2.95/3.3 builds
Fix CMake 3.27 deprecation warnings
Fix XCode 14 sprintf deprecation warning when compiling in C++03 mode
Fix clang/gcc warnings -Wweak-vtables, -Wreserved-macro-identifier

* Update CMakeLists.txt

* pugixml: upgrade to v1.15

* pugixml: Add export directives for non-windows platforms

* pugixml: replace NULL by nullptr.

---------

Co-authored-by: Andrea <realeandrea@yahoo.it>
Co-authored-by: mosfet80 <10235105+mosfet80@users.noreply.github.com>
2025-06-08 02:12:05 +02:00
Jackson LevittandKim Kulling 8621d52430 Updated Inner Cone formula for Spot Lights in GLTF (#6078)
Updated the Inner Cone formula such that exponent values of 0 result in no inner cone and large exponent values result in a inner cone being most of the cone angle-wise.

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-05 09:41:30 +02:00
sSsA01andKim Kulling 5d39661751 fix compile error caused by PR #6087 when ASSIMP_DOUBLE_PRESICION is enabled (#6091)
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-05 09:15:47 +02:00
sSsA01andKim Kulling a98ffe6c6f Fix export fbx: Wrong Materials in LayerElementMaterial if a node contains multi meshes (#6103)
* fix export fbx wrong Materials index in LayerElementMaterial

* Refix export fbx wrong Materials index in LayerElementMaterial. Materials index should be the order of Materials in connections of the Model node.

---------

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-06-05 09:05:36 +02:00
Kim Kulling b3a47a68fa Version: Adapt version (#6212)
* Version: Adapt version

- closes https://github.com/assimp/assimp/issues/6204

* Update utVersion.cpp
2025-06-02 10:54:32 +02:00
217 changed files with 4625 additions and 4482 deletions
+11 -7
View File
@@ -16,9 +16,13 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: 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. # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
include: include:
- name: windows-latest-clang.exe
os: windows-latest
cxx: clang++.exe
cc: clang.exe
- name: windows-latest-cl.exe - name: windows-latest-cl.exe
os: windows-latest os: windows-latest
cxx: cl.exe cxx: cl.exe
@@ -44,7 +48,7 @@ jobs:
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
submodules: true submodules: true
@@ -69,13 +73,13 @@ jobs:
${{ runner.os }}-DX_SDK ${{ runner.os }}-DX_SDK
- name: Download DXSetup - 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: | run: |
curl -s -o DXSDK_Jun10.exe --location https://download.microsoft.com/download/A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe 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" cmd.exe /c start /wait .\DXSDK_Jun10.exe /U /O /F /S /P "${{ github.workspace }}\DX_SDK"
- name: Set Windows specific CMake arguments - name: Set Windows specific CMake arguments
if: contains(matrix.name, 'windows') if: contains(matrix.name, 'windows-latest-cl.exe')
id: windows_extra_cmake_args id: windows_extra_cmake_args
run: echo ":set-output name=args::=-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1" >> $GITHUB_OUTPUT run: echo ":set-output name=args::=-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1" >> $GITHUB_OUTPUT
@@ -105,7 +109,7 @@ jobs:
run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }} run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }}
shell: bash shell: bash
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v5
if: matrix.name == 'windows-msvc' if: matrix.name == 'windows-msvc'
with: with:
name: 'assimp-bins-${{ matrix.name }}' name: 'assimp-bins-${{ matrix.name }}'
@@ -137,7 +141,7 @@ jobs:
prerelease: true prerelease: true
- run: | - run: |
echo '${{steps.create-release.outputs.upload_url}}' > release_upload_url.txt echo '${{steps.create-release.outputs.upload_url}}' > release_upload_url.txt
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v5
with: with:
name: create-release name: create-release
path: release_upload_url.txt path: release_upload_url.txt
@@ -184,7 +188,7 @@ jobs:
- id: upload-url - id: upload-url
run: | run: |
echo "url=$(cat create-release/release_upload_url.txt)" >> $GITHUB_OUTPUT echo "url=$(cat create-release/release_upload_url.txt)" >> $GITHUB_OUTPUT
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v6
with: with:
name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}' name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'
- uses: actions/upload-release-asset@v1 - uses: actions/upload-release-asset@v1
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
os: ubuntu-latest os: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4.2.2 - uses: actions/checkout@v6
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
dry-run: false dry-run: false
language: c++ language: c++
- name: Upload Crash - name: Upload Crash
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
if: failure() && steps.build.outcome == 'success' if: failure() && steps.build.outcome == 'success'
with: with:
name: artifacts name: artifacts
+3 -3
View File
@@ -14,7 +14,7 @@ jobs:
name: adress-sanitizer name: adress-sanitizer
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
- uses: lukka/set-shell-env@v1 - uses: lukka/set-shell-env@v1
with: with:
@@ -38,7 +38,7 @@ jobs:
name: undefined-behavior-sanitizer name: undefined-behavior-sanitizer
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
- uses: lukka/set-shell-env@v1 - uses: lukka/set-shell-env@v1
with: with:
@@ -62,7 +62,7 @@ jobs:
name: printf-sanitizer name: printf-sanitizer
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: run scan_printf script - name: run scan_printf script
run: ./scripts/scan_printf.sh run: ./scripts/scan_printf.sh
+5 -4
View File
@@ -30,7 +30,7 @@ cmake --build .
Note that by default this builds a shared library into the `bin` directory. If you want to build it as a static library see the build options at the bottom of this file. Note that by default this builds a shared library into the `bin` directory. If you want to build it as a static library see the build options at the bottom of this file.
### Build instructions for Windows with Visual-Studio ### Build instructions for Windows with Visual-Studio
First, you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/ First, you have to install Visual-Studio on your windows-system. You can get the Community-Version for free [here](https://visualstudio.microsoft.com/downloads/)
To generate the build environment for your IDE open a command prompt, navigate to your repo and type: To generate the build environment for your IDE open a command prompt, navigate to your repo and type:
```bash ```bash
cmake CMakeLists.txt cmake CMakeLists.txt
@@ -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_NO_EXPORT (default OFF)**: Disable Assimp's export functionality.
- **ASSIMP_BUILD_ZLIB (default OFF)**: Build our own zlib. - **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_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_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_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. - **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. - **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_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_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 prebuild binaries
## Install on all platforms using vcpkg ## Install on all platforms using vcpkg
@@ -109,5 +110,5 @@ You need to have pip installed:
pip install pyassimp pip install pyassimp
``` ```
### Get the SDK from itchi.io ### Get the SDK from itch.io
Just check [itchi.io](https://kimkulling.itch.io/the-asset-importer-lib) Just check [itch.io](https://kimkulling.itch.io/the-asset-importer-lib)
+85 -71
View File
@@ -50,20 +50,21 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.22 )
# M3D format import support (assimp integration no longer supported by M3D format author) # M3D format import support (assimp integration no longer supported by M3D format author)
# User may override these in their CMake script to provide M3D import/export support # User may override these in their CMake script to provide M3D import/export support
# (M3D importer/exporter was disabled for assimp release 5.1 or later) # (M3D importer/exporter was disabled for assimp release 5.1 or later)
option(ASSIMP_BUILD_M3D_IMPORTER "Enable M3D file import" off) OPTION(ASSIMP_BUILD_M3D_IMPORTER "Enable M3D file import" off)
option(ASSIMP_BUILD_M3D_EXPORTER "Enable M3D file export" off) OPTION(ASSIMP_BUILD_M3D_EXPORTER "Enable M3D file export" off)
# Experimental USD importer: disabled, need to opt-in # Experimental USD importer: disabled, need to opt-in
# Note: assimp github PR automatic checks will fail the PR due to compiler warnings in # Note: assimp github PR automatic checks will fail the PR due to compiler warnings in
# the external, 3rd party tinyusdz code which isn't technically part of the PR since it's # the external, 3rd party tinyusdz code which isn't technically part of the PR since it's
# auto-cloned during build; so MUST disable the feature or the PR will be rejected # auto-cloned during build; so MUST disable the feature or the PR will be rejected
option(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off) OPTION(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off)
option(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off) OPTION(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off)
# VRML (.wrl/.x3dv) file import support by leveraging X3D importer and 3rd party file # VRML (.wrl/.x3dv) file import support by leveraging X3D importer and 3rd party file
# format converter to convert .wrl/.x3dv files to X3D-compatible .xml # format converter to convert .wrl/.x3dv files to X3D-compatible .xml
# (Need to make this opt-in because 3rd party code triggers lots of CI code quality warnings) # (Need to make this opt-in because 3rd party code triggers lots of CI code quality warnings)
option(ASSIMP_BUILD_VRML_IMPORTER "Enable VRML (.wrl/.x3dv) file import" off) OPTION(ASSIMP_BUILD_VRML_IMPORTER "Enable VRML (.wrl/.x3dv) file import" off)
#--------------------------------------------------------------------------------# #--------------------------------------------------------------------------------#
# Internal impl for optional model formats # Internal impl for optional model formats
#--------------------------------------------------------------------------------# #--------------------------------------------------------------------------------#
@@ -83,13 +84,13 @@ endif () # if (not ASSIMP_BUILD_VRML_IMPORTER)
option(ASSIMP_BUILD_USE_CCACHE "Use ccache to speed up compilation." on) option(ASSIMP_BUILD_USE_CCACHE "Use ccache to speed up compilation." on)
if(ASSIMP_BUILD_USE_CCACHE) IF(ASSIMP_BUILD_USE_CCACHE)
find_program(CCACHE_PATH ccache) find_program(CCACHE_PATH ccache)
if (CCACHE_PATH) IF (CCACHE_PATH)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH}) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH}) set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH})
endif() ENDIF()
endif() ENDIF()
# Toggles the use of the hunter package manager # Toggles the use of the hunter package manager
option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF) option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
@@ -100,10 +101,13 @@ IF(ASSIMP_HUNTER_ENABLED)
URL "https://github.com/cpp-pm/hunter/archive/v0.25.8.tar.gz" URL "https://github.com/cpp-pm/hunter/archive/v0.25.8.tar.gz"
SHA1 "26c79d587883ec910bce168e25f6ac4595f97033" SHA1 "26c79d587883ec910bce168e25f6ac4595f97033"
) )
add_definitions(-DASSIMP_USE_HUNTER) ADD_DEFINITIONS(-DASSIMP_USE_HUNTER)
ENDIF() ENDIF()
PROJECT(Assimp VERSION 5.4.3) PROJECT(Assimp VERSION 6.0.2
LANGUAGES C CXX
DESCRIPTION "Open Asset Import Library (Assimp) is a library to import various well-known 3D model formats in a uniform manner."
)
# All supported options ############################################### # All supported options ###############################################
@@ -245,7 +249,7 @@ SET (ASSIMP_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
SET (ASSIMP_VERSION_MINOR ${PROJECT_VERSION_MINOR}) SET (ASSIMP_VERSION_MINOR ${PROJECT_VERSION_MINOR})
SET (ASSIMP_VERSION_PATCH ${PROJECT_VERSION_PATCH}) SET (ASSIMP_VERSION_PATCH ${PROJECT_VERSION_PATCH})
SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}) SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
SET (ASSIMP_SOVERSION 5) SET (ASSIMP_SOVERSION 6)
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" ) SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@@ -305,6 +309,17 @@ IF( UNIX )
ENDIF() ENDIF()
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 ######################################## # Grouped compiler settings ########################################
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU) IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU)
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)
@@ -350,14 +365,13 @@ ELSEIF(MSVC)
if(NOT /utf-8 IN_LIST CMAKE_CXX_FLAGS) if(NOT /utf-8 IN_LIST CMAKE_CXX_FLAGS)
# Source code is encoded in UTF-8 # Source code is encoded in UTF-8
ADD_COMPILE_OPTIONS(/source-charset:utf-8) ADD_COMPILE_OPTIONS(/source-charset:utf-8)
endif () endif()
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON) SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
ENDIF() ENDIF()
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_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 "-fno-strict-aliasing ${CMAKE_C_FLAGS}") SET(CMAKE_C_FLAGS "-Wno-deprecated-non-prototype -fno-strict-aliasing ${CMAKE_C_FLAGS}")
ELSEIF( MINGW ) ELSEIF( MINGW )
IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0) 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.") message(FATAL_ERROR "MinGW is too old to be supported. Please update MinGW and try again.")
@@ -480,20 +494,20 @@ ENDIF()
set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") SET(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in") SET(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in")
set(NAMESPACE "${PROJECT_NAME}::") SET(NAMESPACE "${PROJECT_NAME}::")
set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") SET(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") SET(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") SET(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
ELSE() ELSE()
set(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") SET(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in") SET(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in")
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE) string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)
set(NAMESPACE "${PROJECT_NAME_LOWERCASE}::") SET(NAMESPACE "${PROJECT_NAME_LOWERCASE}::")
set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets") SET(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets")
set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}ConfigVersion.cmake") SET(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}ConfigVersion.cmake")
set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}Config.cmake") SET(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}Config.cmake")
ENDIF() ENDIF()
set(INCLUDE_INSTALL_DIR "include") set(INCLUDE_INSTALL_DIR "include")
@@ -510,20 +524,20 @@ configure_package_config_file(
INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
) )
if(ASSIMP_INSTALL) IF(ASSIMP_INSTALL)
install( INSTALL(
FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
DESTINATION "${CONFIG_INSTALL_DIR}" DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT} COMPONENT ${LIBASSIMP-DEV_COMPONENT}
) )
install( INSTALL(
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${NAMESPACE}" NAMESPACE "${NAMESPACE}"
DESTINATION "${CONFIG_INSTALL_DIR}" DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT} COMPONENT ${LIBASSIMP-DEV_COMPONENT}
) )
endif() ENDIF()
IF( ASSIMP_BUILD_DOCS ) IF( ASSIMP_BUILD_DOCS )
ADD_SUBDIRECTORY(doc) ADD_SUBDIRECTORY(doc)
@@ -536,9 +550,9 @@ IF(ASSIMP_HUNTER_ENABLED)
find_package(ZLIB CONFIG REQUIRED) find_package(ZLIB CONFIG REQUIRED)
add_definitions(-DASSIMP_BUILD_NO_OWN_ZLIB) add_definitions(-DASSIMP_BUILD_NO_OWN_ZLIB)
set(ZLIB_FOUND TRUE) SET(ZLIB_FOUND TRUE)
set(ZLIB_LIBRARIES ZLIB::zlib) SET(ZLIB_LIBRARIES ZLIB::zlib)
set(ASSIMP_BUILD_MINIZIP TRUE) SET(ASSIMP_BUILD_MINIZIP TRUE)
ELSE() ELSE()
# If the zlib is already found outside, add an export in case assimpTargets can't find it. # If the zlib is already found outside, add an export in case assimpTargets can't find it.
IF( ZLIB_FOUND AND ASSIMP_INSTALL) IF( ZLIB_FOUND AND ASSIMP_INSTALL)
@@ -565,8 +579,8 @@ ELSE()
# https://github.com/madler/zlib/issues/41#issuecomment-125848075 # https://github.com/madler/zlib/issues/41#issuecomment-125848075
# Also prevents these options from "polluting" the cmake options if assimp is being # Also prevents these options from "polluting" the cmake options if assimp is being
# included as a submodule. # included as a submodule.
set( ASM686 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE ) SET(ASM686 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
set( AMD64 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE ) SET(AMD64 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
# compile from sources # compile from sources
ADD_SUBDIRECTORY(contrib/zlib) ADD_SUBDIRECTORY(contrib/zlib)
@@ -577,7 +591,7 @@ ELSE()
SET(ASSIMP_BUILD_MINIZIP 1) SET(ASSIMP_BUILD_MINIZIP 1)
ELSE() ELSE()
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB) ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
SET(ZLIB_LIBRARIES_LINKED -lz) SET(ZLIB_LIBRARIES_LINKED -l${ZLIB_LIBRARIES})
ENDIF() ENDIF()
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
ENDIF() ENDIF()
@@ -589,7 +603,7 @@ IF( NOT IOS )
ELSE () ELSE ()
IF( NOT BUILD_SHARED_LIBS ) IF( NOT BUILD_SHARED_LIBS )
IF( NOT ASSIMP_BUILD_MINIZIP ) IF( NOT ASSIMP_BUILD_MINIZIP )
use_pkgconfig(UNZIP minizip) USE_PKGCONFIG(UNZIP minizip)
ENDIF() ENDIF()
ENDIF () ENDIF ()
ENDIF () ENDIF ()
@@ -672,48 +686,48 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
"${C4D_LIB_BASE_PATH}/release/libcinewarelib.a" "${C4D_LIB_BASE_PATH}/release/libcinewarelib.a"
"${C4D_LIB_BASE_PATH}/release/libjpeglib.a" "${C4D_LIB_BASE_PATH}/release/libjpeglib.a"
) )
ELSE () ELSE()
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR
"C4D is currently only available on Windows and macOS with Cineware SDK installed in contrib/Cineware" "C4D is currently only available on Windows and macOS with Cineware SDK installed in contrib/Cineware"
) )
ENDIF () ENDIF()
ELSE () ELSE ()
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER ) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
ENDIF () ENDIF ()
if(ASSIMP_BUILD_DRACO_STATIC) IF(ASSIMP_BUILD_DRACO_STATIC)
set(ASSIMP_BUILD_DRACO ON) SET(ASSIMP_BUILD_DRACO ON)
endif() ENDIF()
# Draco requires cmake 3.12 # Draco requires cmake 3.12
IF (DEFINED CMAKE_VERSION AND "${CMAKE_VERSION}" VERSION_LESS "3.12") IF (DEFINED CMAKE_VERSION AND "${CMAKE_VERSION}" VERSION_LESS "3.12")
message(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled") MESSAGE(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled")
SET ( ASSIMP_BUILD_DRACO OFF CACHE BOOL "Disabled: Draco requires newer cmake" FORCE ) SET ( ASSIMP_BUILD_DRACO OFF CACHE BOOL "Disabled: Draco requires newer cmake" FORCE )
ELSE() ELSE()
OPTION ( ASSIMP_BUILD_DRACO "If the Draco libraries are to be built. Primarily for glTF" OFF ) OPTION ( ASSIMP_BUILD_DRACO "If the Draco libraries are to be built. Primarily for glTF" OFF )
IF ( ASSIMP_BUILD_DRACO ) IF ( ASSIMP_BUILD_DRACO )
# Primarily for glTF v2 # Primarily for glTF v2
# Enable Draco glTF feature set # Enable Draco glTF feature set
set(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE) SET(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE)
# Disable unnecessary or omitted components # Disable unnecessary or omitted components
set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE) SET(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
set(DRACO_WASM OFF CACHE BOOL "" FORCE) SET(DRACO_WASM OFF CACHE BOOL "" FORCE)
set(DRACO_MAYA_PLUGIN OFF CACHE BOOL "" FORCE) SET(DRACO_MAYA_PLUGIN OFF CACHE BOOL "" FORCE)
set(DRACO_UNITY_PLUGIN OFF CACHE BOOL "" FORCE) SET(DRACO_UNITY_PLUGIN OFF CACHE BOOL "" FORCE)
set(DRACO_TESTS OFF CACHE BOOL "" FORCE) SET(DRACO_TESTS OFF CACHE BOOL "" FORCE)
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(draco) hunter_add_package(draco)
find_package(draco CONFIG REQUIRED) find_package(draco CONFIG REQUIRED)
set(draco_LIBRARIES draco::draco) SET(draco_LIBRARIES draco::draco)
ELSE() ELSE()
# Draco 1.4.1 has many warnings and will not build with /WX or -Werror # Draco 1.4.1 has many warnings and will not build with /WX or -Werror
# See https://github.com/google/draco/issues/672 # See https://github.com/google/draco/issues/672
# and https://github.com/google/draco/issues/673 # and https://github.com/google/draco/issues/673
IF(MSVC) IF(MSVC)
set(DRACO_CXX_FLAGS "/W0") SET(DRACO_CXX_FLAGS "/W0")
ELSE() ELSE()
list(APPEND DRACO_CXX_FLAGS LIST(APPEND DRACO_CXX_FLAGS
"-Wno-bool-compare" "-Wno-bool-compare"
"-Wno-comment" "-Wno-comment"
"-Wno-maybe-uninitialized" "-Wno-maybe-uninitialized"
@@ -721,30 +735,30 @@ ELSE()
"-Wno-unused-local-typedefs" "-Wno-unused-local-typedefs"
) )
if(NOT ASSIMP_BUILD_DRACO_STATIC) IF(NOT ASSIMP_BUILD_DRACO_STATIC)
# Draco 1.4.1 does not explicitly export any symbols under GCC/clang # Draco 1.4.1 does not explicitly export any symbols under GCC/clang
list(APPEND DRACO_CXX_FLAGS LIST(APPEND DRACO_CXX_FLAGS
"-fvisibility=default" "-fvisibility=default"
) )
endif() ENDIF()
ENDIF() ENDIF()
# Don't build or install all of Draco by default # Don't build or install all of Draco by default
ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL ) ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL )
if(ASSIMP_BUILD_DRACO_STATIC) IF(ASSIMP_BUILD_DRACO_STATIC)
set_property(DIRECTORY "contrib/draco" PROPERTY BUILD_SHARED_LIBS OFF) set_property(DIRECTORY "contrib/draco" PROPERTY BUILD_SHARED_LIBS OFF)
endif() ENDIF()
if(MSVC OR WIN32) IF(MSVC OR WIN32)
set(draco_LIBRARIES "draco") SET(draco_LIBRARIES "draco")
else() ELSE()
if(ASSIMP_BUILD_DRACO_STATIC) IF(ASSIMP_BUILD_DRACO_STATIC)
set(draco_LIBRARIES "draco_static") SET(draco_LIBRARIES "draco_static")
else() ELSE()
set(draco_LIBRARIES "draco_shared") SET(draco_LIBRARIES "draco_shared")
endif() ENDIF()
endif() ENDIF()
# Don't build the draco command-line tools by default # Don't build the draco command-line tools by default
set_target_properties(draco_encoder draco_decoder PROPERTIES set_target_properties(draco_encoder draco_decoder PROPERTIES
@@ -762,10 +776,10 @@ ELSE()
TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_encoder) TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_encoder)
TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_decoder) TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_decoder)
set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src") SET(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
# This is probably wrong # This is probably wrong
if (ASSIMP_INSTALL) IF (ASSIMP_INSTALL)
INSTALL( TARGETS ${draco_LIBRARIES} INSTALL( TARGETS ${draco_LIBRARIES}
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
@@ -775,7 +789,7 @@ ELSE()
COMPONENT ${LIBASSIMP_COMPONENT} COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION include INCLUDES DESTINATION include
) )
endif() ENDIF()
ENDIF() ENDIF()
ENDIF() ENDIF()
ENDIF() ENDIF()
+34
View File
@@ -0,0 +1,34 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 20,
"patch": 0
},
"configurePresets": [
{
"name": "assimp",
"binaryDir": "${sourceDir}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"ASSIMP_BUILD_ASSIMP_TOOLS": "OFF"
}
},
{
"name": "assimp_double_precision",
"binaryDir": "${sourceDir}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"ASSIMP_BUILD_ASSIMP_TOOLS": "OFF",
"ASSIMP_DOUBLE_PRECISION": "ON"
}
},
{
"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 WORKDIR /app
RUN apt install zlib1g-dev
COPY . . COPY . .
+1 -1
View File
@@ -1,6 +1,6 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
Copyright (c) 2006-2021, assimp team Copyright (c) 2006-2025, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
+40 -36
View File
@@ -3,7 +3,7 @@ Open Asset Import Library (assimp)
Open Asset Import Library is a library that loads various 3D file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export. Open Asset Import Library is a library that loads various 3D file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
### Current project status ### ### Current project status
![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg) ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=assimp_assimp&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=assimp_assimp) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=assimp_assimp&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=assimp_assimp)
@@ -16,32 +16,32 @@ Open Asset Import Library is a library that loads various 3D file formats into a
APIs are provided for C and C++. Various bindings exist to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS. APIs are provided for C and C++. Various bindings exist to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
Additionally, assimp features various __mesh post-processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more. Additionally, assimp features various __mesh post-processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
## Project activity ## ## Project activity
![Alt](https://repobeats.axiom.co/api/embed/997f84e5f9fcf772da1e687f3a4f3a8afdbf4cf0.svg "Repobeats analytics image") ![Alt](https://repobeats.axiom.co/api/embed/997f84e5f9fcf772da1e687f3a4f3a8afdbf4cf0.svg "Repobeats analytics image")
### Documentation ### ### 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 ### ### 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 ### ### 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 ### ### Communities
- Ask questions at [the Assimp Discussion Board](https://github.com/assimp/assimp/discussions). - Ask questions at [the Assimp Discussion Board](https://github.com/assimp/assimp/discussions).
- Find us on [https://discord.gg/s9KJfaem](https://discord.gg/kKazXMXDy2) - Find us on [discord](https://discord.gg/kKazXMXDy2)
- Ask [the Assimp community on Reddit](https://www.reddit.com/r/Assimp/). - Ask [the Assimp community on Reddit](https://www.reddit.com/r/Assimp/).
- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). - Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
- Nothing has worked? File a question or an issue report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues) - Nothing has worked? File a question or an issue report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
#### Supported file formats #### #### Supported file formats
See [the complete list of supported formats](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md). See [the complete list of supported formats](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md).
### Building ### ### Building
Start by reading [our build instructions](https://github.com/assimp/assimp/blob/master/Build.md). We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do. Start by reading [our build instructions](https://github.com/assimp/assimp/blob/master/Build.md). We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
### Ports ### ### Ports
* [Android](port/AndroidJNI/README.md) * [Android](port/AndroidJNI/README.md)
* [Python](port/PyAssimp/README.md) * [Python](port/PyAssimp/README.md)
* [.NET](https://github.com/Saalvage/AssimpNetter) * [.NET](https://github.com/Saalvage/AssimpNetter)
@@ -54,36 +54,40 @@ Start by reading [our build instructions](https://github.com/assimp/assimp/blob/
* [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port. * [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port.
* [Rust](https://github.com/jkvargas/russimp) * [Rust](https://github.com/jkvargas/russimp)
### Other tools ### ### Other tools
[Qt5-ModelViewer](https://github.com/sharjith/ModelViewer-Qt5) is a powerful viewer based on Qt5 and Assimp's import and export abilities.<br> [Qt5-ModelViewer](https://github.com/sharjith/ModelViewer-Qt5) is a powerful viewer based on Qt5 and Assimp's import and export abilities.<br>
[Assimp-Viewer](https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental). [Assimp-Viewer](https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental).
#### Repository structure #### #### Repository structure ####
Open Asset Import Library is implemented in C++. The directory structure looks like this: Open Asset Import Library is implemented in C++. The directory structure looks like this:
/code Source code ```txt
/contrib Third-party libraries code Source code
/doc Documentation (Doxygen source and pre-compiled docs) ├── AssetLib/ The asset-importer and exporter lib
/fuzz Contains the test code for the Google Fuzzer project ├── CApi/ C-API files
/include Public header C and C++ header files ├── Common/ Common code used from all modules
/scripts Scripts are used to generate the loading code for some formats ├── Geometry/ Geometry utilities
/port Ports to other languages and scripts to maintain those. ├── Material/ Common materials
/test Unit- and regression tests, test suite of models ├── Pbrt/ Physical based materials
/tools Tools (old assimp viewer, command line `assimp`) ├── PostProcessing/ Post-processing steps
/samples A small number of samples to illustrate possible use cases for Assimp ├── res Resouce files
contrib Third-party libraries
doc Documentation (Doxygen source and pre-compiled docs)
fuzz Contains the test code for the Google Fuzzer project
include Public header C and C++ header files
scripts Scripts are used to generate the loading code for some formats
port Ports to other languages and scripts to maintain those.
test Unit- and regression tests, test suite of models
├── headercheck Implements headerchecks
├── models-nonbsd Non-BSP licensed headers
├── models BSP-licensed models
├── unit Unit tests
tools Tools (old assimp viewer, command line `assimp`)
samples Small number of samples to illustrate possible use cases for Assimp
```
### Contributing
The source code is organized in the following way: We would greatly appreciate for you to contribute to assimp. The easiest way to get involved is to submit
code/Common The base implementation for importers and the infrastructure
code/CApi Special implementations which are only used for the C-API
code/Geometry A collection of geometry tools
code/Material The material system
code/PBR An exporter for physical-based models
code/PostProcessing The post-processing steps
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
a pull request with your changes against the main repository's `master` branch. a pull request with your changes against the main repository's `master` branch.
## Contributors ## Contributors
+3 -4
View File
@@ -2,15 +2,14 @@
## Supported Versions ## Supported Versions
Use this section to tell people about which versions of your project are The current version of Assimp that's being supported with security updates:
currently being supported with security updates.
| Version | Supported | | Version | Supported |
| ------- | ------------------ | | ------- | ------------------ |
| 5.2.4 | :white_check_mark: | | 6.0.2 | :white_check_mark: |
## Reporting a Vulnerability ## Reporting a Vulnerability
If you have found any security vulnerability you can contact us via If you have found any security vulnerability you can contact us via
kim.kulling@googlemail.com kim.kulling@assimp.org
+38 -33
View File
@@ -56,23 +56,27 @@ namespace Assimp {
static constexpr unsigned int NotSet = 0xcdcdcdcd; static constexpr unsigned int NotSet = 0xcdcdcdcd;
using namespace D3DS;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup final material indices, generae a default material if necessary // Setup final material indices, generate a default material if necessary
void Discreet3DSImporter::ReplaceDefaultMaterial() { void Discreet3DSImporter::ReplaceDefaultMaterial() {
// Try to find an existing material that matches the // Try to find an existing material that matches the
// typical default material setting: // typical default material setting:
// - no textures // - no textures
// - diffuse color (in grey!) // - diffuse color (in grey!)
// NOTE: This is here to workaround the fact that some // NOTE: This is here to work-around the fact that some
// exporters are writing a default material, too. // exporters are writing a default material, too.
unsigned int idx(NotSet); unsigned int idx(NotSet);
for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) { for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
std::string s = mScene->mMaterials[i].mName; auto s = mScene->mMaterials[i].mName;
for (char &it : s) { for (char &it : s) {
it = static_cast<char>(::tolower(static_cast<unsigned char>(it))); it = static_cast<char>(::tolower(static_cast<unsigned char>(it)));
} }
if (std::string::npos == s.find("default")) continue; if (std::string::npos == s.find("default")) {
continue;
}
if (mScene->mMaterials[i].mDiffuse.r != if (mScene->mMaterials[i].mDiffuse.r !=
mScene->mMaterials[i].mDiffuse.g || mScene->mMaterials[i].mDiffuse.g ||
@@ -85,22 +89,22 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
idx = i; idx = i;
} }
if (NotSet == idx) { if (NotSet == idx) {
idx = (unsigned int)mScene->mMaterials.size(); idx = static_cast<unsigned int>(mScene->mMaterials.size());
} }
// now iterate through all meshes and through all faces and // now iterate through all meshes and through all faces and
// find all faces that are using the default material // find all faces that are using the default material
unsigned int cnt = 0; unsigned int cnt = 0;
for (auto i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) { for (auto i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) {
for (auto a = (*i).mFaceMaterials.begin(); a != (*i).mFaceMaterials.end(); ++a) { for (auto a = i->mFaceMaterials.begin(); a != i->mFaceMaterials.end(); ++a) {
// NOTE: The additional check seems to be necessary, // NOTE: The additional check seems to be necessary,
// some exporters seem to generate invalid data here // some exporters seem to generate invalid data here
if (NotSet == (*a)) { if (NotSet == *a) {
(*a) = idx; *a = idx;
++cnt; ++cnt;
} else if ((*a) >= mScene->mMaterials.size()) { } else if ((*a) >= mScene->mMaterials.size()) {
(*a) = idx; *a = idx;
ASSIMP_LOG_WARN("Material index overflow in 3DS file. Using default material"); ASSIMP_LOG_WARN("Material index overflow in 3DS file. Using default material");
++cnt; ++cnt;
} }
@@ -174,7 +178,7 @@ void CopyTexture(aiMaterial &mat, Texture &texture, aiTextureType type) {
mat.AddProperty<ai_real>(&texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type, 0)); mat.AddProperty<ai_real>(&texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type, 0));
// Setup the texture mapping mode // Setup the texture mapping mode
int mapMode = static_cast<int>(texture.mMapMode); auto mapMode = static_cast<int>(texture.mMapMode);
mat.AddProperty<int>(&mapMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0)); mat.AddProperty<int>(&mapMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0));
mat.AddProperty<int>(&mapMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0)); mat.AddProperty<int>(&mapMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0));
@@ -326,10 +330,11 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
aiString name; aiString name;
// we need to split all meshes by their materials // we need to split all meshes by their materials
for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) { for (auto i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) {
std::unique_ptr<std::vector<unsigned int>[]> aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]); std::unique_ptr<std::vector<unsigned int>[]> aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]);
name.length = ASSIMP_itoa10(name.data, num++); name.length = ASSIMP_itoa10(name.data, num);
++num;
unsigned int iNum = 0; unsigned int iNum = 0;
for (std::vector<unsigned int>::const_iterator a = (*i).mFaceMaterials.begin(); for (std::vector<unsigned int>::const_iterator a = (*i).mFaceMaterials.begin();
@@ -341,7 +346,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
if (aiSplit[p].empty()) { if (aiSplit[p].empty()) {
continue; continue;
} }
aiMesh *meshOut = new aiMesh(); auto *meshOut = new aiMesh();
meshOut->mName = name; meshOut->mName = name;
meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
@@ -353,7 +358,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
avOutMeshes.push_back(meshOut); avOutMeshes.push_back(meshOut);
// convert vertices // convert vertices
meshOut->mNumFaces = (unsigned int)aiSplit[p].size(); meshOut->mNumFaces = static_cast<unsigned int>(aiSplit[p].size());
meshOut->mNumVertices = meshOut->mNumFaces * 3; meshOut->mNumVertices = meshOut->mNumFaces * 3;
// allocate enough storage for faces // allocate enough storage for faces
@@ -401,8 +406,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Add a node to the scenegraph and setup its final transformation // Add a node to the scenegraph and setup its final transformation
void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::Node *pcIn, aiMatrix4x4 & /*absTrafo*/) {
D3DS::Node *pcIn, aiMatrix4x4 & /*absTrafo*/) {
std::vector<unsigned int> iArray; std::vector<unsigned int> iArray;
iArray.reserve(3); iArray.reserve(3);
@@ -410,7 +414,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
// Find all meshes with the same name as the node // Find all meshes with the same name as the node
for (unsigned int a = 0; a < pcSOut->mNumMeshes; ++a) { for (unsigned int a = 0; a < pcSOut->mNumMeshes; ++a) {
const D3DS::Mesh *pcMesh = (const D3DS::Mesh *)pcSOut->mMeshes[a]->mColors[0]; const auto *pcMesh = (const D3DS::Mesh *)pcSOut->mMeshes[a]->mColors[0];
ai_assert(nullptr != pcMesh); ai_assert(nullptr != pcMesh);
if (pcIn->mName == pcMesh->mName) if (pcIn->mName == pcMesh->mName)
@@ -419,7 +423,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
if (!iArray.empty()) { if (!iArray.empty()) {
// The matrix should be identical for all meshes with the // The matrix should be identical for all meshes with the
// same name. It HAS to be identical for all meshes ..... // same name. It HAS to be identical for all meshes .....
D3DS::Mesh *imesh = ((D3DS::Mesh *)pcSOut->mMeshes[iArray[0]]->mColors[0]); auto *imesh = ((D3DS::Mesh *)pcSOut->mMeshes[iArray[0]]->mColors[0]);
// Compute the inverse of the transformation matrix to move the // Compute the inverse of the transformation matrix to move the
// vertices back to their relative and local space // vertices back to their relative and local space
@@ -428,7 +432,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
mInvTransposed.Transpose(); mInvTransposed.Transpose();
aiVector3D pivot = pcIn->vPivot; aiVector3D pivot = pcIn->vPivot;
pcOut->mNumMeshes = (unsigned int)iArray.size(); pcOut->mNumMeshes = static_cast<unsigned int>(iArray.size());
pcOut->mMeshes = new unsigned int[iArray.size()]; pcOut->mMeshes = new unsigned int[iArray.size()];
for (unsigned int i = 0; i < iArray.size(); ++i) { for (unsigned int i = 0; i < iArray.size(); ++i) {
const unsigned int iIndex = iArray[i]; const unsigned int iIndex = iArray[i];
@@ -447,7 +451,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
// Handle negative transformation matrix determinant -> invert vertex x // Handle negative transformation matrix determinant -> invert vertex x
if (imesh->mMat.Determinant() < 0.0f) { if (imesh->mMat.Determinant() < 0.0f) {
/* we *must* have normals */ // we *must* have normals
for (pvCurrent = mesh->mVertices, t2 = mesh->mNormals; pvCurrent != pvEnd; ++pvCurrent, ++t2) { for (pvCurrent = mesh->mVertices, t2 = mesh->mNormals; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
pvCurrent->x *= -1.f; pvCurrent->x *= -1.f;
t2->x *= -1.f; t2->x *= -1.f;
@@ -474,7 +478,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
// Setup the name of the node // Setup the name of the node
// First instance keeps its name otherwise something might break, all others will be postfixed with their instance number // First instance keeps its name otherwise something might break, all others will be postfixed with their instance number
if (pcIn->mInstanceNumber > 1) { if (pcIn->mInstanceNumber > 1) {
char tmp[12]; char tmp[12] = {'\0'};
ASSIMP_itoa10(tmp, pcIn->mInstanceNumber); ASSIMP_itoa10(tmp, pcIn->mInstanceNumber);
std::string tempStr = pcIn->mName + "_inst_"; std::string tempStr = pcIn->mName + "_inst_";
tempStr += tmp; tempStr += tmp;
@@ -487,7 +491,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
if (pcIn->aRotationKeys.size()) { if (pcIn->aRotationKeys.size()) {
// FIX to get to Assimp's quaternion conventions // FIX to get to Assimp's quaternion conventions
for (std::vector<aiQuatKey>::iterator it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) { for (auto it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) {
(*it).mValue.w *= -1.f; (*it).mValue.w *= -1.f;
} }
@@ -599,11 +603,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
} }
// Allocate a new node anim and setup its name // Allocate a new node anim and setup its name
aiNodeAnim *nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); auto *nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
nda->mNodeName.Set(pcIn->mName); nda->mNodeName.Set(pcIn->mName);
// POSITION keys // POSITION keys
if (pcIn->aPositionKeys.size() > 0) { if (!pcIn->aPositionKeys.empty()) {
nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size(); nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys]; nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
::memcpy(nda->mPositionKeys, &pcIn->aPositionKeys[0], ::memcpy(nda->mPositionKeys, &pcIn->aPositionKeys[0],
@@ -611,7 +615,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
} }
// ROTATION keys // ROTATION keys
if (pcIn->aRotationKeys.size() > 0) { if (!pcIn->aRotationKeys.empty()) {
nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size(); nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys]; nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
@@ -627,7 +631,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
} }
// SCALING keys // SCALING keys
if (pcIn->aScalingKeys.size() > 0) { if (!pcIn->aScalingKeys.empty()) {
nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size(); nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys]; nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
::memcpy(nda->mScalingKeys, &pcIn->aScalingKeys[0], ::memcpy(nda->mScalingKeys, &pcIn->aScalingKeys[0],
@@ -636,7 +640,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
} }
// Allocate storage for children // Allocate storage for children
const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size()); const auto size = static_cast<unsigned int>(pcIn->mChildren.size());
pcOut->mNumChildren = size; pcOut->mNumChildren = size;
if (size == 0) { if (size == 0) {
@@ -679,7 +683,7 @@ void CountTracks(D3DS::Node *node, unsigned int &cnt) {
// Generate the output node graph // Generate the output node graph
void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) { void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
pcOut->mRootNode = new aiNode(); pcOut->mRootNode = new aiNode();
if (0 == mRootNode->mChildren.size()) { if (mRootNode->mChildren.empty()) {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// It seems the file is so messed up that it has not even a hierarchy. // It seems the file is so messed up that it has not even a hierarchy.
// generate a flat hiearachy which looks like this: // generate a flat hiearachy which looks like this:
@@ -701,7 +705,8 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Build dummy nodes for all meshes // Build dummy nodes for all meshes
unsigned int a = 0; unsigned int a = 0;
for (unsigned int i = 0; i < pcOut->mNumMeshes; ++i, ++a) { for (unsigned int i = 0; i < pcOut->mNumMeshes; ++i, ++a) {
aiNode *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); pcOut->mRootNode->mChildren[a] = new aiNode();
auto *pcNode = pcOut->mRootNode->mChildren[a];
pcNode->mParent = pcOut->mRootNode; pcNode->mParent = pcOut->mRootNode;
pcNode->mMeshes = new unsigned int[1]; pcNode->mMeshes = new unsigned int[1];
pcNode->mMeshes[0] = i; pcNode->mMeshes[0] = i;
@@ -713,7 +718,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Build dummy nodes for all cameras // Build dummy nodes for all cameras
for (unsigned int i = 0; i < (unsigned int)mScene->mCameras.size(); ++i, ++a) { for (unsigned int i = 0; i < (unsigned int)mScene->mCameras.size(); ++i, ++a) {
aiNode *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); auto *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
pcNode->mParent = pcOut->mRootNode; pcNode->mParent = pcOut->mRootNode;
// Build a name for the node // Build a name for the node
@@ -722,7 +727,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Build dummy nodes for all lights // Build dummy nodes for all lights
for (unsigned int i = 0; i < (unsigned int)mScene->mLights.size(); ++i, ++a) { for (unsigned int i = 0; i < (unsigned int)mScene->mLights.size(); ++i, ++a) {
aiNode *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); auto *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
pcNode->mParent = pcOut->mRootNode; pcNode->mParent = pcOut->mRootNode;
// Build a name for the node // Build a name for the node
@@ -738,7 +743,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Allocate a primary animation channel // Allocate a primary animation channel
pcOut->mNumAnimations = 1; pcOut->mNumAnimations = 1;
pcOut->mAnimations = new aiAnimation *[1]; pcOut->mAnimations = new aiAnimation *[1];
aiAnimation *anim = pcOut->mAnimations[0] = new aiAnimation(); auto *anim = pcOut->mAnimations[0] = new aiAnimation();
anim->mName.Set("3DSMasterAnim"); anim->mName.Set("3DSMasterAnim");
@@ -781,7 +786,7 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
// ... and convert the 3DS materials to aiMaterial's // ... and convert the 3DS materials to aiMaterial's
for (unsigned int i = 0; i < pcOut->mNumMaterials; ++i) { for (unsigned int i = 0; i < pcOut->mNumMaterials; ++i) {
aiMaterial *pcNew = new aiMaterial(); auto *pcNew = new aiMaterial();
ConvertMaterial(mScene->mMaterials[i], *pcNew); ConvertMaterial(mScene->mMaterials[i], *pcNew);
pcOut->mMaterials[i] = pcNew; pcOut->mMaterials[i] = pcNew;
} }
+15 -18
View File
@@ -76,26 +76,26 @@ class ChunkWriter {
public: public:
ChunkWriter(StreamWriterLE &writer, uint16_t chunk_type) : ChunkWriter(StreamWriterLE &writer, uint16_t chunk_type) :
writer(writer) { mWriter(writer) {
chunk_start_pos = writer.GetCurrentPos(); mChunkStartPos = writer.GetCurrentPos();
writer.PutU2(chunk_type); writer.PutU2(chunk_type);
writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET); writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET);
} }
~ChunkWriter() { ~ChunkWriter() {
std::size_t head_pos = writer.GetCurrentPos(); std::size_t head_pos = mWriter.GetCurrentPos();
ai_assert(head_pos > chunk_start_pos); ai_assert(head_pos > mChunkStartPos);
const std::size_t chunk_size = head_pos - chunk_start_pos; const std::size_t chunk_size = head_pos - mChunkStartPos;
writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET); mWriter.SetCurrentPos(mChunkStartPos + SIZE_OFFSET);
writer.PutU4(static_cast<uint32_t>(chunk_size)); mWriter.PutU4(static_cast<uint32_t>(chunk_size));
writer.SetCurrentPos(head_pos); mWriter.SetCurrentPos(head_pos);
} }
private: private:
StreamWriterLE &writer; StreamWriterLE &mWriter;
std::size_t chunk_start_pos; std::size_t mChunkStartPos;
}; };
// Return an unique name for a given |mesh| attached to |node| that // Return an unique name for a given |mesh| attached to |node| that
@@ -122,8 +122,7 @@ std::string GetMaterialName(const aiMaterial &mat, unsigned int index) {
char postfix[10] = { 0 }; char postfix[10] = { 0 };
ASSIMP_itoa10(postfix, index); ASSIMP_itoa10(postfix, index);
aiString mat_name; if (aiString mat_name; AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
return mat_name.C_Str() + underscore + postfix; return mat_name.C_Str() + underscore + postfix;
} }
@@ -303,8 +302,7 @@ void Discreet3DSExporter::WriteMaterials() {
WriteColor(color); WriteColor(color);
} }
aiShadingMode shading_mode = aiShadingMode_Flat; if (aiShadingMode shading_mode = aiShadingMode_Flat; mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
Discreet3DS::shadetype3ds shading_mode_out; Discreet3DS::shadetype3ds shading_mode_out;
@@ -332,7 +330,7 @@ void Discreet3DSExporter::WriteMaterials() {
default: default:
shading_mode_out = Discreet3DS::Flat; shading_mode_out = Discreet3DS::Flat;
ai_assert(false); ai_assert(false);
}; }
writer.PutU2(static_cast<uint16_t>(shading_mode_out)); writer.PutU2(static_cast<uint16_t>(shading_mode_out));
} }
@@ -346,8 +344,7 @@ void Discreet3DSExporter::WriteMaterials() {
WritePercentChunk(f); WritePercentChunk(f);
} }
int twosided; if (int twosided; mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
writer.PutI2(1); writer.PutI2(1);
} }
@@ -541,7 +538,7 @@ void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh &mesh) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteString(const std::string &s) { void Discreet3DSExporter::WriteString(const std::string &s) {
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { for (auto it = s.begin(); it != s.end(); ++it) {
writer.PutI1(*it); writer.PutI1(*it);
} }
writer.PutI1('\0'); writer.PutI1('\0');
+2 -4
View File
@@ -54,8 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/qnan.h> #include <assimp/qnan.h>
#include <cstdio> //sprintf #include <cstdio> //sprintf
namespace Assimp { namespace Assimp::D3DS {
namespace D3DS {
#include <assimp/Compiler/pushpack1.h> #include <assimp/Compiler/pushpack1.h>
@@ -579,7 +578,6 @@ struct Scene {
// Node* pcRootNode; // Node* pcRootNode;
}; };
} // end of namespace D3DS } // end of namespace Assimp::D3DS
} // end of namespace Assimp
#endif // AI_XFILEHELPER_H_INC #endif // AI_XFILEHELPER_H_INC
+177 -178
View File
@@ -56,6 +56,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
using namespace D3DS;
static constexpr aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Discreet 3DS Importer", "Discreet 3DS Importer",
"", "",
@@ -75,7 +77,7 @@ static constexpr aiImporterDesc desc = {
// - computes its length // - computes its length
#define ASSIMP_3DS_BEGIN_CHUNK() \ #define ASSIMP_3DS_BEGIN_CHUNK() \
while (true) { \ while (true) { \
if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)) { \ if (mStream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)) { \
return; \ return; \
} \ } \
Discreet3DS::Chunk chunk; \ Discreet3DS::Chunk chunk; \
@@ -83,23 +85,23 @@ static constexpr aiImporterDesc desc = {
int chunkSize = chunk.Size - sizeof(Discreet3DS::Chunk); \ int chunkSize = chunk.Size - sizeof(Discreet3DS::Chunk); \
if (chunkSize <= 0) \ if (chunkSize <= 0) \
continue; \ continue; \
const unsigned int oldReadLimit = stream->SetReadLimit( \ const unsigned int oldReadLimit = mStream->SetReadLimit( \
stream->GetCurrentPos() + chunkSize); mStream->GetCurrentPos() + chunkSize);
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// End a parsing block // End a parsing block
// Must follow at the end of each parsing block, reset chunk end marker to previous value // Must follow at the end of each parsing block, reset chunk end marker to previous value
#define ASSIMP_3DS_END_CHUNK() \ #define ASSIMP_3DS_END_CHUNK() \
stream->SkipToReadLimit(); \ mStream->SkipToReadLimit(); \
stream->SetReadLimit(oldReadLimit); \ mStream->SetReadLimit(oldReadLimit); \
if (stream->GetRemainingSizeToLimit() == 0) \ if (mStream->GetRemainingSizeToLimit() == 0) \
return; \ return; \
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
Discreet3DSImporter::Discreet3DSImporter() : Discreet3DSImporter::Discreet3DSImporter() :
stream(), mLastNodeIndex(), mCurrentNode(), mRootNode(), mScene(), mMasterScale(), bHasBG(), bIsPrj() { mStream(nullptr), mLastNodeIndex(), mCurrentNode(), mRootNode(), mScene(), mMasterScale(), bHasBG(), bIsPrj() {
// empty // empty
} }
@@ -124,9 +126,7 @@ void Discreet3DSImporter::SetupProperties(const Importer * /*pImp*/) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void Discreet3DSImporter::InternReadFile(const std::string &pFile, void Discreet3DSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
aiScene *pScene, IOSystem *pIOHandler) {
auto theFile = pIOHandler->Open(pFile, "rb"); auto theFile = pIOHandler->Open(pFile, "rb");
if (!theFile) { if (!theFile) {
throw DeadlyImportError("3DS: Could not open ", pFile); throw DeadlyImportError("3DS: Could not open ", pFile);
@@ -138,14 +138,14 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
if (theStream.GetRemainingSize() < 16) { if (theStream.GetRemainingSize() < 16) {
throw DeadlyImportError("3DS file is either empty or corrupt: ", pFile); throw DeadlyImportError("3DS file is either empty or corrupt: ", pFile);
} }
this->stream = &theStream; mStream = &theStream;
// Allocate our temporary 3DS representation // Allocate our temporary 3DS representation
D3DS::Scene _scene; Scene _scene;
mScene = &_scene; mScene = &_scene;
// Initialize members // Initialize members
D3DS::Node _rootNode("UNNAMED"); Node _rootNode("UNNAMED");
mLastNodeIndex = -1; mLastNodeIndex = -1;
mCurrentNode = &_rootNode; mCurrentNode = &_rootNode;
mRootNode = mCurrentNode; mRootNode = mCurrentNode;
@@ -166,12 +166,12 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
// vectors from the smoothing groups we read from the // vectors from the smoothing groups we read from the
// file. // file.
for (auto &mesh : mScene->mMeshes) { for (auto &mesh : mScene->mMeshes) {
if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) { if (!mesh.mFaces.empty() && mesh.mPositions.empty()) {
throw DeadlyImportError("3DS file contains faces but no vertices: ", pFile); throw DeadlyImportError("3DS file contains faces but no vertices: ", pFile);
} }
CheckIndices(mesh); CheckIndices(mesh);
MakeUnique(mesh); MakeUnique(mesh);
ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh); ComputeNormalsWithSmoothingsGroups<Face>(mesh);
} }
// Replace all occurrences of the default material with a // Replace all occurrences of the default material with a
@@ -196,12 +196,12 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
AI_DEBUG_INVALIDATE_PTR(mRootNode); AI_DEBUG_INVALIDATE_PTR(mRootNode);
AI_DEBUG_INVALIDATE_PTR(mScene); AI_DEBUG_INVALIDATE_PTR(mScene);
AI_DEBUG_INVALIDATE_PTR(this->stream); AI_DEBUG_INVALIDATE_PTR(mStream);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Applies a master-scaling factor to the imported scene // Applies a master-scaling factor to the imported scene
void Discreet3DSImporter::ApplyMasterScale(aiScene *pScene) { void Discreet3DSImporter::ApplyMasterScale(const aiScene *pScene) {
// There are some 3DS files with a zero scaling factor // There are some 3DS files with a zero scaling factor
if (!mMasterScale) if (!mMasterScale)
mMasterScale = 1.0f; mMasterScale = 1.0f;
@@ -223,14 +223,14 @@ void Discreet3DSImporter::ApplyMasterScale(aiScene *pScene) {
void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk *pcOut) { void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk *pcOut) {
ai_assert(pcOut != nullptr); ai_assert(pcOut != nullptr);
pcOut->Flag = stream->GetI2(); pcOut->Flag = mStream->GetI2();
pcOut->Size = stream->GetI4(); pcOut->Size = mStream->GetI4();
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize()) { if (pcOut->Size - sizeof(Discreet3DS::Chunk) > mStream->GetRemainingSize()) {
throw DeadlyImportError("Chunk is too large"); throw DeadlyImportError("Chunk is too large");
} }
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) { if (pcOut->Size - sizeof(Discreet3DS::Chunk) > mStream->GetRemainingSizeToLimit()) {
ASSIMP_LOG_ERROR("3DS: Chunk overflow"); ASSIMP_LOG_ERROR("3DS: Chunk overflow");
} }
} }
@@ -241,8 +241,7 @@ void Discreet3DSImporter::SkipChunk() {
Discreet3DS::Chunk psChunk; Discreet3DS::Chunk psChunk;
ReadChunk(&psChunk); ReadChunk(&psChunk);
stream->IncPtr(psChunk.Size - sizeof(Discreet3DS::Chunk)); mStream->IncPtr(psChunk.Size - sizeof(Discreet3DS::Chunk));
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@@ -259,7 +258,7 @@ void Discreet3DSImporter::ParseMainChunk() {
case Discreet3DS::CHUNK_MAIN: case Discreet3DS::CHUNK_MAIN:
ParseEditorChunk(); ParseEditorChunk();
break; break;
}; }
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
#if defined(__clang__) #if defined(__clang__)
@@ -275,30 +274,29 @@ void Discreet3DSImporter::ParseMainChunk() {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseEditorChunk() { void Discreet3DSImporter::ParseEditorChunk() {
ASSIMP_3DS_BEGIN_CHUNK(); ASSIMP_3DS_BEGIN_CHUNK()
// get chunk type // get chunk type
switch (chunk.Flag) { switch (chunk.Flag) {
case Discreet3DS::CHUNK_OBJMESH: case Discreet3DS::CHUNK_OBJMESH:
ParseObjectChunk();
break;
ParseObjectChunk(); // NOTE: In several documentations in the internet this
// chunk appears at different locations
case Discreet3DS::CHUNK_KEYFRAMER:
ParseKeyframeChunk();
break;
case Discreet3DS::CHUNK_VERSION: {
// print the version number
char buff[10];
ASSIMP_itoa10(buff, mStream->GetI2());
ASSIMP_LOG_INFO("3DS file format version: ", buff);
}
break; break;
// NOTE: In several documentations in the internet this
// chunk appears at different locations
case Discreet3DS::CHUNK_KEYFRAMER:
ParseKeyframeChunk();
break;
case Discreet3DS::CHUNK_VERSION: {
// print the version number
char buff[10];
ASSIMP_itoa10(buff, stream->GetI2());
ASSIMP_LOG_INFO("3DS file format version: ", buff);
} break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@@ -309,10 +307,10 @@ void Discreet3DSImporter::ParseObjectChunk() {
switch (chunk.Flag) { switch (chunk.Flag) {
case Discreet3DS::CHUNK_OBJBLOCK: { case Discreet3DS::CHUNK_OBJBLOCK: {
unsigned int cnt = 0; unsigned int cnt = 0;
const char *sz = (const char *)stream->GetPtr(); const auto *sz = (const char *)mStream->GetPtr();
// Get the name of the geometry object // Get the name of the geometry object
while (stream->GetI1()) while (mStream->GetI1())
++cnt; ++cnt;
ParseChunk(sz, cnt); ParseChunk(sz, cnt);
} break; } break;
@@ -340,8 +338,8 @@ void Discreet3DSImporter::ParseObjectChunk() {
// Specifies the background image. The string should already be // Specifies the background image. The string should already be
// properly 0 terminated but we need to be sure // properly 0 terminated but we need to be sure
unsigned int cnt = 0; unsigned int cnt = 0;
const char *sz = (const char *)stream->GetPtr(); auto *sz = (const char *)mStream->GetPtr();
while (stream->GetI1()) while (mStream->GetI1())
++cnt; ++cnt;
mBackgroundImage = std::string(sz, cnt); mBackgroundImage = std::string(sz, cnt);
} break; } break;
@@ -352,7 +350,7 @@ void Discreet3DSImporter::ParseObjectChunk() {
case Discreet3DS::CHUNK_MASTER_SCALE: case Discreet3DS::CHUNK_MASTER_SCALE:
// Scene master scaling factor // Scene master scaling factor
mMasterScale = stream->GetF4(); mMasterScale = mStream->GetF4();
break; break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
@@ -379,15 +377,15 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
case Discreet3DS::CHUNK_LIGHT: { case Discreet3DS::CHUNK_LIGHT: {
// This starts a new light // This starts a new light
aiLight *light = new aiLight(); auto *light = new aiLight();
mScene->mLights.push_back(light); mScene->mLights.push_back(light);
light->mName.Set(std::string(name, num)); light->mName.Set(std::string(name, num));
// First read the position of the light // First read the position of the light
light->mPosition.x = stream->GetF4(); light->mPosition.x = mStream->GetF4();
light->mPosition.y = stream->GetF4(); light->mPosition.y = mStream->GetF4();
light->mPosition.z = stream->GetF4(); light->mPosition.z = mStream->GetF4();
light->mColorDiffuse = aiColor3D(1.f, 1.f, 1.f); light->mColorDiffuse = aiColor3D(1.f, 1.f, 1.f);
@@ -408,19 +406,19 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
case Discreet3DS::CHUNK_CAMERA: { case Discreet3DS::CHUNK_CAMERA: {
// This starts a new camera // This starts a new camera
aiCamera *camera = new aiCamera(); auto *camera = new aiCamera();
mScene->mCameras.push_back(camera); mScene->mCameras.push_back(camera);
camera->mName.Set(std::string(name, num)); camera->mName.Set(std::string(name, num));
// First read the position of the camera // First read the position of the camera
camera->mPosition.x = stream->GetF4(); camera->mPosition.x = mStream->GetF4();
camera->mPosition.y = stream->GetF4(); camera->mPosition.y = mStream->GetF4();
camera->mPosition.z = stream->GetF4(); camera->mPosition.z = mStream->GetF4();
// Then the camera target // Then the camera target
camera->mLookAt.x = stream->GetF4() - camera->mPosition.x; camera->mLookAt.x = mStream->GetF4() - camera->mPosition.x;
camera->mLookAt.y = stream->GetF4() - camera->mPosition.y; camera->mLookAt.y = mStream->GetF4() - camera->mPosition.y;
camera->mLookAt.z = stream->GetF4() - camera->mPosition.z; camera->mLookAt.z = mStream->GetF4() - camera->mPosition.z;
ai_real len = camera->mLookAt.Length(); ai_real len = camera->mLookAt.Length();
if (len < 1e-5) { if (len < 1e-5) {
@@ -432,12 +430,12 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
camera->mLookAt /= len; camera->mLookAt /= len;
// And finally - the camera rotation angle, in counter clockwise direction // And finally - the camera rotation angle, in counter clockwise direction
const ai_real angle = AI_DEG_TO_RAD(stream->GetF4()); const ai_real angle = AI_DEG_TO_RAD(mStream->GetF4());
aiQuaternion quat(camera->mLookAt, angle); aiQuaternion quat(camera->mLookAt, angle);
camera->mUp = quat.GetMatrix() * aiVector3D(0.0, 1.0, 0.0); camera->mUp = quat.GetMatrix() * aiVector3D(0.0, 1.0, 0.0);
// Read the lense angle // Read the lense angle
camera->mHorizontalFOV = AI_DEG_TO_RAD(stream->GetF4()); camera->mHorizontalFOV = AI_DEG_TO_RAD(mStream->GetF4());
if (camera->mHorizontalFOV < 0.001f) { if (camera->mHorizontalFOV < 0.001f) {
camera->mHorizontalFOV = float(AI_DEG_TO_RAD(45.f)); camera->mHorizontalFOV = float(AI_DEG_TO_RAD(45.f));
} }
@@ -463,34 +461,34 @@ void Discreet3DSImporter::ParseLightChunk() {
light->mType = aiLightSource_SPOT; light->mType = aiLightSource_SPOT;
// We wouldn't need to normalize here, but we do it // We wouldn't need to normalize here, but we do it
light->mDirection.x = stream->GetF4() - light->mPosition.x; light->mDirection.x = mStream->GetF4() - light->mPosition.x;
light->mDirection.y = stream->GetF4() - light->mPosition.y; light->mDirection.y = mStream->GetF4() - light->mPosition.y;
light->mDirection.z = stream->GetF4() - light->mPosition.z; light->mDirection.z = mStream->GetF4() - light->mPosition.z;
light->mDirection.Normalize(); light->mDirection.Normalize();
// Now the hotspot and falloff angles - in degrees // Now the hotspot and falloff angles - in degrees
light->mAngleInnerCone = AI_DEG_TO_RAD(stream->GetF4()); light->mAngleInnerCone = AI_DEG_TO_RAD(mStream->GetF4());
// FIX: the falloff angle is just an offset // FIX: the falloff angle is just an offset
light->mAngleOuterCone = light->mAngleInnerCone + AI_DEG_TO_RAD(stream->GetF4()); light->mAngleOuterCone = light->mAngleInnerCone + AI_DEG_TO_RAD(mStream->GetF4());
break; break;
// intensity multiplier // intensity multiplier
case Discreet3DS::CHUNK_DL_MULTIPLIER: case Discreet3DS::CHUNK_DL_MULTIPLIER:
light->mColorDiffuse = light->mColorDiffuse * stream->GetF4(); light->mColorDiffuse = light->mColorDiffuse * mStream->GetF4();
break; break;
// light color // light color
case Discreet3DS::CHUNK_RGBF: case Discreet3DS::CHUNK_RGBF:
case Discreet3DS::CHUNK_LINRGBF: case Discreet3DS::CHUNK_LINRGBF:
light->mColorDiffuse.r *= stream->GetF4(); light->mColorDiffuse.r *= mStream->GetF4();
light->mColorDiffuse.g *= stream->GetF4(); light->mColorDiffuse.g *= mStream->GetF4();
light->mColorDiffuse.b *= stream->GetF4(); light->mColorDiffuse.b *= mStream->GetF4();
break; break;
// light attenuation // light attenuation
case Discreet3DS::CHUNK_DL_ATTENUATE: case Discreet3DS::CHUNK_DL_ATTENUATE:
light->mAttenuationLinear = stream->GetF4(); light->mAttenuationLinear = mStream->GetF4();
break; break;
}; };
@@ -505,10 +503,10 @@ void Discreet3DSImporter::ParseCameraChunk() {
// get chunk type // get chunk type
switch (chunk.Flag) { switch (chunk.Flag) {
// near and far clip plane // near and far clip plane
case Discreet3DS::CHUNK_CAM_RANGES: case Discreet3DS::CHUNK_CAM_RANGES:
camera->mClipPlaneNear = stream->GetF4(); camera->mClipPlaneNear = mStream->GetF4();
camera->mClipPlaneFar = stream->GetF4(); camera->mClipPlaneFar = mStream->GetF4();
break; break;
} }
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
@@ -555,14 +553,13 @@ void Discreet3DSImporter::InverseNodeSearch(D3DS::Node *pcNode, D3DS::Node *pcCu
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Find a node with a specific name in the import hierarchy // Find a node with a specific name in the import hierarchy
D3DS::Node *FindNode(D3DS::Node *root, const std::string &name) { Node *FindNode(Node *root, const std::string &name) {
if (root->mName == name) { if (root->mName == name) {
return root; return root;
} }
for (std::vector<D3DS::Node *>::iterator it = root->mChildren.begin(); it != root->mChildren.end(); ++it) { for (auto it = root->mChildren.begin(); it != root->mChildren.end(); ++it) {
D3DS::Node *nd = FindNode(*it, name); if (auto *nd = FindNode(*it, name); nullptr != nd) {
if (nullptr != nd) {
return nd; return nd;
} }
} }
@@ -580,7 +577,7 @@ bool KeyUniqueCompare(const T &first, const T &second) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Skip some additional import data. // Skip some additional import data.
void Discreet3DSImporter::SkipTCBInfo() { void Discreet3DSImporter::SkipTCBInfo() {
unsigned int flags = stream->GetI2(); unsigned int flags = mStream->GetI2();
if (!flags) { if (!flags) {
// Currently we can't do anything with these values. They occur // Currently we can't do anything with these values. They occur
@@ -591,19 +588,19 @@ void Discreet3DSImporter::SkipTCBInfo() {
} }
if (flags & Discreet3DS::KEY_USE_TENS) { if (flags & Discreet3DS::KEY_USE_TENS) {
stream->IncPtr(4); mStream->IncPtr(4);
} }
if (flags & Discreet3DS::KEY_USE_BIAS) { if (flags & Discreet3DS::KEY_USE_BIAS) {
stream->IncPtr(4); mStream->IncPtr(4);
} }
if (flags & Discreet3DS::KEY_USE_CONT) { if (flags & Discreet3DS::KEY_USE_CONT) {
stream->IncPtr(4); mStream->IncPtr(4);
} }
if (flags & Discreet3DS::KEY_USE_EASE_FROM) { if (flags & Discreet3DS::KEY_USE_EASE_FROM) {
stream->IncPtr(4); mStream->IncPtr(4);
} }
if (flags & Discreet3DS::KEY_USE_EASE_TO) { if (flags & Discreet3DS::KEY_USE_EASE_TO) {
stream->IncPtr(4); mStream->IncPtr(4);
} }
} }
@@ -622,15 +619,15 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// First of all: get the name of the object // First of all: get the name of the object
unsigned int cnt = 0; unsigned int cnt = 0;
const char *sz = (const char *)stream->GetPtr(); auto *sz = (const char *)mStream->GetPtr();
while (stream->GetI1()) while (mStream->GetI1())
++cnt; ++cnt;
std::string name = std::string(sz, cnt); std::string name = std::string(sz, cnt);
// Now find out whether we have this node already (target animation channels // Now find out whether we have this node already (target animation channels
// are stored with a separate object ID) // are stored with a separate object ID)
D3DS::Node *pcNode = FindNode(mRootNode, name); Node *pcNode = FindNode(mRootNode, name);
int instanceNumber = 1; int instanceNumber = 1;
if (pcNode) { if (pcNode) {
@@ -646,10 +643,10 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
pcNode->mInstanceNumber = instanceNumber; pcNode->mInstanceNumber = instanceNumber;
// There are two unknown values which we can safely ignore // There are two unknown values which we can safely ignore
stream->IncPtr(4); mStream->IncPtr(4);
// Now read the hierarchy position of the object // Now read the hierarchy position of the object
uint16_t hierarchy = stream->GetI2() + 1; uint16_t hierarchy = mStream->GetI2() + 1;
pcNode->mHierarchyPos = hierarchy; pcNode->mHierarchyPos = hierarchy;
pcNode->mHierarchyIndex = mLastNodeIndex; pcNode->mHierarchyIndex = mLastNodeIndex;
@@ -678,8 +675,8 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// This is the "real" name of a $$$DUMMY object // This is the "real" name of a $$$DUMMY object
{ {
const char *sz = (const char *)stream->GetPtr(); const char *sz = (const char *)mStream->GetPtr();
while (stream->GetI1()) while (mStream->GetI1())
; ;
// If object name is DUMMY, take this one instead // If object name is DUMMY, take this one instead
@@ -698,16 +695,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
} }
// Pivot = origin of rotation and scaling // Pivot = origin of rotation and scaling
mCurrentNode->vPivot.x = stream->GetF4(); mCurrentNode->vPivot.x = mStream->GetF4();
mCurrentNode->vPivot.y = stream->GetF4(); mCurrentNode->vPivot.y = mStream->GetF4();
mCurrentNode->vPivot.z = stream->GetF4(); mCurrentNode->vPivot.z = mStream->GetF4();
break; break;
// //////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////
// POSITION KEYFRAME // POSITION KEYFRAME
case Discreet3DS::CHUNK_TRACKPOS: { case Discreet3DS::CHUNK_TRACKPOS: {
stream->IncPtr(10); mStream->IncPtr(10);
const unsigned int numFrames = stream->GetI4(); const unsigned int numFrames = mStream->GetI4();
bool sortKeys = false; bool sortKeys = false;
// This could also be meant as the target position for // This could also be meant as the target position for
@@ -720,16 +717,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
l->reserve(numFrames); l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) { for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = stream->GetI4(); const unsigned int fidx = mStream->GetI4();
// Setup a new position key // Setup a new position key
aiVectorKey v; aiVectorKey v;
v.mTime = (double)fidx; v.mTime = (double)fidx;
SkipTCBInfo(); SkipTCBInfo();
v.mValue.x = stream->GetF4(); v.mValue.x = mStream->GetF4();
v.mValue.y = stream->GetF4(); v.mValue.y = mStream->GetF4();
v.mValue.z = stream->GetF4(); v.mValue.z = mStream->GetF4();
// check whether we'll need to sort the keys // check whether we'll need to sort the keys
if (!l->empty() && v.mTime <= l->back().mTime) if (!l->empty() && v.mTime <= l->back().mTime)
@@ -759,11 +756,11 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
bool sortKeys = false; bool sortKeys = false;
std::vector<aiFloatKey> *l = &mCurrentNode->aCameraRollKeys; std::vector<aiFloatKey> *l = &mCurrentNode->aCameraRollKeys;
stream->IncPtr(10); mStream->IncPtr(10);
const unsigned int numFrames = stream->GetI4(); const unsigned int numFrames = mStream->GetI4();
l->reserve(numFrames); l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) { for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = stream->GetI4(); const unsigned int fidx = mStream->GetI4();
// Setup a new position key // Setup a new position key
aiFloatKey v; aiFloatKey v;
@@ -771,7 +768,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// This is just a single float // This is just a single float
SkipTCBInfo(); SkipTCBInfo();
v.mValue = stream->GetF4(); v.mValue = mStream->GetF4();
// Check whether we'll need to sort the keys // Check whether we'll need to sort the keys
if (!l->empty() && v.mTime <= l->back().mTime) if (!l->empty() && v.mTime <= l->back().mTime)
@@ -798,26 +795,26 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// //////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////
// ROTATION KEYFRAME // ROTATION KEYFRAME
case Discreet3DS::CHUNK_TRACKROTATE: { case Discreet3DS::CHUNK_TRACKROTATE: {
stream->IncPtr(10); mStream->IncPtr(10);
const unsigned int numFrames = stream->GetI4(); const unsigned int numFrames = mStream->GetI4();
bool sortKeys = false; bool sortKeys = false;
std::vector<aiQuatKey> *l = &mCurrentNode->aRotationKeys; std::vector<aiQuatKey> *l = &mCurrentNode->aRotationKeys;
l->reserve(numFrames); l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) { for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = stream->GetI4(); const unsigned int fidx = mStream->GetI4();
SkipTCBInfo(); SkipTCBInfo();
aiQuatKey v; aiQuatKey v;
v.mTime = (double)fidx; v.mTime = (double)fidx;
// The rotation keyframe is given as an axis-angle pair // The rotation keyframe is given as an axis-angle pair
const float rad = stream->GetF4(); const float rad = mStream->GetF4();
aiVector3D axis; aiVector3D axis;
axis.x = stream->GetF4(); axis.x = mStream->GetF4();
axis.y = stream->GetF4(); axis.y = mStream->GetF4();
axis.z = stream->GetF4(); axis.z = mStream->GetF4();
if (!axis.x && !axis.y && !axis.z) if (!axis.x && !axis.y && !axis.z)
axis.y = 1.f; axis.y = 1.f;
@@ -842,16 +839,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// //////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////
// SCALING KEYFRAME // SCALING KEYFRAME
case Discreet3DS::CHUNK_TRACKSCALE: { case Discreet3DS::CHUNK_TRACKSCALE: {
stream->IncPtr(10); mStream->IncPtr(10);
const unsigned int numFrames = stream->GetI2(); const unsigned int numFrames = mStream->GetI2();
stream->IncPtr(2); mStream->IncPtr(2);
bool sortKeys = false; bool sortKeys = false;
std::vector<aiVectorKey> *l = &mCurrentNode->aScalingKeys; std::vector<aiVectorKey> *l = &mCurrentNode->aScalingKeys;
l->reserve(numFrames); l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) { for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = stream->GetI4(); const unsigned int fidx = mStream->GetI4();
SkipTCBInfo(); SkipTCBInfo();
// Setup a new key // Setup a new key
@@ -859,9 +856,9 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
v.mTime = (double)fidx; v.mTime = (double)fidx;
// ... and read its value // ... and read its value
v.mValue.x = stream->GetF4(); v.mValue.x = mStream->GetF4();
v.mValue.y = stream->GetF4(); v.mValue.y = mStream->GetF4();
v.mValue.z = stream->GetF4(); v.mValue.z = mStream->GetF4();
// check whether we'll need to sort the keys // check whether we'll need to sort the keys
if (!l->empty() && v.mTime <= l->back().mTime) if (!l->empty() && v.mTime <= l->back().mTime)
@@ -902,23 +899,23 @@ void Discreet3DSImporter::ParseFaceChunk() {
if (num > mMesh.mFaces.size()) { if (num > mMesh.mFaces.size()) {
throw DeadlyImportError("3DS: More smoothing groups than faces"); throw DeadlyImportError("3DS: More smoothing groups than faces");
} }
for (std::vector<D3DS::Face>::iterator i = mMesh.mFaces.begin(); m != num; ++i, ++m) { for (auto i = mMesh.mFaces.begin(); m != num; ++i, ++m) {
// nth bit is set for nth smoothing group // nth bit is set for nth smoothing group
(*i).iSmoothGroup = stream->GetI4(); i->iSmoothGroup = mStream->GetI4();
} }
} break; } break;
case Discreet3DS::CHUNK_FACEMAT: { case Discreet3DS::CHUNK_FACEMAT: {
// at fist an asciiz with the material name // at fist an asciiz with the material name
const char *sz = (const char *)stream->GetPtr(); const char *sz = (const char *)mStream->GetPtr();
while (stream->GetI1()) while (mStream->GetI1())
; ;
// find the index of the material // find the index of the material
unsigned int idx = 0xcdcdcdcd, cnt = 0; unsigned int idx = 0xcdcdcdcd, cnt = 0;
for (std::vector<D3DS::Material>::const_iterator i = mScene->mMaterials.begin(); i != mScene->mMaterials.end(); ++i, ++cnt) { for (auto i = mScene->mMaterials.begin(); i != mScene->mMaterials.end(); ++i, ++cnt) {
// use case independent comparisons. hopefully it will work. // use case independent comparisons. hopefully it will work.
if ((*i).mName.length() && !ASSIMP_stricmp(sz, (*i).mName.c_str())) { if (i->mName.length() && !ASSIMP_stricmp(sz, i->mName.c_str())) {
idx = cnt; idx = cnt;
break; break;
} }
@@ -928,9 +925,9 @@ void Discreet3DSImporter::ParseFaceChunk() {
} }
// Now continue and read all material indices // Now continue and read all material indices
cnt = (uint16_t)stream->GetI2(); cnt = (uint16_t)mStream->GetI2();
for (unsigned int i = 0; i < cnt; ++i) { for (unsigned int i = 0; i < cnt; ++i) {
unsigned int fidx = (uint16_t)stream->GetI2(); unsigned int fidx = (uint16_t)mStream->GetI2();
// check range // check range
if (fidx >= mMesh.mFaceMaterials.size()) { if (fidx >= mMesh.mFaceMaterials.size()) {
@@ -955,59 +952,59 @@ void Discreet3DSImporter::ParseMeshChunk() {
switch (chunk.Flag) { switch (chunk.Flag) {
case Discreet3DS::CHUNK_VERTLIST: { case Discreet3DS::CHUNK_VERTLIST: {
// This is the list of all vertices in the current mesh // This is the list of all vertices in the current mesh
int num = (int)(uint16_t)stream->GetI2(); int num = (int)(uint16_t)mStream->GetI2();
mMesh.mPositions.reserve(num); mMesh.mPositions.reserve(num);
while (num-- > 0) { while (num-- > 0) {
aiVector3D v; aiVector3D v;
v.x = stream->GetF4(); v.x = mStream->GetF4();
v.y = stream->GetF4(); v.y = mStream->GetF4();
v.z = stream->GetF4(); v.z = mStream->GetF4();
mMesh.mPositions.push_back(v); mMesh.mPositions.push_back(v);
} }
} break; } break;
case Discreet3DS::CHUNK_TRMATRIX: { case Discreet3DS::CHUNK_TRMATRIX: {
// This is the RLEATIVE transformation matrix of the current mesh. Vertices are // This is the RLEATIVE transformation matrix of the current mesh. Vertices are
// pretransformed by this matrix wonder. // pretransformed by this matrix wonder.
mMesh.mMat.a1 = stream->GetF4(); mMesh.mMat.a1 = mStream->GetF4();
mMesh.mMat.b1 = stream->GetF4(); mMesh.mMat.b1 = mStream->GetF4();
mMesh.mMat.c1 = stream->GetF4(); mMesh.mMat.c1 = mStream->GetF4();
mMesh.mMat.a2 = stream->GetF4(); mMesh.mMat.a2 = mStream->GetF4();
mMesh.mMat.b2 = stream->GetF4(); mMesh.mMat.b2 = mStream->GetF4();
mMesh.mMat.c2 = stream->GetF4(); mMesh.mMat.c2 = mStream->GetF4();
mMesh.mMat.a3 = stream->GetF4(); mMesh.mMat.a3 = mStream->GetF4();
mMesh.mMat.b3 = stream->GetF4(); mMesh.mMat.b3 = mStream->GetF4();
mMesh.mMat.c3 = stream->GetF4(); mMesh.mMat.c3 = mStream->GetF4();
mMesh.mMat.a4 = stream->GetF4(); mMesh.mMat.a4 = mStream->GetF4();
mMesh.mMat.b4 = stream->GetF4(); mMesh.mMat.b4 = mStream->GetF4();
mMesh.mMat.c4 = stream->GetF4(); mMesh.mMat.c4 = mStream->GetF4();
} break; } break;
case Discreet3DS::CHUNK_MAPLIST: { case Discreet3DS::CHUNK_MAPLIST: {
// This is the list of all UV coords in the current mesh // This is the list of all UV coords in the current mesh
int num = (int)(uint16_t)stream->GetI2(); int num = (int)(uint16_t)mStream->GetI2();
mMesh.mTexCoords.reserve(num); mMesh.mTexCoords.reserve(num);
while (num-- > 0) { while (num-- > 0) {
aiVector3D v; aiVector3D v;
v.x = stream->GetF4(); v.x = mStream->GetF4();
v.y = stream->GetF4(); v.y = mStream->GetF4();
mMesh.mTexCoords.push_back(v); mMesh.mTexCoords.push_back(v);
} }
} break; } break;
case Discreet3DS::CHUNK_FACELIST: { case Discreet3DS::CHUNK_FACELIST: {
// This is the list of all faces in the current mesh // This is the list of all faces in the current mesh
int num = (int)(uint16_t)stream->GetI2(); int num = (int)(uint16_t)mStream->GetI2();
mMesh.mFaces.reserve(num); mMesh.mFaces.reserve(num);
while (num-- > 0) { while (num-- > 0) {
// 3DS faces are ALWAYS triangles // 3DS faces are ALWAYS triangles
mMesh.mFaces.emplace_back(); mMesh.mFaces.emplace_back();
D3DS::Face &sFace = mMesh.mFaces.back(); Face &sFace = mMesh.mFaces.back();
sFace.mIndices[0] = (uint16_t)stream->GetI2(); sFace.mIndices[0] = (uint16_t)mStream->GetI2();
sFace.mIndices[1] = (uint16_t)stream->GetI2(); sFace.mIndices[1] = (uint16_t)mStream->GetI2();
sFace.mIndices[2] = (uint16_t)stream->GetI2(); sFace.mIndices[2] = (uint16_t)mStream->GetI2();
stream->IncPtr(2); // skip edge visibility flag mStream->IncPtr(2); // skip edge visibility flag
} }
// Resize the material array (0xcdcdcdcd marks the default material; so if a face is // Resize the material array (0xcdcdcdcd marks the default material; so if a face is
@@ -1015,7 +1012,7 @@ void Discreet3DSImporter::ParseMeshChunk() {
mMesh.mFaceMaterials.resize(mMesh.mFaces.size(), 0xcdcdcdcd); mMesh.mFaceMaterials.resize(mMesh.mFaces.size(), 0xcdcdcdcd);
// Larger 3DS files could have multiple FACE chunks here // Larger 3DS files could have multiple FACE chunks here
chunkSize = (int)stream->GetRemainingSizeToLimit(); chunkSize = (int)mStream->GetRemainingSizeToLimit();
if (chunkSize > (int)sizeof(Discreet3DS::Chunk)) if (chunkSize > (int)sizeof(Discreet3DS::Chunk))
ParseFaceChunk(); ParseFaceChunk();
} break; } break;
@@ -1032,9 +1029,9 @@ void Discreet3DSImporter::ParseMaterialChunk() {
{ {
// The material name string is already zero-terminated, but we need to be sure ... // The material name string is already zero-terminated, but we need to be sure ...
const char *sz = (const char *)stream->GetPtr(); const char *sz = (const char *)mStream->GetPtr();
unsigned int cnt = 0; unsigned int cnt = 0;
while (stream->GetI1()) while (mStream->GetI1())
++cnt; ++cnt;
if (!cnt) { if (!cnt) {
@@ -1102,7 +1099,7 @@ void Discreet3DSImporter::ParseMaterialChunk() {
case Discreet3DS::CHUNK_MAT_SHADING: case Discreet3DS::CHUNK_MAT_SHADING:
// This is the material shading mode // This is the material shading mode
mScene->mMaterials.back().mShading = (D3DS::Discreet3DS::shadetype3ds)stream->GetI2(); mScene->mMaterials.back().mShading = (Discreet3DS::shadetype3ds)mStream->GetI2();
break; break;
case Discreet3DS::CHUNK_MAT_TWO_SIDE: case Discreet3DS::CHUNK_MAT_TWO_SIDE:
@@ -1178,31 +1175,31 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) {
switch (chunk.Flag) { switch (chunk.Flag) {
case Discreet3DS::CHUNK_MAPFILE: { case Discreet3DS::CHUNK_MAPFILE: {
// The material name string is already zero-terminated, but we need to be sure ... // The material name string is already zero-terminated, but we need to be sure ...
const char *sz = (const char *)stream->GetPtr(); const char *sz = (const char *)mStream->GetPtr();
unsigned int cnt = 0; unsigned int cnt = 0;
while (stream->GetI1()) while (mStream->GetI1())
++cnt; ++cnt;
pcOut->mMapName = std::string(sz, cnt); pcOut->mMapName = std::string(sz, cnt);
} break; } break;
case Discreet3DS::CHUNK_PERCENTD: case Discreet3DS::CHUNK_PERCENTD:
// Manually parse the blend factor // Manually parse the blend factor
pcOut->mTextureBlend = ai_real(stream->GetF8()); pcOut->mTextureBlend = ai_real(mStream->GetF8());
break; break;
case Discreet3DS::CHUNK_PERCENTF: case Discreet3DS::CHUNK_PERCENTF:
// Manually parse the blend factor // Manually parse the blend factor
pcOut->mTextureBlend = stream->GetF4(); pcOut->mTextureBlend = mStream->GetF4();
break; break;
case Discreet3DS::CHUNK_PERCENTW: case Discreet3DS::CHUNK_PERCENTW:
// Manually parse the blend factor // Manually parse the blend factor
pcOut->mTextureBlend = (ai_real)((uint16_t)stream->GetI2()) / ai_real(100.0); pcOut->mTextureBlend = (ai_real)((uint16_t) mStream->GetI2()) / ai_real(100.0);
break; break;
case Discreet3DS::CHUNK_MAT_MAP_USCALE: case Discreet3DS::CHUNK_MAT_MAP_USCALE:
// Texture coordinate scaling in the U direction // Texture coordinate scaling in the U direction
pcOut->mScaleU = stream->GetF4(); pcOut->mScaleU = mStream->GetF4();
if (0.0f == pcOut->mScaleU) { if (0.0f == pcOut->mScaleU) {
ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1."); ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1.");
pcOut->mScaleU = 1.0f; pcOut->mScaleU = 1.0f;
@@ -1210,7 +1207,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) {
break; break;
case Discreet3DS::CHUNK_MAT_MAP_VSCALE: case Discreet3DS::CHUNK_MAT_MAP_VSCALE:
// Texture coordinate scaling in the V direction // Texture coordinate scaling in the V direction
pcOut->mScaleV = stream->GetF4(); pcOut->mScaleV = mStream->GetF4();
if (0.0f == pcOut->mScaleV) { if (0.0f == pcOut->mScaleV) {
ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1."); ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1.");
pcOut->mScaleV = 1.0f; pcOut->mScaleV = 1.0f;
@@ -1219,21 +1216,21 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) {
case Discreet3DS::CHUNK_MAT_MAP_UOFFSET: case Discreet3DS::CHUNK_MAT_MAP_UOFFSET:
// Texture coordinate offset in the U direction // Texture coordinate offset in the U direction
pcOut->mOffsetU = -stream->GetF4(); pcOut->mOffsetU = -mStream->GetF4();
break; break;
case Discreet3DS::CHUNK_MAT_MAP_VOFFSET: case Discreet3DS::CHUNK_MAT_MAP_VOFFSET:
// Texture coordinate offset in the V direction // Texture coordinate offset in the V direction
pcOut->mOffsetV = stream->GetF4(); pcOut->mOffsetV = mStream->GetF4();
break; break;
case Discreet3DS::CHUNK_MAT_MAP_ANG: case Discreet3DS::CHUNK_MAT_MAP_ANG:
// Texture coordinate rotation, CCW in DEGREES // Texture coordinate rotation, CCW in DEGREES
pcOut->mRotation = -AI_DEG_TO_RAD(stream->GetF4()); pcOut->mRotation = -AI_DEG_TO_RAD(mStream->GetF4());
break; break;
case Discreet3DS::CHUNK_MAT_MAP_TILING: { case Discreet3DS::CHUNK_MAT_MAP_TILING: {
const uint16_t iFlags = stream->GetI2(); const uint16_t iFlags = mStream->GetI2();
// Get the mapping mode (for both axes) // Get the mapping mode (for both axes)
if (iFlags & 0x2u) if (iFlags & 0x2u)
@@ -1258,9 +1255,11 @@ ai_real Discreet3DSImporter::ParsePercentageChunk() {
ReadChunk(&chunk); ReadChunk(&chunk);
if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) { if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) {
return stream->GetF4() * ai_real(100) / ai_real(0xFFFF); return mStream->GetF4() * ai_real(100) / ai_real(0xFFFF);
} else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) { }
return (ai_real)((uint16_t)stream->GetI2()) / (ai_real)0xFFFF;
if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) {
return (ai_real)((uint16_t)mStream->GetI2()) / (ai_real)0xFFFF;
} }
return get_qnan(); return get_qnan();
@@ -1291,9 +1290,9 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
*out = clrError; *out = clrError;
return; return;
} }
out->r = stream->GetF4(); out->r = mStream->GetF4();
out->g = stream->GetF4(); out->g = mStream->GetF4();
out->b = stream->GetF4(); out->b = mStream->GetF4();
break; break;
case Discreet3DS::CHUNK_LINRGBB: case Discreet3DS::CHUNK_LINRGBB:
@@ -1305,15 +1304,15 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
return; return;
} }
const ai_real invVal = ai_real(1.0) / ai_real(255.0); const ai_real invVal = ai_real(1.0) / ai_real(255.0);
out->r = (ai_real)(uint8_t)stream->GetI1() * invVal; out->r = (ai_real)(uint8_t)mStream->GetI1() * invVal;
out->g = (ai_real)(uint8_t)stream->GetI1() * invVal; out->g = (ai_real)(uint8_t)mStream->GetI1() * invVal;
out->b = (ai_real)(uint8_t)stream->GetI1() * invVal; out->b = (ai_real)(uint8_t)mStream->GetI1() * invVal;
} break; } break;
// Percentage chunks are accepted, too. // Percentage chunks are accepted, too.
case Discreet3DS::CHUNK_PERCENTF: case Discreet3DS::CHUNK_PERCENTF:
if (acceptPercent && 4 <= diff) { if (acceptPercent && 4 <= diff) {
out->g = out->b = out->r = stream->GetF4(); out->g = out->b = out->r = mStream->GetF4();
break; break;
} }
*out = clrError; *out = clrError;
@@ -1321,14 +1320,14 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
case Discreet3DS::CHUNK_PERCENTW: case Discreet3DS::CHUNK_PERCENTW:
if (acceptPercent && 1 <= diff) { if (acceptPercent && 1 <= diff) {
out->g = out->b = out->r = (ai_real)(uint8_t)stream->GetI1() / ai_real(255.0); out->g = out->b = out->r = (ai_real)(uint8_t)mStream->GetI1() / ai_real(255.0);
break; break;
} }
*out = clrError; *out = clrError;
return; return;
default: default:
stream->IncPtr(diff); mStream->IncPtr(diff);
// Skip unknown chunks, hope this won't cause any problems. // Skip unknown chunks, hope this won't cause any problems.
return ParseColorChunk(out, acceptPercent); return ParseColorChunk(out, acceptPercent);
}; };
+24 -35
View File
@@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/types.h> #include <assimp/types.h>
#include "3DSHelper.h" #include "3DSHelper.h"
#include <assimp/StreamReader.h> #include <assimp/StreamReader.h>
@@ -57,8 +56,6 @@ struct aiNode;
namespace Assimp { namespace Assimp {
using namespace D3DS;
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files /** Importer class for 3D Studio r3 and r4 3DS files
*/ */
@@ -99,15 +96,14 @@ protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Converts a temporary material to the outer representation /** Converts a temporary material to the outer representation
*/ */
void ConvertMaterial(D3DS::Material& p_cMat, void ConvertMaterial(D3DS::Material& p_cMat, aiMaterial& p_pcOut);
aiMaterial& p_pcOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Read a chunk /** Read a chunk
* *
* @param pcOut Receives the current chunk * @param pcOut Receives the current chunk
*/ */
void ReadChunk(Discreet3DS::Chunk* pcOut); void ReadChunk(D3DS::Discreet3DS::Chunk* pcOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a percentage chunk. mCurrent will point to the next /** Parse a percentage chunk. mCurrent will point to the next
@@ -117,12 +113,10 @@ protected:
ai_real ParsePercentageChunk(); ai_real ParsePercentageChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a color chunk. mCurrent will point to the next /** Parse a color chunk. mCurrent will point to the next chunk behind
* chunk behind afterwards. If no color chunk is found * afterward. If no color chunk is found QNAN is returned in all members.
* QNAN is returned in all members. */
*/ void ParseColorChunk(aiColor3D* p_pcOut, bool p_bAcceptPercent = true);
void ParseColorChunk(aiColor3D* p_pcOut,
bool p_bAcceptPercent = true);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Skip a chunk in the file /** Skip a chunk in the file
@@ -130,7 +124,7 @@ protected:
void SkipChunk(); void SkipChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Generate the nodegraph /** Generate the node-graph
*/ */
void GenerateNodeGraph(aiScene* pcOut); void GenerateNodeGraph(aiScene* pcOut);
@@ -226,19 +220,19 @@ protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Add a node to the node graph /** Add a node to the node graph
*/ */
void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn, void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, D3DS::Node* pcIn,
aiMatrix4x4& absTrafo); aiMatrix4x4& absTrafo);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Search for a node in the graph. /** Search for a node in the graph.
* Called recursively * Called recursively
*/ */
void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent); void InverseNodeSearch(D3DS::Node* pcNode, D3DS::Node* pcCurrent);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Apply the master scaling factor to the mesh /** Apply the master scaling factor to the mesh
*/ */
void ApplyMasterScale(aiScene* pScene); void ApplyMasterScale(const aiScene* pScene);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Clamp all indices in the file to a valid range /** Clamp all indices in the file to a valid range
@@ -250,31 +244,26 @@ protected:
*/ */
void SkipTCBInfo(); void SkipTCBInfo();
protected: private:
/// Stream to read from
/** Stream to read from */ StreamReaderLE* mStream;
StreamReaderLE* stream; /// Last touched node index
/** Last touched node index */
short mLastNodeIndex; short mLastNodeIndex;
/// Current node
/** Current node, root node */ D3DS::Node* mCurrentNode;
D3DS::Node* mCurrentNode, *mRootNode; /// Root node
D3DS::Node *mRootNode;
/** Scene under construction */ /// Scene under construction
D3DS::Scene* mScene; D3DS::Scene* mScene;
/// Ambient base color of the scene
/** Ambient base color of the scene */
aiColor3D mClrAmbient; aiColor3D mClrAmbient;
/// Master scaling factor of the scene
/** Master scaling factor of the scene */
ai_real mMasterScale; ai_real mMasterScale;
/// Path to the background image of the scene
/** Path to the background image of the scene */
std::string mBackgroundImage; std::string mBackgroundImage;
/// true for has a background
bool bHasBG; bool bHasBG;
/// true if PRJ file
/** true if PRJ file */
bool bIsPrj; bool bIsPrj;
}; };
+15 -26
View File
@@ -49,8 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiMaterial; struct aiMaterial;
struct aiMesh; struct aiMesh;
namespace Assimp { namespace Assimp:: D3MF {
namespace D3MF {
enum class ResourceType { enum class ResourceType {
RT_Object, RT_Object,
@@ -65,8 +64,7 @@ class Resource {
public: public:
int mId; int mId;
Resource(int id) : explicit Resource(int id) : mId(id) {
mId(id) {
// empty // empty
} }
@@ -77,7 +75,7 @@ public:
} }
}; };
class EmbeddedTexture : public Resource { class EmbeddedTexture final : public Resource {
public: public:
std::string mPath; std::string mPath;
std::string mContentType; std::string mContentType;
@@ -85,12 +83,7 @@ public:
std::string mTilestyleV; std::string mTilestyleV;
std::vector<char> mBuffer; std::vector<char> mBuffer;
EmbeddedTexture(int id) : explicit EmbeddedTexture(int id) : Resource(id) {
Resource(id),
mPath(),
mContentType(),
mTilestyleU(),
mTilestyleV() {
// empty // empty
} }
@@ -101,13 +94,12 @@ public:
} }
}; };
class Texture2DGroup : public Resource { class Texture2DGroup final : public Resource {
public: public:
std::vector<aiVector2D> mTex2dCoords; std::vector<aiVector2D> mTex2dCoords;
int mTexId; int mTexId;
Texture2DGroup(int id) :
Resource(id), explicit Texture2DGroup(int id) : Resource(id), mTexId(-1) {
mTexId(-1) {
// empty // empty
} }
@@ -118,11 +110,11 @@ public:
} }
}; };
class ColorGroup : public Resource { class ColorGroup final : public Resource {
public: public:
std::vector<aiColor4D> mColors; std::vector<aiColor4D> mColors;
ColorGroup(int id) :
Resource(id){ explicit ColorGroup(int id) : Resource(id) {
// empty // empty
} }
@@ -133,13 +125,11 @@ public:
} }
}; };
class BaseMaterials : public Resource { class BaseMaterials final : public Resource {
public: public:
std::vector<unsigned int> mMaterialIndex; std::vector<unsigned int> mMaterialIndex;
BaseMaterials(int id) : explicit BaseMaterials(int id) : Resource(id) {
Resource(id),
mMaterialIndex() {
// empty // empty
} }
@@ -155,14 +145,14 @@ struct Component {
aiMatrix4x4 mTransformation; aiMatrix4x4 mTransformation;
}; };
class Object : public Resource { class Object final : public Resource {
public: public:
std::vector<aiMesh *> mMeshes; std::vector<aiMesh *> mMeshes;
std::vector<unsigned int> mMeshIndex; std::vector<unsigned int> mMeshIndex;
std::vector<Component> mComponents; std::vector<Component> mComponents;
std::string mName; std::string mName;
Object(int id) : explicit Object(int id) :
Resource(id), Resource(id),
mName(std::string("Object_") + ai_to_string(id)) { mName(std::string("Object_") + ai_to_string(id)) {
// empty // empty
@@ -175,5 +165,4 @@ public:
} }
}; };
} // namespace D3MF } // namespace Assimp::D3MF
} // namespace Assimp
+65 -70
View File
@@ -40,85 +40,80 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #pragma once
namespace Assimp { namespace Assimp::D3MF::XmlTag {
namespace D3MF {
namespace XmlTag {
// Root tag // Root tag
const char* const RootTag = "3MF"; constexpr char RootTag[] = "3MF";
// Meta-data // Meta-data
const char* const meta = "metadata"; constexpr char meta[] = "metadata";
const char* const meta_name = "name"; constexpr char meta_name[] = "name";
// Model-data specific tags // Model-data specific tags
const char* const model = "model"; constexpr char model[] = "model";
const char* const model_unit = "unit"; constexpr char model_unit[] = "unit";
const char* const metadata = "metadata"; constexpr char metadata[] = "metadata";
const char* const resources = "resources"; constexpr char resources[] = "resources";
const char* const object = "object"; constexpr char object[] = "object";
const char* const mesh = "mesh"; constexpr char mesh[] = "mesh";
const char* const components = "components"; constexpr char components[] = "components";
const char* const component = "component"; constexpr char component[] = "component";
const char* const vertices = "vertices"; constexpr char vertices[] = "vertices";
const char* const vertex = "vertex"; constexpr char vertex[] = "vertex";
const char* const triangles = "triangles"; constexpr char triangles[] = "triangles";
const char* const triangle = "triangle"; constexpr char triangle[] = "triangle";
const char* const x = "x"; constexpr char x[] = "x";
const char* const y = "y"; constexpr char y[] = "y";
const char* const z = "z"; constexpr char z[] = "z";
const char* const v1 = "v1"; constexpr char v1[] = "v1";
const char* const v2 = "v2"; constexpr char v2[] = "v2";
const char* const v3 = "v3"; constexpr char v3[] = "v3";
const char* const id = "id"; constexpr char id[] = "id";
const char* const pid = "pid"; constexpr char pid[] = "pid";
const char* const pindex = "pindex"; constexpr char pindex[] = "pindex";
const char* const p1 = "p1"; constexpr char p1[] = "p1";
const char *const p2 = "p2"; constexpr char p2[] = "p2";
const char *const p3 = "p3"; constexpr char p3[] = "p3";
const char* const name = "name"; constexpr char name[] = "name";
const char* const type = "type"; constexpr char type[] = "type";
const char* const build = "build"; constexpr char build[] = "build";
const char* const item = "item"; constexpr char item[] = "item";
const char* const objectid = "objectid"; constexpr char objectid[] = "objectid";
const char* const transform = "transform"; constexpr char transform[] = "transform";
const char *const path = "path"; constexpr char path[] = "path";
// Material definitions // Material definitions
const char* const basematerials = "basematerials"; constexpr char basematerials[] = "basematerials";
const char* const basematerials_base = "base"; constexpr char basematerials_base[] = "base";
const char* const basematerials_name = "name"; constexpr char basematerials_name[] = "name";
const char* const basematerials_displaycolor = "displaycolor"; constexpr char basematerials_displaycolor[] = "displaycolor";
const char* const texture_2d = "m:texture2d"; constexpr char texture_2d[] = "m:texture2d";
const char *const texture_group = "m:texture2dgroup"; constexpr char texture_group[] = "m:texture2dgroup";
const char *const texture_content_type = "contenttype"; constexpr char texture_content_type[] = "contenttype";
const char *const texture_tilestyleu = "tilestyleu"; constexpr char texture_tilestyleu[] = "tilestyleu";
const char *const texture_tilestylev = "tilestylev"; constexpr char texture_tilestylev[] = "tilestylev";
const char *const texture_2d_coord = "m:tex2coord"; constexpr char texture_2d_coord[] = "m:tex2coord";
const char *const texture_cuurd_u = "u"; constexpr char texture_cuurd_u[] = "u";
const char *const texture_cuurd_v = "v"; constexpr char texture_cuurd_v[] = "v";
// vertex color definitions // vertex color definitions
const char *const colorgroup = "m:colorgroup"; constexpr char colorgroup[] = "m:colorgroup";
const char *const color_item = "m:color"; constexpr char color_item[] = "m:color";
const char *const color_vaule = "color"; constexpr char color_value[] = "color";
// Meta info tags // Meta info tags
const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; constexpr char CONTENT_TYPES_ARCHIVE[] = "[Content_Types].xml";
const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; constexpr char ROOT_RELATIONSHIPS_ARCHIVE[] = "_rels/.rels";
const char* const SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; constexpr char SCHEMA_CONTENTTYPES[] = "http://schemas.openxmlformats.org/package/2006/content-types";
const char* const SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; constexpr char SCHEMA_RELATIONSHIPS[] = "http://schemas.openxmlformats.org/package/2006/relationships";
const char* const RELS_RELATIONSHIP_CONTAINER = "Relationships"; constexpr char RELS_RELATIONSHIP_CONTAINER[] = "Relationships";
const char* const RELS_RELATIONSHIP_NODE = "Relationship"; constexpr char RELS_RELATIONSHIP_NODE[] = "Relationship";
const char* const RELS_ATTRIB_TARGET = "Target"; constexpr char RELS_ATTRIB_TARGET[] = "Target";
const char* const RELS_ATTRIB_TYPE = "Type"; constexpr char RELS_ATTRIB_TYPE[] = "Type";
const char* const RELS_ATTRIB_ID = "Id"; constexpr char RELS_ATTRIB_ID[] = "Id";
const char* const PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel"; constexpr char PACKAGE_START_PART_RELATIONSHIP_TYPE[] = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
const char* const PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket"; constexpr char PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE[] = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; constexpr char PACKAGE_TEXTURE_RELATIONSHIP_TYPE[] = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; constexpr char PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE[] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; constexpr char PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE[] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
}
} // Namespace D3MF } // namespace Assimp::D3MF
} // Namespace Assimp
+1 -2
View File
@@ -48,7 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/Exporter.hpp> #include <assimp/Exporter.hpp>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include "3MFXmlTags.h" #include "3MFXmlTags.h"
@@ -94,7 +93,7 @@ D3MFExporter::~D3MFExporter() {
mRelations.clear(); mRelations.clear();
} }
bool D3MFExporter::validate() { bool D3MFExporter::validate() const {
if (mArchiveName.empty()) { if (mArchiveName.empty()) {
return false; return false;
} }
+1 -1
View File
@@ -68,7 +68,7 @@ class D3MFExporter {
public: public:
D3MFExporter( const char* pFile, const aiScene* pScene ); D3MFExporter( const char* pFile, const aiScene* pScene );
~D3MFExporter(); ~D3MFExporter();
bool validate(); bool validate() const;
bool exportArchive( const char *file ); bool exportArchive( const char *file );
bool exportContentTypes(); bool exportContentTypes();
bool exportRelations(); bool exportRelations();
+1 -1
View File
@@ -53,7 +53,7 @@ namespace Assimp {
/// ///
/// Implements the basic topology import and embedded textures. /// Implements the basic topology import and embedded textures.
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
class D3MFImporter : public BaseImporter { class D3MFImporter final : public BaseImporter {
public: public:
/// @brief The default class constructor. /// @brief The default class constructor.
D3MFImporter() = default; D3MFImporter() = default;
+2 -3
View File
@@ -65,10 +65,9 @@ namespace D3MF {
using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>; using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
class OpcPackageRelationshipReader { class OpcPackageRelationshipReader final {
public: public:
OpcPackageRelationshipReader(XmlParser &parser) : explicit OpcPackageRelationshipReader(XmlParser &parser) : mRelations() {
mRelations() {
XmlNode root = parser.getRootNode(); XmlNode root = parser.getRootNode();
ParseRootNode(root); ParseRootNode(root);
} }
+1 -1
View File
@@ -680,7 +680,7 @@ void XmlSerializer::ReadColor(XmlNode &node, ColorGroup *colorGroup) {
for (XmlNode currentNode : node.children()) { for (XmlNode currentNode : node.children()) {
const std::string currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == XmlTag::color_item) { if (currentName == XmlTag::color_item) {
const char *color = currentNode.attribute(XmlTag::color_vaule).as_string(); const char *color = currentNode.attribute(XmlTag::color_value).as_string();
aiColor4D color_value; aiColor4D color_value;
if (parseColor(color, color_value)) { if (parseColor(color, color_value)) {
colorGroup->mColors.push_back(color_value); colorGroup->mColors.push_back(color_value);
+2 -1
View File
@@ -59,9 +59,10 @@ class Texture2DGroup;
class EmbeddedTexture; class EmbeddedTexture;
class ColorGroup; class ColorGroup;
/// @brief his class implements ther 3mf serialization.
class XmlSerializer final { class XmlSerializer final {
public: public:
XmlSerializer(XmlParser &xmlParser); explicit XmlSerializer(XmlParser &xmlParser);
~XmlSerializer(); ~XmlSerializer();
void ImportXml(aiScene *scene); void ImportXml(aiScene *scene);
+38 -5
View File
@@ -75,6 +75,8 @@ static constexpr aiImporterDesc desc = {
"ac acc ac3d" "ac acc ac3d"
}; };
static constexpr auto ACDoubleSidedFlag = 0x20;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// skip to the next token // skip to the next token
inline const char *AcSkipToNextToken(const char *buffer, const char *end) { 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) { for (unsigned int _i = 0; _i < num; ++_i) {
buffer = AcSkipToNextToken(buffer, end); buffer = AcSkipToNextToken(buffer, end);
buffer = fast_atoreal_move<float>(buffer, ((float *)out)[_i]); buffer = fast_atoreal_move(buffer, ((float *)out)[_i]);
} }
return buffer; 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 // Constructor to be privately used by Importer
AC3DImporter::AC3DImporter() : AC3DImporter::AC3DImporter() :
@@ -451,6 +477,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
if ((*it).entries.empty()) { if ((*it).entries.empty()) {
ASSIMP_LOG_WARN("AC3D: surface has zero vertex references"); 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 // validate all vertex indices to make sure we won't crash here
for (it2 = (*it).entries.begin(), for (it2 = (*it).entries.begin(),
@@ -480,8 +508,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
// triangle strip // triangle strip
case Surface::TriangleStrip: case Surface::TriangleStrip:
needMat[idx].first += (unsigned int)(*it).entries.size() - 2; needMat[idx].first += static_cast<unsigned int>(it->entries.size() - 2) * doubleSidedFactor;
needMat[idx].second += ((unsigned int)(*it).entries.size() - 2) * 3; needMat[idx].second += static_cast<unsigned int>(it->entries.size() - 2) * 3 * doubleSidedFactor;
break; break;
default: default:
@@ -494,8 +522,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
case Surface::Polygon: case Surface::Polygon:
// the number of faces increments by one, the number // the number of faces increments by one, the number
// of vertices by surface.numref. // of vertices by surface.numref.
needMat[idx].first++; needMat[idx].first += doubleSidedFactor;
needMat[idx].second += (unsigned int)(*it).entries.size(); needMat[idx].second += static_cast<unsigned int>(it->entries.size()) * doubleSidedFactor;
}; };
} }
unsigned int *pip = node->mMeshes = new unsigned int[node->mNumMeshes]; 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) { for (it = object.surfaces.begin(); it != end; ++it) {
if (mat == (*it).mat) { if (mat == (*it).mat) {
const Surface &src = *it; const Surface &src = *it;
const bool isDoubleSided = ACDoubleSidedFlag == (src.flags & ACDoubleSidedFlag);
// closed polygon // closed polygon
uint8_t type = (*it).GetType(); uint8_t type = (*it).GetType();
@@ -570,6 +599,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
++uv; ++uv;
} }
} }
if(isDoubleSided) // Need a backface?
buildBacksideOfFace(faces[-1], faces, vertices, mesh->mVertices, uv, mesh->mTextureCoords[0], cur);
} }
} else if (type == Surface::TriangleStrip) { } else if (type == Surface::TriangleStrip) {
for (unsigned int i = 0; i < (unsigned int)src.entries.size() - 2; ++i) { 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->y = entry3.second.y;
++uv; ++uv;
} }
if(isDoubleSided) // Need a backface?
buildBacksideOfFace(faces[-1], faces, vertices, mesh->mVertices, uv, mesh->mTextureCoords[0], cur);
} }
} else { } else {
+1 -1
View File
@@ -60,7 +60,7 @@ namespace Assimp {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** AC3D (*.ac) importer class /** AC3D (*.ac) importer class
*/ */
class AC3DImporter : public BaseImporter { class AC3DImporter final : public BaseImporter {
public: public:
AC3DImporter(); AC3DImporter();
~AC3DImporter() override = default; ~AC3DImporter() override = default;
+1 -2
View File
@@ -327,8 +327,7 @@ void AMFImporter::ParseNode_Root() {
// Multi elements - Yes. // Multi elements - Yes.
// Parent element - <amf>. // Parent element - <amf>.
void AMFImporter::ParseNode_Constellation(XmlNode &node) { void AMFImporter::ParseNode_Constellation(XmlNode &node) {
std::string id; std::string id = node.attribute("id").as_string();
id = node.attribute("id").as_string();
// create and if needed - define new grouping object. // create and if needed - define new grouping object.
AMFNodeElementBase *ne = new AMFConstellation(mNodeElement_Cur); AMFNodeElementBase *ne = new AMFConstellation(mNodeElement_Cur);
+1 -1
View File
@@ -97,7 +97,7 @@ namespace Assimp {
/// new - <texmap> and children <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3> /// new - <texmap> and children <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>
/// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3> /// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3>
/// ///
class AMFImporter : public BaseImporter { class AMFImporter final : public BaseImporter {
using AMFMetaDataArray = std::vector<AMFMetadata *>; using AMFMetaDataArray = std::vector<AMFMetadata *>;
using MeshArray = std::vector<aiMesh *>; using MeshArray = std::vector<aiMesh *>;
using NodeArray = std::vector<aiNode *>; using NodeArray = std::vector<aiNode *>;
+48 -31
View File
@@ -107,16 +107,16 @@ protected:
}; // class IAMFImporter_NodeElement }; // class IAMFImporter_NodeElement
/// A collection of objects or constellations with specific relative locations. /// A collection of objects or constellations with specific relative locations.
struct AMFConstellation : public AMFNodeElementBase { struct AMFConstellation final : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFConstellation(AMFNodeElementBase *pParent) : explicit AMFConstellation(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Constellation, pParent) {} AMFNodeElementBase(ENET_Constellation, pParent) {}
}; // struct CAMFImporter_NodeElement_Constellation }; // struct CAMFImporter_NodeElement_Constellation
/// Part of constellation. /// Part of constellation.
struct AMFInstance : public AMFNodeElementBase { struct AMFInstance final : public AMFNodeElementBase {
std::string ObjectID; ///< ID of object for instantiation. std::string ObjectID; ///< ID of object for instantiation.
/// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to /// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to
@@ -129,7 +129,7 @@ struct AMFInstance : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFInstance(AMFNodeElementBase *pParent) : explicit AMFInstance(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Instance, pParent) {} AMFNodeElementBase(ENET_Instance, pParent) {}
}; };
@@ -141,8 +141,10 @@ struct AMFMetadata : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFMetadata(AMFNodeElementBase *pParent) : explicit AMFMetadata(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Metadata, pParent) {} AMFNodeElementBase(ENET_Metadata, pParent) {
// empty
}
}; };
/// Structure that define root node. /// Structure that define root node.
@@ -153,8 +155,10 @@ struct AMFRoot : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFRoot(AMFNodeElementBase *pParent) : explicit AMFRoot(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Root, pParent) {} AMFNodeElementBase(ENET_Root, pParent) {
// empty
}
}; };
/// Structure that define object node. /// Structure that define object node.
@@ -166,7 +170,7 @@ struct AMFColor : public AMFNodeElementBase {
/// @brief Constructor. /// @brief Constructor.
/// @param [in] pParent - pointer to parent node. /// @param [in] pParent - pointer to parent node.
AMFColor(AMFNodeElementBase *pParent) : explicit AMFColor(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color() { AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color() {
// empty // empty
} }
@@ -174,53 +178,62 @@ struct AMFColor : public AMFNodeElementBase {
/// Structure that define material node. /// Structure that define material node.
struct AMFMaterial : public AMFNodeElementBase { struct AMFMaterial : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFMaterial(AMFNodeElementBase *pParent) : explicit AMFMaterial(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Material, pParent) {} AMFNodeElementBase(ENET_Material, pParent) {
// empty
}
}; };
/// Structure that define object node. /// Structure that define object node.
struct AMFObject : public AMFNodeElementBase { struct AMFObject : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFObject(AMFNodeElementBase *pParent) : explicit AMFObject(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Object, pParent) {} AMFNodeElementBase(ENET_Object, pParent) {
// empty
}
}; };
/// \struct CAMFImporter_NodeElement_Mesh
/// Structure that define mesh node. /// Structure that define mesh node.
struct AMFMesh : public AMFNodeElementBase { struct AMFMesh : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFMesh(AMFNodeElementBase *pParent) : explicit AMFMesh(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Mesh, pParent) {} AMFNodeElementBase(ENET_Mesh, pParent) {
// empty
}
}; };
/// Structure that define vertex node. /// Structure that define vertex node.
struct AMFVertex : public AMFNodeElementBase { struct AMFVertex : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFVertex(AMFNodeElementBase *pParent) : explicit AMFVertex(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertex, pParent) {} AMFNodeElementBase(ENET_Vertex, pParent) {
// empty
}
}; };
/// Structure that define edge node. /// Structure that define edge node.
struct AMFEdge : public AMFNodeElementBase { struct AMFEdge : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFEdge(AMFNodeElementBase *pParent) : explicit AMFEdge(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Edge, pParent) {} AMFNodeElementBase(ENET_Edge, pParent) {
// empty
}
}; };
/// Structure that define vertices node. /// Structure that define vertices node.
struct AMFVertices : public AMFNodeElementBase { struct AMFVertices : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFVertices(AMFNodeElementBase *pParent) : explicit AMFVertices(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertices, pParent) {} AMFNodeElementBase(ENET_Vertices, pParent) {
// empty
}
}; };
/// Structure that define volume node. /// Structure that define volume node.
@@ -230,8 +243,10 @@ struct AMFVolume : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFVolume(AMFNodeElementBase *pParent) : explicit AMFVolume(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Volume, pParent) {} AMFNodeElementBase(ENET_Volume, pParent) {
// empty
}
}; };
/// Structure that define coordinates node. /// Structure that define coordinates node.
@@ -240,8 +255,10 @@ struct AMFCoordinates : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFCoordinates(AMFNodeElementBase *pParent) : explicit AMFCoordinates(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Coordinates, pParent) {} AMFNodeElementBase(ENET_Coordinates, pParent) {
// empty
}
}; };
/// Structure that define texture coordinates node. /// Structure that define texture coordinates node.
@@ -254,7 +271,7 @@ struct AMFTexMap : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFTexMap(AMFNodeElementBase *pParent) : explicit AMFTexMap(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{} { AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{} {
// empty // empty
} }
@@ -266,7 +283,7 @@ struct AMFTriangle : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFTriangle(AMFNodeElementBase *pParent) : explicit AMFTriangle(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Triangle, pParent) { AMFNodeElementBase(ENET_Triangle, pParent) {
// empty // empty
} }
@@ -280,7 +297,7 @@ struct AMFTexture : public AMFNodeElementBase {
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.
AMFTexture(AMFNodeElementBase *pParent) : explicit AMFTexture(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Texture, pParent), Width(0), Height(0), Depth(0), Data(), Tiled(false) { AMFNodeElementBase(ENET_Texture, pParent), Width(0), Height(0), Depth(0), Data(), Tiled(false) {
// empty // empty
} }
@@ -57,8 +57,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*pY*/, const float /*pZ*/) const { aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*pY*/, const float /*pZ*/) const {
aiColor4D tcol;
// Check if stored data are supported. // Check if stored data are supported.
if (!Composition.empty()) { if (!Composition.empty()) {
throw DeadlyImportError("IME. GetColor for composition"); throw DeadlyImportError("IME. GetColor for composition");
@@ -68,7 +66,7 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
throw DeadlyImportError("IME. GetColor, composed color"); throw DeadlyImportError("IME. GetColor, composed color");
} }
tcol = Color->Color; aiColor4D tcol = Color->Color;
// Check if default color must be used // Check if default color must be used
if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) { if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) {
@@ -532,11 +530,9 @@ void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const st
col_arr.reserve(VertexCount_Max * 2); col_arr.reserve(VertexCount_Max * 2);
{ // fill arrays { // fill arrays
size_t vert_idx_from, vert_idx_to;
// first iteration. // first iteration.
vert_idx_to = 0; size_t vert_idx_to = 0;
vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr); size_t vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr);
vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from)); vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from));
col_arr.push_back(Vertex_CalculateColor(vert_idx_from)); col_arr.push_back(Vertex_CalculateColor(vert_idx_from));
if (vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to); if (vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to);
+1 -2
View File
@@ -1270,5 +1270,4 @@ bool ASEImporter::GenerateNormals(ASE::Mesh &mesh) {
} }
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER #endif // ASSIMP_BUILD_NO_3DS_IMPORTER
#endif // ASSIMP_BUILD_NO_ASE_IMPORTER
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
+1 -1
View File
@@ -59,7 +59,7 @@ namespace Assimp {
/** Importer class for the 3DS ASE ASCII format. /** Importer class for the 3DS ASE ASCII format.
* *
*/ */
class ASEImporter : public BaseImporter { class ASEImporter final : public BaseImporter {
public: public:
ASEImporter(); ASEImporter();
~ASEImporter() override = default; ~ASEImporter() override = default;
+3 -3
View File
@@ -1427,7 +1427,7 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes
// then parse the vertex weight // then parse the vertex weight
if (!SkipSpaces(&mFilePtr, mEnd)) break; if (!SkipSpaces(&mFilePtr, mEnd)) break;
mFilePtr = fast_atoreal_move<float>(mFilePtr, pairOut.second); mFilePtr = fast_atoreal_move(mFilePtr, pairOut.second);
// -1 marks unused entries // -1 marks unused entries
if (-1 != pairOut.first) { if (-1 != pairOut.first) {
@@ -1893,7 +1893,7 @@ void Parser::ParseLV4MeshReal(ai_real &fOut) {
return; return;
} }
// parse the first float // parse the first float
mFilePtr = fast_atoreal_move<ai_real>(mFilePtr, fOut); mFilePtr = fast_atoreal_move(mFilePtr, fOut);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloat(float &fOut) { void Parser::ParseLV4MeshFloat(float &fOut) {
@@ -1906,7 +1906,7 @@ void Parser::ParseLV4MeshFloat(float &fOut) {
return; return;
} }
// parse the first float // parse the first float
mFilePtr = fast_atoreal_move<float>(mFilePtr, fOut); mFilePtr = fast_atoreal_move(mFilePtr, fOut);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLong(unsigned int &iOut) { void Parser::ParseLV4MeshLong(unsigned int &iOut) {
+6 -8
View File
@@ -57,14 +57,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ASE is quite similar to 3ds. We can reuse some structures // ASE is quite similar to 3ds. We can reuse some structures
#include "AssetLib/3DS/3DSLoader.h" #include "AssetLib/3DS/3DSLoader.h"
namespace Assimp { namespace Assimp::ASE {
namespace ASE {
using namespace D3DS; using namespace D3DS;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing an ASE material */ /** Helper structure representing an ASE material */
struct Material : public D3DS::Material { struct Material final : D3DS::Material {
//! Default constructor has been deleted //! Default constructor has been deleted
Material() = delete; Material() = delete;
@@ -115,7 +114,7 @@ struct Material : public D3DS::Material {
return *this; return *this;
} }
~Material() = default; ~Material() override = default;
//! Contains all sub materials of this material //! Contains all sub materials of this material
std::vector<Material> avSubMaterials; std::vector<Material> avSubMaterials;
@@ -373,8 +372,8 @@ struct Dummy : public BaseNode {
}; };
// Parameters to Parser::Parse() // Parameters to Parser::Parse()
#define AI_ASE_NEW_FILE_FORMAT 200 static constexpr unsigned int AI_ASE_NEW_FILE_FORMAT = 200;
#define AI_ASE_OLD_FILE_FORMAT 110 static constexpr unsigned int AI_ASE_OLD_FILE_FORMAT = 110;
// Internally we're a little bit more tolerant // Internally we're a little bit more tolerant
#define AI_ASE_IS_NEW_FILE_FORMAT() (iFileFormat >= 200) #define AI_ASE_IS_NEW_FILE_FORMAT() (iFileFormat >= 200)
@@ -668,8 +667,7 @@ public:
unsigned int iFileFormat; unsigned int iFileFormat;
}; };
} // Namespace ASE } // Namespace Assimp::ASE
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER #endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+23 -23
View File
@@ -239,29 +239,7 @@ inline size_t WriteArray(IOStream *stream, const T *in, unsigned int size) {
* and the chunk contents to the container stream. This allows relatively easy chunk * and the chunk contents to the container stream. This allows relatively easy chunk
* chunk construction, even recursively. * chunk construction, even recursively.
*/ */
class AssbinChunkWriter : public IOStream { class AssbinChunkWriter final : public IOStream {
private:
uint8_t *buffer;
uint32_t magic;
IOStream *container;
size_t cur_size, cursor, initial;
private:
// -------------------------------------------------------------------
void Grow(size_t need = 0) {
size_t new_size = std::max(initial, std::max(need, cur_size + (cur_size >> 1)));
const uint8_t *const old = buffer;
buffer = new uint8_t[new_size];
if (old) {
memcpy(buffer, old, cur_size);
delete[] old;
}
cur_size = new_size;
}
public: public:
AssbinChunkWriter(IOStream *container, uint32_t magic, size_t initial = 4096) : AssbinChunkWriter(IOStream *container, uint32_t magic, size_t initial = 4096) :
buffer(nullptr), buffer(nullptr),
@@ -315,6 +293,28 @@ public:
return pCount; return pCount;
} }
private:
// -------------------------------------------------------------------
void Grow(size_t need = 0) {
size_t new_size = std::max(initial, std::max(need, cur_size + (cur_size >> 1)));
const uint8_t *const old = buffer;
buffer = new uint8_t[new_size];
if (old) {
memcpy(buffer, old, cur_size);
delete[] old;
}
cur_size = new_size;
}
private:
uint8_t *buffer;
uint32_t magic;
IOStream *container;
size_t cur_size, cursor, initial;
}; };
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
+7 -4
View File
@@ -77,8 +77,7 @@ static int ioprintf(IOStream *io, const char *format, ...) {
} }
static const int Size = 4096; static const int Size = 4096;
char sz[Size]; char sz[Size] = {};
::memset(sz, '\0', Size);
va_list va; va_list va;
va_start(va, format); va_start(va, format);
const unsigned int nSize = vsnprintf(sz, Size - 1, format, va); const unsigned int nSize = vsnprintf(sz, Size - 1, format, va);
@@ -302,7 +301,11 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
bool compressed = (tex->mHeight == 0); bool compressed = (tex->mHeight == 0);
// mesh header // mesh header
ioprintf(io, "\t<Texture width=\"%u\" height=\"%u\" compressed=\"%s\"> \n", std::string texName = "unknown";
if (tex->mFilename.length != 0u) {
texName = tex->mFilename.data;
}
ioprintf(io, "\t<Texture name=\"%s\" width=\"%u\" height=\"%u\" compressed=\"%s\"> \n", texName.c_str(),
(compressed ? -1 : tex->mWidth), (compressed ? -1 : tex->mHeight), (compressed ? -1 : tex->mWidth), (compressed ? -1 : tex->mHeight),
(compressed ? "true" : "false")); (compressed ? "true" : "false"));
@@ -350,7 +353,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
for (unsigned int n = 0; n < mat->mNumProperties; ++n) { for (unsigned int n = 0; n < mat->mNumProperties; ++n) {
const aiMaterialProperty *prop = mat->mProperties[n]; const aiMaterialProperty *prop = mat->mProperties[n];
const char *sz = ""; auto sz = "";
if (prop->mType == aiPTI_Float) { if (prop->mType == aiPTI_Float) {
sz = "float"; sz = "float";
} else if (prop->mType == aiPTI_Integer) { } else if (prop->mType == aiPTI_Integer) {
+1 -1
View File
@@ -60,7 +60,7 @@ struct aiAnimation;
namespace Assimp{ namespace Assimp{
class B3DImporter : public BaseImporter{ class B3DImporter final : public BaseImporter{
public: public:
B3DImporter() = default; B3DImporter() = default;
~B3DImporter() override; ~B3DImporter() override;
+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 // check if the float is valid by testing if the atof() function consumed every char of the token
const char *ctoken = token.c_str(); const char *ctoken = token.c_str();
float result = 0.0f; float result = 0.0f;
ctoken = fast_atoreal_move<float>(ctoken, result); ctoken = fast_atoreal_move(ctoken, result);
if (ctoken != token.c_str() + token.length()) if (ctoken != token.c_str() + token.length())
ThrowException("Expected a floating point number, but found \"", token, "\"."); ThrowException("Expected a floating point number, but found \"", token, "\".");
+1 -1
View File
@@ -61,7 +61,7 @@ namespace Assimp {
* the hierarchy. It contains no actual mesh data, but we generate a dummy mesh * the hierarchy. It contains no actual mesh data, but we generate a dummy mesh
* inside the loader just to be able to see something. * inside the loader just to be able to see something.
*/ */
class BVHLoader : public BaseImporter { class BVHLoader final : public BaseImporter {
/** Possible animation channels for which the motion data holds the values */ /** Possible animation channels for which the motion data holds the values */
enum ChannelType { enum ChannelType {
+3 -1
View File
@@ -74,7 +74,9 @@ BlenderBMeshConverter::~BlenderBMeshConverter() {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BlenderBMeshConverter::ContainsBMesh() const { bool BlenderBMeshConverter::ContainsBMesh() const {
// TODO - Should probably do some additional verification here if (BMesh == nullptr) {
return false;
}
return BMesh->totpoly && BMesh->totloop && BMesh->totvert; return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
} }
+4 -6
View File
@@ -63,14 +63,12 @@ namespace Assimp
struct MLoop; struct MLoop;
} }
class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter > class BlenderBMeshConverter final : public LogFunctions< BlenderBMeshConverter >
{ {
public: public:
BlenderBMeshConverter( const Blender::Mesh* mesh ); explicit BlenderBMeshConverter( const Blender::Mesh* mesh );
~BlenderBMeshConverter( ); ~BlenderBMeshConverter();
bool ContainsBMesh() const;
bool ContainsBMesh( ) const;
const Blender::Mesh* TriangulateBMesh( ); const Blender::Mesh* TriangulateBMesh( );
private: private:
+3 -2
View File
@@ -96,7 +96,7 @@ struct CustomDataTypeDescription {
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures * other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
* use a special readfunction for that cases * use a special readfunction for that cases
*/ */
static std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { { static const std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert), DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
@@ -142,7 +142,8 @@ static std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescript
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION } }; DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
} };
bool isValidCustomDataType(const int cdtype) { bool isValidCustomDataType(const int cdtype) {
return cdtype >= 0 && cdtype < CD_NUMTYPES; return cdtype >= 0 && cdtype < CD_NUMTYPES;
+33 -58
View File
@@ -55,14 +55,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// enable verbose log output. really verbose, so be careful. // enable verbose log output. really verbose, so be careful.
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
#define ASSIMP_BUILD_BLENDER_DEBUG # define ASSIMP_BUILD_BLENDER_DEBUG
#endif #endif
// set this to non-zero to dump BlenderDNA stuff to dna.txt. // set this to non-zero to dump BlenderDNA stuff to dna.txt.
// you could set it on the assimp build command line too without touching it here. // you could set it on the assimp build command line too without touching it here.
// !!! please make sure this is set to 0 in the repo !!! // !!! please make sure this is set to 0 in the repo !!!
#ifndef ASSIMP_BUILD_BLENDER_DEBUG_DNA #ifndef ASSIMP_BUILD_BLENDER_DEBUG_DNA
#define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0 # define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0
#endif #endif
// #define ASSIMP_BUILD_BLENDER_NO_STATS // #define ASSIMP_BUILD_BLENDER_NO_STATS
@@ -124,22 +124,14 @@ struct ElemBase {
* they used to point to.*/ * they used to point to.*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Pointer { struct Pointer {
Pointer() : uint64_t val{0};
val() {
// empty
}
uint64_t val;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Represents a generic offset within a BLEND file */ /** Represents a generic offset within a BLEND file */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct FileOffset { struct FileOffset {
FileOffset() : uint64_t val{0};
val() {
// empty
}
uint64_t val;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@@ -204,7 +196,7 @@ enum ErrorPolicy {
}; };
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #ifdef ASSIMP_BUILD_BLENDER_DEBUG
#define ErrorPolicy_Igno ErrorPolicy_Warn # define ErrorPolicy_Igno ErrorPolicy_Warn
#endif #endif
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@@ -396,10 +388,9 @@ private:
mutable size_t cache_idx; mutable size_t cache_idx;
}; };
// -------------------------------------------------------- // -------------------------------------------------------------------------------------------------------
template <> template<>
struct Structure::_defaultInitializer<ErrorPolicy_Warn> { struct Structure::_defaultInitializer<ErrorPolicy_Warn> {
template <typename T> template <typename T>
void operator()(T &out, const char *reason = "<add reason>") { void operator()(T &out, const char *reason = "<add reason>") {
ASSIMP_LOG_WARN(reason); ASSIMP_LOG_WARN(reason);
@@ -409,9 +400,9 @@ struct Structure::_defaultInitializer<ErrorPolicy_Warn> {
} }
}; };
template <> // -------------------------------------------------------------------------------------------------------
template<>
struct Structure::_defaultInitializer<ErrorPolicy_Fail> { struct Structure::_defaultInitializer<ErrorPolicy_Fail> {
template <typename T> template <typename T>
void operator()(T & /*out*/, const char *message = "") { void operator()(T & /*out*/, const char *message = "") {
// obviously, it is crucial that _DefaultInitializer is used // obviously, it is crucial that _DefaultInitializer is used
@@ -619,31 +610,23 @@ public:
/** Import statistics, i.e. number of file blocks read*/ /** Import statistics, i.e. number of file blocks read*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
class Statistics { class Statistics {
public: public:
Statistics() : Statistics() = default;
fields_read(), pointers_resolved(), cache_hits() ~Statistics() = default;
// , blocks_read ()
,
cached_objects() {}
public: /// total number of fields we read
/** total number of fields we read */
unsigned int fields_read; unsigned int fields_read;
/** total number of resolved pointers */ /// total number of resolved pointers
unsigned int pointers_resolved; unsigned int pointers_resolved;
/** number of pointers resolved from the cache */ /// number of pointers resolved from the cache
unsigned int cache_hits; unsigned int cache_hits;
/** number of blocks (from FileDatabase::entries) /// objects in FileData::cache
we did actually read from. */
// unsigned int blocks_read;
/** objects in FileData::cache */
unsigned int cached_objects; unsigned int cached_objects;
}; };
#endif #endif
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@@ -656,15 +639,13 @@ public:
typedef std::map<Pointer, TOUT<ElemBase>> StructureCache; typedef std::map<Pointer, TOUT<ElemBase>> StructureCache;
public: public:
ObjectCache(const FileDatabase &db) : explicit ObjectCache(const FileDatabase &db) : db(db) {
db(db) {
// currently there are only ~400 structure records per blend file. // currently there are only ~400 structure records per blend file.
// we read only a small part of them and don't cache objects // we read only a small part of them and don't cache objects
// which we don't need, so this should suffice. // which we don't need, so this should suffice.
caches.reserve(64); caches.reserve(64);
} }
public:
// -------------------------------------------------------- // --------------------------------------------------------
/** Check whether a specific item is in the cache. /** Check whether a specific item is in the cache.
* @param s Data type of the item * @param s Data type of the item
@@ -672,10 +653,7 @@ public:
* cache doesn't know the item yet. * cache doesn't know the item yet.
* @param ptr Item address to look for. */ * @param ptr Item address to look for. */
template <typename T> template <typename T>
void get( void get( const Structure &s,TOUT<T> &out, const Pointer &ptr) const;
const Structure &s,
TOUT<T> &out,
const Pointer &ptr) const;
// -------------------------------------------------------- // --------------------------------------------------------
/** Add an item to the cache after the item has /** Add an item to the cache after the item has
@@ -700,7 +678,7 @@ private:
template <> template <>
class ObjectCache<Blender::vector> { class ObjectCache<Blender::vector> {
public: public:
ObjectCache(const FileDatabase &) {} explicit ObjectCache(const FileDatabase &) {}
template <typename T> template <typename T>
void get(const Structure &, vector<T> &, const Pointer &) {} void get(const Structure &, vector<T> &, const Pointer &) {}
@@ -709,7 +687,7 @@ public:
}; };
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4355) # pragma warning(disable : 4355)
#endif #endif
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@@ -724,16 +702,6 @@ public:
FileDatabase() : FileDatabase() :
_cacheArrays(*this), _cache(*this), next_cache_idx() {} _cacheArrays(*this), _cache(*this), next_cache_idx() {}
public:
// publicly accessible fields
bool i64bit;
bool little;
DNA dna;
std::shared_ptr<StreamReaderAny> reader;
vector<FileBlockHead> entries;
public:
Statistics &stats() const { Statistics &stats() const {
return _stats; return _stats;
} }
@@ -752,6 +720,15 @@ public:
return _cacheArrays; return _cacheArrays;
} }
public:
// publicly accessible fields
bool i64bit;
bool little;
DNA dna;
std::shared_ptr<StreamReaderAny> reader;
vector<FileBlockHead> entries;
private: private:
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
mutable Statistics _stats; mutable Statistics _stats;
@@ -764,20 +741,19 @@ private:
}; };
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(default : 4355) # pragma warning(default : 4355)
#endif #endif
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */ /** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
class DNAParser { class DNAParser {
public: public:
/** Bind the parser to a empty DNA and an input stream */ /** Bind the parser to a empty DNA and an input stream */
DNAParser(FileDatabase &db) : explicit DNAParser(FileDatabase &db) : db(db) {
db(db) {} // empty
}
public:
// -------------------------------------------------------- // --------------------------------------------------------
/** Locate the DNA in the file and parse it. The input /** Locate the DNA in the file and parse it. The input
* stream is expected to point to the beginning of the DN1 * stream is expected to point to the beginning of the DN1
@@ -788,7 +764,6 @@ public:
* afterwards.*/ * afterwards.*/
void Parse(); void Parse();
public:
/** Obtain a reference to the extracted DNA information */ /** Obtain a reference to the extracted DNA information */
const Blender::DNA &GetDNA() const { const Blender::DNA &GetDNA() const {
return db.dna; return db.dna;
+1 -1
View File
@@ -105,7 +105,7 @@ class BlenderModifier;
* call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the * call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the
* conversion from intermediate format to aiScene. */ * conversion from intermediate format to aiScene. */
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter> { class BlenderImporter final : public BaseImporter, public LogFunctions<BlenderImporter> {
public: public:
BlenderImporter(); BlenderImporter();
~BlenderImporter() override; ~BlenderImporter() override;
+2 -2
View File
@@ -114,7 +114,7 @@ private:
* Mirror modifier. Status: implemented. * Mirror modifier. Status: implemented.
*/ */
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class BlenderModifier_Mirror : public BlenderModifier { class BlenderModifier_Mirror final : public BlenderModifier {
public: public:
// -------------------- // --------------------
virtual bool IsActive( const ModifierData& modin); virtual bool IsActive( const ModifierData& modin);
@@ -131,7 +131,7 @@ public:
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
/** Subdivision modifier. Status: dummy. */ /** Subdivision modifier. Status: dummy. */
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class BlenderModifier_Subdivision : public BlenderModifier { class BlenderModifier_Subdivision final : public BlenderModifier {
public: public:
// -------------------- // --------------------
+45 -48
View File
@@ -47,8 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h" #include "BlenderDNA.h"
namespace Assimp { namespace Assimp::Blender {
namespace Blender {
// Minor parts of this file are extracts from blender data structures, // Minor parts of this file are extracts from blender data structures,
// declared in the ./source/blender/makesdna directory. // declared in the ./source/blender/makesdna directory.
@@ -115,32 +114,32 @@ struct Collection;
static const size_t MaxNameLen = 1024; static const size_t MaxNameLen = 1024;
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ID : ElemBase { struct ID final : ElemBase {
char name[MaxNameLen] WARN; char name[MaxNameLen] WARN;
short flag; short flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ListBase : ElemBase { struct ListBase final : ElemBase {
std::shared_ptr<ElemBase> first; std::shared_ptr<ElemBase> first;
std::weak_ptr<ElemBase> last; std::weak_ptr<ElemBase> last;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct PackedFile : ElemBase { struct PackedFile final : ElemBase {
int size WARN; int size WARN;
int seek WARN; int seek WARN;
std::shared_ptr<FileOffset> data WARN; std::shared_ptr<FileOffset> data WARN;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct GroupObject : ElemBase { struct GroupObject final : ElemBase {
std::shared_ptr<GroupObject> prev, next FAIL; std::shared_ptr<GroupObject> prev, next FAIL;
std::shared_ptr<Object> ob; std::shared_ptr<Object> ob;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Group : ElemBase { struct Group final : ElemBase {
ID id FAIL; ID id FAIL;
int layer; int layer;
@@ -148,32 +147,32 @@ struct Group : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct CollectionObject : ElemBase { struct CollectionObject final : ElemBase {
//CollectionObject* prev; //CollectionObject* prev;
std::shared_ptr<CollectionObject> next; std::shared_ptr<CollectionObject> next;
Object *ob; Object *ob;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct CollectionChild : ElemBase { struct CollectionChild final : ElemBase {
std::shared_ptr<CollectionChild> next, prev; std::shared_ptr<CollectionChild> next, prev;
std::shared_ptr<Collection> collection; std::shared_ptr<Collection> collection;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Collection : ElemBase { struct Collection final : ElemBase {
ID id FAIL; ID id FAIL;
ListBase gobject; // CollectionObject ListBase gobject; // CollectionObject
ListBase children; // CollectionChild ListBase children; // CollectionChild
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct World : ElemBase { struct World final : ElemBase {
ID id FAIL; ID id FAIL;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MVert : ElemBase { struct MVert final : ElemBase {
float co[3] FAIL; float co[3] FAIL;
float no[3] FAIL; // read as short and divided through / 32767.f float no[3] FAIL; // read as short and divided through / 32767.f
char flag; char flag;
@@ -185,31 +184,31 @@ struct MVert : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MEdge : ElemBase { struct MEdge final : ElemBase {
int v1, v2 FAIL; int v1, v2 FAIL;
char crease, bweight; char crease, bweight;
short flag; short flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MLoop : ElemBase { struct MLoop final : ElemBase {
int v, e; int v, e;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MLoopUV : ElemBase { struct MLoopUV final : ElemBase {
float uv[2]; float uv[2];
int flag; int flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
// Note that red and blue are not swapped, as with MCol // Note that red and blue are not swapped, as with MCol
struct MLoopCol : ElemBase { struct MLoopCol final : ElemBase {
unsigned char r, g, b, a; unsigned char r, g, b, a;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MPoly : ElemBase { struct MPoly final : ElemBase {
int loopstart; int loopstart;
int totloop; int totloop;
short mat_nr; short mat_nr;
@@ -217,26 +216,26 @@ struct MPoly : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MTexPoly : ElemBase { struct MTexPoly final : ElemBase {
Image *tpage; Image *tpage;
char flag, transp; char flag, transp;
short mode, tile, pad; short mode, tile, pad;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MCol : ElemBase { struct MCol final : ElemBase {
char r, g, b, a FAIL; char r, g, b, a FAIL;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MFace : ElemBase { struct MFace final : ElemBase {
int v1, v2, v3, v4 FAIL; int v1, v2, v3, v4 FAIL;
int mat_nr FAIL; int mat_nr FAIL;
char flag; char flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct TFace : ElemBase { struct TFace final : ElemBase {
float uv[4][2] FAIL; float uv[4][2] FAIL;
int col[4] FAIL; int col[4] FAIL;
char flag; char flag;
@@ -246,7 +245,7 @@ struct TFace : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MTFace : ElemBase { struct MTFace final : ElemBase {
MTFace() : MTFace() :
flag(0), flag(0),
mode(0), mode(0),
@@ -264,24 +263,24 @@ struct MTFace : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MDeformWeight : ElemBase { struct MDeformWeight final : ElemBase {
int def_nr FAIL; int def_nr FAIL;
float weight FAIL; float weight FAIL;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MDeformVert : ElemBase { struct MDeformVert final : ElemBase {
vector<MDeformWeight> dw WARN; vector<MDeformWeight> dw WARN;
int totweight; int totweight;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
#define MA_RAYMIRROR 0x40000 constexpr uint32_t MA_RAYMIRROR = 0x40000;
#define MA_TRANSPARENCY 0x10000 constexpr uint32_t MA_TRANSPARENCY = 0x10000;
#define MA_RAYTRANSP 0x20000 constexpr uint32_t MA_RAYTRANSP = 0x20000;
#define MA_ZTRANSP 0x00040 constexpr uint32_t MA_ZTRANSP = 0x00040;
struct Material : ElemBase { struct Material final : ElemBase {
ID id FAIL; ID id FAIL;
float r, g, b WARN; float r, g, b WARN;
@@ -403,7 +402,7 @@ CustomDataLayer 104
char name 32 64 char name 32 64
void *data 96 8 void *data 96 8
*/ */
struct CustomDataLayer : ElemBase { struct CustomDataLayer final : ElemBase {
int type; int type;
int offset; int offset;
int flag; int flag;
@@ -441,7 +440,7 @@ CustomData 208
BLI_mempool *pool 192 8 BLI_mempool *pool 192 8
CustomDataExternal *external 200 8 CustomDataExternal *external 200 8
*/ */
struct CustomData : ElemBase { struct CustomData final : ElemBase {
vector<std::shared_ptr<struct CustomDataLayer>> layers; vector<std::shared_ptr<struct CustomDataLayer>> layers;
int typemap[42]; // CD_NUMTYPES int typemap[42]; // CD_NUMTYPES
int totlayer; int totlayer;
@@ -454,7 +453,7 @@ struct CustomData : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Mesh : ElemBase { struct Mesh final : ElemBase {
ID id FAIL; ID id FAIL;
int totface FAIL; int totface FAIL;
@@ -491,7 +490,7 @@ struct Mesh : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Library : ElemBase { struct Library final : ElemBase {
ID id FAIL; ID id FAIL;
char name[240] WARN; char name[240] WARN;
@@ -515,7 +514,7 @@ struct Camera : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Lamp : ElemBase { struct Lamp final : ElemBase {
enum FalloffType { enum FalloffType {
FalloffType_Constant = 0x0, FalloffType_Constant = 0x0,
@@ -602,7 +601,7 @@ struct Lamp : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ModifierData : ElemBase { struct ModifierData final : ElemBase {
enum ModifierType { enum ModifierType {
eModifierType_None = 0, eModifierType_None = 0,
eModifierType_Subsurf, eModifierType_Subsurf,
@@ -652,9 +651,8 @@ struct SharedModifierData : ElemBase {
ModifierData modifier; ModifierData modifier;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct SubsurfModifierData : SharedModifierData { struct SubsurfModifierData final : SharedModifierData {
enum Type { enum Type {
@@ -674,7 +672,7 @@ struct SubsurfModifierData : SharedModifierData {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MirrorModifierData : SharedModifierData { struct MirrorModifierData final : SharedModifierData {
enum Flags { enum Flags {
Flags_CLIPPING = 1 << 0, Flags_CLIPPING = 1 << 0,
@@ -692,7 +690,7 @@ struct MirrorModifierData : SharedModifierData {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Object : ElemBase { struct Object final : ElemBase {
ID id FAIL; ID id FAIL;
enum Type { enum Type {
@@ -733,7 +731,7 @@ struct Object : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Base : ElemBase { struct Base final : ElemBase {
Base *prev WARN; Base *prev WARN;
std::shared_ptr<Base> next WARN; std::shared_ptr<Base> next WARN;
std::shared_ptr<Object> object WARN; std::shared_ptr<Object> object WARN;
@@ -745,7 +743,7 @@ struct Base : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Scene : ElemBase { struct Scene final : ElemBase {
ID id FAIL; ID id FAIL;
std::shared_ptr<Object> camera WARN; std::shared_ptr<Object> camera WARN;
@@ -759,7 +757,7 @@ struct Scene : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Image : ElemBase { struct Image final : ElemBase {
ID id FAIL; ID id FAIL;
char name[240] WARN; char name[240] WARN;
@@ -789,7 +787,7 @@ struct Image : ElemBase {
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Tex : ElemBase { struct Tex final : ElemBase {
// actually, the only texture type we support is Type_IMAGE // actually, the only texture type we support is Type_IMAGE
enum Type { enum Type {
@@ -874,14 +872,13 @@ struct Tex : ElemBase {
//char use_nodes; //char use_nodes;
Tex() : Tex() : imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS) {
imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS) {
// empty // empty
} }
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MTex : ElemBase { struct MTex final : ElemBase {
enum Projection { enum Projection {
Proj_N = 0, Proj_N = 0,
@@ -970,6 +967,6 @@ struct MTex : ElemBase {
MTex() = default; MTex() = default;
}; };
} // namespace Blender } // namespace Assimp::Blender
} // namespace Assimp
#endif #endif
@@ -381,7 +381,14 @@ inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& poi
# pragma clang diagnostic push # pragma clang diagnostic push
# pragma clang diagnostic ignored "-Winvalid-offsetof" # pragma clang diagnostic ignored "-Winvalid-offsetof"
#endif // __clang__ #endif // __clang__
#if defined __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Winvalid-offsetof"
#endif // __GNUC__
unsigned int pointOffset = offsetof( PointP2T, point2D ); unsigned int pointOffset = offsetof( PointP2T, point2D );
#if defined __GNUC__
# pragma GCC diagnostic pop
#endif // __GNUC__
#if defined __clang__ #if defined __clang__
# pragma clang diagnostic pop # pragma clang diagnostic pop
#endif #endif
+28 -12
View File
@@ -62,6 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory> #include <memory>
namespace Assimp { namespace Assimp {
using namespace Assimp::COB; using namespace Assimp::COB;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
@@ -109,10 +110,29 @@ void COBImporter::SetupProperties(const Importer * /*pImp*/) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/*static*/ AI_WONT_RETURN void COBImporter::ThrowException(const std::string &msg) { AI_WONT_RETURN void COBImporter::ThrowException(const std::string &msg) {
throw DeadlyImportError("COB: ", msg); throw DeadlyImportError("COB: ", msg);
} }
// ------------------------------------------------------------------------------------------------
static bool isValidASCIIHeader(const char *head) {
ai_assert(head != nullptr);
if (strncmp(head, "Caligari ", 9) != 0) {
COBImporter::ThrowException("Could not found magic id: `Caligari`");
}
if (strncmp(&head[9], "V00.", 4) != 0) {
COBImporter::ThrowException("Could not found Version tag: `V00.`");
}
ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6));
if (head[16] != 'L') {
COBImporter::ThrowException("File is big-endian, which is not supported");
}
return true;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
@@ -126,19 +146,15 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(file)); std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(file));
// check header // check header
char head[32]; static constexpr size_t HeaderSize = 32u;
stream->CopyAndAdvance(head, 32); char head[HeaderSize] = {};
if (strncmp(head, "Caligari ", 9) != 0) { stream->CopyAndAdvance(head, HeaderSize);
ThrowException("Could not found magic id: `Caligari`");
}
ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6));
if (head[16] != 'L') {
ThrowException("File is big-endian, which is not supported");
}
// load data into intermediate structures // load data into intermediate structures
if (head[15] == 'A') { if (head[15] == 'A') {
if (!isValidASCIIHeader(head)) {
ThrowException("Invalid ASCII file header");
}
ReadAsciiFile(scene, stream.get()); ReadAsciiFile(scene, stream.get());
} else { } else {
ReadBinaryFile(scene, stream.get()); ReadBinaryFile(scene, stream.get());
@@ -1170,6 +1186,6 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
} }
} } // namespace Assimp
#endif // ASSIMP_BUILD_NO_COB_IMPORTER #endif // ASSIMP_BUILD_NO_COB_IMPORTER
+6 -5
View File
@@ -72,7 +72,7 @@ namespace COB {
* *
* Currently relatively limited, loads only ASCII files and needs more test coverage. */ * Currently relatively limited, loads only ASCII files and needs more test coverage. */
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class COBImporter : public BaseImporter { class COBImporter final : public BaseImporter {
public: public:
COBImporter() = default; COBImporter() = default;
~COBImporter() override = default; ~COBImporter() override = default;
@@ -81,6 +81,10 @@ public:
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
bool checkSig) const override; bool checkSig) const override;
// -------------------------------------------------------------------
/** Prepend 'COB: ' and throw msg.*/
AI_WONT_RETURN static void ThrowException(const std::string &msg) AI_WONT_RETURN_SUFFIX;
protected: protected:
// -------------------- // --------------------
const aiImporterDesc *GetInfo() const override; const aiImporterDesc *GetInfo() const override;
@@ -93,10 +97,6 @@ protected:
IOSystem *pIOHandler) override; IOSystem *pIOHandler) override;
private: private:
// -------------------------------------------------------------------
/** Prepend 'COB: ' and throw msg.*/
AI_WONT_RETURN static void ThrowException(const std::string &msg) AI_WONT_RETURN_SUFFIX;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Read from an ascii scene/object file /** @brief Read from an ascii scene/object file
* @param out Receives output data. * @param out Receives output data.
@@ -148,4 +148,5 @@ private:
}; // !class COBImporter }; // !class COBImporter
} // end of namespace Assimp } // end of namespace Assimp
#endif // AI_UNREALIMPORTER_H_INC #endif // AI_UNREALIMPORTER_H_INC
+82 -75
View File
@@ -52,68 +52,66 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <deque> #include <deque>
#include <map> #include <map>
namespace Assimp { namespace Assimp::COB {
namespace COB {
// ------------------ // ------------------
/** Represents a single vertex index in a face */ /** Represents a single vertex index in a face */
struct VertexIndex struct VertexIndex {
{
// intentionally uninitialized // intentionally uninitialized
unsigned int pos_idx,uv_idx; unsigned int pos_idx,uv_idx;
}; };
// ------------------ // ------------------
/** COB Face data structure */ /** COB Face data structure */
struct Face struct Face {
{
// intentionally uninitialized // intentionally uninitialized
unsigned int material, flags; unsigned int material;
unsigned int flags;
std::vector<VertexIndex> indices; std::vector<VertexIndex> indices;
}; };
// ------------------ // ------------------
/** COB chunk header information */ /** COB chunk header information */
const unsigned int NO_SIZE = UINT_MAX; constexpr unsigned int NO_SIZE = UINT_MAX;
struct ChunkInfo struct ChunkInfo {
{ ChunkInfo() = default;
ChunkInfo () virtual ~ChunkInfo() = default;
: id (0)
, parent_id (0)
, version (0)
, size (NO_SIZE)
{}
// Id of this chunk, unique within file // Id of this chunk, unique within file
unsigned int id; unsigned int id{ 0 };
// and the corresponding parent // and the corresponding parent
unsigned int parent_id; unsigned int parent_id{ 0 };
// version. v1.23 becomes 123 // version. v1.23 becomes 123
unsigned int version; unsigned int version{ 0 };
// chunk size in bytes, only relevant for binary files // chunk size in bytes, only relevant for binary files
// NO_SIZE is also valid. // NO_SIZE is also valid.
unsigned int size; unsigned int size{NO_SIZE};
}; };
// ------------------ // ------------------
/** A node in the scenegraph */ /** A node in the scenegraph */
struct Node : public ChunkInfo struct Node : ChunkInfo {
{
enum Type { enum Type {
TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE TYPE_INVALID = -1,
TYPE_MESH = 0,
TYPE_GROUP,
TYPE_LIGHT,
TYPE_CAMERA,
TYPE_BONE,
TYPE_COUNT
}; };
virtual ~Node() = default; ~Node() override = default;
Node(Type type) : type(type), unit_scale(1.f){} explicit Node(Type type) : type(type), unit_scale(1.f){}
Type type; Type type;
// used during resolving // used during resolving
typedef std::deque<const Node*> ChildList; using ChildList = std::deque<const Node*> ;
mutable ChildList temp_children; mutable ChildList temp_children;
// unique name // unique name
@@ -128,8 +126,7 @@ struct Node : public ChunkInfo
// ------------------ // ------------------
/** COB Mesh data structure */ /** COB Mesh data structure */
struct Mesh : public Node struct Mesh final : Node {
{
using ChunkInfo::operator=; using ChunkInfo::operator=;
enum DrawFlags { enum DrawFlags {
SOLID = 0x1, SOLID = 0x1,
@@ -162,107 +159,118 @@ struct Mesh : public Node
// ------------------ // ------------------
/** COB Group data structure */ /** COB Group data structure */
struct Group : public Node struct Group final : Node {
{
using ChunkInfo::operator=; using ChunkInfo::operator=;
Group() : Node(TYPE_GROUP) {}
Group() : Node(TYPE_GROUP) {
// empty
}
}; };
// ------------------ // ------------------
/** COB Bone data structure */ /** COB Bone data structure */
struct Bone : public Node struct Bone final : Node {
{
using ChunkInfo::operator=; using ChunkInfo::operator=;
Bone() : Node(TYPE_BONE) {}
Bone() : Node(TYPE_BONE) {
// empty
}
}; };
// ------------------ // ------------------
/** COB Light data structure */ /** COB Light data structure */
struct Light : public Node struct Light final : Node {
{
enum LightType { enum LightType {
SPOT,LOCAL,INFINITE SPOT,
LOCAL,
INFINITE
}; };
using ChunkInfo::operator=; using ChunkInfo::operator=;
Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {}
Light() : Node(TYPE_LIGHT), ltype() {
// empty
}
aiColor3D color; aiColor3D color;
float angle,inner_angle; float angle{ 0.0f };
float inner_angle{ 0.0f };
LightType ltype; LightType ltype{SPOT};
}; };
// ------------------ // ------------------
/** COB Camera data structure */ /** COB Camera data structure */
struct Camera : public Node struct Camera final : Node {
{
using ChunkInfo::operator=; using ChunkInfo::operator=;
Camera() : Node(TYPE_CAMERA) {}
Camera() : Node(TYPE_CAMERA) {
// empty
}
}; };
// ------------------ // ------------------
/** COB Texture data structure */ /** COB Texture data structure */
struct Texture struct Texture {
{
std::string path; std::string path;
aiUVTransform transform; aiUVTransform transform;
}; };
// ------------------ // ------------------
/** COB Material data structure */ /** COB Material data structure */
struct Material : ChunkInfo struct Material : ChunkInfo {
{
using ChunkInfo::operator=; using ChunkInfo::operator=;
enum Shader { enum Shader {
FLAT,PHONG,METAL FLAT,
PHONG,
METAL
}; };
enum AutoFacet { enum AutoFacet {
FACETED,AUTOFACETED,SMOOTH FACETED,
AUTOFACETED,
SMOOTH
}; };
Material() : alpha(),exp(),ior(),ka(),ks(1.f), Material() : shader(FLAT) {
matnum(UINT_MAX), // empty
shader(FLAT),autofacet(FACETED), }
autofacet_angle()
{}
std::string type; std::string type;
aiColor3D rgb; aiColor3D rgb;
float alpha, exp, ior,ka,ks; float alpha{ 0.0f };
float exp{ 0.0f };
unsigned int matnum; float ior{ 0.0f };
float ka{ 0.0f };
float ks{ 1.0f };
unsigned int matnum{ UINT_MAX };
Shader shader; Shader shader;
AutoFacet autofacet{FACETED};
AutoFacet autofacet; float autofacet_angle{ 0.0f };
float autofacet_angle;
std::shared_ptr<Texture> tex_env,tex_bump,tex_color; std::shared_ptr<Texture> tex_env,tex_bump,tex_color;
}; };
// ------------------ // ------------------
/** Embedded bitmap, for instance for the thumbnail image */ /** Embedded bitmap, for instance for the thumbnail image */
struct Bitmap : ChunkInfo struct Bitmap : ChunkInfo {
{ Bitmap() = default;
Bitmap() : orig_size() {}
struct BitmapHeader struct BitmapHeader {
{ // empty
}; };
BitmapHeader head; BitmapHeader head;
size_t orig_size; size_t orig_size{ 0u };
std::vector<char> buff_zipped; std::vector<char> buff_zipped;
}; };
typedef std::deque< std::shared_ptr<Node> > NodeList; using NodeList = std::deque< std::shared_ptr<Node>>;
typedef std::vector< Material > MaterialList; using MaterialList = std::vector< Material >;
// ------------------ // ------------------
/** Represents a master COB scene, even if we loaded just a single COB file */ /** Represents a master COB scene, even if we loaded just a single COB file */
struct Scene struct Scene {
{
NodeList nodes; NodeList nodes;
MaterialList materials; MaterialList materials;
@@ -270,7 +278,6 @@ struct Scene
Bitmap thumbnail; Bitmap thumbnail;
}; };
} // end COB } // end Assimp::COB
} // end Assimp
#endif #endif // INCLUDED_AI_COB_SCENE_H
+20 -6
View File
@@ -135,7 +135,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
else if (TokenMatchI(buffer,"rate",4)) { else if (TokenMatchI(buffer,"rate",4)) {
SkipSpaces(&buffer, end); SkipSpaces(&buffer, end);
float d = { 0.0f }; float d = { 0.0f };
buffer = fast_atoreal_move<float>(buffer,d); buffer = fast_atoreal_move(buffer,d);
anim->mTicksPerSecond = d; anim->mTicksPerSecond = d;
} }
else if (TokenMatchI(buffer,"order",5)) { else if (TokenMatchI(buffer,"order",5)) {
@@ -176,9 +176,17 @@ void CSMImporter::InternReadFile( const std::string& pFile,
// If we know how many frames we'll read, we can preallocate some storage // If we know how many frames we'll read, we can preallocate some storage
unsigned int alloc = 100; unsigned int alloc = 100;
if (last != 0x00ffffff) { if (last != 0x00ffffff) {
// re-init if the file has last frame data
alloc = last-first; alloc = last-first;
alloc += alloc>>2u; // + 25% alloc += alloc>>2u; // + 25%
for (unsigned int i = 0; i < anim->mNumChannels; ++i) { for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
if (anim->mChannels[i]->mPositionKeys != nullptr) delete[] anim->mChannels[i]->mPositionKeys;
anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
}
} else {
// default init
for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
if (anim->mChannels[i]->mPositionKeys != nullptr) continue;
anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc]; anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
} }
} }
@@ -202,7 +210,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
if (s->mNumPositionKeys == alloc) { if (s->mNumPositionKeys == alloc) {
// need to reallocate? // need to reallocate?
aiVectorKey* old = s->mPositionKeys; aiVectorKey* old = s->mPositionKeys;
s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2]; s->mPositionKeys = new aiVectorKey[alloc*2];
::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc); ::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
delete[] old; delete[] old;
} }
@@ -218,17 +226,17 @@ void CSMImporter::InternReadFile( const std::string& pFile,
} else { } else {
aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys; aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
sub->mTime = (double)frame; 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)) { if (!SkipSpacesAndLineEnd(&buffer, end)) {
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample y coord"); 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)) { if (!SkipSpacesAndLineEnd(&buffer, end)) {
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample z coord"); 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; ++s->mNumPositionKeys;
} }
@@ -271,7 +279,13 @@ void CSMImporter::InternReadFile( const std::string& pFile,
nd->mName = anim->mChannels[i]->mNodeName; nd->mName = anim->mChannels[i]->mNodeName;
nd->mParent = pScene->mRootNode; nd->mParent = pScene->mRootNode;
aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation); if (na->mPositionKeys != nullptr && na->mNumPositionKeys > 0) {
aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
} else {
// Use identity matrix if no valid position data is available
nd->mTransformation = aiMatrix4x4();
DefaultLogger::get()->warn("CSM: No position keys available for node - using identity transformation");
}
} }
// Store the one and only animation in the scene // Store the one and only animation in the scene
+1 -1
View File
@@ -58,7 +58,7 @@ namespace Assimp {
* Link to file format specification: * Link to file format specification:
* <max_8_dvd>\samples\Motion\Docs\CSM.rtf * <max_8_dvd>\samples\Motion\Docs\CSM.rtf
*/ */
class CSMImporter : public BaseImporter { class CSMImporter final : public BaseImporter {
public: public:
CSMImporter(); CSMImporter();
~CSMImporter() override = default; ~CSMImporter() override = default;
+1 -1
View File
@@ -65,7 +65,7 @@ class IOSystem;
/// Helper class to export a given scene to a Collada file. Just for my personal /// Helper class to export a given scene to a Collada file. Just for my personal
/// comfort when implementing it. /// comfort when implementing it.
class ColladaExporter { class ColladaExporter final {
public: public:
/// Constructor for a specific scene to export /// Constructor for a specific scene to export
ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file); ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file);
+1 -1
View File
@@ -341,7 +341,7 @@ struct SubMesh {
/// Contains data for a single mesh /// Contains data for a single mesh
struct Mesh { struct Mesh {
Mesh(const std::string &id) : explicit Mesh(const std::string &id) :
mId(id) { mId(id) {
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
mNumUVComponents[i] = 2; mNumUVComponents[i] = 2;
+4 -4
View File
@@ -77,12 +77,12 @@ static constexpr aiImporterDesc desc = {
"dae xml zae" "dae xml zae"
}; };
static const float kMillisecondsFromSeconds = 1000.f; static constexpr float kMillisecondsFromSeconds = 1000.f;
// Add an item of metadata to a node // Add an item of metadata to a node
// Assumes the key is not already in the list // Assumes the key is not already in the list
template <typename T> template <typename T>
inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) { void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) {
if (nullptr == node->mMetaData) { if (nullptr == node->mMetaData) {
node->mMetaData = new aiMetadata(); node->mMetaData = new aiMetadata();
} }
@@ -92,7 +92,7 @@ inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a float value from an accessor and its data array. // Reads a float value from an accessor and its data array.
static ai_real ReadFloat(const Accessor &pAccessor, const Data &pData, size_t pIndex, size_t pOffset) { static ai_real ReadFloat(const Accessor &pAccessor, const Data &pData, size_t pIndex, size_t pOffset) {
size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset; const size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size()); ai_assert(pos < pData.mValues.size());
return pData.mValues[pos]; return pData.mValues[pos];
} }
@@ -1819,4 +1819,4 @@ std::string ColladaLoader::FindNameForNode(const Node *pNode) {
} // Namespace Assimp } // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER #endif // !! ASSIMP_BUILD_NO_COLLADA_IMPORTER
+1 -1
View File
@@ -82,7 +82,7 @@ struct ColladaMeshIndex {
* Collada is over-engineered to death, with every new iteration bringing more useless stuff, * Collada is over-engineered to death, with every new iteration bringing more useless stuff,
* so I limited the data to what I think is useful for games. * so I limited the data to what I think is useful for games.
*/ */
class ColladaLoader : public BaseImporter { class ColladaLoader final : public BaseImporter {
public: public:
/// The class constructor. /// The class constructor.
ColladaLoader(); ColladaLoader();
+17 -14
View File
@@ -129,7 +129,7 @@ static void ReadNodeTransformation(XmlNode &node, Node *pNode, TransformType pTy
// skip whitespace before the number // skip whitespace before the number
SkipSpacesAndLineEnd(&content, end); SkipSpacesAndLineEnd(&content, end);
// read a number // 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 // 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 *content = v.c_str();
const char *end = content + v.size(); 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); 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); 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); SkipSpacesAndLineEnd(&content, end);
} else if (currentName == "constant_attenuation") { } else if (currentName == "constant_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttConstant); XmlParser::getValueAsReal(currentNode, pLight.mAttConstant);
@@ -631,7 +631,7 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
std::string tUnitSizeString; std::string tUnitSizeString;
if (XmlParser::getStdStrAttribute(currentNode, "meter", tUnitSizeString)) { if (XmlParser::getStdStrAttribute(currentNode, "meter", tUnitSizeString)) {
try { try {
fast_atoreal_move<ai_real>(tUnitSizeString.data(), mUnitSize); fast_atoreal_move(tUnitSizeString.data(), mUnitSize);
} catch (const DeadlyImportError& die) { } catch (const DeadlyImportError& die) {
std::string warning("Collada: Failed to parse meter parameter to real number. Exception:\n"); std::string warning("Collada: Failed to parse meter parameter to real number. Exception:\n");
warning.append(die.what()); warning.append(die.what());
@@ -886,10 +886,10 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
XmlParser::getValueAsString(currentNode, v); XmlParser::getValueAsString(currentNode, v);
const char *content = v.c_str(); const char *content = v.c_str();
const char *end = content + v.size(); const char *end = content + v.size();
for (float & a : controller.mBindShapeMatrix) { for (auto & a : controller.mBindShapeMatrix) {
SkipSpacesAndLineEnd(&content, end); SkipSpacesAndLineEnd(&content, end);
// read a number // read a number
content = fast_atoreal_move<ai_real>(content, a); content = fast_atoreal_move(content, a);
// skip whitespace after it // skip whitespace after it
SkipSpacesAndLineEnd(&content, end); SkipSpacesAndLineEnd(&content, end);
} }
@@ -1262,16 +1262,16 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
const char *content = v.c_str(); const char *content = v.c_str();
const char *end = v.c_str() + v.size() + 1; 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); SkipSpacesAndLineEnd(&content, end);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.g); content = fast_atoreal_move(content, pColor.g);
SkipSpacesAndLineEnd(&content, end); SkipSpacesAndLineEnd(&content, end);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.b); content = fast_atoreal_move(content, pColor.b);
SkipSpacesAndLineEnd(&content, end); SkipSpacesAndLineEnd(&content, end);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.a); content = fast_atoreal_move(content, pColor.a);
SkipSpacesAndLineEnd(&content, end); SkipSpacesAndLineEnd(&content, end);
} else if (currentName == "texture") { } else if (currentName == "texture") {
// get name of source texture/sampler // get name of source texture/sampler
@@ -1494,7 +1494,7 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
// read a number // read a number
ai_real value; ai_real value;
content = fast_atoreal_move<ai_real>(content, value); content = fast_atoreal_move(content, value);
data.mValues.push_back(value); data.mValues.push_back(value);
// skip whitespace after it // skip whitespace after it
SkipSpacesAndLineEnd(&content, end); SkipSpacesAndLineEnd(&content, end);
@@ -1929,7 +1929,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh &pMesh, void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh &pMesh,
std::vector<InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices) { std::vector<InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices) {
// calculate the base offset of the vertex whose attributes we ant to copy // calculate the base offset of the vertex whose attributes we ant to copy
size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets; const auto baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets;
// don't overrun the boundaries of the index list // don't overrun the boundaries of the index list
ai_assert((baseOffset + numOffsets - 1) < indices.size()); ai_assert((baseOffset + numOffsets - 1) < indices.size());
@@ -1944,6 +1944,9 @@ void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t n
} }
// store the vertex-data index for later assignment of bone vertex weights // store the vertex-data index for later assignment of bone vertex weights
if (const auto indexOffset = baseOffset + perVertexOffset; indexOffset >= indices.size()) {
throw DeadlyImportError("index offset out of range");
}
pMesh.mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]); pMesh.mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]);
} }
@@ -2423,4 +2426,4 @@ InputType ColladaParser::GetTypeForSemantic(const std::string &semantic) {
return IT_Invalid; return IT_Invalid;
} }
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER #endif // !! ASSIMP_BUILD_NO_COLLADA_IMPORTER
+4 -6
View File
@@ -53,15 +53,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
namespace Assimp { namespace Assimp::DXF {
namespace DXF {
// read pairs of lines, parse group code and value and provide utilities // read pairs of lines, parse group code and value and provide utilities
// to convert the data to the target data type. // to convert the data to the target data type.
// do NOT skip empty lines. In DXF files, they count as valid data. // do NOT skip empty lines. In DXF files, they count as valid data.
class LineReader { class LineReader {
public: public:
LineReader(StreamReaderLE& reader) : splitter(reader,false,true), groupcode( 0 ), end() { explicit LineReader(StreamReaderLE& reader) : splitter(reader,false,true), groupcode( 0 ), end() {
// empty // empty
} }
@@ -101,7 +100,7 @@ public:
} }
// ----------------------------------------- // -----------------------------------------
float ValueAsFloat() const { ai_real ValueAsFloat() const {
return fast_atof(value.c_str()); return fast_atof(value.c_str());
} }
@@ -203,7 +202,6 @@ struct FileData {
std::vector<Block> blocks; std::vector<Block> blocks;
}; };
} // namespace DXF } // namespace Assimp::DXF
} // namespace Assimp
#endif // INCLUDED_DXFHELPER_H #endif // INCLUDED_DXFHELPER_H
+1 -1
View File
@@ -66,7 +66,7 @@ namespace DXF {
/** /**
* @brief DXF importer implementation. * @brief DXF importer implementation.
*/ */
class DXFImporter : public BaseImporter { class DXFImporter final : public BaseImporter {
public: public:
DXFImporter() = default; DXFImporter() = default;
~DXFImporter() override = default; ~DXFImporter() override = default;
+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) { size_t Offset(const char* begin, const char* cursor) {
ai_assert(begin <= cursor); if (begin > cursor) {
return 0;
}
return cursor - begin; return cursor - begin;
} }
+2 -4
View File
@@ -47,8 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER #ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
namespace Assimp { namespace Assimp::FBX {
namespace FBX {
static constexpr size_t NumNullRecords = 25; static constexpr size_t NumNullRecords = 25;
@@ -84,8 +83,7 @@ enum TransformInheritance {
TransformInheritance_MAX // end-of-enum sentinel TransformInheritance_MAX // end-of-enum sentinel
}; };
} // namespace FBX } // namespace Assimp::FBX
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER #endif // ASSIMP_BUILD_NO_FBX_EXPORTER
+1 -1
View File
@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <set> #include <set>
// //
#if _MSC_VER > 1500 || (defined __GNUC___) #if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_FBX_USE_UNORDERED_MULTIMAP # define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
# else # else
# define fbx_unordered_map map # define fbx_unordered_map map
+1 -1
View File
@@ -237,7 +237,7 @@ std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiN
/// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released. /// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
struct FBXConverter::PotentialNode { struct FBXConverter::PotentialNode {
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {} PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {} explicit PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
aiNode* operator->() { return mNode; } aiNode* operator->() { return mNode; }
std::unique_ptr<aiNode> mOwnership; std::unique_ptr<aiNode> mOwnership;
aiNode* mNode; aiNode* mNode;
+29 -29
View File
@@ -174,7 +174,7 @@ class NodeAttribute : public Object {
public: public:
NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name); NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~NodeAttribute() = default; ~NodeAttribute() override = default;
const PropertyTable& Props() const { const PropertyTable& Props() const {
ai_assert(props.get()); ai_assert(props.get());
@@ -186,11 +186,11 @@ private:
}; };
/** DOM base class for FBX camera settings attached to a node */ /** DOM base class for FBX camera settings attached to a node */
class CameraSwitcher : public NodeAttribute { class CameraSwitcher final : public NodeAttribute {
public: public:
CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name); CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~CameraSwitcher() = default; ~CameraSwitcher() override= default;
int CameraID() const { int CameraID() const {
return cameraId; return cameraId;
@@ -231,11 +231,11 @@ private:
/** DOM base class for FBX cameras attached to a node */ /** DOM base class for FBX cameras attached to a node */
class Camera : public NodeAttribute { class Camera final : public NodeAttribute {
public: public:
Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name); Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Camera() = default; ~Camera() override = default;
fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0)) fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0)) fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
@@ -257,24 +257,24 @@ public:
}; };
/** DOM base class for FBX null markers attached to a node */ /** DOM base class for FBX null markers attached to a node */
class Null : public NodeAttribute { class Null final : public NodeAttribute {
public: public:
Null(uint64_t id, const Element& element, const Document& doc, const std::string& name); Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Null() = default; ~Null() override = default;
}; };
/** DOM base class for FBX limb node markers attached to a node */ /** DOM base class for FBX limb node markers attached to a node */
class LimbNode : public NodeAttribute { class LimbNode final : public NodeAttribute {
public: public:
LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name); LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~LimbNode() = default; ~LimbNode() override = default;
}; };
/** DOM base class for FBX lights attached to a node */ /** DOM base class for FBX lights attached to a node */
class Light : public NodeAttribute { class Light final : public NodeAttribute {
public: public:
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name); Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Light() = default; ~Light() override = default;
enum Type { enum Type {
Type_Point, Type_Point,
@@ -329,7 +329,7 @@ public:
}; };
/** DOM base class for FBX models (even though its semantics are more "node" than "model" */ /** DOM base class for FBX models (even though its semantics are more "node" than "model" */
class Model : public Object { class Model final : public Object {
public: public:
enum RotOrder { enum RotOrder {
RotOrder_EulerXYZ = 0, RotOrder_EulerXYZ = 0,
@@ -354,7 +354,7 @@ public:
Model(uint64_t id, const Element& element, const Document& doc, const std::string& name); Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Model() = default; ~Model() override = default;
fbx_simple_property(QuaternionInterpolate, int, 0) fbx_simple_property(QuaternionInterpolate, int, 0)
@@ -477,11 +477,11 @@ private:
}; };
/** DOM class for generic FBX textures */ /** DOM class for generic FBX textures */
class Texture : public Object { class Texture final : public Object {
public: public:
Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name); Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Texture(); ~Texture() override;
const std::string& Type() const { const std::string& Type() const {
return type; return type;
@@ -542,10 +542,10 @@ private:
}; };
/** DOM class for layered FBX textures */ /** DOM class for layered FBX textures */
class LayeredTexture : public Object { class LayeredTexture final : public Object {
public: public:
LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name); LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~LayeredTexture(); ~LayeredTexture() override;
// Can only be called after construction of the layered texture object due to construction flag. // Can only be called after construction of the layered texture object due to construction flag.
void fillTexture(const Document& doc); void fillTexture(const Document& doc);
@@ -608,11 +608,11 @@ using TextureMap = std::fbx_unordered_map<std::string, const Texture*>;
using LayeredTextureMap = std::fbx_unordered_map<std::string, const LayeredTexture*>; using LayeredTextureMap = std::fbx_unordered_map<std::string, const LayeredTexture*>;
/** DOM class for generic FBX videos */ /** DOM class for generic FBX videos */
class Video : public Object { class Video final : public Object {
public: public:
Video(uint64_t id, const Element& element, const Document& doc, const std::string& name); Video(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Video(); ~Video() override;
const std::string& Type() const { const std::string& Type() const {
return type; return type;
@@ -697,10 +697,10 @@ using KeyTimeList = std::vector<int64_t>;
using KeyValueList = std::vector<float>; using KeyValueList = std::vector<float>;
/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */ /** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */
class AnimationCurve : public Object { class AnimationCurve final : public Object {
public: public:
AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc); AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationCurve() = default; ~AnimationCurve() override = default;
/** get list of keyframe positions (time). /** get list of keyframe positions (time).
* Invariant: |GetKeys()| > 0 */ * Invariant: |GetKeys()| > 0 */
@@ -733,7 +733,7 @@ private:
using AnimationCurveMap = std::map<std::string, const AnimationCurve*>; using AnimationCurveMap = std::map<std::string, const AnimationCurve*>;
/** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */ /** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
class AnimationCurveNode : public Object { class AnimationCurveNode final : public Object {
public: public:
/* the optional white list specifies a list of property names for which the caller /* the optional white list specifies a list of property names for which the caller
wants animations for. If the curve node does not match one of these, std::range_error wants animations for. If the curve node does not match one of these, std::range_error
@@ -741,7 +741,7 @@ public:
AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0); const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
virtual ~AnimationCurveNode() = default; ~AnimationCurveNode() override = default;
const PropertyTable& Props() const { const PropertyTable& Props() const {
ai_assert(props.get()); ai_assert(props.get());
@@ -783,7 +783,7 @@ private:
using AnimationCurveNodeList = std::vector<const AnimationCurveNode*>; using AnimationCurveNodeList = std::vector<const AnimationCurveNode*>;
/** Represents a FBX animation layer (i.e. a list of node animations) */ /** Represents a FBX animation layer (i.e. a list of node animations) */
class AnimationLayer : public Object { class AnimationLayer final : public Object {
public: public:
AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc); AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationLayer() = default; virtual ~AnimationLayer() = default;
@@ -806,7 +806,7 @@ private:
using AnimationLayerList = std::vector<const AnimationLayer*>; using AnimationLayerList = std::vector<const AnimationLayer*>;
/** Represents a FBX animation stack (i.e. a list of animation layers) */ /** Represents a FBX animation stack (i.e. a list of animation layers) */
class AnimationStack : public Object { class AnimationStack final : public Object {
public: public:
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc); AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationStack() = default; virtual ~AnimationStack() = default;
@@ -851,7 +851,7 @@ using WeightIndexArray = std::vector<unsigned int>;
/** DOM class for BlendShapeChannel deformers */ /** DOM class for BlendShapeChannel deformers */
class BlendShapeChannel : public Deformer { class BlendShapeChannel final : public Deformer {
public: public:
BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name); BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name);
@@ -876,7 +876,7 @@ private:
}; };
/** DOM class for BlendShape deformers */ /** DOM class for BlendShape deformers */
class BlendShape : public Deformer { class BlendShape final : public Deformer {
public: public:
BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name); BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name);
@@ -891,7 +891,7 @@ private:
}; };
/** DOM class for skin deformer clusters (aka sub-deformers) */ /** DOM class for skin deformer clusters (aka sub-deformers) */
class Cluster : public Deformer { class Cluster final : public Deformer {
public: public:
Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name); Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name);
@@ -935,7 +935,7 @@ private:
}; };
/** DOM class for skin deformers */ /** DOM class for skin deformers */
class Skin : public Deformer { class Skin final : public Deformer {
public: public:
Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name); Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+48 -13
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) { 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 // Defensive: handle zero or near-zero mTicksPerSecond
double tps = anim->mTicksPerSecond; double tps = anim->mTicksPerSecond;
double timeVal; double timeVal;
@@ -1062,7 +1066,7 @@ inline int64_t to_ktime(double ticks, const aiAnimation* anim) {
if (timeVal < kMin) { if (timeVal < kMin) {
return INT64_MIN; 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) { inline int64_t to_ktime(double time) {
@@ -1094,6 +1098,7 @@ void FBXExporter::WriteObjects () {
bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true); bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true);
// save vertex_indices as it is needed later // save vertex_indices as it is needed later
std::vector<std::vector<int32_t>> vVertexIndice(mScene->mNumMeshes); 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); 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]; const aiMesh *m = mScene->mMeshes[mi];
size_t v_offset = vertex_indices.size(); 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 // map of vertex value to its index in the data vector
std::map<aiVector3D,size_t> index_by_vertex_value; std::map<aiVector3D,size_t> index_by_vertex_value;
@@ -1182,11 +1188,17 @@ void FBXExporter::WriteObjects () {
if (f.mNumIndices == 0) continue; if (f.mNumIndices == 0) continue;
size_t pvi = 0; size_t pvi = 0;
for (; pvi < f.mNumIndices - 1; pvi++) { 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()) { if (m->HasNormals()) {
normal_data.reserve(3 * polygon_data.size()); normal_data.reserve(3 * polygon_data.size());
for (size_t fi = 0; fi < m->mNumFaces; fi++) { for (size_t fi = 0; fi < m->mNumFaces; fi++) {
@@ -1329,14 +1341,13 @@ void FBXExporter::WriteObjects () {
} else { } else {
mat.AddChild("MappingInformationType", "ByPolygon"); mat.AddChild("MappingInformationType", "ByPolygon");
mat.AddChild("ReferenceInformationType", "IndexToDirect"); mat.AddChild("ReferenceInformationType", "IndexToDirect");
std::vector<int32_t> mat_indices(polygon_data.size()); std::vector<int32_t> mat_indices;
uint32_t curr_offset = 0; for (uint32_t n_mi = 0; n_mi < node->mNumMeshes; n_mi++) {
for (uint32_t mi = 0; mi < node->mNumMeshes; mi++) { const auto mi = node->mMeshes[n_mi];
uint32_t num_faces = mScene->mMeshes[node->mMeshes[mi]]->mNumFaces; const auto *const m = mScene->mMeshes[mi];
for (uint32_t fi = 0; fi < num_faces; fi++) { for (size_t fi = 0; fi < m->mNumFaces; fi++) {
mat_indices[curr_offset + fi] = mi; mat_indices.push_back(n_mi);
} }
curr_offset += num_faces;
} }
mat.AddChild("Materials", mat_indices); mat.AddChild("Materials", mat_indices);
} }
@@ -1571,6 +1582,7 @@ void FBXExporter::WriteObjects () {
} }
} }
std::map<std::string, std::string> tpath_by_image;
// FbxVideo - stores images used by textures. // FbxVideo - stores images used by textures.
for (const auto &it : uid_by_image) { for (const auto &it : uid_by_image) {
FBX::Node n("Video"); FBX::Node n("Video");
@@ -1590,10 +1602,21 @@ void FBXExporter::WriteObjects () {
std::stringstream newPath; std::stringstream newPath;
if (embedded_texture->mFilename.length > 0) { if (embedded_texture->mFilename.length > 0) {
newPath << embedded_texture->mFilename.C_Str(); newPath << embedded_texture->mFilename.C_Str();
// If newPath doesn't end in an extension, add extension from embedded_texture->achFormatHint
std::string np = newPath.str();
size_t dot_pos = np.find_last_of('.');
if (dot_pos == std::string::npos || dot_pos < np.find_last_of("/\\")) {
// No extension found, add one
newPath << "." << embedded_texture->achFormatHint;
}
} else if (embedded_texture->achFormatHint[0]) { } else if (embedded_texture->achFormatHint[0]) {
int texture_index = std::stoi(path.substr(1, path.size() - 1)); int texture_index = std::stoi(path.substr(1, path.size() - 1));
newPath << texture_index << "." << embedded_texture->achFormatHint; newPath << texture_index << "." << embedded_texture->achFormatHint;
} }
auto elem = tpath_by_image.find(path);
if (elem == tpath_by_image.end()) {
tpath_by_image[path] = newPath.str();
}
path = newPath.str(); path = newPath.str();
// embed the texture // embed the texture
size_t texture_size = static_cast<size_t>(embedded_texture->mWidth * std::max(embedded_texture->mHeight, 1u)); size_t texture_size = static_cast<size_t>(embedded_texture->mWidth * std::max(embedded_texture->mHeight, 1u));
@@ -1712,6 +1735,17 @@ void FBXExporter::WriteObjects () {
unsigned int max = sizeof(aiUVTransform); unsigned int max = sizeof(aiUVTransform);
aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE, 0), (ai_real *)&trafo, &max); aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE, 0), (ai_real *)&trafo, &max);
auto tp_elem = tpath_by_image.find(texture_path);
std::string tfile_path = texture_path;
if (tp_elem != tpath_by_image.end()) {
tfile_path = tp_elem->second;
} else {
std::stringstream err;
err << "Texture path not found for texure " << texture_path;
err << " on material " << i;
ASSIMP_LOG_WARN(err.str());
}
// now write the actual texture node // now write the actual texture node
FBX::Node tnode("Texture"); FBX::Node tnode("Texture");
// TODO: some way to determine texture name? // TODO: some way to determine texture name?
@@ -1732,8 +1766,8 @@ void FBXExporter::WriteObjects () {
// can't easily determine which texture path will be correct, // can't easily determine which texture path will be correct,
// so just store what we have in every field. // so just store what we have in every field.
// these being incorrect is a common problem with FBX anyway. // these being incorrect is a common problem with FBX anyway.
tnode.AddChild("FileName", texture_path); tnode.AddChild("FileName", tp_elem->second);
tnode.AddChild("RelativeFilename", texture_path); tnode.AddChild("RelativeFilename", tp_elem->second);
tnode.AddChild("ModelUVTranslation", double(0.0), double(0.0)); tnode.AddChild("ModelUVTranslation", double(0.0), double(0.0));
tnode.AddChild("ModelUVScaling", double(1.0), double(1.0)); tnode.AddChild("ModelUVScaling", double(1.0), double(1.0));
tnode.AddChild("Texture_Alpha_Source", "None"); tnode.AddChild("Texture_Alpha_Source", "None");
@@ -2059,7 +2093,8 @@ void FBXExporter::WriteObjects () {
ASSIMP_LOG_ERROR("UNREAL: Skipping vertex index to prevent buffer overflow."); ASSIMP_LOG_ERROR("UNREAL: Skipping vertex index to prevent buffer overflow.");
continue; 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()); bool bIsWeightedAlready = (setWeightedVertex.find(vi) != setWeightedVertex.end());
if (vi == last_index || bIsWeightedAlready) { if (vi == last_index || bIsWeightedAlready) {
// only for vertices we exported to fbx // only for vertices we exported to fbx
+1 -1
View File
@@ -67,7 +67,7 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
/// ///
/// See http://en.wikipedia.org/wiki/FBX /// See http://en.wikipedia.org/wiki/FBX
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> { class FBXImporter final : public BaseImporter, public LogFunctions<FBXImporter> {
public: public:
/// @brief The class constructor. /// @brief The class constructor.
FBXImporter() = default; FBXImporter() = default;
+60 -16
View File
@@ -365,10 +365,14 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
} }
if (data[0] == 'F') { 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 { 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') { if (type == 'd') {
const double* d = reinterpret_cast<const double*>(&buff[0]); const double* d = reinterpret_cast<const double*>(&buff[0]);
for (unsigned int i = 0; i < count3; ++i, d += 3) { for (unsigned int i = 0; i < count3; ++i, d += 3) {
out.emplace_back(static_cast<ai_real>(d[0]), BE_NCONST double val1 = d[0];
static_cast<ai_real>(d[1]), BE_NCONST double val2 = d[1];
static_cast<ai_real>(d[2])); 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 debugging
/*for ( size_t i = 0; i < out.size(); i++ ) { /*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') { else if (type == 'f') {
const float* f = reinterpret_cast<const float*>(&buff[0]); const float* f = reinterpret_cast<const float*>(&buff[0]);
for (unsigned int i = 0; i < count3; ++i, f += 3) { 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') { if (type == 'd') {
const double* d = reinterpret_cast<const double*>(&buff[0]); const double* d = reinterpret_cast<const double*>(&buff[0]);
for (unsigned int i = 0; i < count4; ++i, d += 4) { for (unsigned int i = 0; i < count4; ++i, d += 4) {
out.emplace_back(static_cast<float>(d[0]), BE_NCONST double val1 = d[0];
static_cast<float>(d[1]), BE_NCONST double val2 = d[1];
static_cast<float>(d[2]), BE_NCONST double val3 = d[2];
static_cast<float>(d[3])); 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') { else if (type == 'f') {
const float* f = reinterpret_cast<const float*>(&buff[0]); const float* f = reinterpret_cast<const float*>(&buff[0]);
for (unsigned int i = 0; i < count4; ++i, f += 4) { 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; return;
@@ -807,13 +839,21 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el) {
if (type == 'd') { if (type == 'd') {
const double* d = reinterpret_cast<const double*>(&buff[0]); const double* d = reinterpret_cast<const double*>(&buff[0]);
for (unsigned int i = 0; i < count2; ++i, d += 2) { for (unsigned int i = 0; i < count2; ++i, d += 2) {
out.emplace_back(static_cast<float>(d[0]), BE_NCONST double val1 = d[0];
static_cast<float>(d[1])); 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') { } else if (type == 'f') {
const float* f = reinterpret_cast<const float*>(&buff[0]); const float* f = reinterpret_cast<const float*>(&buff[0]);
for (unsigned int i = 0; i < count2; ++i, f += 2) { 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') { if (type == 'd') {
const double* d = reinterpret_cast<const double*>(&buff[0]); const double* d = reinterpret_cast<const double*>(&buff[0]);
for (unsigned int i = 0; i < count; ++i, ++d) { 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') { else if (type == 'f') {
const float* f = reinterpret_cast<const float*>(&buff[0]); const float* f = reinterpret_cast<const float*>(&buff[0]);
for (unsigned int i = 0; i < count; ++i, ++f) { 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);
} }
} }
+2 -9
View File
@@ -50,11 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <cstring> #include <cstring>
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER namespace Assimp::FBX::Util {
namespace Assimp {
namespace FBX {
namespace Util {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const char* TokenTypeString(TokenType t) const char* TokenTypeString(TokenType t)
@@ -233,8 +229,5 @@ std::string EncodeBase64(const char* data, size_t length)
return encoded_string; return encoded_string;
} }
} // !Util } // namespace Assimp::FBX::Util
} // !FBX
} // !Assimp
#endif
+1 -9
View File
@@ -49,10 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXTokenizer.h" #include "FBXTokenizer.h"
#include <stdint.h> #include <stdint.h>
namespace Assimp { namespace Assimp::FBX::Util {
namespace FBX {
namespace Util {
/** helper for std::for_each to delete all heap-allocated items in a container */ /** helper for std::for_each to delete all heap-allocated items in a container */
template<typename T> template<typename T>
@@ -73,12 +70,9 @@ struct destructor_fun {
} }
}; };
/** Get a string representation for a #TokenType. */ /** Get a string representation for a #TokenType. */
const char* TokenTypeString(TokenType t); const char* TokenTypeString(TokenType t);
/** Format log/error messages using a given offset in the source binary file /** Format log/error messages using a given offset in the source binary file
* *
* @param offset offset within the file * @param offset offset within the file
@@ -129,8 +123,6 @@ char EncodeBase64(char byte);
* @return base64-encoded string*/ * @return base64-encoded string*/
std::string EncodeBase64(const char* data, size_t length); std::string EncodeBase64(const char* data, size_t length);
}
}
} }
#endif // ! INCLUDED_AI_FBX_UTIL_H #endif // ! INCLUDED_AI_FBX_UTIL_H
+16 -16
View File
@@ -433,24 +433,24 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, const char *end, Verte
aiColor4D c; aiColor4D c;
// Read the vertex position // Read the vertex position
sz = fast_atoreal_move<float>(sz, (float &)temp.x); sz = fast_atoreal_move(sz, temp.x);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
sz = fast_atoreal_move<float>(sz, (float &)temp.y); sz = fast_atoreal_move(sz, temp.y);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
sz = fast_atoreal_move<float>(sz, (float &)temp.z); sz = fast_atoreal_move(sz, temp.z);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
vertices.push_back(temp); vertices.push_back(temp);
// Read the vertex normals // Read the vertex normals
sz = fast_atoreal_move<float>(sz, (float &)temp.x); sz = fast_atoreal_move(sz, temp.x);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
sz = fast_atoreal_move<float>(sz, (float &)temp.y); sz = fast_atoreal_move(sz, temp.y);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
sz = fast_atoreal_move<float>(sz, (float &)temp.z); sz = fast_atoreal_move(sz, temp.z);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
normals.push_back(temp); normals.push_back(temp);
@@ -466,10 +466,10 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, const char *end, Verte
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
// read the first UV coordinate set // 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); SkipSpaces(&sz, end);
sz = fast_atoreal_move<float>(sz, (float &)temp.y); sz = fast_atoreal_move(sz, temp.y);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
temp.z = 0.f; temp.z = 0.f;
temp.y = 1.f - temp.y; // DX to OGL 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 // So by definition, all buffers have either UV2 or tangents or neither
// read the (optional) second UV coordinate set // read the (optional) second UV coordinate set
if (vertexFormat == VertexFormat::t2coord) { if (vertexFormat == VertexFormat::t2coord) {
sz = fast_atoreal_move<float>(sz, (float &)temp.x); sz = fast_atoreal_move(sz, temp.x);
SkipSpaces(&sz, end); 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 temp.y = 1.f - temp.y; // DX to OGL
UV2s.push_back(temp); UV2s.push_back(temp);
} }
// read optional tangent and bitangent vectors // read optional tangent and bitangent vectors
else if (vertexFormat == VertexFormat::tangent) { else if (vertexFormat == VertexFormat::tangent) {
// tangents // tangents
sz = fast_atoreal_move<float>(sz, (float &)temp.x); sz = fast_atoreal_move(sz, temp.x);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
sz = fast_atoreal_move<float>(sz, (float &)temp.z); sz = fast_atoreal_move(sz, temp.z);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
sz = fast_atoreal_move<float>(sz, (float &)temp.y); sz = fast_atoreal_move(sz, temp.y);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
temp.y *= -1.0f; temp.y *= -1.0f;
tangents.push_back(temp); tangents.push_back(temp);
// bitangents // bitangents
sz = fast_atoreal_move<float>(sz, (float &)temp.x); sz = fast_atoreal_move(sz, temp.x);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
sz = fast_atoreal_move<float>(sz, (float &)temp.z); sz = fast_atoreal_move(sz, temp.z);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
sz = fast_atoreal_move<float>(sz, (float &)temp.y); sz = fast_atoreal_move(sz, temp.y);
SkipSpaces(&sz, end); SkipSpaces(&sz, end);
temp.y *= -1.0f; temp.y *= -1.0f;
bitangents.push_back(temp); 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; const char *end = ptr + len;
SkipSpaces(&ptr, end); SkipSpaces(&ptr, end);
ptr = fast_atoreal_move<float>(ptr, (float &)out.value.x); ptr = fast_atoreal_move(ptr, out.value.x);
SkipSpaces(&ptr, end); SkipSpaces(&ptr, end);
if (',' != *ptr) { if (',' != *ptr) {
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition"); ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
} else { } else {
SkipSpaces(ptr + 1, &ptr, end); 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); SkipSpaces(&ptr, end);
if (',' != *ptr) { if (',' != *ptr) {
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition"); ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
} else { } else {
SkipSpaces(ptr + 1, &ptr, end); 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
@@ -212,7 +212,7 @@ void AnimResolver::UpdateAnimRangeSetup() {
unsigned int tt = 1; unsigned int tt = 1;
for (const double tmp = delta * (num + 1); cur_minus <= tmp; cur_minus += delta, ++tt) { for (const double tmp = delta * (num + 1); cur_minus <= tmp; cur_minus += delta, ++tt) {
m = (delta == tmp ? (*it).keys.begin() : n - (old_size + 1)); m = (delta == tmp ? (*it).keys.begin() : n - (old_size + 1));
for (; m != n; --n) { for (; m < n; --n) {
(*n).time -= cur_minus; (*n).time -= cur_minus;
// offset repeat? add delta offset to key value // offset repeat? add delta offset to key value
+1 -3
View File
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2025, assimp team Copyright (c) 2006-2025, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@@ -1150,4 +1148,4 @@ void LWOImporter::LoadLWO3Surface(unsigned int size) {
} }
} }
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER #endif // ASSIMP_BUILD_NO_LWO_IMPORTER
+12 -12
View File
@@ -208,9 +208,9 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
float f; float f;
SkipSpaces(&c, end); SkipSpaces(&c, end);
c = fast_atoreal_move<float>(c, key.value); c = fast_atoreal_move(c, key.value);
SkipSpaces(&c, end); SkipSpaces(&c, end);
c = fast_atoreal_move<float>(c, f); c = fast_atoreal_move(c, f);
key.time = 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) { for (unsigned int i = 0; i < num; ++i) {
SkipSpaces(&c, end); 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") { } else if ((*it).tokens[0] == "Behaviors") {
SkipSpaces(&c, end); 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. // parse value and time, skip the rest for the moment.
LWO::Key key; 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(); const char *end = c + (*it).tokens[0].size();
SkipSpaces(&c, end); SkipSpaces(&c, end);
float f; float f;
fast_atoreal_move<float>((*it).tokens[0].c_str(), f); fast_atoreal_move((*it).tokens[0].c_str(), f);
key.time = f; key.time = f;
envl.keys.emplace_back(key); 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"); ASSIMP_LOG_ERROR("LWS: envelopes for LightIntensity not supported, set to 1.0");
nodes.back().lightIntensity = (ai_real)1.0; nodes.back().lightIntensity = (ai_real)1.0;
} else { } 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) { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) {
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'"); ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'");
} else { } else {
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.r); c = fast_atoreal_move(c, nodes.back().lightColor.r);
SkipSpaces(&c, end); 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); 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()) { if (nodes.empty()) {
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'"); ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'");
} else { } else {
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.x); c = fast_atoreal_move(c, nodes.back().pivotPos.x);
SkipSpaces(&c, end); 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); 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 // Mark pivotPos as set
nodes.back().isPivotSet = true; nodes.back().isPivotSet = true;
} }
+1 -1
View File
@@ -332,7 +332,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) {
/* if we have the texture loaded, set format hint and pcData too */ /* if we have the texture loaded, set format hint and pcData too */
tx->mWidth = t->w; tx->mWidth = t->w;
tx->mHeight = t->h; tx->mHeight = t->h;
strcpy(tx->achFormatHint, formatHint[t->f - 1]); strncpy(tx->achFormatHint, formatHint[t->f - 1], 8);
tx->pcData = new aiTexel[tx->mWidth * tx->mHeight]; tx->pcData = new aiTexel[tx->mWidth * tx->mHeight];
for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) { for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) {
switch (t->f) { switch (t->f) {
+18 -10
View File
@@ -246,11 +246,11 @@ inline void AI_MD5_READ_TRIPLE(aiVector3D &vec, const char **sz, const char *buf
return; return;
++*sz; ++*sz;
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
*sz = fast_atoreal_move<float>(*sz, (float &)vec.x); *sz = fast_atoreal_move(*sz, vec.x);
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); 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); 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); AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
if (')' != **sz) { if (')' != **sz) {
MD5Parser::ReportWarning("Unexpected token: ) was expected", linenumber); MD5Parser::ReportWarning("Unexpected token: ) was expected", linenumber);
@@ -277,6 +277,8 @@ inline bool AI_MD5_PARSE_STRING(const char **sz, const char *bufferEnd, aiString
} }
} }
out.length = (ai_uint32)(szEnd - szStart); out.length = (ai_uint32)(szEnd - szStart);
if (out.length >= AI_MAXLEN)
out.length = AI_MAXLEN - 1;
::memcpy(out.data, szStart, out.length); ::memcpy(out.data, szStart, out.length);
out.data[out.length] = '\0'; out.data[out.length] = '\0';
@@ -299,6 +301,8 @@ inline void AI_MD5_PARSE_STRING_IN_QUOTATION(const char **sz, const char *buffer
const char *szEnd = *sz; const char *szEnd = *sz;
++*sz; ++*sz;
out.length = (ai_uint32)(szEnd - szStart); out.length = (ai_uint32)(szEnd - szStart);
if (out.length >= AI_MAXLEN)
out.length = AI_MAXLEN - 1;
::memcpy(out.data, szStart, out.length); ::memcpy(out.data, szStart, out.length);
} }
} }
@@ -373,9 +377,9 @@ MD5MeshParser::MD5MeshParser(SectionArray &mSections) {
if ('(' != *sz++) if ('(' != *sz++)
MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber); MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber);
AI_MD5_SKIP_SPACES(&sz, elem.end, 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); 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); AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
if (')' != *sz++) if (')' != *sz++)
MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber); MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber);
@@ -389,11 +393,15 @@ MD5MeshParser::MD5MeshParser(SectionArray &mSections) {
else if (TokenMatch(sz, "tri", 3)) { else if (TokenMatch(sz, "tri", 3)) {
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
const unsigned int idx = strtoul10(sz, &sz); const unsigned int idx = strtoul10(sz, &sz);
if (idx >= desc.mFaces.size()) if (idx >= desc.mFaces.size()) {
desc.mFaces.resize(idx + 1); desc.mFaces.resize(idx + 1);
}
aiFace &face = desc.mFaces[idx]; aiFace &face = desc.mFaces[idx];
face.mIndices = new unsigned int[face.mNumIndices = 3]; if (face.mNumIndices != 3) {
delete [] face.mIndices;
face.mIndices = new unsigned int[face.mNumIndices = 3];
}
for (unsigned int i = 0; i < 3; ++i) { for (unsigned int i = 0; i < 3; ++i) {
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
face.mIndices[i] = strtoul10(sz, &sz); face.mIndices[i] = strtoul10(sz, &sz);
@@ -411,7 +419,7 @@ MD5MeshParser::MD5MeshParser(SectionArray &mSections) {
WeightDesc &weight = desc.mWeights[idx]; WeightDesc &weight = desc.mWeights[idx];
weight.mBone = strtoul10(sz, &sz); weight.mBone = strtoul10(sz, &sz);
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber); 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); AI_MD5_READ_TRIPLE(weight.vOffsetPosition, &sz, elem.end, elem.iLineNumber);
} }
} }
@@ -482,7 +490,7 @@ MD5AnimParser::MD5AnimParser(SectionArray &mSections) {
const char *sz = elem.szStart; const char *sz = elem.szStart;
while (SkipSpacesAndLineEnd(&sz, elem.end)) { while (SkipSpacesAndLineEnd(&sz, elem.end)) {
float f; float f;
sz = fast_atoreal_move<float>(sz, f); sz = fast_atoreal_move(sz, f);
desc.mValues.push_back(f); desc.mValues.push_back(f);
} }
} }
@@ -499,7 +507,7 @@ MD5AnimParser::MD5AnimParser(SectionArray &mSections) {
} else if ((*iter).mName == "numAnimatedComponents") { } else if ((*iter).mName == "numAnimatedComponents") {
mAnimatedBones.reserve(strtoul10((*iter).mGlobalValue.c_str())); mAnimatedBones.reserve(strtoul10((*iter).mGlobalValue.c_str()));
} else if ((*iter).mName == "frameRate") { } 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"); ASSIMP_LOG_DEBUG("MD5AnimParser end");
+6
View File
@@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "MDLLoader.h" #include "MDLLoader.h"
#include "AssetLib/MD2/MD2FileData.h" #include "AssetLib/MD2/MD2FileData.h"
#include "HalfLife/HL1MDLLoader.h" #include "HalfLife/HL1MDLLoader.h"
#include "HalfLife/HL1FileData.h"
#include "MDLDefaultColorMap.h" #include "MDLDefaultColorMap.h"
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
@@ -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) 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."); 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. // Read the MDL file.
HalfLife::HL1MDLLoader loader( HalfLife::HL1MDLLoader loader(
pScene, pScene,
+4 -7
View File
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2025, assimp team Copyright (c) 2006-2025, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@@ -46,10 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Written against http://chumbalum.swissquake.ch/ms3d/ms3dspec.txt * Written against http://chumbalum.swissquake.ch/ms3d/ms3dspec.txt
*/ */
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER #ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
// internal headers
#include "MS3DLoader.h" #include "MS3DLoader.h"
#include <assimp/StreamReader.h> #include <assimp/StreamReader.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
@@ -392,13 +388,14 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
if (need_default && materials.size()) { if (need_default && materials.size()) {
ASSIMP_LOG_WARN("MS3D: Found group with no material assigned, spawning default material"); ASSIMP_LOG_WARN("MS3D: Found group with no material assigned, spawning default material");
// if one of the groups has no material assigned, but there are other // if one of the groups has no material assigned, but there are other
// groups with materials, a default material needs to be added ( // groups with materials, a default material needs to be added (
// scenepreprocessor adds a default material only if nummat==0). // scenepreprocessor adds a default material only if nummat==0).
materials.emplace_back(); materials.emplace_back();
TempMaterial& m = materials.back(); TempMaterial& m = materials.back();
constexpr char DefaultMat[18] = "<MS3D_DefaultMat>";
strcpy(m.name,"<MS3D_DefaultMat>"); strncpy(m.name, DefaultMat, sizeof(m.name));
m.name[18]='\0';
m.diffuse = aiColor4D(0.6f,0.6f,0.6f,1.0); m.diffuse = aiColor4D(0.6f,0.6f,0.6f,1.0);
m.transparency = 1.f; m.transparency = 1.f;
m.shininess = 0.f; m.shininess = 0.f;
+1 -1
View File
@@ -86,7 +86,7 @@ const aiImporterDesc *NFFImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#define AI_NFF_PARSE_FLOAT(f) \ #define AI_NFF_PARSE_FLOAT(f) \
SkipSpaces(&sz, lineEnd); \ 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) \ #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 // stop at dimensions: this allows loading 1D or 2D coordinate vertices
for (unsigned int dim = 0; dim < dimensions; ++dim) { for (unsigned int dim = 0; dim < dimensions; ++dim) {
SkipSpaces(&sz, lineEnd); 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 has homogeneous coordinate, divide others by this one
if (hasHomogenous) { if (hasHomogenous) {
SkipSpaces(&sz, lineEnd); SkipSpaces(&sz, lineEnd);
ai_real w = 1.; 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) { for (unsigned int dim = 0; dim < dimensions; ++dim) {
*(vec[dim]) /= w; *(vec[dim]) /= w;
} }
@@ -229,11 +229,11 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
if (hasNormals) { if (hasNormals) {
aiVector3D &n = mesh->mNormals[i]; aiVector3D &n = mesh->mNormals[i];
SkipSpaces(&sz, lineEnd); SkipSpaces(&sz, lineEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.x); sz = fast_atoreal_move(sz, n.x);
SkipSpaces(&sz, lineEnd); SkipSpaces(&sz, lineEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.y); sz = fast_atoreal_move(sz, n.y);
SkipSpaces(&sz, lineEnd); 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 // 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) { if (hasColors) {
aiColor4D &c = mesh->mColors[0][i]; aiColor4D &c = mesh->mColors[0][i];
SkipSpaces(&sz, lineEnd); 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') { if (*sz != '#' && *sz != '\n' && *sz != '\r') {
SkipSpaces(&sz, lineEnd); SkipSpaces(&sz, lineEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.g); sz = fast_atoreal_move(sz, c.g);
} else { } else {
c.g = 0.; c.g = 0.;
} }
if (*sz != '#' && *sz != '\n' && *sz != '\r') { if (*sz != '#' && *sz != '\n' && *sz != '\r') {
SkipSpaces(&sz, lineEnd); SkipSpaces(&sz, lineEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.b); sz = fast_atoreal_move(sz, c.b);
} else { } else {
c.b = 0.; c.b = 0.;
} }
if (*sz != '#' && *sz != '\n' && *sz != '\r') { if (*sz != '#' && *sz != '\n' && *sz != '\r') {
SkipSpaces(&sz, lineEnd); SkipSpaces(&sz, lineEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.a); sz = fast_atoreal_move(sz, c.a);
} else { } else {
c.a = 1.; c.a = 1.;
} }
@@ -266,9 +266,9 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
if (hasTexCoord) { if (hasTexCoord) {
aiVector3D &t = mesh->mTextureCoords[0][i]; aiVector3D &t = mesh->mTextureCoords[0][i];
SkipSpaces(&sz, lineEnd); SkipSpaces(&sz, lineEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)t.x); sz = fast_atoreal_move(sz, t.x);
SkipSpaces(&sz, lineEnd); 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 Copyright (c) 2006-2025, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@@ -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) { void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices) {
if (nd == nullptr) {
return;
}
const aiMatrix4x4& mAbs = mParent * nd->mTransformation; const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
aiMesh *cm{nullptr};
aiMesh *cm( nullptr );
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
cm = pScene->mMeshes[nd->mMeshes[i]]; cm = pScene->mMeshes[nd->mMeshes[i]];
if (nullptr != cm) { if (nullptr != cm) {
+27 -23
View File
@@ -165,21 +165,23 @@ struct Material {
//! Ambient color //! Ambient color
aiColor3D ambient; aiColor3D ambient;
//! Diffuse color //! Diffuse color
aiColor3D diffuse; aiColor3D diffuse = aiColor3D(0.6f, 0.6f, 0.6f);
//! Specular color //! Specular color
aiColor3D specular; aiColor3D specular;
//! Emissive color //! Emissive color
aiColor3D emissive; aiColor3D emissive;
//! Alpha value //! Alpha value
ai_real alpha; ai_real alpha = ai_real(1.0);
//! Shineness factor //! Shineness factor
ai_real shineness; ai_real shineness = ai_real(0.0);
//! Illumination model //! Illumination model
int illumination_model; int illumination_model = 1;
//! Index of refraction //! Index of refraction
ai_real ior; ai_real ior = ai_real(1.0);
//! Transparency color //! Transparency color
aiColor3D transparent; aiColor3D transparent = aiColor3D(1.0f, 1.0f, 1.0f);
//! Ambient occlusion
Maybe<ai_real> ambient_occlusion;
//! PBR Roughness //! PBR Roughness
Maybe<ai_real> roughness; Maybe<ai_real> roughness;
@@ -187,31 +189,33 @@ struct Material {
Maybe<ai_real> metallic; Maybe<ai_real> metallic;
//! PBR Metallic //! PBR Metallic
Maybe<aiColor3D> sheen; 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 //! PBR Clearcoat Thickness
Maybe<ai_real> clearcoat_thickness; Maybe<ai_real> clearcoat_thickness;
//! PBR Clearcoat Rougness //! PBR Clearcoat Rougness
Maybe<ai_real> clearcoat_roughness; 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 //! 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) //! bump map multiplier (normal map scalar)(-bm)
ai_real bump_multiplier; ai_real bump_multiplier = ai_real(1.0);
//! Constructor //! Constructor
Material() : 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)) {
std::fill_n(clamp, static_cast<unsigned int>(TextureTypeCount), false); std::fill_n(clamp, static_cast<unsigned int>(TextureTypeCount), false);
} }
+114 -8
View File
@@ -235,24 +235,64 @@ void ObjFileMtlImporter::load() {
++m_DataIt; ++m_DataIt;
if (m_pModel->mCurrentMaterial != nullptr) if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->clearcoat_roughness); getFloatValue(m_pModel->mCurrentMaterial->clearcoat_roughness);
} else { } else if (*m_DataIt == 't') {
++m_DataIt;
if (m_pModel->mCurrentMaterial != nullptr) if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->clearcoat_thickness); getFloatValue(m_pModel->mCurrentMaterial->clearcoat_thickness);
} else {
if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->clearcoat);
} }
break; break;
} }
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} }
break; 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 'b': // quick'n'dirty - for 'bump' sections
case 'r': // quick'n'dirty - for 'refl' sections
{ {
getTexture(); getTexture();
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break; } 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 case 'i': // Illumination model
{ {
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); 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); m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break; } break;
case 'a': // Anisotropy case 'a': {
{ auto tokenStart = m_DataIt;
++m_DataIt; auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd);
if (m_pModel->mCurrentMaterial != nullptr) std::string keyword(tokenStart, tokenEnd);
getFloatValue(m_pModel->mCurrentMaterial->anisotropy); 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); m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break; } break;
@@ -332,6 +421,23 @@ void ObjFileMtlImporter::getFloatValue(Maybe<ai_real> &value) {
value = Maybe<ai_real>(); 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. // Creates a material from loaded data.
void ObjFileMtlImporter::createMaterial() { void ObjFileMtlImporter::createMaterial() {
+2
View File
@@ -87,6 +87,8 @@ private:
/// Gets a float value from data. /// Gets a float value from data.
void getFloatValue(ai_real &value); void getFloatValue(ai_real &value);
void getFloatValue(Maybe<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. /// Creates a new material from loaded data.
void createMaterial(); void createMaterial();
/// Get texture name from loaded data. /// Get texture name from loaded data.
+8 -1
View File
@@ -80,7 +80,7 @@ ObjFileParser::ObjFileParser(IOStreamBuffer<char> &streamBuffer, const std::stri
m_buffer(), m_buffer(),
m_pIO(io), m_pIO(io),
m_progress(progress), m_progress(progress),
m_originalObjFileName(originalObjFileName) { m_originalObjFileName(originalObjFileName) {
std::fill_n(m_buffer, Buffersize, '\0'); std::fill_n(m_buffer, Buffersize, '\0');
// Create the model instance to store all the data // Create the model instance to store all the data
@@ -121,6 +121,13 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
m_DataItEnd = buffer.end(); m_DataItEnd = buffer.end();
mEnd = &buffer[buffer.size() - 1] + 1; 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 // Handle progress reporting
const size_t filePos(streamBuffer.getFilePos()); const size_t filePos(streamBuffer.getFilePos());
if (lastFilePos < filePos) { 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 // 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 // this is the best way to not risk losing precision on import and it doesn't hurt to do this
ai_real f; ai_real f;
pCur = fast_atoreal_move<ai_real>(pCur, f); pCur = fast_atoreal_move(pCur, f);
out->fFloat = (ai_real)f; out->fFloat = (ai_real)f;
break; break;
case EDT_Double: case EDT_Double:
double d; double d;
pCur = fast_atoreal_move<double>(pCur, d); pCur = fast_atoreal_move(pCur, d);
out->fDouble = (double)d; out->fDouble = (double)d;
break; break;
+7
View File
@@ -55,6 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <limits>
namespace Assimp { namespace Assimp {
static constexpr aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
@@ -309,6 +311,11 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero"); throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero");
} }
const unsigned int uint_max = std::numeric_limits<unsigned int>::max();
if (tex->mWidth > (uint_max / tex->mHeight)) {
throw DeadlyImportError("Quick3D: Texture dimensions are too large, resulting in overflow.");
}
unsigned int mul = tex->mWidth * tex->mHeight; unsigned int mul = tex->mWidth * tex->mHeight;
aiTexel *begin = tex->pcData = new aiTexel[mul]; aiTexel *begin = tex->pcData = new aiTexel[mul];
aiTexel *const end = &begin[mul - 1] + 1; aiTexel *const end = &begin[mul - 1] + 1;
+1 -1
View File
@@ -136,7 +136,7 @@ void RAWImporter::InternReadFile(const std::string &pFile,
unsigned int num; unsigned int num;
for (num = 0; num < 12; ++num) { for (num = 0; num < 12; ++num) {
if (!SkipSpaces(&sz, end) || !IsNumeric(*sz)) break; 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) { if (num != 12 && num != 9) {
ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture"); ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture");
+1 -1
View File
@@ -982,7 +982,7 @@ bool SMDImporter::ParseFloat(const char *szCurrent, const char **szCurrentOut, c
return false; return false;
} }
*szCurrentOut = fast_atoreal_move<float>(szCurrent,out); *szCurrentOut = fast_atoreal_move(szCurrent,out);
return true; 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) { for(;*cur && *cur != ',' && *cur != ')' && !IsSpace(*cur);++cur) {
if (*cur == '.') { if (*cur == '.') {
double f; double f;
inout = fast_atoreal_move<double>(start,f); inout = fast_atoreal_move(start,f);
return std::make_shared<EXPRESS::REAL>(f); return std::make_shared<EXPRESS::REAL>(f);
} }
} }
+6 -6
View File
@@ -294,11 +294,11 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
aiVector3D vn; aiVector3D vn;
sz += 7; sz += 7;
SkipSpaces(&sz, bufferEnd); SkipSpaces(&sz, bufferEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.x); sz = fast_atoreal_move(sz, vn.x);
SkipSpaces(&sz, bufferEnd); SkipSpaces(&sz, bufferEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.y); sz = fast_atoreal_move(sz, vn.y);
SkipSpaces(&sz, bufferEnd); 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); normalBuffer.emplace_back(vn);
normalBuffer.emplace_back(vn); normalBuffer.emplace_back(vn);
@@ -315,11 +315,11 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
SkipSpaces(&sz, bufferEnd); SkipSpaces(&sz, bufferEnd);
positionBuffer.emplace_back(); positionBuffer.emplace_back();
aiVector3D *vn = &positionBuffer.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); SkipSpaces(&sz, bufferEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->y); sz = fast_atoreal_move(sz, vn->y);
SkipSpaces(&sz, bufferEnd); SkipSpaces(&sz, bufferEnd);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->z); sz = fast_atoreal_move(sz, vn->z);
faceVertexCounter++; faceVertexCounter++;
} }
} else if (!::strncmp(sz, "endsolid", 8)) { } else if (!::strncmp(sz, "endsolid", 8)) {
+5 -1
View File
@@ -58,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pragma warning(disable : 4127 4456 4245 4512 ) # pragma warning(disable : 4127 4456 4245 4512 )
#endif // _MSC_VER #endif // _MSC_VER
#if _MSC_VER > 1500 || (defined __GNUC___) #if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP # define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
#else #else
# define step_unordered_map map # define step_unordered_map map
@@ -919,6 +919,10 @@ private:
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER #endif // _MSC_VER
#if _MSC_VER > 1920
#pragma warning(pop)
#endif
} // namespace STEP } // namespace STEP
} // namespace Assimp } // namespace Assimp
+1 -1
View File
@@ -63,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory> #include <memory>
// //
#if _MSC_VER > 1500 || (defined __GNUC___) #if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP # define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
# else # else
# define step_unordered_map map # define step_unordered_map map
@@ -61,6 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "assimp/MemoryIOWrapper.h" #include "assimp/MemoryIOWrapper.h"
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
#include <assimp/StreamReader.h> #include <assimp/StreamReader.h>
#include <assimp/metadata.h>
#include "io-util.hh" // namespace tinyusdz::io #include "io-util.hh" // namespace tinyusdz::io
#include "tydra/scene-access.hh" #include "tydra/scene-access.hh"
@@ -219,6 +220,9 @@ void USDImporterImplTinyusdz::InternReadFile(
textures(render_scene, pScene, nameWExt); textures(render_scene, pScene, nameWExt);
textureImages(render_scene, pScene, nameWExt); textureImages(render_scene, pScene, nameWExt);
buffers(render_scene, pScene, nameWExt); buffers(render_scene, pScene, nameWExt);
std::map<size_t, tinyusdz::tydra::Node> meshNodes;
setupNodes(render_scene, pScene, stage, meshNodes, nameWExt);
pScene->mRootNode = nodesRecursive(nullptr, render_scene.nodes[0], render_scene.skeletons); pScene->mRootNode = nodesRecursive(nullptr, render_scene.nodes[0], render_scene.skeletons);
setupBlendShapes(render_scene, pScene, nameWExt); setupBlendShapes(render_scene, pScene, nameWExt);
@@ -798,11 +802,50 @@ void USDImporterImplTinyusdz::buffers(
} }
} }
void USDImporterImplTinyusdz::setupNodes(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const tinyusdz::Stage &usdStage,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes,
const std::string &nameWExt) {
stringstream ss;
pScene->mRootNode = nodes(render_scene, usdStage, meshNodes, nameWExt);
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mMeshes = new unsigned int[pScene->mRootNode->mNumMeshes];
ss.str("");
ss << "setupNodes(): pScene->mNumMeshes: " << pScene->mNumMeshes;
if (pScene->mRootNode != nullptr) {
ss << ", mRootNode->mNumMeshes: " << pScene->mRootNode->mNumMeshes;
}
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
for (unsigned int meshIdx = 0; meshIdx < pScene->mNumMeshes; meshIdx++) {
pScene->mRootNode->mMeshes[meshIdx] = meshIdx;
}
}
aiNode *USDImporterImplTinyusdz::nodes(
const tinyusdz::tydra::RenderScene &render_scene,
const tinyusdz::Stage &usdStage,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes,
const std::string &nameWExt) {
const size_t numNodes{render_scene.nodes.size()};
(void) numNodes; // Ignore unused variable when -Werror enabled
stringstream ss;
ss.str("");
ss << "nodes(): model" << nameWExt << ", numNodes: " << numNodes;
TINYUSDZLOGD(TAG, "%s", ss.str().c_str());
return nodesRecursive(nullptr, usdStage.root_prims()[0], render_scene.nodes[0], meshNodes);
}
using Assimp::tinyusdzNodeTypeFor; using Assimp::tinyusdzNodeTypeFor;
using Assimp::tinyUsdzMat4ToAiMat4; using Assimp::tinyUsdzMat4ToAiMat4;
using tinyusdz::tydra::NodeType; using tinyusdz::tydra::NodeType;
aiNode *USDImporterImplTinyusdz::nodesRecursive( aiNode *USDImporterImplTinyusdz::nodesRecursive(
aiNode *pNodeParent, aiNode *pNodeParent,
const tinyusdz::Prim& prim,
const tinyusdz::tydra::Node &node, const tinyusdz::tydra::Node &node,
const std::vector<tinyusdz::tydra::SkelHierarchy> &skeletons) { const std::vector<tinyusdz::tydra::SkelHierarchy> &skeletons) {
stringstream ss; stringstream ss;
@@ -844,6 +887,22 @@ aiNode *USDImporterImplTinyusdz::nodesRecursive(
} }
} }
// Composition: references
if (prim.metas().references.has_value())
{
const tinyusdz::ListEditQual referenceQual = prim.metas().references->first;
const std::vector<tinyusdz::Reference> references = prim.metas().references->second;
for (const auto &reference : references)
{
cNode->mMetaData = aiMetadata::Alloc(1);
cNode->mMetaData->Add("ref", aiString(reference.asset_path.GetAssetPath()));
}
}
size_t i{0};
for (const auto &childNode: node.children) {
cNode->mChildren[i] = nodesRecursive(cNode, prim.children()[i], childNode, meshNodes);
cNode->mNumChildren = numChildren; cNode->mNumChildren = numChildren;
// Done. No more children. // Done. No more children.
+15
View File
@@ -124,8 +124,23 @@ public:
aiScene *pScene, aiScene *pScene,
const std::string &nameWExt); const std::string &nameWExt);
void setupNodes(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,
const tinyusdz::Stage &usdStage,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes,
const std::string &nameWExt
);
aiNode *nodes(
const tinyusdz::tydra::RenderScene &render_scene,
const tinyusdz::Stage &usdStage,
std::map<size_t, tinyusdz::tydra::Node> &meshNodes,
const std::string &nameWExt);
aiNode *nodesRecursive( aiNode *nodesRecursive(
aiNode *pNodeParent, aiNode *pNodeParent,
const tinyusdz::Prim &prim,
const tinyusdz::tydra::Node &node, const tinyusdz::tydra::Node &node,
const std::vector<tinyusdz::tydra::SkelHierarchy> &skeletons); const std::vector<tinyusdz::tydra::SkelHierarchy> &skeletons);
+3 -3
View File
@@ -383,11 +383,11 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
for (; !IsLineEnd(*data); ++data) { for (; !IsLineEnd(*data); ++data) {
if (data[0] == 'X' && data[1] == '=') { 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] == '=') { } 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] == '=') { } 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
@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#if !defined(ASSIMP_BUILD_NO_VRML_IMPORTER) #if !defined(ASSIMP_BUILD_NO_VRML_IMPORTER)
#include "contrib/meshlab/autoclone/meshlab_repo-src/src/meshlabplugins/io_x3d/vrml/Parser.h" #include "meshlabplugins/io_x3d/vrml/Parser.h"
#endif // #if !defined(ASSIMP_BUILD_NO_VRML_IMPORTER) #endif // #if !defined(ASSIMP_BUILD_NO_VRML_IMPORTER)
namespace Assimp { namespace Assimp {
+1 -1
View File
@@ -1277,7 +1277,7 @@ ai_real XFileParser::ReadFloat() {
} }
ai_real result = 0.0; ai_real result = 0.0;
mP = fast_atoreal_move<ai_real>(mP, result); mP = fast_atoreal_move(mP, result);
CheckForSeparator(); 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 #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) { 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<int32_t> f_data(pCoordIdx);
std::vector<unsigned int> inds; std::vector<unsigned int> inds;
unsigned int prim_type = 0; unsigned int prim_type = 0;
if (f_data.back() != (-1)) { if (!f_data.empty()) {
f_data.push_back(-1); if (f_data.back() != InvalidIndex) {
f_data.push_back(InvalidIndex);
}
} }
// reserve average size. // 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) { void X3DGeoHelper::coordIdx_str2lines_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces) {
std::vector<int32_t> f_data(pCoordIdx); std::vector<int32_t> f_data(pCoordIdx);
if (f_data.back() != (-1)) { if (!f_data.empty()) {
f_data.push_back(-1); if (f_data.back() != InvalidIndex) {
f_data.push_back(InvalidIndex);
}
} }
// reserve average size. // reserve average size.
+1 -5
View File
@@ -49,8 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GLTFASSET_H_INC #ifndef GLTFASSET_H_INC
#define GLTFASSET_H_INC #define GLTFASSET_H_INC
#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF1_IMPORTER)
#include "AssetLib/glTFCommon/glTFCommon.h" #include "AssetLib/glTFCommon/glTFCommon.h"
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include <list> #include <list>
@@ -83,7 +81,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
#if _MSC_VER > 1500 || (defined __GNUC___) #if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP # define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
# else # else
# define gltf_unordered_map map # define gltf_unordered_map map
@@ -1008,6 +1006,4 @@ private:
// Include the implementation of the methods // Include the implementation of the methods
#include "glTFAsset.inl" #include "glTFAsset.inl"
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
#endif // GLTFASSET_H_INC #endif // GLTFASSET_H_INC

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