update assimp to 6.0.5

This commit is contained in:
AzaezelX 2026-06-09 12:46:56 -05:00
parent 2d2eb57e2e
commit f5cf21cfeb
941 changed files with 22718 additions and 12240 deletions

View file

@ -70,7 +70,7 @@ IncludeCategories:
- Regex: '^<.*'
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentCaseLabels: false
#IndentPPDirectives: AfterHash
IndentWidth: 4
# IndentWrappedFunctionNames: false

207
Engine/lib/assimp/AGENTS.md Normal file
View file

@ -0,0 +1,207 @@
# AGENTS.md - Agent Guidelines for Assimp
This document provides guidelines for AI agents working on the Assimp codebase.
## Project Overview
Assimp (Open Asset Import Library) is a C++ library that loads various 3D file formats into a shared, in-memory format. It supports 40+ import formats and several export formats.
## Build Commands
### Basic Build (CMake + Ninja recommended)
```bash
# Configure with CMake
cmake -G Ninja -DASSIMP_BUILD_TESTS=ON -DASSIMP_WARNINGS_AS_ERRORS=ON -S . -B build
# Build
cmake --build build
```
### Key CMake Options
- `-DASSIMP_BUILD_TESTS=ON` - Build unit tests (default ON)
- `-DASSIMP_WARNINGS_AS_ERRORS=ON` - Treat warnings as errors (default ON)
- `-DASSIMP_BUILD_ASSIMP_TOOLS=ON` - Build command-line tools
- `-DASSIMP_BUILD_SAMPLES=ON` - Build sample applications
- `-DASSIMP_DOUBLE_PRECISION=ON` - Use double precision for calculations
- `-DASSIMP_NO_EXPORT=ON` - Disable export functionality
- `-DBUILD_SHARED_LIBS=OFF` - Build static library
### Running Tests
#### Run All Tests
```bash
# Using ctest
cd build && ctest
# Or run unit directly
./build/unit
```
#### Run Single Test
```bash
# Using ctest with filter
cd build && ctest -R "TestName"
# Or run unit with filter
./build/unit --gtest_filter="TestSuiteName.TestName"
```
For example:
```bash
./build/unit --gtest_filter="utObjImportExport.*"
./build/unit --gtest_filter="utMaterialSystem.*"
```
#### Test Directory
Tests are located in `test/unit/` and use Google Test. Test files are named `ut<Feature>.cpp`.
## Code Style
### Formatting
- **Use clang-format** before committing. Run: `clang-format -i <file>`
- The project uses a `.clang-format` file at the root with LLVM-based style
- Key settings:
- Indent width: 4 spaces
- Tab width: 4, UseTab: Never
- ColumnLimit: 0 (no line length limit)
- BreakConstructorInitializers: AfterColon
- AccessModifierOffset: -4
### Header File Organization
```cpp
// Order of includes (use clang-format to enforce):
// 1. Module's own header
// 2. Other assimp headers (assimp/*)
// 3. External headers (contrib/*)
// 4. Standard library headers
// 5. System headers
#include "Common/Importer.h"
#include <assimp/version.h>
#include <assimp/config.h>
#include "../contrib/some_lib/some.h"
#include <vector>
#include <string>
```
### Naming Conventions
- **Classes/Types**: PascalCase (e.g., `Importer`, `aiScene`)
- **Functions**: PascalCase (e.g., `ReadFile`, `GetExtension`)
- **Variables**: camelCase (e.g., `scene`, `importStep`)
- **Constants**: kCamelCase or UPPER_SNAKE_CASE (e.g., `kMaxVertices`)
- **Member variables**: Often prefixed with `m_` (e.g., `mScene`)
- **Static variables**: Often prefixed with `s_`
### File Naming
- **Header files**: PascalCase (e.g., `Importer.h`, `ScenePrivate.h`)
- **Source files**: PascalCase (e.g., `Importer.cpp`)
- **Test files**: Prefixed with `ut` (e.g., `utObjImportExport.cpp`)
### C++ Guidelines
#### Language Standard
- Minimum: C++17
- Use modern C++ features (smart pointers, constexpr, etc.)
#### Error Handling
- Use exceptions for recoverable errors (derived from `std::exception`)
- Use `ai_assert` for debugging assertions in code
- Return error codes from C API functions
#### Classes
- Use `ai_enable_erasing` pattern for optional features
- Use PImpl idiom for ABI stability where appropriate
#### Memory Management
- Use smart pointers (`std::unique_ptr`, `std::shared_ptr`)
- Prefer RAII patterns
- Document ownership semantics in function comments
### Importers/Exporters
#### Structure
Each importer typically has:
1. Header in `code/AssetLib/<Format>/`
2. Implementation in `code/AssetLib/<Format>/`
3. Registration in `code/Common/ImporterRegistry.cpp`
4. Unit tests in `test/unit/ImportExport/`
#### Registration
```cpp
void GetImporterInstanceList(std::vector<BaseImporter*>& out);
// Add to registry
out.push_back(new MyFormatImporter());
```
### Post-Processing
- Located in `code/PostProcessing/`
- Each process inherits from `BaseProcess`
- Implement `ExecuteOnScene` method
### Documentation
- Use Doxygen-style comments for public APIs
- Example:
```cpp
/// <summary>
/// Loads a file from disk.
/// </summary>
/// <param name="pFile">Path to the file.</param>
/// <returns>Pointer to the imported scene.</returns>
aiScene* Importer::ReadFile(const char* pFile);
```
### Contributing
1. Create a fork of assimp
2. Create a branch for your feature/fix
3. Run `clang-format` on modified files
4. Ensure tests pass
5. Open a PR against `master` branch
## Directory Structure
```
code/
AssetLib/ - Importers and exporters
CApi/ - C API wrapper
Common/ - Shared utilities
Geometry/ - Geometry processing
Material/ - Material handling
PostProcessing/ - Mesh post-processing
include/ - Public headers (assimp/)
test/
unit/ - Unit tests
models/ - Test 3D models
test/ - Test data (non-BSD licensed)
contrib/ - Third-party libraries
```
## CI/CD
The project runs CI on GitHub Actions:
- Builds on Linux and Windows
- Runs tests including memory leak detection
- Checks compiler warnings
## Common Tasks
### Adding a New Importer
1. Create `code/AssetLib/<Format>/<Format>Importer.h`
2. Create `code/AssetLib/<Format>/<Format>Importer.cpp`
3. Register in `code/Common/ImporterRegistry.cpp`
4. Add tests in `test/unit/ImportExport/`
5. Add to CMakeLists.txt if needed
### Running Specific Test Suite
```bash
# Test specific importer
./build/unit --gtest_filter="utglTF2ImportExport.*"
# Test post-processing
./build/unit --gtest_filter="utTriangulate.*"
# Test math operations
./build/unit --gtest_filter="utMatrix4x4.*"
```

View file

@ -0,0 +1,172 @@
# Asset-Importer-Lib AI Tool Use Policy
## Policy
Assimp's policy is that contributors can use whatever tools they would like to
craft their contributions, but there must be a **human in the loop**.
**Contributors must read and review all LLM-generated code or text before they
ask other project members to review it.** The contributor is always the author
and is fully accountable for their contributions. Contributors should be
sufficiently confident that the contribution is high enough quality that asking
for a review is a good use of scarce maintainer time, and they should be **able
to answer questions about their work** during review.
We expect that new contributors will be less confident in their contributions,
and our guidance to them is to **start with small contributions** that they can
fully understand to build confidence. We aspire to be a welcoming community
that helps new contributors grow their expertise, but learning involves taking
small steps, getting feedback, and iterating. Passing maintainer feedback to an
LLM doesn't help anyone grow, and does not sustain our community.
Contributors are expected to **be transparent and label contributions that
contain substantial amounts of tool-generated content**. Our policy on
labelling is intended to facilitate reviews, and not to track which parts of
Assimp are generated. Contributors should note tool usage in their pull request
description, commit message, or wherever authorship is normally indicated for
the work. For instance, use a commit message trailer like Assisted-by: <name of
code assistant>. This transparency helps the community develop best practices
and understand the role of these new tools.
This policy includes, but is not limited to, the following kinds of
contributions:
- Code, usually in the form of a pull request
- RFCs or design proposals
- Issues or security vulnerabilities
- Comments and feedback on pull requests
## Details
To ensure sufficient self review and understanding of the work, it is strongly
recommended that contributors write PR descriptions themselves (if needed,
using tools for translation or copy-editing). The description should explain
the motivation, implementation approach, expected impact, and any open
questions or uncertainties to the same extent as a contribution made without
tool assistance.
AI tools must not be used to fix GitHub issues labelled [`good first
issue`][good-first-issue]. These issues are generally not urgent, and are
intended to be learning opportunities for new contributors to get familiar with
the codebase. Whether you are a newcomer or not, fully automating the process
of fixing this issue squanders the learning opportunity and doesn't add much
value to the project. **Using AI tools to fix issues labelled as "good first
issues" is forbidden**.
[good-first-issue]: https://github.com/llvm/llvm-project/issues/?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22
## Extractive Contributions
The reason for our "human-in-the-loop" contribution policy is that processing
patches, PRs, RFCs, and comments to Assimp is not free -- it takes a lot of
maintainer time and energy to review those contributions! Sending the
unreviewed output of an Assimp to open source project maintainers *extracts* work
from them in the form of design and code review, so we call this kind of
contribution an "extractive contribution".
Our **golden rule** is that a contribution should be worth more to the project
than the time it takes to review it. These ideas are captured by this quote
from the book [Working in Public][public] by Nadia Eghbal:
[public]: https://press.stripe.com/working-in-public
> \"When attention is being appropriated, producers need to weigh the costs and
> benefits of the transaction. To assess whether the appropriation of attention
> is net-positive, it's useful to distinguish between *extractive* and
> *non-extractive* contributions. Extractive contributions are those where the
> marginal cost of reviewing and merging that contribution is greater than the
> marginal benefit to the project's producers. In the case of a code
> contribution, it might be a pull request that's too complex or unwieldy to
> review, given the potential upside.\" \-- Nadia Eghbal
Prior to the advent of LLMs, open source project maintainers would often review
any and all changes sent to the project simply because posting a change for
review was a sign of interest from a potential long-term contributor. While new
tools enable more development, it shifts effort from the implementor to the
reviewer, and our policy exists to ensure that we value and do not squander
maintainer time.
Reviewing changes from new contributors is part of growing the next generation
of contributors and sustaining the project. We want the LLVM project to be
welcoming and open to aspiring compiler engineers who are willing to invest
time and effort to learn and grow, because growing our contributor base and
recruiting new maintainers helps sustain the project over the long term. Being
open to contributions and [liberally granting commit access][commit-access]
is a big part of how LLVM has grown and successfully been adopted all across
the industry. We therefore automatically post a greeting comment to pull
requests from new contributors and encourage maintainers to spend their time to
help new contributors learn.
[commit-access]: https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access
## Handling Violations
If a maintainer judges that a contribution doesn't comply with this policy,
they should paste the following response to request changes:
This PR doesn't appear to comply with our policy on tool-generated content,
and requires additional justification for why it is valuable enough to the
project for us to review it. Please see our developer policy on
AI-generated contributions: http://llvm.org/docs/AIToolPolicy.html
The best ways to make a change less extractive and more valuable are to reduce
its size or complexity or to increase its usefulness to the community. These
factors are impossible to weigh objectively, and our project policy leaves this
determination up to the maintainers of the project, i.e. those who are doing
the work of sustaining the project.
If or when it becomes clear that a GitHub issue or PR is off-track and not
moving in the right direction, maintainers should apply the `extractive` label
to help other reviewers prioritize their review time.
If a contributor fails to make their change meaningfully less extractive,
maintainers should escalate to the relevant moderation or admin team for the
space (GitHub, Discourse, Discord, etc) to lock the conversation.
## Copyright
Artificial intelligence systems raise many questions around copyright that have
yet to be answered. Our policy on AI tools is similar to our copyright policy:
Contributors are responsible for ensuring that they have the right to
contribute code under the terms of our license, typically meaning that either
they, their employer, or their collaborators hold the copyright. Using AI tools
to regenerate copyrighted material does not remove the copyright, and
contributors are responsible for ensuring that such material does not appear in
their contributions. Contributions found to violate this policy will be removed
just like any other offending contribution.
## Examples
Here are some examples of contributions that demonstrate how to apply
the principles of this policy:
- [This PR][alive-pr] contains a proof from Alive2, which is a strong signal of
value and correctness.
- This [generated documentation][gsym-docs] was reviewed for correctness by a
human before being posted.
[alive-pr]: https://github.com/llvm/llvm-project/pull/142869
[gsym-docs]: https://discourse.llvm.org/t/searching-for-gsym-documentation/85185/2
## References
Our policy was informed by experiences in other communities:
- [Fedora Council Policy Proposal: Policy on AI-Assisted Contributions (fetched
2025-10-01)][fedora]: Some of the text above was copied from the Fedora
project policy proposal, which is licensed under the [Creative Commons
Attribution 4.0 International License][cca]. This link serves as attribution.
- [Rust draft policy on burdensome PRs][rust-burdensome]
- [Seth Larson's post][security-slop]
on slop security reports in the Python ecosystem
- The METR paper [Measuring the Impact of Early-2025 AI on Experienced
Open-Source Developer Productivity][metr-paper].
- [QEMU bans use of AI content generators][qemu-ban]
- [Slop is the new name for unwanted AI-generated content][ai-slop]
[fedora]: https://communityblog.fedoraproject.org/council-policy-proposal-policy-on-ai-assisted-contributions/
[cca]: https://creativecommons.org/licenses/by/4.0/
[rust-burdensome]: https://github.com/rust-lang/compiler-team/issues/893
[security-slop]: https://sethmlarson.dev/slop-security-reports
[metr-paper]: https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/
[qemu-ban]: https://www.qemu.org/docs/master/devel/code-provenance.html#use-of-ai-content-generators
[ai-slop]: https://simonwillison.net/2024/May/8/slop/

View file

@ -4,7 +4,9 @@
### Install prerequisites
You need to install
* cmake
* Your compiler
* Your compiler (must support C++17 and C99 at least)
* For Windows
* DX-SDK 9 if you want to use our 3D-Viewer
### Get the source
Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via:
@ -28,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.
### 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:
```bash
cmake CMakeLists.txt
@ -39,7 +41,7 @@ This will generate the project files for the visual studio. All dependencies use
See <https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app>
### Build instructions for MinGW
Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag
Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag
required to compile some of assimp's files, especially for debug builds.
Version 7.3.0 of g++-mingw-w64 & gcc-mingw-w64 appears to work.
@ -65,7 +67,7 @@ The cmake-build-environment provides options to configure the build. The followi
- **ASSIMP_NO_EXPORT (default OFF)**: Disable Assimp's export functionality.
- **ASSIMP_BUILD_ZLIB (default OFF)**: Build our own zlib.
- **ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all exporters enabled.
- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all importers enabled.
- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with (most) importers enabled. Currently, USD importer is not included. See ASSIMP_BUILD_USD_IMPORTER.
- **ASSIMP_BUILD_ASSIMP_TOOLS (default OFF)**: If the supplementary tools for Assimp are built in addition to the library.
- **ASSIMP_BUILD_SAMPLES (default OFF)**: If the official samples are built as well (needs Glut).
- **ASSIMP_BUILD_TESTS (default ON)**: If the test suite for Assimp is built in addition to the library.
@ -81,6 +83,7 @@ The cmake-build-environment provides options to configure the build. The followi
- **USE_STATIC_CRT (default OFF)**: Link against the static MSVC runtime libraries.
- **ASSIMP_BUILD_DRACO (default OFF)**: Build Draco libraries. Primarily for glTF.
- **ASSIMP_BUILD_ASSIMP_VIEW (default ON, if DirectX found, OFF otherwise)**: Build Assimp view tool (requires DirectX).
- **ASSIMP_BUILD_USD_IMPORTER (default OFF, requires ASSIMP_WARNINGS_AS_ERRORS to be OFF)**: Build USD importer, defaults to off for CI purposes
### Install prebuild binaries
## Install on all platforms using vcpkg
@ -107,5 +110,5 @@ You need to have pip installed:
pip install pyassimp
```
### Get the SDK from itchi.io
Just check [itchi.io](https://kimkulling.itch.io/the-asset-importer-lib)
### Get the SDK from itch.io
Just check [itch.io](https://kimkulling.itch.io/the-asset-importer-lib)

View file

@ -1,607 +0,0 @@
----------------------------------------------------------------------
CHANGELOG
----------------------------------------------------------------------
4.1.0 (2017-12):
- FEATURES:
- Export 3MF ( experimental )
- Import / Export glTF 2
- Introduce new zib-lib to eb able to export zip-archives
- FIXES/HOUSEKEEPING:
- Added missing include to stdlib.h and remove load library call
- Fix install for builds with MSVC compiler and NMake.
- Update list of supported file formats.
- Add TriLib to the official list of supported ports.
- Re-enabling PACK_STRUCT for MDL files.
- Use std.::unique_ptr
- Update D3MFExporter.h
- Update MD3Loader.cpp, using index
- Fix all warnings on MSVC14
- Copy assimp dll to unit folder on windows
- Update jvm port supported formats
- Add support for building Mac OS X Framework bundles
- Check for nullptr dereferencing before copying scene data
- Update ValidateDataStructure.h, typo
- Enable data structure validation in cases where it doesn't cause failures
- Remove some dead assignments
- fast_atof: Silence some uninitialized variable warnings
- Check for area test if the face is a triangle.
- Set mNumUVComponents to 0 when deleting texture coordinate sets
- Only scale the root node because this will rescale all children nodes as well.
- Issue 1514: Fix frame pointer arithmetic
- Prevent failing stringstream to crash the export process
- powf -> pow
- add Defines.h to include folder for install.
- Android:
- Fix android build
- Fix assimp for cross compile for android
- Use define for D_FILE_OFFSET_BITS only for not-android systems.
- FBX:
- Fix handling with embedded textures
- FBX 7500 Binary reading
- Remove dead assignment
- Fix export of deleted meshes; Add LazyDict::Remove method
- Log an error instead of letting the fbx-importer crash. ( issue 213 )
- Replace bad pointer casting with memcpy
- Remove useless const qualifier from return value
- Add explicit instantiation of log_prefix so other FBX source files can see it
- add missing inversion of postrotation matrix for fbx.
- FIReader: Silence uninitialized variable warning
- Update version check in FBX reader to check for version >= 7500
- Use actual min/max of anim keys when start/stop time is missing
- GLTF1:
- Fix output of glTF 1 version string
- Fix delete / delete[] mismatch in glTFAsset
- Dont ignore rgba(1,1,1,1) color properties
- glTF2 primitives fixes
- Dont ignore rgba(1,1,1,1) color properties
- Fix delete / delete[] mismatch in glTFAsset
- Remove KHR_binary_glTF code
- glTF nodes can only hold one mesh. this simply assigns to and checks a Nodes Mesh
- version in glb header is stored as uint32_t
- GLTF2:
- node name conflict fix
- Fix transform matrices multiplication order
- Preserve node names when importing
- Add support for tangents in import
- Fix typo on gltf2 camera parameters
- Moved byteStride from accessor to bufferView
- Implemented reading binary glTF2 (glb) files
- Fix signed/unsigned warning
- Add postprocess step for scaling
- Fix shininess to roughness conversion
- Prefer “BLEND” over “MASK” as an alphaMode default
- Approximate specularity / glossiness in metallicRoughness materials
- Diffuse color and diffuse texture import and export improvements
- Addressed some mismatched news/deletes caused by the new glTF2 sources.
- Fix delete / delete[] mismatches in glTF2 importer
- use correct name of exporter to gltf2
- Fix possible infinite loop when exporting to gltf2
- Fix glTF2::Asset::FindUniqueID() when the input string is >= 256 chars
- Fix glTF2 alphaMode storage and reading
- Fix glTF 2.0 multi-primitive support
- Load gltf .bin files from correct directory
- Add support for importing both glTF and glTF2 files
- ampler improvements; Add new LazyDict method
- Changes to GLTF2 materials
- Remove Light, Technique references
- Start removing materials common, and adding pbrSpecularGlossiness
- Use !ObjectEmpty() vs. MemberCount() > 0
- Working read, import, export, and write of gltf2 (pbr) material
- Check in gltf2 models to test directory
- Remove un-needed test models
- Start managing and importing gltf2 pbr materials
- Update glTF2 Asset to use indexes
- Duplicate gltfImporter as gltf2Importer; Include glTF2 importer in CMake List
- glTF2: Fix animation export
- use opacity for diffuse alpha + alphaMode
- STL:
- Restore import of multi mesh binary STLs
- Blender:
- Silence warning about uninitialized member
- MDLImporter:
- Don't take address of packed struct member
- assimp_cmd:
- Fix strict-aliasing warnings
- Open3DGC:
- Fix strict-aliasing warnings
- Add assertions to silence static analyzer warnings
- Remove redundant const qualifiers from return types
- Fix some uninitialized variable warnings
- Remove OPEN3DGC and compression references
- unzip:
- Remove dead assignment
- Bail on bad compression method
- Fix possibly uninitialized variables
- clipper:
- Add assertion to silence a static analyzer warning
- OpenDDLExport:
- Reduce scope of a variable
- Remove dead variable
- Remove dead assignment
- Fix another potential memory leak
- X3DImporter:
- Add assertions to silence static analyzer warnings
- Add missing unittest
- Workaround for buggy Android NDK (issue #1361)
- TerragenLoader:
- Remove unused variable
- SIBImporter:
- Add assertions to silence static analyzer warnings
- IFC:
- Remove dead code
- Add explicit instantiation of log_prefix so IFCMaterial.cpp can see it
- PLY:
- Remove dead assignment and reduce scope of a variable
- fix vertex attribute lookup.
- OpenGEX:
- Add assertion to silence a static analyzer warning
- Fix for TextureFile with number in file name
- Return early when element is TextureFile
- NFF:
- Add assertions to silence static analyzer warnings
- Split up some complicated assignments
- Raw: Fix misleading indentation warning
- Reduce scope of a variable
- LWO
- Reduce scope of a variable
- IRRLoader:
- Fix confusing boolean casting
- AssbinExporter:
- Add assertion to silence a static analyzer warning
- ASE:
- Add assertion to silence a static analyzer warning
- AMFImporter:
- Add assertion to silence a static analyzer warning
- Add a block
- OptimizeGraph:
- Fix possible null pointer dereference
- RemoveRedundantMaterials:
- Add assertion to silence a static analyzer warning
- ImproveCacheLocality:
- Add assertion to silence a static analyzer warning
- RemoveRedundantMaterials:
- Set pointer to nullptr after deleting it
- Travis:
- Disable unit tests in scan-build config
- Move slower builds earlier to improve parallelization
- Add static analysis to build
- Remove unused branch rule for travis.
- Add Clang UBSan build configuration
- Treat warnings as errors, without typos this time
- Unittests:
- Add VS-based source groups for the unittests.
- Collada:
- export <library_animations> tag
- Update ColladaExporter.cpp
- Silence uninitialized variable warning
- Add support for line strip primitives
- Obj Wavefront:
- check in exporting against out-of-bounds-access .
- Issue 1351: use correct name for obj-meshname export for groups.
- fix mem-lead: face will be not released in case of an error.
- Anatoscope obj exporter nomtl
- Raise exception when obj file contains invalid face indices
- Added alternative displacement texture token in OBJ MTL material.
- Obj: rename attribute from exporter.
- Fix OBJ discarding all material names if the material library is missing
- Step:
- use correct lookup for utf32
- MD2:
- Fix MD2 frames containing garbage
- STL
- add missing const.
- Fix memory-alignment bug.
- Fix issue 104: deal with more solids in one STL file.
- CMake
- Fix issue 213: use correct include folder for assimp
- Doxygen
- Fix issue 1513: put irrXML onto exclucde list for doxygen run
- PyAssimp:
- Search for libassimp.so in LD_LIBRARY_PATH if available.
- Fix operator precedence issue in header check
- Split setup.py into multiple lines
- Detect if Anaconda and fixed 3d_viewer for Python 3
- created a python3 version of the 3dviewer and fixed the / = float in py3
- Blender:
- Fix invalid access to mesh array when the array is empty.
- Fix short overflow.
- Silence warning about inline function which is declared but not defined
- JAssimp
- Changed license header for IHMC contributions from Apache 2.0 to BSD
- Add Node metadata to the Jassmip Java API
- Added supported for custom IO Systems in Java. Implemented ClassLoader IO System
- Added a link to pure jvm assimp port
- Clang sanitizer:
- Undefined Behavior sanitizer
- Fixed a divide by zero error in IFCBoolean that was latent, but nevertheless a bug
- B3DImporter:
- Replace bad pointer casting with memcpy
- AppVeyor:
- Cleanup and Addition of VS 2017 and running Tests
- Fixed File Size reported as 0 in tests that use temporary files
- x86 isn't a valid VS platform. Win32 it is, then.
- Replaced the worker image name, which doesn't work as generator name, with a manually created generator name.
- Cleaned up appveyor setup, added VS 2017 to the build matrix and attempted to add running of tests.
- Treat warnings as errors on Appveyor
- Disable warning 4351 on MSVC 2013
- OpenGEXImporter:
- Copy materials to scene
- Store RefInfo in unique_ptr so they get automatically cleaned up
- Fix IOStream leak
- Store ChildInfo in unique_ptr so they get automatically cleaned up
- improve logging to be able to detect error-prone situations.
- AMFImporter:
- Fix memory leak
- UnrealLoader:
- Fix IOStream leak
- Upgrade RapidJSON to get rid of a clang warning
- zlib:
- Update zlib contribution
- Removed unnecessary files from zlib contribution
- Replaced unsigned long for the crc table to z_crc_t, to match what is returned by get-crc_table
- MakeVerboseFormat:
- Fix delete / delete[] mismatches in MakeVerboseFormat
- MaterialSystem:
- Fix out-of-bounds read in MaterialSystem unit test
- SIB:
- Added support for SIB models from Silo 2.5
- AssbinExporter:
- Fix strict aliasing violation
- Add Write specialization for aiColor3D
- DefaultLogger:
- Whitespace cleanup to fix GCC misleading indentation warning
- MDP:
- Fix encoding issues.
- PreTransformVertices:
- fix name lost in mesh and nodes when load with flag
- C4D:
- Fixes for C4D importer
- Unzip:
- Latest greatest.
4.0.1 (2017-07-28)
- FIXES/HOUSEKEEPING:
- fix version test.
- Not compiling when using ASSIMP_DOUBLE_PRECISION
- Added support for python3
- Check if cmake is installed with brew
- Low performance in OptimizeMeshesProcess::ProcessNode with huge numbers of meshes
- Elapsed seconds not shown correctly
- StreamReader: fix out-of-range exception
- PPdPmdParser: fix compilation for clang
4.0.0 (2017-07-18)
FEATURES:
- Double precision support provided ( available via cmake option )
- QT-Widget based assimp-viewer ( works for windows, linux, osx )
- Open3DGC codec supported by glFT-importer
- glTF: Read and write transparency values
- Add Triangulate post-processing step to glTF exporters
- Update rapidjson to v1.0.2
- Added method to append new metadata to structure
- Unittests: intoduce a prototype model differ
- X3D support
- AMF support
- Lugdunum3D support
- Obj-Importer: obj-homogeneous_coords support
- Obj-Importer: new streaming handling
- Added support for 64 bit version header introduced in FbxSdk2016
- Travis: enable coverall support.
- PyAssimp: New version of the pyASSIMP 3D viewer, with much improved 3D controls
- Morph animation support for collada
- Added support for parameters Ni and Tf in OBJ/MTL file format
- aiScene: add method to add children
- Added new option to IFC importer to control tessellation angle + removed unused IFC option
- aiMetaData: introduce aiMetaData::Dealloc
- Samples: add a DX11 example
- travis ci: test on OXS ( XCode 6.3 ) as well
- travis ci: enable sudo support.
- openddlparser: integrate release v0.4.0
- aiMetaData: Added support for metadata in assbin format
FIXES/HOUSEKEEPING:
- Introduce usage of #pragma statement
- Put cmake-scripts into their own folder
- Fix install pathes ( issue 938 )
- Fix object_compare in blender importer( issue 946 )
- Fix OSX compilation error
- Fix unzip path when no other version was found ( issue 967 )
- Set _FILE_OFFSET_BITS=64 for 32-bit linux ( issue 975 )
- Fix constructor for radjson on OSX
- Use Assimp namespace to fix build for big-endian architectures
- Add -fPIC to C Flags for 64bit linux Shared Object builds
- MDLLoader: fix resource leak.
- MakeVerboseFormat: fix invalid delete statement
- IFC: fix possible use after free access bug
- ComputeUVMappingprocess: add missing initialization for scalar value
- Fix invalid release of mat + mesh
- IrrImporter: Fix release functions
- Split mesh before exporting gltf ( issue 995 )
- 3MFImporter: add source group for visual studio
- IFC: Switch generated file to 2 files to fix issue related to <mingw4.9 ( Thanks Qt! )
- ObjImporter: fix test for vertices import
- export scene combiner ( issues177 )
- FBX: make lookup test less strict ( issues 994 )
- OpenGEX-Importer: add import of vertex colors ( issue 954 )
- fix bug when exporting mRotationKeys data
- fix mingw build (mingw supports stat64 nowadays)
- cfileio: fix leaks by not closing files in the destructor
- Fix OBJ parser mtllib statement parsing bug.
- Q3BSP-Importer: remove dead code
- Fix BlenderDNA for clang cross compiler.
- ScenePreprocessor: fix invalid index counter.
- Fix compiler warnings ( issue 957 )
- Fix obj .mtl file loading
- Fixed a compile error on MSVC14 x64 caused by the /bigobj flag failing to be set for the 1 and 2-suffixed versions introduced in commit 0a25b076b8968b7ea2aa96d7d1b4381be2d72ce6
- Fixed build warnings on MSVC14 x64
- Remove scaling of specular exponent in OBJFileImporter.cpp
- use ai_assert instead of assert ( issue 1076 )
- Added a preprocessor definition for MSVC to silence safety warnings regarding C library functions. This addresses all warnings for MSVC x86 and x64 when building zlib, tools and viewer as a static lib
- fix parsing of texture name ( issue 899 )
- add warning when detecting invalid mat definition ( issue 1111 )
- copy aiTexture type declaration instead of using decltype for declaration to fix iOS build( issue 1101 )
- FBX: Add additional material properties
- FBX: Correct camera position and clip planes
- FBX: Add correct light locations and falloff values
- fix typo ( issue 1141 )
- Fix collada export. Don't duplicate TEXCOORD/NORMALS/COLORS in <vertices> and <polylist> ( issue 1084 )
- OBJParser: set material index when changing current material
- OBJ: check for null mesh before updating material index
- add vertex color export support ( issue 809 )
- Fix memory leak in Collada importer ( issue 1169 )
- add stp to the list of supported extensions for step-files ( issue 1183 )
- fix clang build ( Issue-1169 )
- fix for FreeBSD
- Import FindPkgMacros to main CMake Configuration
- Extended support for tessellation parameter to more IFC shapes
- defensice handling of utf-8 decode issues ( issue 1211 )
- Fixed compiler error on clang 4.0 running on OSX
- use test extension for exported test files ( issue 1228 )
- Set UVW index material properties for OBJ files
- Fixed no member named 'atop' in global namespace issue for Android NDK compilation
- Apply mechanism to decide use for IrrXML external or internal
- Fix static init ordering bug in OpenGEX importer
- GLTF exporter: ensure animation accessors have same count
- GLTF exporter: convert animation time from ticks to seconds
- Add support for reading texture coordinates from PLY meshes with properties named 'texture_u' and 'texture_v'
- Added TokensForSearch in BlenderLoader to allow CanRead return true for in-memory files.
- fix wrong delete ( issue 1266 )
- OpenGEX: fix invalid handling with color4 token ( issue 1262 )
- LWOLoader: fix link in loader description
- Fix error when custom CMAKE_C_FLAGS is specified
- Fast-atof: log overflow errors
- Obj-Importer: do not break when detecting an overflow ( issue 1244 )
- Obj-Importer: fix parsing of multible line data definitions
- Fixed bug where IFC models with multiple IFCSite only loaded 1 site instead of the complete model
- PLYImporter: - optimize memory and speed on ply importer / change parser to use a file stream - manage texture path in ply
import - manage texture coords on faces in ply import - correction on point cloud faces generation
- Utf8: integrate new lib ( issue 1158 )
- fixed CMAKE_MODULE_PATH overwriting previous values
- OpenGEX: Fixed bug in material color processing ( issue 1271 )
- SceneCombiner: move header for scenecombiner to public folder.
- GLTF exporter: ensure buffer view byte offsets are correctly aligned
- X3D importer: Added EXPORT and IMPORT to the list of ignored XML tags
- X3D Exporter: fixed missing attributes
- X3D importer: Fixed import of normals for the single index / normal per vertex case
- X3D importer: Fixed handling of inlined files
- X3D importer: fixed whitespace handling (issue 1202)
- X3D importer: Fixed iterator on MSVC 2015
- X3D importer: Fixed problems with auto, override and regex on older compilers
- X3D importer: Fixed missing header file
- X3D importer: Fixed path handling
- X3D importer: Implemented support for binary X3D files
- fix build without 3DS ( issue 1319 )
- pyassimp: Fixed indices for IndexedTriangleFanSet, IndexedTriangleSet and IndexedTriangleStripSet
- Fixes parameters to pyassimp.load
- Obj-Importe: Fixed texture bug due simultaneously using 'usemtl' and 'usemap' attributes
- check if all exporters are disabled ( issue 1320 )
- Remove std functions deprecated by C++11.
- X-Importer: make it deal with lines
- use correct path for compilers ( issue 1335 )
- Collada: add workaround to deal with polygon with holes
- update python readme
- Use unique node names when loading Collada files
- Fixed many FBX bugs
API COMPATIBILITY:
- Changed ABI-compatibility to v3.3.1, please rebuild your precompiled libraries ( see issue 1182 )
- VS2010 outdated
3.3.1 (2016-07-08)
FIXES/HOUSEKEEPING:
- Setup of default precision for 17 exporters
- Fix xcode project files
- Fix BlenderTesselator: offsetof operator
- Invalid version in cmake file
- Update pstdint.h to latest greatest
3.3.0 (2016-07-05)
FEATURES:
- C++11 support enabled
- New regression-test-UI
- Experimental glTF-importer support
- OpenGEX: add support for cameras and lights
- C4D: update to latest Melange-SDK
- Add a gitter channel
- Coverity check enabled
- Switch to <...> include brackets for public headers
- Enable export by pyAssimp
- CI: check windows build
- Add functionality to perform a singlepost-processing step
- many more, just check the history
FIXES/HOUSEKEEPING:
- Fix of many resource leaks in unittests and main lib
- Fix iOS-buildfor X64
- Choosing zlib manually for cmake
- many more, just check the history
3.2.1 (2016-010-10)
FEATURES:
- Updated glTF exporter to meet 1.0 specification.
FIXES/HOUSEKEEPING:
- Fixed glTF Validator errors for exported glTF format.
ISSUES:
- Hard coded sampler setting for
- magFilter
- minFilter
- void* in ExportData for accessor max and min.
3.2.0 (2015-11-03)
FEATURES:
- OpenDDL-Parser is part of contrib-source.
- Experimental OpenGEX-support
- CI-check for linux and windows
- Coverity check added
- New regression testsuite.
FIXES/HOUSEKEEPING:
- Hundreds of bugfixes in all parts of the library
- Unified line endings
API COMPATIBILITY:
- Removed precompiled header to increase build speed for linux
3.1.1 (2014-06-15)
FEATURES:
- Support for FBX 2013 and newer, binary and ASCII (this is partly
work from Google Summer of Code 2012)
- Support for OGRE binary mesh and skeleton format
- Updated BLEND support for newer Blender versions
- Support for arbitrary meta data, used to hold FBX and DAE metadata
- OBJ Export now produces smaller files
- Meshes can now have names, this is supported by the major importers
- Improved IFC geometry generation
- M3 support has been removed
FIXES/HOUSEKEEPING:
- Hundreds of bugfixes in all parts of the library
- CMake is now the primary build system
API COMPATIBILITY:
- 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData
and aiMesh::mName
- Export interface has been cleaned up and unified
- Other than that no relevant changes
3.0 (2012-07-07)
FEATURES:
- new export interface similar to the import API.
- Supported export formats: Collada, OBJ, PLY and STL
- added new import formats: XGL/ZGL, M3 (experimental)
- new postprocessing steps: Debone
- vastly improved IFC (Industry Foundation Classes) support
- introduced API to query importer meta information (such as supported
format versions, full name, maintainer info).
- reworked Ogre XML import
- C-API now supports per-import properties
FIXES/HOUSEKEEPING:
- hundreds of bugfixes in all parts of the library
- unified naming and cleanup of public headers
- improved CMake build system
- templatized math library
- reduce dependency on boost.thread, only remaining spot
is synchronization for the C logging API
API COMPATIBILITY:
- renamed headers, export interface, C API properties and meta data
prevent compatibility with code written for 2.0, but in
most cases these can be easily resolved
- Note: 3.0 is not binary compatible with 2.0
2.0 (2010-11-21)
FEATURES:
- Add support for static Blender (*.blend) scenes
- Add support for Q3BSP scenes
- Add a windows-based OpenGL sample featuring texturing & basic materials
- Add an experimental progress feedback interface.
- Vastly improved performance (up to 500%, depending on mesh size and
spatial structure) in some expensive postprocessing steps
- AssimpView now uses a reworked layout which leaves more space
to the scene hierarchy window
- Add C# bindings ('Assimp.NET')
- Keep BSD-licensed and otherwise free test files in separate
folders (./test/models and ./test/models-nonbsd).
FIXES:
- Many Collada bugfixes, improve fault tolerance
- Fix possible crashes in the Obj loader
- Improve the Ogre XML loader
- OpenGL-sample now works with MinGW
- Fix Importer::FindLoader failing on uppercase file extensions
- Fix flawed path handling when locating external files
- Limit the maximum number of vertices, faces, face indices and
weights that Assimp is able to handle. This is to avoid
crashes due to overflowing counters.
- Updated XCode project files
- Further CMAKE build improvements
API CHANGES:
- Add data structures for vertex-based animations (These are not
currently used, however ...)
- Some Assimp::Importer methods are const now.
1.1 (2010-04-17)
This is the list of relevant changes from the 1.0 (r412) release to 1.1 (r700).
FEATURES:
- Vastly improved Collada support
- Add MS3D (Milkshape 3D) support
- Add support for Ogre XML static meshes
- Add experimental COB (TrueSpace) support
- Automatic test suite to quickly locate regressions
- D bindings (`dAssimp`)
- Python 2.n bindings (`PyAssimp`)
- Add basic support for Unicode input files (utf8, utf16 and utf32)
- Add further utilities to the `assimp` tool (xml/binary dumps, quick file stats)
- Switch to a CMAKE-based build system including an install target for unix'es
- Automatic evaluation of subdivision surfaces for some formats.
- Add `Importer::ReadFileFromMemory` and the corresponding C-API `aiReadFileFromMemory`
- Expose further math utilities via the C-API (i.e. `aiMultiplyMatrix4`)
- Move noboost files away from the public include directory
- Many, many bugfixes and improvements in existing loaders and postprocessing steps
- Documentation improved and clarified in many places.
- Add a sample on using Assimp in conjunction with OpenGL
- Distribution/packaging: comfortable SDK installer for Windows
- Distribution/packaging: improved release packages for other architectures
CRITICAL FIXES:
- Resolve problems with clashing heap managers, STL ABIs and runtime libraries (win32)
- Fix automatic detection of file type if no file extension is given
- Improved exception safety and robustness, prevent leaking of exceptions through the C interface
- Fix possible heap corruption due to material properties pulled in incorrectly
- Avoid leaking in certain error scenarios
- Fix 64 bit compatibility problems in some loaders (i.e. MDL)
BREAKING API CHANGES:
- None -
MINOR API BEHAVIOUR CHANGES:
- Change quaternion orientation to suit to the more common convention (-w).
- aiString is utf8 now. Not yet consistent, however.

3961
Engine/lib/assimp/CHANGES.md Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
# Open Asset Import Library (assimp)
# ----------------------------------------------------------------------
# Copyright (c) 2006-2024, assimp team
# Copyright (c) 2006-2026, assimp team
#
# All rights reserved.
#
@ -40,27 +40,34 @@ SET(CMAKE_POLICY_DEFAULT_CMP0092 NEW)
CMAKE_MINIMUM_REQUIRED( VERSION 3.22 )
#================================================================================#
# Model formats not enabled by default
#
# 3rd party projects may not adhere to strict standards enforced by assimp,
# in which case those formats must be opt-in; otherwise the 3rd party code
# would fail assimp CI checks
#================================================================================#
# M3D format import support (assimp integration no longer supported by M3D format author)
# User may override these in their CMake script to provide M3D import/export support
# (M3D importer/exporter was disabled for assimp release 5.1 or later)
OPTION(ASSIMP_BUILD_M3D_IMPORTER "Enable M3D file import" off)
OPTION(ASSIMP_BUILD_M3D_EXPORTER "Enable M3D file export" off)
# Experimental USD importer: disabled, need to opt-in
# Note: assimp github PR automatic checks will fail the PR due to compiler warnings in
# the external, 3rd party tinyusdz code which isn't technically part of the PR since it's
# auto-cloned during build; so MUST disable the feature or the PR will be rejected
option(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off)
option(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off)
option(ASSIMP_BUILD_USE_CCACHE "Use ccache to speed up compilation." on)
OPTION(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off)
OPTION(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off)
if(ASSIMP_BUILD_USE_CCACHE)
find_program(CCACHE_PATH ccache)
if (CCACHE_PATH)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH})
endif()
endif()
# User may override these in their CMake script to provide M3D import/export support
# (M3D importer/exporter was disabled for assimp release 5.1 or later)
option(ASSIMP_BUILD_M3D_IMPORTER "Enable M3D file import" off)
option(ASSIMP_BUILD_M3D_EXPORTER "Enable M3D file export" off)
# VRML (.wrl/.x3dv) file import support by leveraging X3D importer and 3rd party file
# format converter to convert .wrl/.x3dv files to X3D-compatible .xml
# (Need to make this opt-in because 3rd party code triggers lots of CI code quality warnings)
OPTION(ASSIMP_BUILD_VRML_IMPORTER "Enable VRML (.wrl/.x3dv) file import" off)
#--------------------------------------------------------------------------------#
# Internal impl for optional model formats
#--------------------------------------------------------------------------------#
# Internal/private M3D logic
if (NOT ASSIMP_BUILD_M3D_IMPORTER)
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER)
@ -69,6 +76,22 @@ if (NOT ASSIMP_BUILD_M3D_EXPORTER)
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_EXPORTER)
endif () # if (not ASSIMP_BUILD_M3D_EXPORTER)
# Internal/private VRML logic
if (NOT ASSIMP_BUILD_VRML_IMPORTER)
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_VRML_IMPORTER)
endif () # if (not ASSIMP_BUILD_VRML_IMPORTER)
#================================================================================#
option(ASSIMP_BUILD_USE_CCACHE "Use ccache to speed up compilation." on)
IF(ASSIMP_BUILD_USE_CCACHE)
find_program(CCACHE_PATH ccache)
IF (CCACHE_PATH)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH})
ENDIF()
ENDIF()
# Toggles the use of the hunter package manager
option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
@ -78,10 +101,13 @@ IF(ASSIMP_HUNTER_ENABLED)
URL "https://github.com/cpp-pm/hunter/archive/v0.25.8.tar.gz"
SHA1 "26c79d587883ec910bce168e25f6ac4595f97033"
)
add_definitions(-DASSIMP_USE_HUNTER)
ADD_DEFINITIONS(-DASSIMP_USE_HUNTER)
ENDIF()
PROJECT(Assimp VERSION 5.4.3)
PROJECT(Assimp VERSION 6.0.5
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 ###############################################
@ -223,7 +249,7 @@ SET (ASSIMP_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
SET (ASSIMP_VERSION_MINOR ${PROJECT_VERSION_MINOR})
SET (ASSIMP_VERSION_PATCH ${PROJECT_VERSION_PATCH})
SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
SET (ASSIMP_SOVERSION 5)
SET (ASSIMP_SOVERSION 6)
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
set(CMAKE_CXX_STANDARD 17)
@ -283,6 +309,17 @@ IF( UNIX )
ENDIF()
ENDIF()
IF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND WIN32)
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
ENDIF()
IF( MSVC OR "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") # clang with MSVC ABI
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
endif ()
# Grouped compiler settings ########################################
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU)
IF(NOT ASSIMP_HUNTER_ENABLED)
@ -325,14 +362,16 @@ ELSEIF(MSVC)
elseif((GENERATOR_IS_MULTI_CONFIG) OR (CMAKE_BUILD_TYPE MATCHES Release))
message("-- MSVC PDB generation disabled. Release binary will not be debuggable.")
endif()
# Source code is encoded in UTF-8
ADD_COMPILE_OPTIONS(/source-charset:utf-8)
if(NOT CMAKE_CXX_FLAGS MATCHES "/utf-8")
# Source code is encoded in UTF-8
ADD_COMPILE_OPTIONS(/source-charset:utf-8)
endif()
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
ENDIF()
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
SET(CMAKE_CXX_FLAGS "-Wno-deprecated-non-prototype -fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
SET(CMAKE_C_FLAGS "-Wno-deprecated-non-prototype -fno-strict-aliasing ${CMAKE_C_FLAGS}")
ELSEIF( MINGW )
IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
message(FATAL_ERROR "MinGW is too old to be supported. Please update MinGW and try again.")
@ -455,20 +494,20 @@ ENDIF()
set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
IF(ASSIMP_HUNTER_ENABLED)
set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in")
set(NAMESPACE "${PROJECT_NAME}::")
set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
SET(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
SET(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in")
SET(NAMESPACE "${PROJECT_NAME}::")
SET(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
SET(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
SET(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
ELSE()
set(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in")
SET(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
SET(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in")
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)
set(NAMESPACE "${PROJECT_NAME_LOWERCASE}::")
set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets")
set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}ConfigVersion.cmake")
set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}Config.cmake")
SET(NAMESPACE "${PROJECT_NAME_LOWERCASE}::")
SET(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets")
SET(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}ConfigVersion.cmake")
SET(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}Config.cmake")
ENDIF()
set(INCLUDE_INSTALL_DIR "include")
@ -485,20 +524,20 @@ configure_package_config_file(
INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
)
if(ASSIMP_INSTALL)
install(
IF(ASSIMP_INSTALL)
INSTALL(
FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
)
install(
INSTALL(
EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${NAMESPACE}"
DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
)
endif()
ENDIF()
IF( ASSIMP_BUILD_DOCS )
ADD_SUBDIRECTORY(doc)
@ -511,9 +550,9 @@ IF(ASSIMP_HUNTER_ENABLED)
find_package(ZLIB CONFIG REQUIRED)
add_definitions(-DASSIMP_BUILD_NO_OWN_ZLIB)
set(ZLIB_FOUND TRUE)
set(ZLIB_LIBRARIES ZLIB::zlib)
set(ASSIMP_BUILD_MINIZIP TRUE)
SET(ZLIB_FOUND TRUE)
SET(ZLIB_LIBRARIES ZLIB::zlib)
SET(ASSIMP_BUILD_MINIZIP TRUE)
ELSE()
# If the zlib is already found outside, add an export in case assimpTargets can't find it.
IF( ZLIB_FOUND AND ASSIMP_INSTALL)
@ -540,8 +579,8 @@ ELSE()
# https://github.com/madler/zlib/issues/41#issuecomment-125848075
# Also prevents these options from "polluting" the cmake options if assimp is being
# included as a submodule.
set( ASM686 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
set( AMD64 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
SET(ASM686 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
SET(AMD64 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
# compile from sources
ADD_SUBDIRECTORY(contrib/zlib)
@ -552,7 +591,7 @@ ELSE()
SET(ASSIMP_BUILD_MINIZIP 1)
ELSE()
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
SET(ZLIB_LIBRARIES_LINKED -lz)
SET(ZLIB_LIBRARIES_LINKED -l${ZLIB_LIBRARIES})
ENDIF()
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
ENDIF()
@ -564,7 +603,7 @@ IF( NOT IOS )
ELSE ()
IF( NOT BUILD_SHARED_LIBS )
IF( NOT ASSIMP_BUILD_MINIZIP )
use_pkgconfig(UNZIP minizip)
USE_PKGCONFIG(UNZIP minizip)
ENDIF()
ENDIF ()
ENDIF ()
@ -647,48 +686,48 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
"${C4D_LIB_BASE_PATH}/release/libcinewarelib.a"
"${C4D_LIB_BASE_PATH}/release/libjpeglib.a"
)
ELSE ()
ELSE()
MESSAGE( FATAL_ERROR
"C4D is currently only available on Windows and macOS with Cineware SDK installed in contrib/Cineware"
)
ENDIF ()
ENDIF()
ELSE ()
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
ENDIF ()
if(ASSIMP_BUILD_DRACO_STATIC)
set(ASSIMP_BUILD_DRACO ON)
endif()
IF(ASSIMP_BUILD_DRACO_STATIC)
SET(ASSIMP_BUILD_DRACO ON)
ENDIF()
# Draco requires cmake 3.12
IF (DEFINED CMAKE_VERSION AND "${CMAKE_VERSION}" VERSION_LESS "3.12")
message(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled")
MESSAGE(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled")
SET ( ASSIMP_BUILD_DRACO OFF CACHE BOOL "Disabled: Draco requires newer cmake" FORCE )
ELSE()
OPTION ( ASSIMP_BUILD_DRACO "If the Draco libraries are to be built. Primarily for glTF" OFF )
IF ( ASSIMP_BUILD_DRACO )
# Primarily for glTF v2
# Enable Draco glTF feature set
set(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE)
SET(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE)
# Disable unnecessary or omitted components
set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
set(DRACO_WASM OFF CACHE BOOL "" FORCE)
set(DRACO_MAYA_PLUGIN OFF CACHE BOOL "" FORCE)
set(DRACO_UNITY_PLUGIN OFF CACHE BOOL "" FORCE)
set(DRACO_TESTS OFF CACHE BOOL "" FORCE)
SET(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
SET(DRACO_WASM OFF CACHE BOOL "" FORCE)
SET(DRACO_MAYA_PLUGIN OFF CACHE BOOL "" FORCE)
SET(DRACO_UNITY_PLUGIN OFF CACHE BOOL "" FORCE)
SET(DRACO_TESTS OFF CACHE BOOL "" FORCE)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(draco)
find_package(draco CONFIG REQUIRED)
set(draco_LIBRARIES draco::draco)
SET(draco_LIBRARIES draco::draco)
ELSE()
# Draco 1.4.1 has many warnings and will not build with /WX or -Werror
# See https://github.com/google/draco/issues/672
# and https://github.com/google/draco/issues/673
IF(MSVC)
set(DRACO_CXX_FLAGS "/W0")
SET(DRACO_CXX_FLAGS "/W0")
ELSE()
list(APPEND DRACO_CXX_FLAGS
LIST(APPEND DRACO_CXX_FLAGS
"-Wno-bool-compare"
"-Wno-comment"
"-Wno-maybe-uninitialized"
@ -696,30 +735,30 @@ ELSE()
"-Wno-unused-local-typedefs"
)
if(NOT ASSIMP_BUILD_DRACO_STATIC)
IF(NOT ASSIMP_BUILD_DRACO_STATIC)
# Draco 1.4.1 does not explicitly export any symbols under GCC/clang
list(APPEND DRACO_CXX_FLAGS
LIST(APPEND DRACO_CXX_FLAGS
"-fvisibility=default"
)
endif()
ENDIF()
ENDIF()
# Don't build or install all of Draco by default
ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL )
if(ASSIMP_BUILD_DRACO_STATIC)
IF(ASSIMP_BUILD_DRACO_STATIC)
set_property(DIRECTORY "contrib/draco" PROPERTY BUILD_SHARED_LIBS OFF)
endif()
ENDIF()
if(MSVC OR WIN32)
set(draco_LIBRARIES "draco")
else()
if(ASSIMP_BUILD_DRACO_STATIC)
set(draco_LIBRARIES "draco_static")
else()
set(draco_LIBRARIES "draco_shared")
endif()
endif()
IF(MSVC OR WIN32)
SET(draco_LIBRARIES "draco")
ELSE()
IF(ASSIMP_BUILD_DRACO_STATIC)
SET(draco_LIBRARIES "draco_static")
ELSE()
SET(draco_LIBRARIES "draco_shared")
ENDIF()
ENDIF()
# Don't build the draco command-line tools by default
set_target_properties(draco_encoder draco_decoder PROPERTIES
@ -737,10 +776,10 @@ ELSE()
TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_encoder)
TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_decoder)
set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
SET(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
# This is probably wrong
if (ASSIMP_INSTALL)
IF (ASSIMP_INSTALL)
INSTALL( TARGETS ${draco_LIBRARIES}
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
@ -750,7 +789,7 @@ ELSE()
COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION include
)
endif()
ENDIF()
ENDIF()
ENDIF()
ENDIF()
@ -883,24 +922,24 @@ if(WIN32)
IF(MSVC12 OR MSVC14 OR MSVC15 )
ADD_CUSTOM_TARGET(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM)
IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ELSE()
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ENDIF()
ENDIF()
ENDIF ()

View file

@ -0,0 +1,53 @@
{
"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_static",
"binaryDir": "${sourceDir}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"BUILD_SHARED_LIBS": "OFF",
"ASSIMP_BUILD_ASSIMP_TOOLS": "OFF",
"ASSIMP_DOUBLE_PRECISION": "ON"
}
},
{
"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"
}
},
{
"name": "assimp_all",
"binaryDir": "${sourceDir}",
"cacheVariables": {
"ASSIMP_BUILD_ASSIMP_TOOLS": "ON",
"ASSIMP_BUILD_SAMPLES": "ON",
"ASSIMP_BUILD_DOCS": "ON"
}
}
]
}

View file

@ -60,7 +60,7 @@ The GUY who performed some of the CSM mocaps.
Contributed fixes for the documentation and the doxygen markup
- Zhao Lei
Contributed several bugfixes fixing memory leaks and improving float parsing
Contributed several bugfixes fixing memory leaks and improving float parsing
- sueastside
Updated PyAssimp to the latest Assimp data structures and provided a script to keep the Python binding up-to-date.
@ -129,7 +129,7 @@ Contributed a patch to fix the VertexTriangleAdjacency postprocessing step.
Contributed the Debian build fixes ( architecture macro ).
- gellule
Several LWO and LWS fixes (pivoting).
Several LWO and LWS fixes (pivoting).
- Marcel Metz
GCC/Linux fixes for the SimpleOpenGL sample.

View file

@ -1,22 +1,17 @@
FROM ubuntu:22.04
FROM gcc:1.5.1.0
RUN apt-get update && apt-get install --no-install-recommends -y ninja-build \
git cmake build-essential software-properties-common
RUN apt-get update \
apt-get install --no-install-recommends -y ninja-build cmake zlib1g-dev
RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update
WORKDIR /app
WORKDIR /opt
RUN apt install zlib1g-dev
COPY . .
# Build Assimp
RUN git clone https://github.com/assimp/assimp.git /opt/assimp
WORKDIR /opt/assimp
RUN git checkout master \
&& mkdir build && cd build && \
RUN mkdir build && cd build && \
cmake -G 'Ninja' \
-DCMAKE_BUILD_TYPE=Release \
-DASSIMP_BUILD_ASSIMP_TOOLS=ON \
.. && \
ninja -j4 && ninja install
CMD ["/app/build/bin/unit"]

View file

@ -1,17 +1,17 @@
========================================================================
Open Asset Import Library (assimp) INSTALL
Open Asset Import Library (assimp) INSTALL
========================================================================
------------------------------
Getting the documentation
------------------------------
A regularly-updated copy is available at
A regularly-updated copy is available at
https://assimp-docs.readthedocs.io/en/latest/
------------------------------
Building Assimp
Building Assimp
------------------------------
Just check the build-instructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md

View file

@ -1,6 +1,6 @@
Open Asset Import Library (assimp)
Copyright (c) 2006-2021, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,

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.
### Current project status ###
## Current project status
![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)
[![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,35 +16,44 @@ 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.
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")
### Documentation ###
Read [our latest documentation](https://assimp-docs.readthedocs.io/en/latest/).
## Developer quickstart
```bash
git clone https://github.com/assimp/assimp
cd assimp
cmake -G Ninja -DASSIMP_BUILD_TESTS=off -DASSIMP_INSTALL=off -S . -B build
cd build
ninja
```
### Pre-built binaries ###
Download binaries from [our Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib).
## Documentation
Read [our latest documentation](https://the-asset-importer-lib-documentation.readthedocs.io/en/latest/).
### Test data ###
Clone [our model database](https://github.com/assimp/assimp-mdb).
## Pre-built binaries
Download binaries from [our Itch Projectspace](https://kimkulling.itch.io/the-asset-importer-lib).
### Communities ###
## Test data
Clone [our model database for testing purposes](https://github.com/assimp/assimp-mdb).
## Communities
- Ask questions at [the Assimp Discussion Board](https://github.com/assimp/assimp/discussions).
- Find us on [https://discord.gg/s9KJfaem](https://discord.gg/kKazXMXDy2)
- Find us on [discord](https://discord.gg/kKazXMXDy2)
- Ask [the Assimp community on Reddit](https://www.reddit.com/r/Assimp/).
- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
- 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)
#### Supported file formats ####
## Supported file formats
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.
### Ports ###
## Ports
* [Android](port/AndroidJNI/README.md)
* [Python](port/PyAssimp/README.md)
* [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/)
* [.NET](https://github.com/Saalvage/AssimpNetter)
* [Pascal](port/AssimpPascal/Readme.md)
* [Javascript (Alpha)](https://github.com/makc/assimp2json)
* [Javascript/Node.js Interface](https://github.com/kovacsv/assimpjs)
@ -54,36 +63,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.
* [Rust](https://github.com/jkvargas/russimp)
### Other tools ###
[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
## 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>
[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:
/code Source code
/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
/tools Tools (old assimp viewer, command line `assimp`)
/samples A small number of samples to illustrate possible use cases for Assimp
```txt
code Source code
├── AssetLib/ The asset-importer and exporter lib
├── CApi/ C-API files
├── Common/ Common code used from all modules
├── Geometry/ Geometry utilities
├── Material/ Common materials
├── Pbrt/ Physical based materials
├── PostProcessing/ Post-processing steps
├── 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:
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
We would greatly appreciate for you to contribute to assimp. The easiest way to get involved is to submit
a pull request with your changes against the main repository's `master` branch.
## Contributors
@ -109,7 +122,7 @@ You can support the project with your organization. Your logo will show up here
<a href="https://opencollective.com/assimp/organization/0/website"><img src="https://opencollective.com/assimp/organization/0/avatar.svg"></a>
### License ###
## License ###
Our license is based on the modified, __3-clause BSD__-License.
An _informal_ summary is: do whatever you want, but include Assimp's license text with your product -

View file

@ -2,15 +2,14 @@
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
The current version of Assimp that's being supported with security updates:
| Version | Supported |
| ------- | ------------------ |
| 5.2.4 | :white_check_mark: |
| 6.0.5 | :white_check_mark: |
## Reporting a Vulnerability
If you have found any security vulnerability you can contact us via
kim.kulling@googlemail.com
If you have found any security vulnerability you can contact us via
kim.kulling@assimp.org

View file

@ -6,7 +6,7 @@
# Creates source debian files and manages library dependencies
#
# Features:
#
#
# - Automatically generates symbols and run-time dependencies from the build dependencies
# - Custom copy of source directory via CPACK_DEBIAN_PACKAGE_SOURCE_COPY
# - Simultaneous output of multiple debian source packages for each distribution
@ -114,7 +114,6 @@ foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES})
endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n"
"Standards-Version: 3.8.4\n"
"Homepage: ${CPACK_PACKAGE_VENDOR}\n"
@ -173,7 +172,7 @@ foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES})
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS})
endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n"
"Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n"
"${DEB_LONG_DESCRIPTION}"

View file

@ -1,72 +0,0 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#.rst:
# FindDevIL
# ---------
#
#
#
# This module locates the developer's image library.
# http://openil.sourceforge.net/
#
# This module sets:
#
# ::
#
# IL_LIBRARIES - the name of the IL library. These include the full path to
# the core DevIL library. This one has to be linked into the
# application.
# ILU_LIBRARIES - the name of the ILU library. Again, the full path. This
# library is for filters and effects, not actual loading. It
# doesn't have to be linked if the functionality it provides
# is not used.
# ILUT_LIBRARIES - the name of the ILUT library. Full path. This part of the
# library interfaces with OpenGL. It is not strictly needed
# in applications.
# IL_INCLUDE_DIR - where to find the il.h, ilu.h and ilut.h files.
# IL_FOUND - this is set to TRUE if all the above variables were set.
# This will be set to false if ILU or ILUT are not found,
# even if they are not needed. In most systems, if one
# library is found all the others are as well. That's the
# way the DevIL developers release it.
# TODO: Add version support.
# Tested under Linux and Windows (MSVC)
#include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
include(FindPackageHandleStandardArgs)
find_path(IL_INCLUDE_DIR il.h
PATH_SUFFIXES include IL
DOC "The path to the directory that contains il.h"
)
#message("IL_INCLUDE_DIR is ${IL_INCLUDE_DIR}")
find_library(IL_LIBRARIES
NAMES IL DEVIL
PATH_SUFFIXES lib64 lib lib32
DOC "The file that corresponds to the base il library."
)
#message("IL_LIBRARIES is ${IL_LIBRARIES}")
find_library(ILUT_LIBRARIES
NAMES ILUT
PATH_SUFFIXES lib64 lib lib32
DOC "The file that corresponds to the il (system?) utility library."
)
#message("ILUT_LIBRARIES is ${ILUT_LIBRARIES}")
find_library(ILU_LIBRARIES
NAMES ILU
PATH_SUFFIXES lib64 lib lib32
DOC "The file that corresponds to the il utility library."
)
#message("ILU_LIBRARIES is ${ILU_LIBRARIES}")
FIND_PACKAGE_HANDLE_STANDARD_ARGS(IL DEFAULT_MSG
IL_LIBRARIES IL_INCLUDE_DIR)

View file

@ -26,7 +26,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
getenv_path(DIRECTX_BASE)
# construct search paths
set(DirectX_PREFIX_PATH
set(DirectX_PREFIX_PATH
"${DXSDK_DIR}" "${ENV_DXSDK_DIR}"
"${DIRECTX_HOME}" "${ENV_DIRECTX_HOME}"
"${DIRECTX_ROOT}" "${ENV_DIRECTX_ROOT}"
@ -66,7 +66,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
find_library(DirectX_D3DCOMPILER_LIBRARY NAMES d3dcompiler HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
findpkg_finish(DirectX)
set(DirectX_LIBRARIES ${DirectX_LIBRARIES}
set(DirectX_LIBRARIES ${DirectX_LIBRARIES}
${DirectX_D3DX9_LIBRARY}
${DirectX_DXERR_LIBRARY}
${DirectX_DXGUID_LIBRARY}
@ -82,7 +82,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
get_filename_component(DirectX_LIBRARY_DIR "${DirectX_LIBRARY}" PATH)
message(STATUS "DX lib dir: ${DirectX_LIBRARY_DIR}")
find_library(DirectX_D3D11_LIBRARY NAMES d3d11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
if (DirectX_D3D11_INCLUDE_DIR AND DirectX_D3D11_LIBRARY)
set(DirectX_D3D11_FOUND TRUE)
set(DirectX_D3D11_INCLUDE_DIR ${DirectX_D3D11_INCLUDE_DIR})
@ -92,8 +92,8 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
${DirectX_DXGI_LIBRARY}
${DirectX_DXERR_LIBRARY}
${DirectX_DXGUID_LIBRARY}
${DirectX_D3DCOMPILER_LIBRARY}
)
${DirectX_D3DCOMPILER_LIBRARY}
)
endif ()
mark_as_advanced(DirectX_D3D11_INCLUDE_DIR DirectX_D3D11_LIBRARY DirectX_D3DX11_LIBRARY)
endif ()

View file

@ -3,7 +3,7 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ASSIMP_ARCHITECTURE "32")
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
if(WIN32)
set(ASSIMP_ROOT_DIR CACHE PATH "ASSIMP root directory")
@ -17,29 +17,29 @@ if(WIN32)
if(MSVC12)
set(ASSIMP_MSVC_VERSION "vc120")
elseif(MSVC14)
elseif(MSVC14)
set(ASSIMP_MSVC_VERSION "vc140")
endif(MSVC12)
if(MSVC12 OR MSVC14)
find_path(ASSIMP_LIBRARY_DIR
NAMES
assimp-${ASSIMP_MSVC_VERSION}-mt.lib
HINTS
${ASSIMP_ROOT_DIR}/lib${ASSIMP_ARCHITECTURE}
)
find_library(ASSIMP_LIBRARY_RELEASE assimp-${ASSIMP_MSVC_VERSION}-mt.lib PATHS ${ASSIMP_LIBRARY_DIR})
find_library(ASSIMP_LIBRARY_DEBUG assimp-${ASSIMP_MSVC_VERSION}-mtd.lib PATHS ${ASSIMP_LIBRARY_DIR})
set(ASSIMP_LIBRARY
set(ASSIMP_LIBRARY
optimized ${ASSIMP_LIBRARY_RELEASE}
debug ${ASSIMP_LIBRARY_DEBUG}
)
set(ASSIMP_LIBRARIES "ASSIMP_LIBRARY_RELEASE" "ASSIMP_LIBRARY_DEBUG")
FUNCTION(ASSIMP_COPY_BINARIES TargetDirectory)
ADD_CUSTOM_TARGET(AssimpCopyBinaries
COMMAND ${CMAKE_COMMAND} -E copy ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE}/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${TargetDirectory}/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll
@ -47,9 +47,37 @@ if(WIN32)
COMMENT "Copying Assimp binaries to '${TargetDirectory}'"
VERBATIM)
ENDFUNCTION(ASSIMP_COPY_BINARIES)
if (NOT TARGET ASSIMP)
set(INCLUDE_DIRS ${ASSIMP_ROOT_DIR}/include)
find_library(ASSIMP_LIB_DEBUG
NAMES assimp-${ASSIMP_MSVC_VERSION}-mtd.lib
PATHS ${ASSIMP_LIBRARY_DIR})
find_file(ASSIMP_DLL_DEBUG
NAMES assimp-${ASSIMP_MSVC_VERSION}-mtd.dll
PATHS ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE})
find_library(ASSIMP_LIB_RELEASE
NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.lib
PATHS ${ASSIMP_LIBRARY_DIR})
find_file(ASSIMP_DLL_RELEASE
NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.dll
PATHS ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE})
add_library(ASSIMP SHARED IMPORTED)
set_target_properties(ASSIMP PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${INCLUDE_DIRS}"
IMPORTED_IMPLIB_DEBUG ${ASSIMP_LIB_DEBUG}
IMPORTED_IMPLIB_RELEASE ${ASSIMP_LIB_RELEASE}
IMPORTED_LOCATION_DEBUG ${ASSIMP_DLL_DEBUG}
IMPORTED_LOCATION_RELEASE ${ASSIMP_DLL_RELEASE}
)
endif()
endif()
else(WIN32)
find_path(
@ -81,5 +109,5 @@ else(WIN32)
message(FATAL_ERROR "Could not find asset importer library")
endif (assimp_FIND_REQUIRED)
endif (assimp_FOUND)
endif(WIN32)

View file

@ -31,7 +31,7 @@ option(HUNTER_STATUS_PRINT "Print working status" ON)
option(HUNTER_STATUS_DEBUG "Print a lot info" OFF)
option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON)
set(HUNTER_ERROR_PAGE "https://docs.hunter.sh/en/latest/reference/errors")
set(HUNTER_ERROR_PAGE "https://hunter.readthedocs.io/en/latest/reference/errors")
function(hunter_gate_status_print)
if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG)

View file

@ -9,14 +9,14 @@ MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar
OBJECT_OUTPUTS "${PrecompiledBinary}")
# Do not consider .c files
foreach(fname ${Sources})
foreach(fname ${Sources})
GET_FILENAME_COMPONENT(fext ${fname} EXT)
if(fext STREQUAL ".cpp")
SET_SOURCE_FILES_PROPERTIES(${fname}
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledBinary}\" /FI\"${PrecompiledBinary}\" /Fp\"${PrecompiledBinary}\""
OBJECT_DEPENDS "${PrecompiledBinary}")
OBJECT_DEPENDS "${PrecompiledBinary}")
endif(fext STREQUAL ".cpp")
endforeach(fname)
endforeach(fname)
ENDIF(MSVC)
# Add precompiled header to SourcesVar

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -56,23 +56,27 @@ namespace Assimp {
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() {
// Try to find an existing material that matches the
// typical default material setting:
// - no textures
// - 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.
unsigned int idx(NotSet);
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) {
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 !=
mScene->mMaterials[i].mDiffuse.g ||
@ -85,25 +89,22 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
idx = i;
}
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
// find all faces that are using the default material
unsigned int cnt = 0;
for (std::vector<D3DS::Mesh>::iterator
i = mScene->mMeshes.begin();
i != mScene->mMeshes.end(); ++i) {
for (std::vector<unsigned int>::iterator
a = (*i).mFaceMaterials.begin();
a != (*i).mFaceMaterials.end(); ++a) {
for (auto i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) {
for (auto a = i->mFaceMaterials.begin(); a != i->mFaceMaterials.end(); ++a) {
// NOTE: The additional check seems to be necessary,
// some exporters seem to generate invalid data here
if (0xcdcdcdcd == (*a)) {
(*a) = idx;
if (NotSet == *a) {
*a = idx;
++cnt;
} else if ((*a) >= mScene->mMaterials.size()) {
(*a) = idx;
*a = idx;
ASSIMP_LOG_WARN("Material index overflow in 3DS file. Using default material");
++cnt;
}
@ -111,7 +112,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
}
if (cnt && idx == mScene->mMaterials.size()) {
// We need to create our own default material
D3DS::Material sMat("%%%DEFAULT");
Material sMat("%%%DEFAULT");
sMat.mDiffuse = aiColor3D(0.3f, 0.3f, 0.3f);
mScene->mMaterials.push_back(sMat);
@ -121,17 +122,17 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
// ------------------------------------------------------------------------------------------------
// Check whether all indices are valid. Otherwise we'd crash before the validation step is reached
void Discreet3DSImporter::CheckIndices(D3DS::Mesh &sMesh) {
for (std::vector<D3DS::Face>::iterator i = sMesh.mFaces.begin(); i != sMesh.mFaces.end(); ++i) {
void Discreet3DSImporter::CheckIndices(Mesh &sMesh) {
for (auto i = sMesh.mFaces.begin(); i != sMesh.mFaces.end(); ++i) {
// check whether all indices are in range
for (unsigned int a = 0; a < 3; ++a) {
if ((*i).mIndices[a] >= sMesh.mPositions.size()) {
ASSIMP_LOG_WARN("3DS: Vertex index overflow)");
(*i).mIndices[a] = (uint32_t)sMesh.mPositions.size() - 1;
(*i).mIndices[a] = static_cast<uint32_t>(sMesh.mPositions.size() - 1);
}
if (!sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size()) {
ASSIMP_LOG_WARN("3DS: Texture coordinate index overflow)");
(*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size() - 1;
(*i).mIndices[a] = static_cast<uint32_t>(sMesh.mTexCoords.size() - 1);
}
}
}
@ -139,7 +140,7 @@ void Discreet3DSImporter::CheckIndices(D3DS::Mesh &sMesh) {
// ------------------------------------------------------------------------------------------------
// Generate out unique verbose format representation
void Discreet3DSImporter::MakeUnique(D3DS::Mesh &sMesh) {
void Discreet3DSImporter::MakeUnique(Mesh &sMesh) {
// TODO: really necessary? I don't think. Just a waste of memory and time
// to do it now in a separate buffer.
@ -150,7 +151,7 @@ void Discreet3DSImporter::MakeUnique(D3DS::Mesh &sMesh) {
vNew2.resize(sMesh.mFaces.size() * 3);
for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size(); ++i) {
D3DS::Face &face = sMesh.mFaces[i];
Face &face = sMesh.mFaces[i];
// Positions
for (unsigned int a = 0; a < 3; ++a, ++base) {
@ -167,10 +168,9 @@ void Discreet3DSImporter::MakeUnique(D3DS::Mesh &sMesh) {
// ------------------------------------------------------------------------------------------------
// Convert a 3DS texture to texture keys in an aiMaterial
void CopyTexture(aiMaterial &mat, D3DS::Texture &texture, aiTextureType type) {
void CopyTexture(aiMaterial &mat, Texture &texture, aiTextureType type) {
// Setup the texture name
aiString tex;
tex.Set(texture.mMapName);
aiString tex(texture.mMapName);
mat.AddProperty(&tex, AI_MATKEY_TEXTURE(type, 0));
// Setup the texture blend factor
@ -178,7 +178,7 @@ void CopyTexture(aiMaterial &mat, D3DS::Texture &texture, aiTextureType type) {
mat.AddProperty<ai_real>(&texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type, 0));
// 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_V(type, 0));
@ -197,13 +197,11 @@ void CopyTexture(aiMaterial &mat, D3DS::Texture &texture, aiTextureType type) {
// ------------------------------------------------------------------------------------------------
// Convert a 3DS material to an aiMaterial
void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
aiMaterial &mat) {
void Discreet3DSImporter::ConvertMaterial(Material &oldMat, aiMaterial &mat) {
// NOTE: Pass the background image to the viewer by bypassing the
// material system. This is an evil hack, never do it again!
if (0 != mBackgroundImage.length() && bHasBG) {
aiString tex;
tex.Set(mBackgroundImage);
if (mBackgroundImage.empty() && bHasBG) {
aiString tex(mBackgroundImage);
mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
// Be sure this is only done for the first material
@ -215,8 +213,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
oldMat.mAmbient.g += mClrAmbient.g;
oldMat.mAmbient.b += mClrAmbient.b;
aiString name;
name.Set(oldMat.mName);
aiString name(oldMat.mName);
mat.AddProperty(&name, AI_MATKEY_NAME);
// Material colors
@ -226,10 +223,9 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
mat.AddProperty(&oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
// Phong shininess and shininess strength
if (D3DS::Discreet3DS::Phong == oldMat.mShading ||
D3DS::Discreet3DS::Metal == oldMat.mShading) {
if (Discreet3DS::Phong == oldMat.mShading || Discreet3DS::Metal == oldMat.mShading) {
if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength) {
oldMat.mShading = D3DS::Discreet3DS::Gouraud;
oldMat.mShading = Discreet3DS::Gouraud;
} else {
mat.AddProperty(&oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
mat.AddProperty(&oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
@ -251,40 +247,41 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
// Shading mode
aiShadingMode eShading = aiShadingMode_NoShading;
switch (oldMat.mShading) {
case D3DS::Discreet3DS::Flat:
case Discreet3DS::Flat:
eShading = aiShadingMode_Flat;
break;
// I don't know what "Wire" shading should be,
// assume it is simple lambertian diffuse shading
case D3DS::Discreet3DS::Wire: {
case Discreet3DS::Wire: {
// Set the wireframe flag
unsigned int iWire = 1;
mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
[[fallthrough]];
case D3DS::Discreet3DS::Gouraud:
case Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud;
break;
// assume cook-torrance shading for metals.
case D3DS::Discreet3DS::Phong:
case Discreet3DS::Phong:
eShading = aiShadingMode_Phong;
break;
case D3DS::Discreet3DS::Metal:
case Discreet3DS::Metal:
eShading = aiShadingMode_CookTorrance;
break;
// FIX to workaround a warning with GCC 4 who complained
// about a missing case Blinn: here - Blinn isn't a valid
// value in the 3DS Loader, it is just needed for ASE
case D3DS::Discreet3DS::Blinn:
case Discreet3DS::Blinn:
eShading = aiShadingMode_Blinn;
break;
}
int eShading_ = static_cast<int>(eShading);
const int eShading_ = eShading;
mat.AddProperty<int>(&eShading_, 1, AI_MATKEY_SHADING_MODEL);
// DIFFUSE texture
@ -333,10 +330,11 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
aiString name;
// 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()]);
name.length = ASSIMP_itoa10(name.data, num++);
name.length = ASSIMP_itoa10(name.data, num);
++num;
unsigned int iNum = 0;
for (std::vector<unsigned int>::const_iterator a = (*i).mFaceMaterials.begin();
@ -348,7 +346,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
if (aiSplit[p].empty()) {
continue;
}
aiMesh *meshOut = new aiMesh();
auto *meshOut = new aiMesh();
meshOut->mName = name;
meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
@ -360,7 +358,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
avOutMeshes.push_back(meshOut);
// convert vertices
meshOut->mNumFaces = (unsigned int)aiSplit[p].size();
meshOut->mNumFaces = static_cast<unsigned int>(aiSplit[p].size());
meshOut->mNumVertices = meshOut->mNumFaces * 3;
// allocate enough storage for faces
@ -408,8 +406,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
// ------------------------------------------------------------------------------------------------
// Add a node to the scenegraph and setup its final transformation
void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
D3DS::Node *pcIn, aiMatrix4x4 & /*absTrafo*/) {
void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::Node *pcIn, aiMatrix4x4 & /*absTrafo*/) {
std::vector<unsigned int> iArray;
iArray.reserve(3);
@ -417,7 +414,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
// Find all meshes with the same name as the node
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);
if (pcIn->mName == pcMesh->mName)
@ -426,7 +423,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
if (!iArray.empty()) {
// The matrix should be identical for all meshes with the
// 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
// vertices back to their relative and local space
@ -435,7 +432,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
mInvTransposed.Transpose();
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()];
for (unsigned int i = 0; i < iArray.size(); ++i) {
const unsigned int iIndex = iArray[i];
@ -454,7 +451,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
// Handle negative transformation matrix determinant -> invert vertex x
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) {
pvCurrent->x *= -1.f;
t2->x *= -1.f;
@ -481,7 +478,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
// Setup the name of the node
// First instance keeps its name otherwise something might break, all others will be postfixed with their instance number
if (pcIn->mInstanceNumber > 1) {
char tmp[12];
char tmp[12] = {'\0'};
ASSIMP_itoa10(tmp, pcIn->mInstanceNumber);
std::string tempStr = pcIn->mName + "_inst_";
tempStr += tmp;
@ -494,7 +491,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
if (pcIn->aRotationKeys.size()) {
// 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;
}
@ -606,11 +603,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
}
// 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);
// POSITION keys
if (pcIn->aPositionKeys.size() > 0) {
if (!pcIn->aPositionKeys.empty()) {
nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
::memcpy(nda->mPositionKeys, &pcIn->aPositionKeys[0],
@ -618,7 +615,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
}
// ROTATION keys
if (pcIn->aRotationKeys.size() > 0) {
if (!pcIn->aRotationKeys.empty()) {
nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
@ -634,7 +631,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
}
// SCALING keys
if (pcIn->aScalingKeys.size() > 0) {
if (!pcIn->aScalingKeys.empty()) {
nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
::memcpy(nda->mScalingKeys, &pcIn->aScalingKeys[0],
@ -643,7 +640,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
}
// 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;
if (size == 0) {
@ -653,7 +650,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
pcOut->mChildren = new aiNode *[pcIn->mChildren.size()];
// Recursively process all children
for (unsigned int i = 0; i < size; ++i) {
pcOut->mChildren[i] = new aiNode();
pcOut->mChildren[i]->mParent = pcOut;
@ -686,7 +683,7 @@ void CountTracks(D3DS::Node *node, unsigned int &cnt) {
// Generate the output node graph
void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
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.
// generate a flat hiearachy which looks like this:
@ -708,7 +705,8 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Build dummy nodes for all meshes
unsigned int a = 0;
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->mMeshes = new unsigned int[1];
pcNode->mMeshes[0] = i;
@ -720,7 +718,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Build dummy nodes for all cameras
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;
// Build a name for the node
@ -729,7 +727,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Build dummy nodes for all lights
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;
// Build a name for the node
@ -745,7 +743,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Allocate a primary animation channel
pcOut->mNumAnimations = 1;
pcOut->mAnimations = new aiAnimation *[1];
aiAnimation *anim = pcOut->mAnimations[0] = new aiAnimation();
auto *anim = pcOut->mAnimations[0] = new aiAnimation();
anim->mName.Set("3DSMasterAnim");
@ -783,12 +781,12 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Convert all meshes in the scene and generate the final output scene.
void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
// Allocate enough storage for all output materials
pcOut->mNumMaterials = (unsigned int)mScene->mMaterials.size();
pcOut->mNumMaterials = static_cast<unsigned int>(mScene->mMaterials.size());
pcOut->mMaterials = new aiMaterial *[pcOut->mNumMaterials];
// ... and convert the 3DS materials to aiMaterial's
for (unsigned int i = 0; i < pcOut->mNumMaterials; ++i) {
aiMaterial *pcNew = new aiMaterial();
auto *pcNew = new aiMaterial();
ConvertMaterial(mScene->mMaterials[i], *pcNew);
pcOut->mMaterials[i] = pcNew;
}
@ -797,17 +795,17 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
ConvertMeshes(pcOut);
// Now copy all light sources to the output scene
pcOut->mNumLights = (unsigned int)mScene->mLights.size();
pcOut->mNumLights = static_cast<unsigned int>(mScene->mLights.size());
if (pcOut->mNumLights) {
pcOut->mLights = new aiLight *[pcOut->mNumLights];
::memcpy(pcOut->mLights, &mScene->mLights[0], sizeof(void *) * pcOut->mNumLights);
memcpy(pcOut->mLights, &mScene->mLights[0], sizeof(void *) * pcOut->mNumLights);
}
// Now copy all cameras to the output scene
pcOut->mNumCameras = (unsigned int)mScene->mCameras.size();
pcOut->mNumCameras = static_cast<unsigned int>(mScene->mCameras.size());
if (pcOut->mNumCameras) {
pcOut->mCameras = new aiCamera *[pcOut->mNumCameras];
::memcpy(pcOut->mCameras, &mScene->mCameras[0], sizeof(void *) * pcOut->mNumCameras);
memcpy(pcOut->mCameras, &mScene->mCameras[0], sizeof(void *) * pcOut->mNumCameras);
}
}

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -77,33 +76,33 @@ class ChunkWriter {
public:
ChunkWriter(StreamWriterLE &writer, uint16_t chunk_type) :
writer(writer) {
chunk_start_pos = writer.GetCurrentPos();
mWriter(writer) {
mChunkStartPos = writer.GetCurrentPos();
writer.PutU2(chunk_type);
writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET);
}
~ChunkWriter() {
std::size_t head_pos = writer.GetCurrentPos();
std::size_t head_pos = mWriter.GetCurrentPos();
ai_assert(head_pos > chunk_start_pos);
const std::size_t chunk_size = head_pos - chunk_start_pos;
ai_assert(head_pos > mChunkStartPos);
const std::size_t chunk_size = head_pos - mChunkStartPos;
writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
writer.PutU4(static_cast<uint32_t>(chunk_size));
writer.SetCurrentPos(head_pos);
mWriter.SetCurrentPos(mChunkStartPos + SIZE_OFFSET);
mWriter.PutU4(static_cast<uint32_t>(chunk_size));
mWriter.SetCurrentPos(head_pos);
}
private:
StreamWriterLE &writer;
std::size_t chunk_start_pos;
StreamWriterLE &mWriter;
std::size_t mChunkStartPos;
};
// Return an unique name for a given |mesh| attached to |node| that
// preserves the mesh's given name if it has one. |index| is the index
// of the mesh in |aiScene::mMeshes|.
std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) {
static const char underscore = '_';
static constexpr char underscore = '_';
char postfix[10] = { 0 };
ASSIMP_itoa10(postfix, index);
@ -123,8 +122,7 @@ std::string GetMaterialName(const aiMaterial &mat, unsigned int index) {
char postfix[10] = { 0 };
ASSIMP_itoa10(postfix, index);
aiString mat_name;
if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
if (aiString mat_name; AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
return mat_name.C_Str() + underscore + postfix;
}
@ -209,9 +207,6 @@ Discreet3DSExporter::Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, con
}
}
// ------------------------------------------------------------------------------------------------
Discreet3DSExporter::~Discreet3DSExporter() = default;
// ------------------------------------------------------------------------------------------------
int Discreet3DSExporter::WriteHierarchy(const aiNode &node, int seq, int sibling_level) {
// 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec
@ -307,8 +302,7 @@ void Discreet3DSExporter::WriteMaterials() {
WriteColor(color);
}
aiShadingMode shading_mode = aiShadingMode_Flat;
if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
if (aiShadingMode shading_mode = aiShadingMode_Flat; mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
Discreet3DS::shadetype3ds shading_mode_out;
@ -336,7 +330,7 @@ void Discreet3DSExporter::WriteMaterials() {
default:
shading_mode_out = Discreet3DS::Flat;
ai_assert(false);
};
}
writer.PutU2(static_cast<uint16_t>(shading_mode_out));
}
@ -350,8 +344,7 @@ void Discreet3DSExporter::WriteMaterials() {
WritePercentChunk(f);
}
int twosided;
if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
if (int twosided; mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
writer.PutI2(1);
}
@ -545,7 +538,7 @@ void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh &mesh) {
// ------------------------------------------------------------------------------------------------
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('\0');

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -63,10 +63,10 @@ namespace Assimp {
* @brief Helper class to export a given scene to a 3DS file.
*/
// ------------------------------------------------------------------------------------------------
class Discreet3DSExporter {
class Discreet3DSExporter final {
public:
Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, const aiScene* pScene);
~Discreet3DSExporter();
~Discreet3DSExporter() = default;
private:
void WriteMeshes();
@ -88,7 +88,6 @@ private:
using MeshesByNodeMap = std::multimap<const aiNode*, unsigned int>;
MeshesByNodeMap meshes;
};
} // Namespace Assimp

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -55,8 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/qnan.h>
#include <cstdio> //sprintf
namespace Assimp {
namespace D3DS {
namespace Assimp::D3DS {
#include <assimp/Compiler/pushpack1.h>
@ -580,7 +578,6 @@ struct Scene {
// Node* pcRootNode;
};
} // end of namespace D3DS
} // end of namespace Assimp
} // end of namespace Assimp::D3DS
#endif // AI_XFILEHELPER_H_INC

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -56,6 +56,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
using namespace D3DS;
static constexpr aiImporterDesc desc = {
"Discreet 3DS Importer",
"",
@ -75,7 +77,7 @@ static constexpr aiImporterDesc desc = {
// - computes its length
#define ASSIMP_3DS_BEGIN_CHUNK() \
while (true) { \
if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)) { \
if (mStream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)) { \
return; \
} \
Discreet3DS::Chunk chunk; \
@ -83,30 +85,30 @@ static constexpr aiImporterDesc desc = {
int chunkSize = chunk.Size - sizeof(Discreet3DS::Chunk); \
if (chunkSize <= 0) \
continue; \
const unsigned int oldReadLimit = stream->SetReadLimit( \
stream->GetCurrentPos() + chunkSize);
const unsigned int oldReadLimit = mStream->SetReadLimit( \
mStream->GetCurrentPos() + chunkSize);
// ------------------------------------------------------------------------------------------------
// End a parsing block
// Must follow at the end of each parsing block, reset chunk end marker to previous value
#define ASSIMP_3DS_END_CHUNK() \
stream->SkipToReadLimit(); \
stream->SetReadLimit(oldReadLimit); \
if (stream->GetRemainingSizeToLimit() == 0) \
mStream->SkipToReadLimit(); \
mStream->SetReadLimit(oldReadLimit); \
if (mStream->GetRemainingSizeToLimit() == 0) \
return; \
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
Discreet3DSImporter::Discreet3DSImporter() :
stream(), mLastNodeIndex(), mCurrentNode(), mRootNode(), mScene(), mMasterScale(), bHasBG(), bIsPrj() {
mStream(nullptr), mLastNodeIndex(), mCurrentNode(), mRootNode(), mScene(), mMasterScale(), bHasBG(), bIsPrj() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint16_t token[] = { 0x4d4d, 0x3dc2 /*, 0x3daa */ };
static constexpr uint16_t token[] = { 0x4d4d, 0x3dc2 /*, 0x3daa */ };
return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token), 0, sizeof token[0]);
}
@ -124,9 +126,7 @@ void Discreet3DSImporter::SetupProperties(const Importer * /*pImp*/) {
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void Discreet3DSImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) {
void Discreet3DSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
auto theFile = pIOHandler->Open(pFile, "rb");
if (!theFile) {
throw DeadlyImportError("3DS: Could not open ", pFile);
@ -138,14 +138,14 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
if (theStream.GetRemainingSize() < 16) {
throw DeadlyImportError("3DS file is either empty or corrupt: ", pFile);
}
this->stream = &theStream;
mStream = &theStream;
// Allocate our temporary 3DS representation
D3DS::Scene _scene;
Scene _scene;
mScene = &_scene;
// Initialize members
D3DS::Node _rootNode("UNNAMED");
Node _rootNode("UNNAMED");
mLastNodeIndex = -1;
mCurrentNode = &_rootNode;
mRootNode = mCurrentNode;
@ -166,12 +166,12 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
// vectors from the smoothing groups we read from the
// file.
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);
}
CheckIndices(mesh);
MakeUnique(mesh);
ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh);
ComputeNormalsWithSmoothingsGroups<Face>(mesh);
}
// 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(mScene);
AI_DEBUG_INVALIDATE_PTR(this->stream);
AI_DEBUG_INVALIDATE_PTR(mStream);
}
// ------------------------------------------------------------------------------------------------
// 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
if (!mMasterScale)
mMasterScale = 1.0f;
@ -223,14 +223,14 @@ void Discreet3DSImporter::ApplyMasterScale(aiScene *pScene) {
void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk *pcOut) {
ai_assert(pcOut != nullptr);
pcOut->Flag = stream->GetI2();
pcOut->Size = stream->GetI4();
pcOut->Flag = mStream->GetI2();
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");
}
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) {
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > mStream->GetRemainingSizeToLimit()) {
ASSIMP_LOG_ERROR("3DS: Chunk overflow");
}
}
@ -241,8 +241,7 @@ void Discreet3DSImporter::SkipChunk() {
Discreet3DS::Chunk psChunk;
ReadChunk(&psChunk);
stream->IncPtr(psChunk.Size - sizeof(Discreet3DS::Chunk));
return;
mStream->IncPtr(psChunk.Size - sizeof(Discreet3DS::Chunk));
}
// ------------------------------------------------------------------------------------------------
@ -259,7 +258,7 @@ void Discreet3DSImporter::ParseMainChunk() {
case Discreet3DS::CHUNK_MAIN:
ParseEditorChunk();
break;
};
}
ASSIMP_3DS_END_CHUNK();
#if defined(__clang__)
@ -275,30 +274,29 @@ void Discreet3DSImporter::ParseMainChunk() {
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseEditorChunk() {
ASSIMP_3DS_BEGIN_CHUNK();
ASSIMP_3DS_BEGIN_CHUNK()
// get chunk type
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;
// 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) {
case Discreet3DS::CHUNK_OBJBLOCK: {
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
while (stream->GetI1())
while (mStream->GetI1())
++cnt;
ParseChunk(sz, cnt);
} break;
@ -340,8 +338,8 @@ void Discreet3DSImporter::ParseObjectChunk() {
// Specifies the background image. The string should already be
// properly 0 terminated but we need to be sure
unsigned int cnt = 0;
const char *sz = (const char *)stream->GetPtr();
while (stream->GetI1())
auto *sz = (const char *)mStream->GetPtr();
while (mStream->GetI1())
++cnt;
mBackgroundImage = std::string(sz, cnt);
} break;
@ -352,7 +350,7 @@ void Discreet3DSImporter::ParseObjectChunk() {
case Discreet3DS::CHUNK_MASTER_SCALE:
// Scene master scaling factor
mMasterScale = stream->GetF4();
mMasterScale = mStream->GetF4();
break;
};
ASSIMP_3DS_END_CHUNK();
@ -379,15 +377,15 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
case Discreet3DS::CHUNK_LIGHT: {
// This starts a new light
aiLight *light = new aiLight();
auto *light = new aiLight();
mScene->mLights.push_back(light);
light->mName.Set(std::string(name, num));
// First read the position of the light
light->mPosition.x = stream->GetF4();
light->mPosition.y = stream->GetF4();
light->mPosition.z = stream->GetF4();
light->mPosition.x = mStream->GetF4();
light->mPosition.y = mStream->GetF4();
light->mPosition.z = mStream->GetF4();
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: {
// This starts a new camera
aiCamera *camera = new aiCamera();
auto *camera = new aiCamera();
mScene->mCameras.push_back(camera);
camera->mName.Set(std::string(name, num));
// First read the position of the camera
camera->mPosition.x = stream->GetF4();
camera->mPosition.y = stream->GetF4();
camera->mPosition.z = stream->GetF4();
camera->mPosition.x = mStream->GetF4();
camera->mPosition.y = mStream->GetF4();
camera->mPosition.z = mStream->GetF4();
// Then the camera target
camera->mLookAt.x = stream->GetF4() - camera->mPosition.x;
camera->mLookAt.y = stream->GetF4() - camera->mPosition.y;
camera->mLookAt.z = stream->GetF4() - camera->mPosition.z;
camera->mLookAt.x = mStream->GetF4() - camera->mPosition.x;
camera->mLookAt.y = mStream->GetF4() - camera->mPosition.y;
camera->mLookAt.z = mStream->GetF4() - camera->mPosition.z;
ai_real len = camera->mLookAt.Length();
if (len < 1e-5) {
@ -432,12 +430,12 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
camera->mLookAt /= len;
// 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);
camera->mUp = quat.GetMatrix() * aiVector3D(0.0, 1.0, 0.0);
// 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) {
camera->mHorizontalFOV = float(AI_DEG_TO_RAD(45.f));
}
@ -463,34 +461,34 @@ void Discreet3DSImporter::ParseLightChunk() {
light->mType = aiLightSource_SPOT;
// We wouldn't need to normalize here, but we do it
light->mDirection.x = stream->GetF4() - light->mPosition.x;
light->mDirection.y = stream->GetF4() - light->mPosition.y;
light->mDirection.z = stream->GetF4() - light->mPosition.z;
light->mDirection.x = mStream->GetF4() - light->mPosition.x;
light->mDirection.y = mStream->GetF4() - light->mPosition.y;
light->mDirection.z = mStream->GetF4() - light->mPosition.z;
light->mDirection.Normalize();
// 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
light->mAngleOuterCone = light->mAngleInnerCone + AI_DEG_TO_RAD(stream->GetF4());
light->mAngleOuterCone = light->mAngleInnerCone + AI_DEG_TO_RAD(mStream->GetF4());
break;
// intensity multiplier
case Discreet3DS::CHUNK_DL_MULTIPLIER:
light->mColorDiffuse = light->mColorDiffuse * stream->GetF4();
light->mColorDiffuse = light->mColorDiffuse * mStream->GetF4();
break;
// light color
case Discreet3DS::CHUNK_RGBF:
case Discreet3DS::CHUNK_LINRGBF:
light->mColorDiffuse.r *= stream->GetF4();
light->mColorDiffuse.g *= stream->GetF4();
light->mColorDiffuse.b *= stream->GetF4();
light->mColorDiffuse.r *= mStream->GetF4();
light->mColorDiffuse.g *= mStream->GetF4();
light->mColorDiffuse.b *= mStream->GetF4();
break;
// light attenuation
case Discreet3DS::CHUNK_DL_ATTENUATE:
light->mAttenuationLinear = stream->GetF4();
light->mAttenuationLinear = mStream->GetF4();
break;
};
@ -505,10 +503,10 @@ void Discreet3DSImporter::ParseCameraChunk() {
// get chunk type
switch (chunk.Flag) {
// near and far clip plane
case Discreet3DS::CHUNK_CAM_RANGES:
camera->mClipPlaneNear = stream->GetF4();
camera->mClipPlaneFar = stream->GetF4();
break;
case Discreet3DS::CHUNK_CAM_RANGES:
camera->mClipPlaneNear = mStream->GetF4();
camera->mClipPlaneFar = mStream->GetF4();
break;
}
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
D3DS::Node *FindNode(D3DS::Node *root, const std::string &name) {
Node *FindNode(Node *root, const std::string &name) {
if (root->mName == name) {
return root;
}
for (std::vector<D3DS::Node *>::iterator it = root->mChildren.begin(); it != root->mChildren.end(); ++it) {
D3DS::Node *nd = FindNode(*it, name);
if (nullptr != nd) {
for (auto it = root->mChildren.begin(); it != root->mChildren.end(); ++it) {
if (auto *nd = FindNode(*it, name); nullptr != nd) {
return nd;
}
}
@ -580,7 +577,7 @@ bool KeyUniqueCompare(const T &first, const T &second) {
// ------------------------------------------------------------------------------------------------
// Skip some additional import data.
void Discreet3DSImporter::SkipTCBInfo() {
unsigned int flags = stream->GetI2();
unsigned int flags = mStream->GetI2();
if (!flags) {
// Currently we can't do anything with these values. They occur
@ -591,19 +588,19 @@ void Discreet3DSImporter::SkipTCBInfo() {
}
if (flags & Discreet3DS::KEY_USE_TENS) {
stream->IncPtr(4);
mStream->IncPtr(4);
}
if (flags & Discreet3DS::KEY_USE_BIAS) {
stream->IncPtr(4);
mStream->IncPtr(4);
}
if (flags & Discreet3DS::KEY_USE_CONT) {
stream->IncPtr(4);
mStream->IncPtr(4);
}
if (flags & Discreet3DS::KEY_USE_EASE_FROM) {
stream->IncPtr(4);
mStream->IncPtr(4);
}
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
unsigned int cnt = 0;
const char *sz = (const char *)stream->GetPtr();
auto *sz = (const char *)mStream->GetPtr();
while (stream->GetI1())
while (mStream->GetI1())
++cnt;
std::string name = std::string(sz, cnt);
// Now find out whether we have this node already (target animation channels
// are stored with a separate object ID)
D3DS::Node *pcNode = FindNode(mRootNode, name);
Node *pcNode = FindNode(mRootNode, name);
int instanceNumber = 1;
if (pcNode) {
@ -646,10 +643,10 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
pcNode->mInstanceNumber = instanceNumber;
// There are two unknown values which we can safely ignore
stream->IncPtr(4);
mStream->IncPtr(4);
// Now read the hierarchy position of the object
uint16_t hierarchy = stream->GetI2() + 1;
uint16_t hierarchy = mStream->GetI2() + 1;
pcNode->mHierarchyPos = hierarchy;
pcNode->mHierarchyIndex = mLastNodeIndex;
@ -678,8 +675,8 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// This is the "real" name of a $$$DUMMY object
{
const char *sz = (const char *)stream->GetPtr();
while (stream->GetI1())
const char *sz = (const char *)mStream->GetPtr();
while (mStream->GetI1())
;
// 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
mCurrentNode->vPivot.x = stream->GetF4();
mCurrentNode->vPivot.y = stream->GetF4();
mCurrentNode->vPivot.z = stream->GetF4();
mCurrentNode->vPivot.x = mStream->GetF4();
mCurrentNode->vPivot.y = mStream->GetF4();
mCurrentNode->vPivot.z = mStream->GetF4();
break;
// ////////////////////////////////////////////////////////////////////
// POSITION KEYFRAME
case Discreet3DS::CHUNK_TRACKPOS: {
stream->IncPtr(10);
const unsigned int numFrames = stream->GetI4();
mStream->IncPtr(10);
const unsigned int numFrames = mStream->GetI4();
bool sortKeys = false;
// This could also be meant as the target position for
@ -720,16 +717,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
l->reserve(numFrames);
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
aiVectorKey v;
v.mTime = (double)fidx;
SkipTCBInfo();
v.mValue.x = stream->GetF4();
v.mValue.y = stream->GetF4();
v.mValue.z = stream->GetF4();
v.mValue.x = mStream->GetF4();
v.mValue.y = mStream->GetF4();
v.mValue.z = mStream->GetF4();
// check whether we'll need to sort the keys
if (!l->empty() && v.mTime <= l->back().mTime)
@ -759,11 +756,11 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
bool sortKeys = false;
std::vector<aiFloatKey> *l = &mCurrentNode->aCameraRollKeys;
stream->IncPtr(10);
const unsigned int numFrames = stream->GetI4();
mStream->IncPtr(10);
const unsigned int numFrames = mStream->GetI4();
l->reserve(numFrames);
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
aiFloatKey v;
@ -771,7 +768,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// This is just a single float
SkipTCBInfo();
v.mValue = stream->GetF4();
v.mValue = mStream->GetF4();
// Check whether we'll need to sort the keys
if (!l->empty() && v.mTime <= l->back().mTime)
@ -798,26 +795,26 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// ////////////////////////////////////////////////////////////////////
// ROTATION KEYFRAME
case Discreet3DS::CHUNK_TRACKROTATE: {
stream->IncPtr(10);
const unsigned int numFrames = stream->GetI4();
mStream->IncPtr(10);
const unsigned int numFrames = mStream->GetI4();
bool sortKeys = false;
std::vector<aiQuatKey> *l = &mCurrentNode->aRotationKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = stream->GetI4();
const unsigned int fidx = mStream->GetI4();
SkipTCBInfo();
aiQuatKey v;
v.mTime = (double)fidx;
// The rotation keyframe is given as an axis-angle pair
const float rad = stream->GetF4();
const float rad = mStream->GetF4();
aiVector3D axis;
axis.x = stream->GetF4();
axis.y = stream->GetF4();
axis.z = stream->GetF4();
axis.x = mStream->GetF4();
axis.y = mStream->GetF4();
axis.z = mStream->GetF4();
if (!axis.x && !axis.y && !axis.z)
axis.y = 1.f;
@ -842,16 +839,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// ////////////////////////////////////////////////////////////////////
// SCALING KEYFRAME
case Discreet3DS::CHUNK_TRACKSCALE: {
stream->IncPtr(10);
const unsigned int numFrames = stream->GetI2();
stream->IncPtr(2);
mStream->IncPtr(10);
const unsigned int numFrames = mStream->GetI2();
mStream->IncPtr(2);
bool sortKeys = false;
std::vector<aiVectorKey> *l = &mCurrentNode->aScalingKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = stream->GetI4();
const unsigned int fidx = mStream->GetI4();
SkipTCBInfo();
// Setup a new key
@ -859,9 +856,9 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
v.mTime = (double)fidx;
// ... and read its value
v.mValue.x = stream->GetF4();
v.mValue.y = stream->GetF4();
v.mValue.z = stream->GetF4();
v.mValue.x = mStream->GetF4();
v.mValue.y = mStream->GetF4();
v.mValue.z = mStream->GetF4();
// check whether we'll need to sort the keys
if (!l->empty() && v.mTime <= l->back().mTime)
@ -902,23 +899,23 @@ void Discreet3DSImporter::ParseFaceChunk() {
if (num > mMesh.mFaces.size()) {
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
(*i).iSmoothGroup = stream->GetI4();
i->iSmoothGroup = mStream->GetI4();
}
} break;
case Discreet3DS::CHUNK_FACEMAT: {
// at fist an asciiz with the material name
const char *sz = (const char *)stream->GetPtr();
while (stream->GetI1())
const char *sz = (const char *)mStream->GetPtr();
while (mStream->GetI1())
;
// find the index of the material
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.
if ((*i).mName.length() && !ASSIMP_stricmp(sz, (*i).mName.c_str())) {
if (i->mName.length() && !ASSIMP_stricmp(sz, i->mName.c_str())) {
idx = cnt;
break;
}
@ -928,9 +925,9 @@ void Discreet3DSImporter::ParseFaceChunk() {
}
// 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) {
unsigned int fidx = (uint16_t)stream->GetI2();
unsigned int fidx = (uint16_t)mStream->GetI2();
// check range
if (fidx >= mMesh.mFaceMaterials.size()) {
@ -955,59 +952,59 @@ void Discreet3DSImporter::ParseMeshChunk() {
switch (chunk.Flag) {
case Discreet3DS::CHUNK_VERTLIST: {
// 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);
while (num-- > 0) {
aiVector3D v;
v.x = stream->GetF4();
v.y = stream->GetF4();
v.z = stream->GetF4();
v.x = mStream->GetF4();
v.y = mStream->GetF4();
v.z = mStream->GetF4();
mMesh.mPositions.push_back(v);
}
} break;
case Discreet3DS::CHUNK_TRMATRIX: {
// This is the RLEATIVE transformation matrix of the current mesh. Vertices are
// pretransformed by this matrix wonder.
mMesh.mMat.a1 = stream->GetF4();
mMesh.mMat.b1 = stream->GetF4();
mMesh.mMat.c1 = stream->GetF4();
mMesh.mMat.a2 = stream->GetF4();
mMesh.mMat.b2 = stream->GetF4();
mMesh.mMat.c2 = stream->GetF4();
mMesh.mMat.a3 = stream->GetF4();
mMesh.mMat.b3 = stream->GetF4();
mMesh.mMat.c3 = stream->GetF4();
mMesh.mMat.a4 = stream->GetF4();
mMesh.mMat.b4 = stream->GetF4();
mMesh.mMat.c4 = stream->GetF4();
mMesh.mMat.a1 = mStream->GetF4();
mMesh.mMat.b1 = mStream->GetF4();
mMesh.mMat.c1 = mStream->GetF4();
mMesh.mMat.a2 = mStream->GetF4();
mMesh.mMat.b2 = mStream->GetF4();
mMesh.mMat.c2 = mStream->GetF4();
mMesh.mMat.a3 = mStream->GetF4();
mMesh.mMat.b3 = mStream->GetF4();
mMesh.mMat.c3 = mStream->GetF4();
mMesh.mMat.a4 = mStream->GetF4();
mMesh.mMat.b4 = mStream->GetF4();
mMesh.mMat.c4 = mStream->GetF4();
} break;
case Discreet3DS::CHUNK_MAPLIST: {
// 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);
while (num-- > 0) {
aiVector3D v;
v.x = stream->GetF4();
v.y = stream->GetF4();
v.x = mStream->GetF4();
v.y = mStream->GetF4();
mMesh.mTexCoords.push_back(v);
}
} break;
case Discreet3DS::CHUNK_FACELIST: {
// 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);
while (num-- > 0) {
// 3DS faces are ALWAYS triangles
mMesh.mFaces.emplace_back();
D3DS::Face &sFace = mMesh.mFaces.back();
Face &sFace = mMesh.mFaces.back();
sFace.mIndices[0] = (uint16_t)stream->GetI2();
sFace.mIndices[1] = (uint16_t)stream->GetI2();
sFace.mIndices[2] = (uint16_t)stream->GetI2();
sFace.mIndices[0] = (uint16_t)mStream->GetI2();
sFace.mIndices[1] = (uint16_t)mStream->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
@ -1015,7 +1012,7 @@ void Discreet3DSImporter::ParseMeshChunk() {
mMesh.mFaceMaterials.resize(mMesh.mFaces.size(), 0xcdcdcdcd);
// Larger 3DS files could have multiple FACE chunks here
chunkSize = (int)stream->GetRemainingSizeToLimit();
chunkSize = (int)mStream->GetRemainingSizeToLimit();
if (chunkSize > (int)sizeof(Discreet3DS::Chunk))
ParseFaceChunk();
} break;
@ -1032,9 +1029,9 @@ void Discreet3DSImporter::ParseMaterialChunk() {
{
// 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;
while (stream->GetI1())
while (mStream->GetI1())
++cnt;
if (!cnt) {
@ -1102,7 +1099,7 @@ void Discreet3DSImporter::ParseMaterialChunk() {
case Discreet3DS::CHUNK_MAT_SHADING:
// This is the material shading mode
mScene->mMaterials.back().mShading = (D3DS::Discreet3DS::shadetype3ds)stream->GetI2();
mScene->mMaterials.back().mShading = (Discreet3DS::shadetype3ds)mStream->GetI2();
break;
case Discreet3DS::CHUNK_MAT_TWO_SIDE:
@ -1178,31 +1175,31 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) {
switch (chunk.Flag) {
case Discreet3DS::CHUNK_MAPFILE: {
// 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;
while (stream->GetI1())
while (mStream->GetI1())
++cnt;
pcOut->mMapName = std::string(sz, cnt);
} break;
case Discreet3DS::CHUNK_PERCENTD:
// Manually parse the blend factor
pcOut->mTextureBlend = ai_real(stream->GetF8());
pcOut->mTextureBlend = ai_real(mStream->GetF8());
break;
case Discreet3DS::CHUNK_PERCENTF:
// Manually parse the blend factor
pcOut->mTextureBlend = stream->GetF4();
pcOut->mTextureBlend = mStream->GetF4();
break;
case Discreet3DS::CHUNK_PERCENTW:
// 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;
case Discreet3DS::CHUNK_MAT_MAP_USCALE:
// Texture coordinate scaling in the U direction
pcOut->mScaleU = stream->GetF4();
pcOut->mScaleU = mStream->GetF4();
if (0.0f == pcOut->mScaleU) {
ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1.");
pcOut->mScaleU = 1.0f;
@ -1210,7 +1207,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) {
break;
case Discreet3DS::CHUNK_MAT_MAP_VSCALE:
// Texture coordinate scaling in the V direction
pcOut->mScaleV = stream->GetF4();
pcOut->mScaleV = mStream->GetF4();
if (0.0f == pcOut->mScaleV) {
ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1.");
pcOut->mScaleV = 1.0f;
@ -1219,21 +1216,21 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) {
case Discreet3DS::CHUNK_MAT_MAP_UOFFSET:
// Texture coordinate offset in the U direction
pcOut->mOffsetU = -stream->GetF4();
pcOut->mOffsetU = -mStream->GetF4();
break;
case Discreet3DS::CHUNK_MAT_MAP_VOFFSET:
// Texture coordinate offset in the V direction
pcOut->mOffsetV = stream->GetF4();
pcOut->mOffsetV = mStream->GetF4();
break;
case Discreet3DS::CHUNK_MAT_MAP_ANG:
// Texture coordinate rotation, CCW in DEGREES
pcOut->mRotation = -AI_DEG_TO_RAD(stream->GetF4());
pcOut->mRotation = -AI_DEG_TO_RAD(mStream->GetF4());
break;
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)
if (iFlags & 0x2u)
@ -1258,9 +1255,11 @@ ai_real Discreet3DSImporter::ParsePercentageChunk() {
ReadChunk(&chunk);
if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) {
return stream->GetF4() * ai_real(100) / ai_real(0xFFFF);
} else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) {
return (ai_real)((uint16_t)stream->GetI2()) / (ai_real)0xFFFF;
return mStream->GetF4() * ai_real(100) / ai_real(0xFFFF);
}
if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) {
return (ai_real)((uint16_t)mStream->GetI2()) / (ai_real)0xFFFF;
}
return get_qnan();
@ -1291,9 +1290,9 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
*out = clrError;
return;
}
out->r = stream->GetF4();
out->g = stream->GetF4();
out->b = stream->GetF4();
out->r = mStream->GetF4();
out->g = mStream->GetF4();
out->b = mStream->GetF4();
break;
case Discreet3DS::CHUNK_LINRGBB:
@ -1305,15 +1304,15 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
return;
}
const ai_real invVal = ai_real(1.0) / ai_real(255.0);
out->r = (ai_real)(uint8_t)stream->GetI1() * invVal;
out->g = (ai_real)(uint8_t)stream->GetI1() * invVal;
out->b = (ai_real)(uint8_t)stream->GetI1() * invVal;
out->r = (ai_real)(uint8_t)mStream->GetI1() * invVal;
out->g = (ai_real)(uint8_t)mStream->GetI1() * invVal;
out->b = (ai_real)(uint8_t)mStream->GetI1() * invVal;
} break;
// Percentage chunks are accepted, too.
case Discreet3DS::CHUNK_PERCENTF:
if (acceptPercent && 4 <= diff) {
out->g = out->b = out->r = stream->GetF4();
out->g = out->b = out->r = mStream->GetF4();
break;
}
*out = clrError;
@ -1321,14 +1320,14 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
case Discreet3DS::CHUNK_PERCENTW:
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;
}
*out = clrError;
return;
default:
stream->IncPtr(diff);
mStream->IncPtr(diff);
// Skip unknown chunks, hope this won't cause any problems.
return ParseColorChunk(out, acceptPercent);
};

View file

@ -1,10 +1,8 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -51,20 +49,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h>
#include <assimp/types.h>
#include "3DSHelper.h"
#include <assimp/StreamReader.h>
struct aiNode;
namespace Assimp {
using namespace D3DS;
namespace Assimp {
// ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files
*/
class Discreet3DSImporter : public BaseImporter {
class Discreet3DSImporter final : public BaseImporter {
public:
Discreet3DSImporter();
~Discreet3DSImporter() override = default;
@ -101,15 +96,14 @@ protected:
// -------------------------------------------------------------------
/** Converts a temporary material to the outer representation
*/
void ConvertMaterial(D3DS::Material& p_cMat,
aiMaterial& p_pcOut);
void ConvertMaterial(D3DS::Material& p_cMat, aiMaterial& p_pcOut);
// -------------------------------------------------------------------
/** Read a 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
@ -119,13 +113,10 @@ protected:
ai_real ParsePercentageChunk();
// -------------------------------------------------------------------
/** Parse a color chunk. mCurrent will point to the next
* chunk behind afterwards. If no color chunk is found
* QNAN is returned in all members.
*/
void ParseColorChunk(aiColor3D* p_pcOut,
bool p_bAcceptPercent = true);
/** Parse a color chunk. mCurrent will point to the next chunk behind
* afterward. If no color chunk is found QNAN is returned in all members.
*/
void ParseColorChunk(aiColor3D* p_pcOut, bool p_bAcceptPercent = true);
// -------------------------------------------------------------------
/** Skip a chunk in the file
@ -133,7 +124,7 @@ protected:
void SkipChunk();
// -------------------------------------------------------------------
/** Generate the nodegraph
/** Generate the node-graph
*/
void GenerateNodeGraph(aiScene* pcOut);
@ -229,19 +220,19 @@ protected:
// -------------------------------------------------------------------
/** 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);
// -------------------------------------------------------------------
/** Search for a node in the graph.
* 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
*/
void ApplyMasterScale(aiScene* pScene);
void ApplyMasterScale(const aiScene* pScene);
// -------------------------------------------------------------------
/** Clamp all indices in the file to a valid range
@ -253,31 +244,26 @@ protected:
*/
void SkipTCBInfo();
protected:
/** Stream to read from */
StreamReaderLE* stream;
/** Last touched node index */
private:
/// Stream to read from
StreamReaderLE* mStream;
/// Last touched node index
short mLastNodeIndex;
/** Current node, root node */
D3DS::Node* mCurrentNode, *mRootNode;
/** Scene under construction */
/// Current node
D3DS::Node* mCurrentNode;
/// Root node
D3DS::Node *mRootNode;
/// Scene under construction
D3DS::Scene* mScene;
/** Ambient base color of the scene */
/// Ambient base color of the scene
aiColor3D mClrAmbient;
/** Master scaling factor of the scene */
/// Master scaling factor of the scene
ai_real mMasterScale;
/** Path to the background image of the scene */
/// Path to the background image of the scene
std::string mBackgroundImage;
/// true for has a background
bool bHasBG;
/** true if PRJ file */
/// true if PRJ file
bool bIsPrj;
};

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -49,8 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiMaterial;
struct aiMesh;
namespace Assimp {
namespace D3MF {
namespace Assimp:: D3MF {
enum class ResourceType {
RT_Object,
@ -65,8 +64,7 @@ class Resource {
public:
int mId;
Resource(int id) :
mId(id) {
explicit Resource(int id) : mId(id) {
// empty
}
@ -77,7 +75,7 @@ public:
}
};
class EmbeddedTexture : public Resource {
class EmbeddedTexture final : public Resource {
public:
std::string mPath;
std::string mContentType;
@ -85,12 +83,7 @@ public:
std::string mTilestyleV;
std::vector<char> mBuffer;
EmbeddedTexture(int id) :
Resource(id),
mPath(),
mContentType(),
mTilestyleU(),
mTilestyleV() {
explicit EmbeddedTexture(int id) : Resource(id) {
// empty
}
@ -101,13 +94,12 @@ public:
}
};
class Texture2DGroup : public Resource {
class Texture2DGroup final : public Resource {
public:
std::vector<aiVector2D> mTex2dCoords;
int mTexId;
Texture2DGroup(int id) :
Resource(id),
mTexId(-1) {
explicit Texture2DGroup(int id) : Resource(id), mTexId(-1) {
// empty
}
@ -118,11 +110,11 @@ public:
}
};
class ColorGroup : public Resource {
class ColorGroup final : public Resource {
public:
std::vector<aiColor4D> mColors;
ColorGroup(int id) :
Resource(id){
explicit ColorGroup(int id) : Resource(id) {
// empty
}
@ -133,13 +125,11 @@ public:
}
};
class BaseMaterials : public Resource {
class BaseMaterials final : public Resource {
public:
std::vector<unsigned int> mMaterialIndex;
BaseMaterials(int id) :
Resource(id),
mMaterialIndex() {
explicit BaseMaterials(int id) : Resource(id) {
// empty
}
@ -155,14 +145,14 @@ struct Component {
aiMatrix4x4 mTransformation;
};
class Object : public Resource {
class Object final : public Resource {
public:
std::vector<aiMesh *> mMeshes;
std::vector<unsigned int> mMeshIndex;
std::vector<Component> mComponents;
std::string mName;
Object(int id) :
explicit Object(int id) :
Resource(id),
mName(std::string("Object_") + ai_to_string(id)) {
// empty
@ -175,5 +165,4 @@ public:
}
};
} // namespace D3MF
} // namespace Assimp
} // namespace Assimp::D3MF

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -40,85 +40,80 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
namespace Assimp {
namespace D3MF {
namespace XmlTag {
namespace Assimp::D3MF::XmlTag {
// Root tag
const char* const RootTag = "3MF";
constexpr char RootTag[] = "3MF";
// Meta-data
const char* const meta = "metadata";
const char* const meta_name = "name";
constexpr char meta[] = "metadata";
constexpr char meta_name[] = "name";
// Model-data specific tags
const char* const model = "model";
const char* const model_unit = "unit";
const char* const metadata = "metadata";
const char* const resources = "resources";
const char* const object = "object";
const char* const mesh = "mesh";
const char* const components = "components";
const char* const component = "component";
const char* const vertices = "vertices";
const char* const vertex = "vertex";
const char* const triangles = "triangles";
const char* const triangle = "triangle";
const char* const x = "x";
const char* const y = "y";
const char* const z = "z";
const char* const v1 = "v1";
const char* const v2 = "v2";
const char* const v3 = "v3";
const char* const id = "id";
const char* const pid = "pid";
const char* const pindex = "pindex";
const char* const p1 = "p1";
const char *const p2 = "p2";
const char *const p3 = "p3";
const char* const name = "name";
const char* const type = "type";
const char* const build = "build";
const char* const item = "item";
const char* const objectid = "objectid";
const char* const transform = "transform";
const char *const path = "path";
constexpr char model[] = "model";
constexpr char model_unit[] = "unit";
constexpr char metadata[] = "metadata";
constexpr char resources[] = "resources";
constexpr char object[] = "object";
constexpr char mesh[] = "mesh";
constexpr char components[] = "components";
constexpr char component[] = "component";
constexpr char vertices[] = "vertices";
constexpr char vertex[] = "vertex";
constexpr char triangles[] = "triangles";
constexpr char triangle[] = "triangle";
constexpr char x[] = "x";
constexpr char y[] = "y";
constexpr char z[] = "z";
constexpr char v1[] = "v1";
constexpr char v2[] = "v2";
constexpr char v3[] = "v3";
constexpr char id[] = "id";
constexpr char pid[] = "pid";
constexpr char pindex[] = "pindex";
constexpr char p1[] = "p1";
constexpr char p2[] = "p2";
constexpr char p3[] = "p3";
constexpr char name[] = "name";
constexpr char type[] = "type";
constexpr char build[] = "build";
constexpr char item[] = "item";
constexpr char objectid[] = "objectid";
constexpr char transform[] = "transform";
constexpr char path[] = "path";
// Material definitions
const char* const basematerials = "basematerials";
const char* const basematerials_base = "base";
const char* const basematerials_name = "name";
const char* const basematerials_displaycolor = "displaycolor";
const char* const texture_2d = "m:texture2d";
const char *const texture_group = "m:texture2dgroup";
const char *const texture_content_type = "contenttype";
const char *const texture_tilestyleu = "tilestyleu";
const char *const texture_tilestylev = "tilestylev";
const char *const texture_2d_coord = "m:tex2coord";
const char *const texture_cuurd_u = "u";
const char *const texture_cuurd_v = "v";
constexpr char basematerials[] = "basematerials";
constexpr char basematerials_base[] = "base";
constexpr char basematerials_name[] = "name";
constexpr char basematerials_displaycolor[] = "displaycolor";
constexpr char texture_2d[] = "m:texture2d";
constexpr char texture_group[] = "m:texture2dgroup";
constexpr char texture_content_type[] = "contenttype";
constexpr char texture_tilestyleu[] = "tilestyleu";
constexpr char texture_tilestylev[] = "tilestylev";
constexpr char texture_2d_coord[] = "m:tex2coord";
constexpr char texture_cuurd_u[] = "u";
constexpr char texture_cuurd_v[] = "v";
// vertex color definitions
const char *const colorgroup = "m:colorgroup";
const char *const color_item = "m:color";
const char *const color_vaule = "color";
constexpr char colorgroup[] = "m:colorgroup";
constexpr char color_item[] = "m:color";
constexpr char color_value[] = "color";
// Meta info tags
const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
const char* const SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
const char* const SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
const char* const RELS_RELATIONSHIP_CONTAINER = "Relationships";
const char* const RELS_RELATIONSHIP_NODE = "Relationship";
const char* const RELS_ATTRIB_TARGET = "Target";
const char* const RELS_ATTRIB_TYPE = "Type";
const char* const RELS_ATTRIB_ID = "Id";
const char* const 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";
const char* const 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";
const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
}
constexpr char CONTENT_TYPES_ARCHIVE[] = "[Content_Types].xml";
constexpr char ROOT_RELATIONSHIPS_ARCHIVE[] = "_rels/.rels";
constexpr char SCHEMA_CONTENTTYPES[] = "http://schemas.openxmlformats.org/package/2006/content-types";
constexpr char SCHEMA_RELATIONSHIPS[] = "http://schemas.openxmlformats.org/package/2006/relationships";
constexpr char RELS_RELATIONSHIP_CONTAINER[] = "Relationships";
constexpr char RELS_RELATIONSHIP_NODE[] = "Relationship";
constexpr char RELS_ATTRIB_TARGET[] = "Target";
constexpr char RELS_ATTRIB_TYPE[] = "Type";
constexpr char RELS_ATTRIB_ID[] = "Id";
constexpr char PACKAGE_START_PART_RELATIONSHIP_TYPE[] = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
constexpr char PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE[] = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
constexpr char PACKAGE_TEXTURE_RELATIONSHIP_TYPE[] = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
constexpr char PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE[] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
constexpr char PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE[] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
} // Namespace D3MF
} // Namespace Assimp
} // namespace Assimp::D3MF

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -48,7 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include "3MFXmlTags.h"
@ -94,7 +93,7 @@ D3MFExporter::~D3MFExporter() {
mRelations.clear();
}
bool D3MFExporter::validate() {
bool D3MFExporter::validate() const {
if (mArchiveName.empty()) {
return false;
}

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -68,7 +68,7 @@ class D3MFExporter {
public:
D3MFExporter( const char* pFile, const aiScene* pScene );
~D3MFExporter();
bool validate();
bool validate() const;
bool exportArchive( const char *file );
bool exportContentTypes();
bool exportRelations();

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -85,7 +85,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
return false;
}
static const char *const ModelRef = "3D/3dmodel.model";
static constexpr char ModelRef[] = "3D/3dmodel.model";
ZipArchiveIOSystem archive(pIOHandler, filename);
if (!archive.Exists(ModelRef)) {
return false;
@ -107,7 +107,7 @@ void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene,
XmlParser xmlParser;
if (xmlParser.parse(opcPackage.RootStream())) {
XmlSerializer xmlSerializer(&xmlParser);
XmlSerializer xmlSerializer(xmlParser);
xmlSerializer.ImportXml(pScene);
const std::vector<aiTexture*> &tex = opcPackage.GetEmbeddedTextures();

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -53,7 +53,7 @@ namespace Assimp {
///
/// Implements the basic topology import and embedded textures.
// ---------------------------------------------------------------------------
class D3MFImporter : public BaseImporter {
class D3MFImporter final : public BaseImporter {
public:
/// @brief The default class constructor.
D3MFImporter() = default;

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -65,10 +65,9 @@ namespace D3MF {
using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
class OpcPackageRelationshipReader {
class OpcPackageRelationshipReader final {
public:
OpcPackageRelationshipReader(XmlParser &parser) :
mRelations() {
explicit OpcPackageRelationshipReader(XmlParser &parser) : mRelations() {
XmlNode root = parser.getRootNode();
ParseRootNode(root);
}

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -199,11 +199,11 @@ void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
} // namespace
XmlSerializer::XmlSerializer(XmlParser *xmlParser) :
XmlSerializer::XmlSerializer(XmlParser &xmlParser) :
mResourcesDictionnary(),
mMeshCount(0),
mXmlParser(xmlParser) {
ai_assert(nullptr != xmlParser);
// empty
}
XmlSerializer::~XmlSerializer() {
@ -218,7 +218,7 @@ void XmlSerializer::ImportXml(aiScene *scene) {
}
scene->mRootNode = new aiNode(XmlTag::RootTag);
XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
XmlNode node = mXmlParser.getRootNode().child(XmlTag::model);
if (node.empty()) {
return;
}
@ -680,7 +680,7 @@ void XmlSerializer::ReadColor(XmlNode &node, ColorGroup *colorGroup) {
for (XmlNode currentNode : node.children()) {
const std::string currentName = currentNode.name();
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;
if (parseColor(color, color_value)) {
colorGroup->mColors.push_back(color_value);

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -59,9 +59,10 @@ class Texture2DGroup;
class EmbeddedTexture;
class ColorGroup;
class XmlSerializer {
/// @brief his class implements ther 3mf serialization.
class XmlSerializer final {
public:
XmlSerializer(XmlParser *xmlParser);
explicit XmlSerializer(XmlParser &xmlParser);
~XmlSerializer();
void ImportXml(aiScene *scene);
@ -92,7 +93,7 @@ private:
std::vector<aiMaterial *> mMaterials;
std::map<unsigned int, Resource *> mResourcesDictionnary;
unsigned int mMeshCount;
XmlParser *mXmlParser;
XmlParser &mXmlParser;
};
} // namespace D3MF

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -75,6 +75,8 @@ static constexpr aiImporterDesc desc = {
"ac acc ac3d"
};
static constexpr auto ACDoubleSidedFlag = 0x20;
// ------------------------------------------------------------------------------------------------
// skip to the next token
inline const char *AcSkipToNextToken(const char *buffer, const char *end) {
@ -123,12 +125,36 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *end,
}
for (unsigned int _i = 0; _i < num; ++_i) {
buffer = AcSkipToNextToken(buffer, end);
buffer = fast_atoreal_move<float>(buffer, ((float *)out)[_i]);
buffer = fast_atoreal_move(buffer, ((float *)out)[_i]);
}
return buffer;
}
// ------------------------------------------------------------------------------------------------
// Reverses vertex indices in a face.
static void flipWindingOrder(aiFace &f) {
std::reverse(f.mIndices, f.mIndices + f.mNumIndices);
}
// ------------------------------------------------------------------------------------------------
// Duplicates a face and inverts it. Also duplicates all vertices (so the new face gets its own
// set of normals and isnt smoothed against the original).
static void buildBacksideOfFace(const aiFace &origFace, aiFace *&outFaces, aiVector3D *&outVertices, const aiVector3D *allVertices,
aiVector3D *&outUV, const aiVector3D *allUV, unsigned &curIdx) {
auto &newFace = *outFaces++;
newFace = origFace;
flipWindingOrder(newFace);
for (unsigned f = 0; f < newFace.mNumIndices; ++f) {
*outVertices++ = allVertices[newFace.mIndices[f]];
if (outUV) {
*outUV = allUV[newFace.mIndices[f]];
outUV++;
}
newFace.mIndices[f] = curIdx++;
}
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
AC3DImporter::AC3DImporter() :
@ -144,14 +170,10 @@ AC3DImporter::AC3DImporter() :
// nothing to be done here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
AC3DImporter::~AC3DImporter() = default;
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint32_t tokens[] = { AI_MAKE_MAGIC("AC3D") };
static constexpr uint32_t tokens[] = { AI_MAKE_MAGIC("AC3D") };
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
@ -171,8 +193,9 @@ bool AC3DImporter::GetNextLine() {
// ------------------------------------------------------------------------------------------------
// Parse an object section in an AC file
bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
if (!TokenMatch(mBuffer.data, "OBJECT", 6))
if (!TokenMatch(mBuffer.data, "OBJECT", 6)) {
return false;
}
SkipSpaces(&mBuffer.data, mBuffer.end);
@ -192,7 +215,6 @@ bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
light->mAttenuationConstant = 1.f;
// Generate a default name for both the light source and the node
// FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version.
light->mName.length = ::ai_snprintf(light->mName.data, AI_MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
obj.name = std::string(light->mName.data);
@ -202,8 +224,10 @@ bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
obj.type = Object::Group;
} else if (!ASSIMP_strincmp(mBuffer.data, "world", 5)) {
obj.type = Object::World;
} else
} else {
obj.type = Object::Poly;
}
while (GetNextLine()) {
if (TokenMatch(mBuffer.data, "kids", 4)) {
SkipSpaces(&mBuffer.data, mBuffer.end);
@ -344,6 +368,7 @@ bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
}
}
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: \'kids\' line was expected");
return false;
}
@ -452,6 +477,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
if ((*it).entries.empty()) {
ASSIMP_LOG_WARN("AC3D: surface has zero vertex references");
}
const bool isDoubleSided = ACDoubleSidedFlag == (it->flags & ACDoubleSidedFlag);
const int doubleSidedFactor = isDoubleSided ? 2 : 1;
// validate all vertex indices to make sure we won't crash here
for (it2 = (*it).entries.begin(),
@ -481,8 +508,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
// triangle strip
case Surface::TriangleStrip:
needMat[idx].first += (unsigned int)(*it).entries.size() - 2;
needMat[idx].second += ((unsigned int)(*it).entries.size() - 2) * 3;
needMat[idx].first += static_cast<unsigned int>(it->entries.size() - 2) * doubleSidedFactor;
needMat[idx].second += static_cast<unsigned int>(it->entries.size() - 2) * 3 * doubleSidedFactor;
break;
default:
@ -495,8 +522,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
case Surface::Polygon:
// the number of faces increments by one, the number
// of vertices by surface.numref.
needMat[idx].first++;
needMat[idx].second += (unsigned int)(*it).entries.size();
needMat[idx].first += doubleSidedFactor;
needMat[idx].second += static_cast<unsigned int>(it->entries.size()) * doubleSidedFactor;
};
}
unsigned int *pip = node->mMeshes = new unsigned int[node->mNumMeshes];
@ -546,6 +573,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
for (it = object.surfaces.begin(); it != end; ++it) {
if (mat == (*it).mat) {
const Surface &src = *it;
const bool isDoubleSided = ACDoubleSidedFlag == (src.flags & ACDoubleSidedFlag);
// closed polygon
uint8_t type = (*it).GetType();
@ -571,12 +599,18 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
++uv;
}
}
if(isDoubleSided) // Need a backface?
buildBacksideOfFace(faces[-1], faces, vertices, mesh->mVertices, uv, mesh->mTextureCoords[0], cur);
}
} else if (type == Surface::TriangleStrip) {
for (unsigned int i = 0; i < (unsigned int)src.entries.size() - 2; ++i) {
const Surface::SurfaceEntry &entry1 = src.entries[i];
const Surface::SurfaceEntry &entry2 = src.entries[i + 1];
const Surface::SurfaceEntry &entry3 = src.entries[i + 2];
const unsigned int verticesNeeded = isDoubleSided ? 6 : 3;
if (static_cast<unsigned>(vertices - mesh->mVertices) + verticesNeeded > mesh->mNumVertices) {
throw DeadlyImportError("AC3D: Invalid number of vertices");
}
aiFace &face = *faces++;
face.mNumIndices = 3;
@ -620,6 +654,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
uv->y = entry3.second.y;
++uv;
}
if(isDoubleSided) // Need a backface?
buildBacksideOfFace(faces[-1], faces, vertices, mesh->mVertices, uv, mesh->mTextureCoords[0], cur);
}
} else {
@ -629,6 +665,10 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
unsigned int tmp = (unsigned int)(*it).entries.size();
if (Surface::OpenLine == type) --tmp;
for (unsigned int m = 0; m < tmp; ++m) {
if (static_cast<unsigned>(vertices - mesh->mVertices) + 2 > mesh->mNumVertices) {
throw DeadlyImportError("AC3D: Invalid number of vertices");
}
aiFace &face = *faces++;
face.mNumIndices = 2;

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -60,10 +60,10 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** AC3D (*.ac) importer class
*/
class AC3DImporter : public BaseImporter {
class AC3DImporter final : public BaseImporter {
public:
AC3DImporter();
~AC3DImporter() override;
~AC3DImporter() override = default;
// Represents an AC3D material
struct Material {
@ -103,7 +103,7 @@ public:
unsigned int mat, flags;
typedef std::pair<unsigned int, aiVector2D> SurfaceEntry;
using SurfaceEntry = std::pair<unsigned int, aiVector2D>;
std::vector<SurfaceEntry> entries;
// Type is low nibble of flags

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -327,8 +327,7 @@ void AMFImporter::ParseNode_Root() {
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Constellation(XmlNode &node) {
std::string id;
id = node.attribute("id").as_string();
std::string id = node.attribute("id").as_string();
// create and if needed - define new grouping object.
AMFNodeElementBase *ne = new AMFConstellation(mNodeElement_Cur);
@ -474,7 +473,7 @@ void AMFImporter::ParseNode_Metadata(XmlNode &node) {
// read attribute
ne = new AMFMetadata(mNodeElement_Cur);
((AMFMetadata *)ne)->Type = type;
((AMFMetadata *)ne)->MetaType = type;
((AMFMetadata *)ne)->Value = value;
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -97,7 +97,7 @@ namespace Assimp {
/// new - <texmap> and children <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>
/// 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 MeshArray = std::vector<aiMesh *>;
using NodeArray = std::vector<aiNode *>;

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -202,7 +202,7 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
((AMFVolume *)ne)->MaterialID = node.attribute("materialid").as_string();
((AMFVolume *)ne)->Type = type;
((AMFVolume *)ne)->VolumeType = type;
// Check for child nodes
bool col_read = false;
if (!node.empty()) {

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -263,22 +263,22 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
const std::string &name = currentNode.name();
if (name == "utex1") {
read_flag[0] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[0].x);
XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[0].x);
} else if (name == "utex2") {
read_flag[1] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[1].x);
XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[1].x);
} else if (name == "utex3") {
read_flag[2] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[2].x);
XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[2].x);
} else if (name == "vtex1") {
read_flag[3] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[0].y);
XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[0].y);
} else if (name == "vtex2") {
read_flag[4] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[1].y);
XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[1].y);
} else if (name == "vtex3") {
read_flag[5] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[2].y);
XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[2].y);
}
}
ParseHelper_Node_Exit();

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -86,7 +86,8 @@ public:
AMFNodeElementBase *Parent; ///< Parent element. If nullptr then this node is root.
std::list<AMFNodeElementBase *> Child; ///< Child elements.
public: /// Destructor, virtual..
public:
/// Destructor, virtual..
virtual ~AMFNodeElementBase() = default;
/// Disabled copy constructor and co.
@ -97,25 +98,25 @@ public: /// Destructor, virtual..
protected:
/// In constructor inheritor must set element type.
/// \param [in] pType - element type.
/// \param [in] type - element type.
/// \param [in] pParent - parent element.
AMFNodeElementBase(const EType pType, AMFNodeElementBase *pParent) :
Type(pType), Parent(pParent) {
AMFNodeElementBase(EType type, AMFNodeElementBase *pParent) :
Type(type), Parent(pParent) {
// empty
}
}; // class IAMFImporter_NodeElement
/// A collection of objects or constellations with specific relative locations.
struct AMFConstellation : public AMFNodeElementBase {
struct AMFConstellation final : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFConstellation(AMFNodeElementBase *pParent) :
explicit AMFConstellation(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Constellation, pParent) {}
}; // struct CAMFImporter_NodeElement_Constellation
/// Part of constellation.
struct AMFInstance : public AMFNodeElementBase {
struct AMFInstance final : public AMFNodeElementBase {
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
@ -128,20 +129,22 @@ struct AMFInstance : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFInstance(AMFNodeElementBase *pParent) :
explicit AMFInstance(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Instance, pParent) {}
};
/// Structure that define metadata node.
struct AMFMetadata : public AMFNodeElementBase {
std::string Type; ///< Type of "Value".
std::string Value; ///< Value.
std::string MetaType; ///< Type of "Value".
std::string Value; ///< Value.
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFMetadata(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Metadata, pParent) {}
explicit AMFMetadata(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Metadata, pParent) {
// empty
}
};
/// Structure that define root node.
@ -152,8 +155,10 @@ struct AMFRoot : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFRoot(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Root, pParent) {}
explicit AMFRoot(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Root, pParent) {
// empty
}
};
/// Structure that define object node.
@ -165,7 +170,7 @@ struct AMFColor : public AMFNodeElementBase {
/// @brief Constructor.
/// @param [in] pParent - pointer to parent node.
AMFColor(AMFNodeElementBase *pParent) :
explicit AMFColor(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color() {
// empty
}
@ -173,64 +178,75 @@ struct AMFColor : public AMFNodeElementBase {
/// Structure that define material node.
struct AMFMaterial : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFMaterial(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Material, pParent) {}
explicit AMFMaterial(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Material, pParent) {
// empty
}
};
/// Structure that define object node.
struct AMFObject : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFObject(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Object, pParent) {}
explicit AMFObject(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Object, pParent) {
// empty
}
};
/// \struct CAMFImporter_NodeElement_Mesh
/// Structure that define mesh node.
struct AMFMesh : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFMesh(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Mesh, pParent) {}
explicit AMFMesh(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Mesh, pParent) {
// empty
}
};
/// Structure that define vertex node.
struct AMFVertex : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFVertex(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertex, pParent) {}
explicit AMFVertex(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertex, pParent) {
// empty
}
};
/// Structure that define edge node.
struct AMFEdge : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFEdge(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Edge, pParent) {}
explicit AMFEdge(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Edge, pParent) {
// empty
}
};
/// Structure that define vertices node.
struct AMFVertices : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFVertices(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertices, pParent) {}
explicit AMFVertices(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertices, pParent) {
// empty
}
};
/// Structure that define volume node.
struct AMFVolume : public AMFNodeElementBase {
std::string MaterialID; ///< Which material to use.
std::string Type; ///< What this volume describes can be "region" or "support". If none specified, "object" is assumed.
std::string VolumeType; ///< What this volume describes can be "region" or "support". If none specified, "object" is assumed.
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFVolume(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Volume, pParent) {}
explicit AMFVolume(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Volume, pParent) {
// empty
}
};
/// Structure that define coordinates node.
@ -239,8 +255,10 @@ struct AMFCoordinates : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFCoordinates(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Coordinates, pParent) {}
explicit AMFCoordinates(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Coordinates, pParent) {
// empty
}
};
/// Structure that define texture coordinates node.
@ -253,7 +271,7 @@ struct AMFTexMap : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFTexMap(AMFNodeElementBase *pParent) :
explicit AMFTexMap(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{} {
// empty
}
@ -265,7 +283,7 @@ struct AMFTriangle : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFTriangle(AMFNodeElementBase *pParent) :
explicit AMFTriangle(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Triangle, pParent) {
// empty
}
@ -279,7 +297,7 @@ struct AMFTexture : public AMFNodeElementBase {
/// Constructor.
/// \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) {
// empty
}

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -57,8 +57,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*pY*/, const float /*pZ*/) const {
aiColor4D tcol;
// Check if stored data are supported.
if (!Composition.empty()) {
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");
}
tcol = Color->Color;
aiColor4D tcol = Color->Color;
// Check if default color must be used
if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) {
@ -333,7 +331,7 @@ void AMFImporter::Postprocess_AddMetadata(const AMFMetaDataArray &metadataList,
size_t meta_idx(0);
for (const AMFMetadata *metadata : metadataList) {
sceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata->Type, aiString(metadata->Value));
sceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata->MetaType, aiString(metadata->Value));
}
}
@ -532,11 +530,9 @@ void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const st
col_arr.reserve(VertexCount_Max * 2);
{ // fill arrays
size_t vert_idx_from, vert_idx_to;
// first iteration.
vert_idx_to = 0;
vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr);
size_t vert_idx_to = 0;
size_t vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr);
vert_arr.push_back(pVertexCoordinateArray.at(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);

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -731,6 +731,10 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh &mesh) {
unsigned int iCurrent = 0, fi = 0;
for (std::vector<ASE::Face>::iterator i = mesh.mFaces.begin(); i != mesh.mFaces.end(); ++i, ++fi) {
for (unsigned int n = 0; n < 3; ++n, ++iCurrent) {
const uint32_t curIndex = (*i).mIndices[n];
if (curIndex >= mesh.mPositions.size()) {
throw DeadlyImportError("ASE: Invalid vertex index in face ", fi, ".");
}
mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]];
// add texture coordinates
@ -1266,5 +1270,4 @@ bool ASEImporter::GenerateNormals(ASE::Mesh &mesh) {
}
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
#endif // ASSIMP_BUILD_NO_ASE_IMPORTER

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -59,7 +59,7 @@ namespace Assimp {
/** Importer class for the 3DS ASE ASCII format.
*
*/
class ASEImporter : public BaseImporter {
class ASEImporter final : public BaseImporter {
public:
ASEImporter();
~ASEImporter() override = default;

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -1406,10 +1406,13 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes
if (TokenMatch(mFilePtr, "MESH_BONE_VERTEX", 16)) {
// read the vertex index
unsigned int iIndex = strtoul10(mFilePtr, &mFilePtr);
if (iIndex >= mesh.mPositions.size()) {
iIndex = (unsigned int)mesh.mPositions.size() - 1;
if (mesh.mBoneVertices.empty()) {
SkipSection();
}
if (iIndex >= mesh.mBoneVertices.size() ) {
LogWarning("Bone vertex index is out of bounds. Using the largest valid "
"bone vertex index instead");
iIndex = (unsigned int)mesh.mBoneVertices.size() - 1;
}
// --- ignored
@ -1424,7 +1427,7 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes
// then parse the vertex weight
if (!SkipSpaces(&mFilePtr, mEnd)) break;
mFilePtr = fast_atoreal_move<float>(mFilePtr, pairOut.second);
mFilePtr = fast_atoreal_move(mFilePtr, pairOut.second);
// -1 marks unused entries
if (-1 != pairOut.first) {
@ -1890,7 +1893,7 @@ void Parser::ParseLV4MeshReal(ai_real &fOut) {
return;
}
// parse the first float
mFilePtr = fast_atoreal_move<ai_real>(mFilePtr, fOut);
mFilePtr = fast_atoreal_move(mFilePtr, fOut);
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloat(float &fOut) {
@ -1903,7 +1906,7 @@ void Parser::ParseLV4MeshFloat(float &fOut) {
return;
}
// parse the first float
mFilePtr = fast_atoreal_move<float>(mFilePtr, fOut);
mFilePtr = fast_atoreal_move(mFilePtr, fOut);
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLong(unsigned int &iOut) {

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -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
#include "AssetLib/3DS/3DSLoader.h"
namespace Assimp {
namespace ASE {
namespace Assimp::ASE {
using namespace D3DS;
// ---------------------------------------------------------------------------
/** Helper structure representing an ASE material */
struct Material : public D3DS::Material {
struct Material final : D3DS::Material {
//! Default constructor has been deleted
Material() = delete;
@ -115,7 +114,7 @@ struct Material : public D3DS::Material {
return *this;
}
~Material() = default;
~Material() override = default;
//! Contains all sub materials of this material
std::vector<Material> avSubMaterials;
@ -373,8 +372,8 @@ struct Dummy : public BaseNode {
};
// Parameters to Parser::Parse()
#define AI_ASE_NEW_FILE_FORMAT 200
#define AI_ASE_OLD_FILE_FORMAT 110
static constexpr unsigned int AI_ASE_NEW_FILE_FORMAT = 200;
static constexpr unsigned int AI_ASE_OLD_FILE_FORMAT = 110;
// Internally we're a little bit more tolerant
#define AI_ASE_IS_NEW_FILE_FORMAT() (iFileFormat >= 200)
@ -668,8 +667,7 @@ public:
unsigned int iFileFormat;
};
} // Namespace ASE
} // namespace Assimp
} // Namespace Assimp::ASE
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -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
* chunk construction, even recursively.
*/
class AssbinChunkWriter : 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;
}
class AssbinChunkWriter final : public IOStream {
public:
AssbinChunkWriter(IOStream *container, uint32_t magic, size_t initial = 4096) :
buffer(nullptr),
@ -315,6 +293,28 @@ public:
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;
};
// ----------------------------------------------------------------------------------

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
// internal headers
#include "AssetLib/Assbin/AssbinLoader.h"
#include "AssbinLoader.h"
#include "Common/assbin_chunks.h"
#include <assimp/MemoryIOWrapper.h>
#include <assimp/anim.h>
@ -94,7 +94,7 @@ bool AssbinImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, boo
const size_t read = in->Read(s, sizeof(char), 32);
pIOHandler->Close(in);
if (read < 19) {
return false;
}
@ -149,11 +149,18 @@ aiQuaternion Read<aiQuaternion>(IOStream *stream) {
template <>
aiString Read<aiString>(IOStream *stream) {
aiString s;
stream->Read(&s.length, 4, 1);
if (s.length) {
stream->Read(s.data, s.length, 1);
uint32_t len;
if (stream->Read(&len, 4, 1) != 1) {
throw DeadlyImportError("ASSBIN: Unexpected EOF reading string length");
}
s.data[s.length] = 0;
if (len >= AI_MAXLEN) {
throw DeadlyImportError("ASSBIN: String length too large, potential buffer overflow attempt");
}
s.length = len;
if ((s.length > 0) && (stream->Read(s.data, s.length, 1) != 1)) {
throw DeadlyImportError("ASSBIN: Unexpected EOF reading string data");
}
s.data[s.length] = '\0';
return s;
}
@ -688,6 +695,7 @@ void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, I
unsigned int versionMajor = Read<unsigned int>(stream);
unsigned int versionMinor = Read<unsigned int>(stream);
if (versionMinor != ASSBIN_VERSION_MINOR || versionMajor != ASSBIN_VERSION_MAJOR) {
pIOHandler->Close(stream);
throw DeadlyImportError("Invalid version, data format not compatible!");
}
@ -697,8 +705,10 @@ void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, I
shortened = Read<uint16_t>(stream) > 0;
compressed = Read<uint16_t>(stream) > 0;
if (shortened)
if (shortened) {
pIOHandler->Close(stream);
throw DeadlyImportError("Shortened binaries are not supported!");
}
stream->Seek(256, aiOrigin_CUR); // original filename
stream->Seek(128, aiOrigin_CUR); // options

View file

@ -1,9 +1,8 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -61,7 +60,7 @@ struct aiCamera;
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
namespace Assimp {
namespace Assimp {
// ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
namespace Assimp {
namespace Assimp {
void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -36,7 +35,6 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
@ -79,8 +77,7 @@ static int ioprintf(IOStream *io, const char *format, ...) {
}
static const int Size = 4096;
char sz[Size];
::memset(sz, '\0', Size);
char sz[Size] = {};
va_list va;
va_start(va, format);
const unsigned int nSize = vsnprintf(sz, Size - 1, format, va);
@ -223,7 +220,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
const unsigned int majorVersion(aiGetVersionMajor());
const unsigned int minorVersion(aiGetVersionMinor());
const unsigned int rev(aiGetVersionRevision());
const char *curtime(asctime(p));
const char *curtime = asctime(p);
ioprintf(io, header.c_str(), majorVersion, minorVersion, rev, pFile, c.c_str(), curtime, scene->mFlags, 0u);
// write the node graph
@ -304,7 +301,11 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
bool compressed = (tex->mHeight == 0);
// 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 ? "true" : "false"));
@ -352,7 +353,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
for (unsigned int n = 0; n < mat->mNumProperties; ++n) {
const aiMaterialProperty *prop = mat->mProperties[n];
const char *sz = "";
auto sz = "";
if (prop->mType == aiPTI_Float) {
sz = "float";
} else if (prop->mType == aiPTI_Integer) {

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
// internal headers
#include "AssetLib/B3D/B3DImporter.h"
#include "B3DImporter.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include "PostProcessing/TextureTransform.h"
@ -469,9 +469,11 @@ void B3DImporter::ReadBONE(int id) {
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadKEYS(aiNodeAnim *nodeAnim) {
vector<aiVectorKey> trans, scale;
vector<aiQuatKey> rot;
void B3DImporter::ReadKEYS(AnimKeys& keys) {
vector<aiVectorKey>& trans = keys.positionKeys;
vector<aiVectorKey>& scale = keys.scalingKeys;
vector<aiQuatKey>& rot = keys.rotationKeys;
int flags = ReadInt();
while (ChunkSize()) {
int frame = ReadInt();
@ -485,21 +487,6 @@ void B3DImporter::ReadKEYS(aiNodeAnim *nodeAnim) {
rot.emplace_back(frame, ReadQuat());
}
}
if (flags & 1) {
nodeAnim->mNumPositionKeys = static_cast<unsigned int>(trans.size());
nodeAnim->mPositionKeys = to_array(trans);
}
if (flags & 2) {
nodeAnim->mNumScalingKeys = static_cast<unsigned int>(scale.size());
nodeAnim->mScalingKeys = to_array(scale);
}
if (flags & 4) {
nodeAnim->mNumRotationKeys = static_cast<unsigned int>(rot.size());
nodeAnim->mRotationKeys = to_array(rot);
}
}
// ------------------------------------------------------------------------------------------------
@ -542,6 +529,7 @@ aiNode *B3DImporter::ReadNODE(aiNode *parent) {
std::unique_ptr<aiNodeAnim> nodeAnim;
vector<unsigned> meshes;
vector<aiNode *> children;
AnimKeys keys;
while (ChunkSize()) {
const string chunk = ReadChunk();
@ -560,7 +548,7 @@ aiNode *B3DImporter::ReadNODE(aiNode *parent) {
nodeAnim.reset(new aiNodeAnim);
nodeAnim->mNodeName = node->mName;
}
ReadKEYS(nodeAnim.get());
ReadKEYS(keys);
} else if (chunk == "NODE") {
aiNode *child = ReadNODE(node);
children.push_back(child);
@ -569,6 +557,21 @@ aiNode *B3DImporter::ReadNODE(aiNode *parent) {
}
if (nodeAnim) {
if (!keys.positionKeys.empty()) {
nodeAnim->mNumPositionKeys = static_cast<unsigned int>(keys.positionKeys.size());
nodeAnim->mPositionKeys = to_array(keys.positionKeys);
}
if (!keys.scalingKeys.empty()) {
nodeAnim->mNumScalingKeys = static_cast<unsigned int>(keys.scalingKeys.size());
nodeAnim->mScalingKeys = to_array(keys.scalingKeys);
}
if (!keys.rotationKeys.empty()) {
nodeAnim->mNumRotationKeys = static_cast<unsigned int>(keys.rotationKeys.size());
nodeAnim->mRotationKeys = to_array(keys.rotationKeys);
}
_nodeAnims.emplace_back(std::move(nodeAnim));
}

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/types.h>
#include <assimp/mesh.h>
#include <assimp/material.h>
#include <assimp/anim.h>
#include <assimp/BaseImporter.h>
#include <memory>
@ -60,7 +61,7 @@ struct aiAnimation;
namespace Assimp{
class B3DImporter : public BaseImporter{
class B3DImporter final : public BaseImporter{
public:
B3DImporter() = default;
~B3DImporter() override;
@ -94,6 +95,12 @@ private:
float weights[4];
};
struct AnimKeys {
std::vector<aiVectorKey> positionKeys;
std::vector<aiVectorKey> scalingKeys;
std::vector<aiQuatKey> rotationKeys;
};
AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Fail(const std::string &str) AI_WONT_RETURN_SUFFIX;
@ -104,7 +111,7 @@ private:
void ReadTRIS( int v0 );
void ReadMESH();
void ReadBONE( int id );
void ReadKEYS( aiNodeAnim *nodeAnim );
void ReadKEYS( AnimKeys& keys );
void ReadANIM();
aiNode *ReadNODE( aiNode *parent );

View file

@ -4,9 +4,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -85,11 +83,9 @@ BVHLoader::BVHLoader() :
mLine(),
mAnimTickDuration(),
mAnimNumFrames(),
noSkeletonMesh() {}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
BVHLoader::~BVHLoader() = default;
noSkeletonMesh() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
@ -389,7 +385,7 @@ float BVHLoader::GetNextTokenAsFloat() {
// check if the float is valid by testing if the atof() function consumed every char of the token
const char *ctoken = token.c_str();
float result = 0.0f;
ctoken = fast_atoreal_move<float>(ctoken, result);
ctoken = fast_atoreal_move(ctoken, result);
if (ctoken != token.c_str() + token.length())
ThrowException("Expected a floating point number, but found \"", token, "\".");

View file

@ -4,8 +4,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -62,7 +61,7 @@ namespace Assimp {
* the hierarchy. It contains no actual mesh data, but we generate a dummy mesh
* 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 */
enum ChannelType {
@ -80,32 +79,27 @@ class BVHLoader : public BaseImporter {
std::vector<ChannelType> mChannels;
std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
Node() :
mNode(nullptr) {}
explicit Node(const aiNode *pNode) :
mNode(pNode) {}
Node() : mNode(nullptr) {}
explicit Node(const aiNode *pNode) :mNode(pNode) {}
};
public:
BVHLoader();
~BVHLoader();
~BVHLoader() override = default;
public:
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const;
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const override;
void SetupProperties(const Importer *pImp);
const aiImporterDesc *GetInfo() const;
void SetupProperties(const Importer *pImp) override;
const aiImporterDesc *GetInfo() const override;
protected:
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
protected:
/** Reads the file */
void ReadStructure(aiScene *pScene);

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -74,7 +74,9 @@ BlenderBMeshConverter::~BlenderBMeshConverter() {
// ------------------------------------------------------------------------------------------------
bool BlenderBMeshConverter::ContainsBMesh() const {
// TODO - Should probably do some additional verification here
if (BMesh == nullptr) {
return false;
}
return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
}

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -63,14 +63,12 @@ namespace Assimp
struct MLoop;
}
class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
class BlenderBMeshConverter final : public LogFunctions< BlenderBMeshConverter >
{
public:
BlenderBMeshConverter( const Blender::Mesh* mesh );
~BlenderBMeshConverter( );
bool ContainsBMesh( ) const;
explicit BlenderBMeshConverter( const Blender::Mesh* mesh );
~BlenderBMeshConverter();
bool ContainsBMesh() const;
const Blender::Mesh* TriangulateBMesh( );
private:

View file

@ -96,7 +96,7 @@ struct CustomDataTypeDescription {
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
* 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_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
} };
bool isValidCustomDataType(const int cdtype) {
return cdtype >= 0 && cdtype < CD_NUMTYPES;

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -56,14 +55,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// enable verbose log output. really verbose, so be careful.
#ifdef ASSIMP_BUILD_DEBUG
#define ASSIMP_BUILD_BLENDER_DEBUG
# define ASSIMP_BUILD_BLENDER_DEBUG
#endif
// 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.
// !!! please make sure this is set to 0 in the repo !!!
#ifndef ASSIMP_BUILD_BLENDER_DEBUG_DNA
#define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0
# define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0
#endif
// #define ASSIMP_BUILD_BLENDER_NO_STATS
@ -125,22 +124,14 @@ struct ElemBase {
* they used to point to.*/
// -------------------------------------------------------------------------------
struct Pointer {
Pointer() :
val() {
// empty
}
uint64_t val;
uint64_t val{0};
};
// -------------------------------------------------------------------------------
/** Represents a generic offset within a BLEND file */
// -------------------------------------------------------------------------------
struct FileOffset {
FileOffset() :
val() {
// empty
}
uint64_t val;
uint64_t val{0};
};
// -------------------------------------------------------------------------------
@ -205,7 +196,7 @@ enum ErrorPolicy {
};
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
#define ErrorPolicy_Igno ErrorPolicy_Warn
# define ErrorPolicy_Igno ErrorPolicy_Warn
#endif
// -------------------------------------------------------------------------------
@ -397,10 +388,9 @@ private:
mutable size_t cache_idx;
};
// --------------------------------------------------------
template <>
// -------------------------------------------------------------------------------------------------------
template<>
struct Structure::_defaultInitializer<ErrorPolicy_Warn> {
template <typename T>
void operator()(T &out, const char *reason = "<add reason>") {
ASSIMP_LOG_WARN(reason);
@ -410,9 +400,9 @@ struct Structure::_defaultInitializer<ErrorPolicy_Warn> {
}
};
template <>
// -------------------------------------------------------------------------------------------------------
template<>
struct Structure::_defaultInitializer<ErrorPolicy_Fail> {
template <typename T>
void operator()(T & /*out*/, const char *message = "") {
// obviously, it is crucial that _DefaultInitializer is used
@ -620,31 +610,23 @@ public:
/** Import statistics, i.e. number of file blocks read*/
// -------------------------------------------------------------------------------
class Statistics {
public:
Statistics() :
fields_read(), pointers_resolved(), cache_hits()
// , blocks_read ()
,
cached_objects() {}
Statistics() = default;
~Statistics() = default;
public:
/** total number of fields we read */
/// total number of fields we read
unsigned int fields_read;
/** total number of resolved pointers */
/// total number of resolved pointers
unsigned int pointers_resolved;
/** number of pointers resolved from the cache */
/// number of pointers resolved from the cache
unsigned int cache_hits;
/** number of blocks (from FileDatabase::entries)
we did actually read from. */
// unsigned int blocks_read;
/** objects in FileData::cache */
/// objects in FileData::cache
unsigned int cached_objects;
};
#endif
// -------------------------------------------------------------------------------
@ -657,15 +639,13 @@ public:
typedef std::map<Pointer, TOUT<ElemBase>> StructureCache;
public:
ObjectCache(const FileDatabase &db) :
db(db) {
explicit ObjectCache(const FileDatabase &db) : db(db) {
// currently there are only ~400 structure records per blend file.
// we read only a small part of them and don't cache objects
// which we don't need, so this should suffice.
caches.reserve(64);
}
public:
// --------------------------------------------------------
/** Check whether a specific item is in the cache.
* @param s Data type of the item
@ -673,10 +653,7 @@ public:
* cache doesn't know the item yet.
* @param ptr Item address to look for. */
template <typename T>
void get(
const Structure &s,
TOUT<T> &out,
const Pointer &ptr) const;
void get( const Structure &s,TOUT<T> &out, const Pointer &ptr) const;
// --------------------------------------------------------
/** Add an item to the cache after the item has
@ -701,7 +678,7 @@ private:
template <>
class ObjectCache<Blender::vector> {
public:
ObjectCache(const FileDatabase &) {}
explicit ObjectCache(const FileDatabase &) {}
template <typename T>
void get(const Structure &, vector<T> &, const Pointer &) {}
@ -710,7 +687,7 @@ public:
};
#ifdef _MSC_VER
#pragma warning(disable : 4355)
# pragma warning(disable : 4355)
#endif
// -------------------------------------------------------------------------------
@ -725,16 +702,6 @@ public:
FileDatabase() :
_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 {
return _stats;
}
@ -753,6 +720,15 @@ public:
return _cacheArrays;
}
public:
// publicly accessible fields
bool i64bit;
bool little;
DNA dna;
std::shared_ptr<StreamReaderAny> reader;
vector<FileBlockHead> entries;
private:
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
mutable Statistics _stats;
@ -765,20 +741,19 @@ private:
};
#ifdef _MSC_VER
#pragma warning(default : 4355)
# pragma warning(default : 4355)
#endif
// -------------------------------------------------------------------------------
/** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */
// -------------------------------------------------------------------------------
class DNAParser {
public:
/** Bind the parser to a empty DNA and an input stream */
DNAParser(FileDatabase &db) :
db(db) {}
explicit DNAParser(FileDatabase &db) : db(db) {
// empty
}
public:
// --------------------------------------------------------
/** Locate the DNA in the file and parse it. The input
* stream is expected to point to the beginning of the DN1
@ -789,7 +764,6 @@ public:
* afterwards.*/
void Parse();
public:
/** Obtain a reference to the extracted DNA information */
const Blender::DNA &GetDNA() const {
return db.dna;

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -841,5 +841,7 @@ template <template <typename> class TOUT> template <typename T> void ObjectCache
#endif
}
}}
}
}
#endif

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -117,7 +116,7 @@ namespace Blender {
mywrap arr;
};
#ifdef _MSC_VER
#if defined(_MSC_VER) && _MSC_VER < 1900
# pragma warning(disable:4351)
#endif
@ -172,7 +171,7 @@ namespace Blender {
// original file data
const FileDatabase& db;
};
#ifdef _MSC_VER
#if defined(_MSC_VER) && _MSC_VER < 1900
# pragma warning(default:4351)
#endif

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -108,7 +108,7 @@ BlenderImporter::~BlenderImporter() {
delete modifier_cache;
}
static const char Token[] = "BLENDER";
static constexpr char Token[] = "BLENDER";
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -105,7 +105,7 @@ class BlenderModifier;
* call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the
* conversion from intermediate format to aiScene. */
// -------------------------------------------------------------------------------------------
class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter> {
class BlenderImporter final : public BaseImporter, public LogFunctions<BlenderImporter> {
public:
BlenderImporter();
~BlenderImporter() override;

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -115,7 +114,7 @@ private:
* Mirror modifier. Status: implemented.
*/
// -------------------------------------------------------------------------------------------
class BlenderModifier_Mirror : public BlenderModifier {
class BlenderModifier_Mirror final : public BlenderModifier {
public:
// --------------------
virtual bool IsActive( const ModifierData& modin);
@ -132,7 +131,7 @@ public:
// -------------------------------------------------------------------------------------------
/** Subdivision modifier. Status: dummy. */
// -------------------------------------------------------------------------------------------
class BlenderModifier_Subdivision : public BlenderModifier {
class BlenderModifier_Subdivision final : public BlenderModifier {
public:
// --------------------

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -48,8 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h"
namespace Assimp {
namespace Blender {
namespace Assimp::Blender {
// Minor parts of this file are extracts from blender data structures,
// declared in the ./source/blender/makesdna directory.
@ -116,32 +114,32 @@ struct Collection;
static const size_t MaxNameLen = 1024;
// -------------------------------------------------------------------------------
struct ID : ElemBase {
struct ID final : ElemBase {
char name[MaxNameLen] WARN;
short flag;
};
// -------------------------------------------------------------------------------
struct ListBase : ElemBase {
struct ListBase final : ElemBase {
std::shared_ptr<ElemBase> first;
std::weak_ptr<ElemBase> last;
};
// -------------------------------------------------------------------------------
struct PackedFile : ElemBase {
struct PackedFile final : ElemBase {
int size WARN;
int seek WARN;
std::shared_ptr<FileOffset> data WARN;
};
// -------------------------------------------------------------------------------
struct GroupObject : ElemBase {
struct GroupObject final : ElemBase {
std::shared_ptr<GroupObject> prev, next FAIL;
std::shared_ptr<Object> ob;
};
// -------------------------------------------------------------------------------
struct Group : ElemBase {
struct Group final : ElemBase {
ID id FAIL;
int layer;
@ -149,32 +147,32 @@ struct Group : ElemBase {
};
// -------------------------------------------------------------------------------
struct CollectionObject : ElemBase {
struct CollectionObject final : ElemBase {
//CollectionObject* prev;
std::shared_ptr<CollectionObject> next;
Object *ob;
};
// -------------------------------------------------------------------------------
struct CollectionChild : ElemBase {
struct CollectionChild final : ElemBase {
std::shared_ptr<CollectionChild> next, prev;
std::shared_ptr<Collection> collection;
};
// -------------------------------------------------------------------------------
struct Collection : ElemBase {
struct Collection final : ElemBase {
ID id FAIL;
ListBase gobject; // CollectionObject
ListBase children; // CollectionChild
};
// -------------------------------------------------------------------------------
struct World : ElemBase {
struct World final : ElemBase {
ID id FAIL;
};
// -------------------------------------------------------------------------------
struct MVert : ElemBase {
struct MVert final : ElemBase {
float co[3] FAIL;
float no[3] FAIL; // read as short and divided through / 32767.f
char flag;
@ -186,31 +184,31 @@ struct MVert : ElemBase {
};
// -------------------------------------------------------------------------------
struct MEdge : ElemBase {
struct MEdge final : ElemBase {
int v1, v2 FAIL;
char crease, bweight;
short flag;
};
// -------------------------------------------------------------------------------
struct MLoop : ElemBase {
struct MLoop final : ElemBase {
int v, e;
};
// -------------------------------------------------------------------------------
struct MLoopUV : ElemBase {
struct MLoopUV final : ElemBase {
float uv[2];
int flag;
};
// -------------------------------------------------------------------------------
// Note that red and blue are not swapped, as with MCol
struct MLoopCol : ElemBase {
struct MLoopCol final : ElemBase {
unsigned char r, g, b, a;
};
// -------------------------------------------------------------------------------
struct MPoly : ElemBase {
struct MPoly final : ElemBase {
int loopstart;
int totloop;
short mat_nr;
@ -218,26 +216,26 @@ struct MPoly : ElemBase {
};
// -------------------------------------------------------------------------------
struct MTexPoly : ElemBase {
struct MTexPoly final : ElemBase {
Image *tpage;
char flag, transp;
short mode, tile, pad;
};
// -------------------------------------------------------------------------------
struct MCol : ElemBase {
struct MCol final : ElemBase {
char r, g, b, a FAIL;
};
// -------------------------------------------------------------------------------
struct MFace : ElemBase {
struct MFace final : ElemBase {
int v1, v2, v3, v4 FAIL;
int mat_nr FAIL;
char flag;
};
// -------------------------------------------------------------------------------
struct TFace : ElemBase {
struct TFace final : ElemBase {
float uv[4][2] FAIL;
int col[4] FAIL;
char flag;
@ -247,7 +245,7 @@ struct TFace : ElemBase {
};
// -------------------------------------------------------------------------------
struct MTFace : ElemBase {
struct MTFace final : ElemBase {
MTFace() :
flag(0),
mode(0),
@ -265,24 +263,24 @@ struct MTFace : ElemBase {
};
// -------------------------------------------------------------------------------
struct MDeformWeight : ElemBase {
struct MDeformWeight final : ElemBase {
int def_nr FAIL;
float weight FAIL;
};
// -------------------------------------------------------------------------------
struct MDeformVert : ElemBase {
struct MDeformVert final : ElemBase {
vector<MDeformWeight> dw WARN;
int totweight;
};
// -------------------------------------------------------------------------------
#define MA_RAYMIRROR 0x40000
#define MA_TRANSPARENCY 0x10000
#define MA_RAYTRANSP 0x20000
#define MA_ZTRANSP 0x00040
constexpr uint32_t MA_RAYMIRROR = 0x40000;
constexpr uint32_t MA_TRANSPARENCY = 0x10000;
constexpr uint32_t MA_RAYTRANSP = 0x20000;
constexpr uint32_t MA_ZTRANSP = 0x00040;
struct Material : ElemBase {
struct Material final : ElemBase {
ID id FAIL;
float r, g, b WARN;
@ -404,7 +402,7 @@ CustomDataLayer 104
char name 32 64
void *data 96 8
*/
struct CustomDataLayer : ElemBase {
struct CustomDataLayer final : ElemBase {
int type;
int offset;
int flag;
@ -442,7 +440,7 @@ CustomData 208
BLI_mempool *pool 192 8
CustomDataExternal *external 200 8
*/
struct CustomData : ElemBase {
struct CustomData final : ElemBase {
vector<std::shared_ptr<struct CustomDataLayer>> layers;
int typemap[42]; // CD_NUMTYPES
int totlayer;
@ -455,7 +453,7 @@ struct CustomData : ElemBase {
};
// -------------------------------------------------------------------------------
struct Mesh : ElemBase {
struct Mesh final : ElemBase {
ID id FAIL;
int totface FAIL;
@ -492,7 +490,7 @@ struct Mesh : ElemBase {
};
// -------------------------------------------------------------------------------
struct Library : ElemBase {
struct Library final : ElemBase {
ID id FAIL;
char name[240] WARN;
@ -516,7 +514,7 @@ struct Camera : ElemBase {
};
// -------------------------------------------------------------------------------
struct Lamp : ElemBase {
struct Lamp final : ElemBase {
enum FalloffType {
FalloffType_Constant = 0x0,
@ -603,7 +601,7 @@ struct Lamp : ElemBase {
};
// -------------------------------------------------------------------------------
struct ModifierData : ElemBase {
struct ModifierData final : ElemBase {
enum ModifierType {
eModifierType_None = 0,
eModifierType_Subsurf,
@ -653,9 +651,8 @@ struct SharedModifierData : ElemBase {
ModifierData modifier;
};
// -------------------------------------------------------------------------------
struct SubsurfModifierData : SharedModifierData {
struct SubsurfModifierData final : SharedModifierData {
enum Type {
@ -675,7 +672,7 @@ struct SubsurfModifierData : SharedModifierData {
};
// -------------------------------------------------------------------------------
struct MirrorModifierData : SharedModifierData {
struct MirrorModifierData final : SharedModifierData {
enum Flags {
Flags_CLIPPING = 1 << 0,
@ -693,7 +690,7 @@ struct MirrorModifierData : SharedModifierData {
};
// -------------------------------------------------------------------------------
struct Object : ElemBase {
struct Object final : ElemBase {
ID id FAIL;
enum Type {
@ -734,7 +731,7 @@ struct Object : ElemBase {
};
// -------------------------------------------------------------------------------
struct Base : ElemBase {
struct Base final : ElemBase {
Base *prev WARN;
std::shared_ptr<Base> next WARN;
std::shared_ptr<Object> object WARN;
@ -746,7 +743,7 @@ struct Base : ElemBase {
};
// -------------------------------------------------------------------------------
struct Scene : ElemBase {
struct Scene final : ElemBase {
ID id FAIL;
std::shared_ptr<Object> camera WARN;
@ -760,7 +757,7 @@ struct Scene : ElemBase {
};
// -------------------------------------------------------------------------------
struct Image : ElemBase {
struct Image final : ElemBase {
ID id FAIL;
char name[240] WARN;
@ -790,7 +787,7 @@ struct Image : ElemBase {
};
// -------------------------------------------------------------------------------
struct Tex : ElemBase {
struct Tex final : ElemBase {
// actually, the only texture type we support is Type_IMAGE
enum Type {
@ -875,14 +872,13 @@ struct Tex : ElemBase {
//char use_nodes;
Tex() :
imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS) {
Tex() : imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS) {
// empty
}
};
// -------------------------------------------------------------------------------
struct MTex : ElemBase {
struct MTex final : ElemBase {
enum Projection {
Proj_N = 0,
@ -971,6 +967,6 @@ struct MTex : ElemBase {
MTex() = default;
};
} // namespace Blender
} // namespace Assimp
} // namespace Assimp::Blender
#endif

View file

@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h"
#include "BlenderScene.h"
namespace Assimp {
namespace Assimp {
namespace Blender {
template <> void Structure :: Convert<Object> (

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -381,7 +381,14 @@ inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& poi
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Winvalid-offsetof"
#endif // __clang__
#if defined __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Winvalid-offsetof"
#endif // __GNUC__
unsigned int pointOffset = offsetof( PointP2T, point2D );
#if defined __GNUC__
# pragma GCC diagnostic pop
#endif // __GNUC__
#if defined __clang__
# pragma clang diagnostic pop
#endif

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2021, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -64,7 +64,7 @@ namespace {
aiString aiStringFrom(cineware::String const & cinestring) {
aiString result;
cinestring.GetCString(result.data, MAXLEN-1);
cinestring.GetCString(result.data, AI_MAXLEN - 1);
result.length = static_cast<ai_uint32>(cinestring.GetLength());
return result;
}
@ -86,7 +86,7 @@ namespace Assimp {
}
}
static const aiImporterDesc desc = {
static constexpr aiImporterDesc desc = {
"Cinema4D Importer",
"",
"",
@ -99,13 +99,6 @@ static const aiImporterDesc desc = {
"c4d"
};
// ------------------------------------------------------------------------------------------------
C4DImporter::C4DImporter() = default;
// ------------------------------------------------------------------------------------------------
C4DImporter::~C4DImporter() = default;
// ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
const std::string& extension = GetExtension(pFile);
@ -196,7 +189,6 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
std::copy(materials.begin(), materials.end(), pScene->mMaterials);
}
// ------------------------------------------------------------------------------------------------
bool C4DImporter::ReadShader(aiMaterial* out, BaseShader* shader) {
// based on Cineware sample code (C4DImportExport.cpp)

View file

@ -63,7 +63,7 @@ namespace cineware {
class BaseShader;
}
namespace Assimp {
namespace Assimp {
// TinyFormatter.h
namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter;
@ -78,8 +78,8 @@ namespace Assimp {
// -------------------------------------------------------------------------------------------
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
public:
C4DImporter();
~C4DImporter() override;
C4DImporter() = default;
~C4DImporter() override = default;
bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override;
protected:

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -45,8 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
#include "AssetLib/COB/COBLoader.h"
#include "AssetLib/COB/COBScene.h"
#include "COBLoader.h"
#include "COBScene.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include <assimp/LineSplitter.h>
@ -62,6 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
namespace Assimp {
using namespace Assimp::COB;
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);
}
// ------------------------------------------------------------------------------------------------
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.
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));
// check header
char head[32];
stream->CopyAndAdvance(head, 32);
if (strncmp(head, "Caligari ", 9) != 0) {
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");
}
static constexpr size_t HeaderSize = 32u;
char head[HeaderSize] = {};
stream->CopyAndAdvance(head, HeaderSize);
// load data into intermediate structures
if (head[15] == 'A') {
if (!isValidASCIIHeader(head)) {
ThrowException("Invalid ASCII file header");
}
ReadAsciiFile(scene, stream.get());
} else {
ReadBinaryFile(scene, stream.get());
@ -228,7 +244,7 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
const Mesh &ndmesh = (const Mesh &)(root);
if (ndmesh.vertex_positions.size() && ndmesh.texture_coords.size()) {
typedef std::pair<const unsigned int, Mesh::FaceRefList> Entry;
using Entry = std::pair<const unsigned int, Mesh::FaceRefList>;
for (const Entry &reflist : ndmesh.temp_map) {
{ // create mesh
size_t n = 0;
@ -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");
}
}
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_COB_IMPORTER

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -73,7 +72,7 @@ namespace COB {
*
* Currently relatively limited, loads only ASCII files and needs more test coverage. */
// -------------------------------------------------------------------------------------------
class COBImporter : public BaseImporter {
class COBImporter final : public BaseImporter {
public:
COBImporter() = default;
~COBImporter() override = default;
@ -82,6 +81,10 @@ public:
bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
bool checkSig) const override;
// -------------------------------------------------------------------
/** Prepend 'COB: ' and throw msg.*/
AI_WONT_RETURN static void ThrowException(const std::string &msg) AI_WONT_RETURN_SUFFIX;
protected:
// --------------------
const aiImporterDesc *GetInfo() const override;
@ -94,10 +97,6 @@ protected:
IOSystem *pIOHandler) override;
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
* @param out Receives output data.
@ -149,4 +148,5 @@ private:
}; // !class COBImporter
} // end of namespace Assimp
#endif // AI_UNREALIMPORTER_H_INC

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -52,68 +52,66 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <deque>
#include <map>
namespace Assimp {
namespace COB {
namespace Assimp::COB {
// ------------------
/** Represents a single vertex index in a face */
struct VertexIndex
{
struct VertexIndex {
// intentionally uninitialized
unsigned int pos_idx,uv_idx;
};
// ------------------
/** COB Face data structure */
struct Face
{
struct Face {
// intentionally uninitialized
unsigned int material, flags;
unsigned int material;
unsigned int flags;
std::vector<VertexIndex> indices;
};
// ------------------
/** COB chunk header information */
const unsigned int NO_SIZE = UINT_MAX;
constexpr unsigned int NO_SIZE = UINT_MAX;
struct ChunkInfo
{
ChunkInfo ()
: id (0)
, parent_id (0)
, version (0)
, size (NO_SIZE)
{}
struct ChunkInfo {
ChunkInfo() = default;
virtual ~ChunkInfo() = default;
// Id of this chunk, unique within file
unsigned int id;
unsigned int id{ 0 };
// and the corresponding parent
unsigned int parent_id;
unsigned int parent_id{ 0 };
// version. v1.23 becomes 123
unsigned int version;
unsigned int version{ 0 };
// chunk size in bytes, only relevant for binary files
// NO_SIZE is also valid.
unsigned int size;
unsigned int size{NO_SIZE};
};
// ------------------
/** A node in the scenegraph */
struct Node : public ChunkInfo
{
struct Node : ChunkInfo {
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(Type type) : type(type), unit_scale(1.f){}
~Node() override = default;
explicit Node(Type type) : type(type), unit_scale(1.f){}
Type type;
// used during resolving
typedef std::deque<const Node*> ChildList;
using ChildList = std::deque<const Node*> ;
mutable ChildList temp_children;
// unique name
@ -128,8 +126,7 @@ struct Node : public ChunkInfo
// ------------------
/** COB Mesh data structure */
struct Mesh : public Node
{
struct Mesh final : Node {
using ChunkInfo::operator=;
enum DrawFlags {
SOLID = 0x1,
@ -162,107 +159,118 @@ struct Mesh : public Node
// ------------------
/** COB Group data structure */
struct Group : public Node
{
struct Group final : Node {
using ChunkInfo::operator=;
Group() : Node(TYPE_GROUP) {}
Group() : Node(TYPE_GROUP) {
// empty
}
};
// ------------------
/** COB Bone data structure */
struct Bone : public Node
{
struct Bone final : Node {
using ChunkInfo::operator=;
Bone() : Node(TYPE_BONE) {}
Bone() : Node(TYPE_BONE) {
// empty
}
};
// ------------------
/** COB Light data structure */
struct Light : public Node
{
struct Light final : Node {
enum LightType {
SPOT,LOCAL,INFINITE
SPOT,
LOCAL,
INFINITE
};
using ChunkInfo::operator=;
Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {}
Light() : Node(TYPE_LIGHT), ltype() {
// empty
}
aiColor3D color;
float angle,inner_angle;
float angle{ 0.0f };
float inner_angle{ 0.0f };
LightType ltype;
LightType ltype{SPOT};
};
// ------------------
/** COB Camera data structure */
struct Camera : public Node
{
struct Camera final : Node {
using ChunkInfo::operator=;
Camera() : Node(TYPE_CAMERA) {}
Camera() : Node(TYPE_CAMERA) {
// empty
}
};
// ------------------
/** COB Texture data structure */
struct Texture
{
struct Texture {
std::string path;
aiUVTransform transform;
};
// ------------------
/** COB Material data structure */
struct Material : ChunkInfo
{
struct Material : ChunkInfo {
using ChunkInfo::operator=;
enum Shader {
FLAT,PHONG,METAL
FLAT,
PHONG,
METAL
};
enum AutoFacet {
FACETED,AUTOFACETED,SMOOTH
FACETED,
AUTOFACETED,
SMOOTH
};
Material() : alpha(),exp(),ior(),ka(),ks(1.f),
matnum(UINT_MAX),
shader(FLAT),autofacet(FACETED),
autofacet_angle()
{}
Material() : shader(FLAT) {
// empty
}
std::string type;
aiColor3D rgb;
float alpha, exp, ior,ka,ks;
unsigned int matnum;
float alpha{ 0.0f };
float exp{ 0.0f };
float ior{ 0.0f };
float ka{ 0.0f };
float ks{ 1.0f };
unsigned int matnum{ UINT_MAX };
Shader shader;
AutoFacet autofacet;
float autofacet_angle;
AutoFacet autofacet{FACETED};
float autofacet_angle{ 0.0f };
std::shared_ptr<Texture> tex_env,tex_bump,tex_color;
};
// ------------------
/** Embedded bitmap, for instance for the thumbnail image */
struct Bitmap : ChunkInfo
{
Bitmap() : orig_size() {}
struct BitmapHeader
{
struct Bitmap : ChunkInfo {
Bitmap() = default;
struct BitmapHeader {
// empty
};
BitmapHeader head;
size_t orig_size;
size_t orig_size{ 0u };
std::vector<char> buff_zipped;
};
typedef std::deque< std::shared_ptr<Node> > NodeList;
typedef std::vector< Material > MaterialList;
using NodeList = std::deque< std::shared_ptr<Node>>;
using MaterialList = std::vector< Material >;
// ------------------
/** Represents a master COB scene, even if we loaded just a single COB file */
struct Scene
{
struct Scene {
NodeList nodes;
MaterialList materials;
@ -270,7 +278,6 @@ struct Scene
Bitmap thumbnail;
};
} // end COB
} // end Assimp
} // end Assimp::COB
#endif
#endif // INCLUDED_AI_COB_SCENE_H

View file

@ -3,9 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -73,10 +71,9 @@ static constexpr aiImporterDesc desc = {
"csm"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
CSMImporter::CSMImporter() : noSkeletonMesh(){
CSMImporter::CSMImporter() : noSkeletonMesh() {
// empty
}
@ -102,8 +99,7 @@ void CSMImporter::SetupProperties(const Importer* pImp) {
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void CSMImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
aiScene* pScene, IOSystem* pIOHandler) {
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
// Check whether we can read from the file
@ -122,23 +118,24 @@ void CSMImporter::InternReadFile( const std::string& pFile,
// now process the file and look out for '$' sections
while (true) {
SkipSpaces(&buffer, end);
if ('\0' == *buffer)
if ('\0' == *buffer) {
break;
}
if ('$' == *buffer) {
if ('$' == *buffer) {
++buffer;
if (TokenMatchI(buffer,"firstframe",10)) {
if (TokenMatchI(buffer,"firstframe",10)) {
SkipSpaces(&buffer, end);
first = strtol10(buffer,&buffer);
}
else if (TokenMatchI(buffer,"lastframe",9)) {
else if (TokenMatchI(buffer,"lastframe",9)) {
SkipSpaces(&buffer, end);
last = strtol10(buffer,&buffer);
}
else if (TokenMatchI(buffer,"rate",4)) {
SkipSpaces(&buffer, end);
float d = { 0.0f };
buffer = fast_atoreal_move<float>(buffer,d);
buffer = fast_atoreal_move(buffer,d);
anim->mTicksPerSecond = d;
}
else if (TokenMatchI(buffer,"order",5)) {
@ -153,8 +150,9 @@ void CSMImporter::InternReadFile( const std::string& pFile,
anims_temp.push_back(new aiNodeAnim());
aiNodeAnim* nda = anims_temp.back();
char* ot = nda->mNodeName.data;
while (!IsSpaceOrNewLine(*buffer)) {
char *ot = nda->mNodeName.data;
const char *ot_end = nda->mNodeName.data + AI_MAXLEN;
while (!IsSpaceOrNewLine(*buffer) && buffer != end && ot != ot_end) {
*ot++ = *buffer++;
}
@ -178,9 +176,17 @@ void CSMImporter::InternReadFile( const std::string& pFile,
// If we know how many frames we'll read, we can preallocate some storage
unsigned int alloc = 100;
if (last != 0x00ffffff) {
// re-init if the file has last frame data
alloc = last-first;
alloc += alloc>>2u; // + 25%
for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
if (anim->mChannels[i]->mPositionKeys != nullptr) delete[] anim->mChannels[i]->mPositionKeys;
anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
}
} else {
// default init
for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
if (anim->mChannels[i]->mPositionKeys != nullptr) continue;
anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
}
}
@ -204,7 +210,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
if (s->mNumPositionKeys == alloc) {
// need to reallocate?
aiVectorKey* old = s->mPositionKeys;
s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
s->mPositionKeys = new aiVectorKey[alloc*2];
::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
delete[] old;
}
@ -220,17 +226,17 @@ void CSMImporter::InternReadFile( const std::string& pFile,
} else {
aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
sub->mTime = (double)frame;
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
buffer = fast_atoreal_move(buffer, sub->mValue.x);
if (!SkipSpacesAndLineEnd(&buffer, end)) {
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample y coord");
}
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
buffer = fast_atoreal_move(buffer, sub->mValue.y);
if (!SkipSpacesAndLineEnd(&buffer, end)) {
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample z coord");
}
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
buffer = fast_atoreal_move(buffer, sub->mValue.z);
++s->mNumPositionKeys;
}
@ -273,7 +279,13 @@ void CSMImporter::InternReadFile( const std::string& pFile,
nd->mName = anim->mChannels[i]->mNodeName;
nd->mParent = pScene->mRootNode;
aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
if (na->mPositionKeys != nullptr && na->mNumPositionKeys > 0) {
aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
} else {
// Use identity matrix if no valid position data is available
nd->mTransformation = aiMatrix4x4();
DefaultLogger::get()->warn("CSM: No position keys available for node - using identity transformation");
}
}
// Store the one and only animation in the scene

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -58,7 +58,7 @@ namespace Assimp {
* Link to file format specification:
* <max_8_dvd>\samples\Motion\Docs\CSM.rtf
*/
class CSMImporter : public BaseImporter {
class CSMImporter final : public BaseImporter {
public:
CSMImporter();
~CSMImporter() override = default;

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -36,7 +35,6 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
@ -64,6 +62,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
static const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) {
std::set<const aiNode *> topParentBoneNodes;
if (mesh && mesh->mNumBones > 0) {
for (unsigned int i = 0; i < mesh->mNumBones; ++i) {
aiBone *bone = mesh->mBones[i];
const aiNode *node = scene->mRootNode->findBoneNode(bone);
if (node) {
while (node->mParent && scene->findBone(node->mParent->mName) != nullptr) {
node = node->mParent;
}
topParentBoneNodes.insert(node);
}
}
}
if (!topParentBoneNodes.empty()) {
const aiNode *parentBoneNode = *topParentBoneNodes.begin();
if (topParentBoneNodes.size() == 1) {
return parentBoneNode;
} else {
for (auto it : topParentBoneNodes) {
if (it->mParent) return it->mParent;
}
return parentBoneNode;
}
}
return nullptr;
}
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
void ExportSceneCollada(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties * /*pProperties*/) {
@ -152,10 +181,6 @@ ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, con
WriteFile();
}
// ------------------------------------------------------------------------------------------------
// Destructor
ColladaExporter::~ColladaExporter() = default;
// ------------------------------------------------------------------------------------------------
// Starts writing the contents
void ColladaExporter::WriteFile() {
@ -331,60 +356,68 @@ void ColladaExporter::WriteHeader() {
// ------------------------------------------------------------------------------------------------
// Write the embedded textures
void ColladaExporter::WriteTextures() {
static const unsigned int buffer_size = 1024;
char str[buffer_size];
static constexpr unsigned int buffer_size = 1024;
char str[buffer_size] = {'\0'};
if (mScene->HasTextures()) {
for (unsigned int i = 0; i < mScene->mNumTextures; i++) {
// It would be great to be able to create a directory in portable standard C++, but it's not the case,
// so we just write the textures in the current directory.
if (!mScene->HasTextures()) {
return;
}
aiTexture *texture = mScene->mTextures[i];
if (nullptr == texture) {
continue;
}
for (unsigned int i = 0; i < mScene->mNumTextures; i++) {
// It would be great to be able to create a directory in portable standard C++, but it's not the case,
// so we just write the textures in the current directory.
ASSIMP_itoa10(str, buffer_size, i + 1);
std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char *)texture->achFormatHint);
std::unique_ptr<IOStream> outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb"));
if (outfile == nullptr) {
throw DeadlyExportError("could not open output texture file: " + mPath + name);
}
if (texture->mHeight == 0) {
outfile->Write((void *)texture->pcData, texture->mWidth, 1);
} else {
Bitmap::Save(texture, outfile.get());
}
outfile->Flush();
textures.insert(std::make_pair(i, name));
aiTexture *texture = mScene->mTextures[i];
if (nullptr == texture) {
continue;
}
ASSIMP_itoa10(str, buffer_size, i + 1);
std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char *)texture->achFormatHint);
std::unique_ptr<IOStream> outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb"));
if (outfile == nullptr) {
throw DeadlyExportError("could not open output texture file: " + mPath + name);
}
if (texture->mHeight == 0) {
outfile->Write((void *)texture->pcData, texture->mWidth, 1);
} else {
Bitmap::Save(texture, outfile.get());
}
outfile->Flush();
textures.insert(std::make_pair(i, name));
}
}
// ------------------------------------------------------------------------------------------------
// Write the embedded textures
void ColladaExporter::WriteCamerasLibrary() {
if (mScene->HasCameras()) {
mOutput << startstr << "<library_cameras>" << endstr;
PushTag();
for (size_t a = 0; a < mScene->mNumCameras; ++a)
WriteCamera(a);
PopTag();
mOutput << startstr << "</library_cameras>" << endstr;
if (!mScene->HasCameras()) {
return;
}
mOutput << startstr << "<library_cameras>" << endstr;
PushTag();
for (size_t a = 0; a < mScene->mNumCameras; ++a) {
WriteCamera(a);
}
PopTag();
mOutput << startstr << "</library_cameras>" << endstr;
}
void ColladaExporter::WriteCamera(size_t pIndex) {
const aiCamera *cam = mScene->mCameras[pIndex];
if (cam == nullptr) {
return;
}
const std::string cameraId = GetObjectUniqueId(AiObjectType::Camera, pIndex);
const std::string cameraName = GetObjectName(AiObjectType::Camera, pIndex);
@ -422,22 +455,27 @@ void ColladaExporter::WriteCamera(size_t pIndex) {
// ------------------------------------------------------------------------------------------------
// Write the embedded textures
void ColladaExporter::WriteLightsLibrary() {
if (mScene->HasLights()) {
mOutput << startstr << "<library_lights>" << endstr;
PushTag();
for (size_t a = 0; a < mScene->mNumLights; ++a)
WriteLight(a);
PopTag();
mOutput << startstr << "</library_lights>" << endstr;
if (!mScene->HasLights()) {
return;
}
mOutput << startstr << "<library_lights>" << endstr;
PushTag();
for (size_t a = 0; a < mScene->mNumLights; ++a) {
WriteLight(a);
}
PopTag();
mOutput << startstr << "</library_lights>" << endstr;
}
void ColladaExporter::WriteLight(size_t pIndex) {
const aiLight *light = mScene->mLights[pIndex];
if (light == nullptr) {
return;
}
const std::string lightId = GetObjectUniqueId(AiObjectType::Light, pIndex);
const std::string lightName = GetObjectName(AiObjectType::Light, pIndex);
@ -462,6 +500,7 @@ void ColladaExporter::WriteLight(size_t pIndex) {
case aiLightSource_AREA:
case aiLightSource_UNDEFINED:
case _aiLightSource_Force32Bit:
default:
break;
}
PopTag();
@ -521,10 +560,6 @@ void ColladaExporter::WriteSpotLight(const aiLight *const light) {
mOutput << startstr << "<quadratic_attenuation>"
<< light->mAttenuationQuadratic
<< "</quadratic_attenuation>" << endstr;
/*
out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
srcLight->mFalloffAngle);
*/
const ai_real fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone);
mOutput << startstr << "<falloff_angle sid=\"fall_off_angle\">"
@ -559,41 +594,43 @@ void ColladaExporter::WriteAmbientLight(const aiLight *const light) {
// ------------------------------------------------------------------------------------------------
// Reads a single surface entry from the given material keys
bool ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial &pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex) {
if (pSrcMat.GetTextureCount(pTexture) > 0) {
aiString texfile;
unsigned int uvChannel = 0;
pSrcMat.GetTexture(pTexture, 0, &texfile, nullptr, &uvChannel);
std::string index_str(texfile.C_Str());
if (index_str.size() != 0 && index_str[0] == '*') {
unsigned int index;
index_str = index_str.substr(1, std::string::npos);
try {
index = (unsigned int)strtoul10_64<DeadlyExportError>(index_str.c_str());
} catch (std::exception &error) {
throw DeadlyExportError(error.what());
}
std::map<unsigned int, std::string>::const_iterator name = textures.find(index);
if (name != textures.end()) {
poSurface.texture = name->second;
} else {
throw DeadlyExportError("could not find embedded texture at index " + index_str);
}
} else {
poSurface.texture = texfile.C_Str();
}
poSurface.channel = uvChannel;
poSurface.exist = true;
} else {
if (pSrcMat.GetTextureCount(pTexture) == 0) {
if (pKey)
poSurface.exist = pSrcMat.Get(pKey, static_cast<unsigned int>(pType), static_cast<unsigned int>(pIndex), poSurface.color) == aiReturn_SUCCESS;
return poSurface.exist;
}
aiString texfile;
unsigned int uvChannel = 0;
pSrcMat.GetTexture(pTexture, 0, &texfile, nullptr, &uvChannel);
std::string index_str(texfile.C_Str());
if (index_str.size() != 0 && index_str[0] == '*') {
unsigned int index;
index_str = index_str.substr(1, std::string::npos);
try {
index = (unsigned int)strtoul10_64<DeadlyExportError>(index_str.c_str());
} catch (std::exception &error) {
throw DeadlyExportError(error.what());
}
std::map<unsigned int, std::string>::const_iterator name = textures.find(index);
if (name != textures.end()) {
poSurface.texture = name->second;
} else {
throw DeadlyExportError("could not find embedded texture at index " + index_str);
}
} else {
poSurface.texture = texfile.C_Str();
}
poSurface.channel = uvChannel;
poSurface.exist = true;
return poSurface.exist;
}
@ -606,79 +643,87 @@ static bool isalnum_C(char c) {
// ------------------------------------------------------------------------------------------------
// Writes an image entry for the given surface
void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string &imageId) {
if (!pSurface.texture.empty()) {
mOutput << startstr << "<image id=\"" << imageId << "\">" << endstr;
PushTag();
mOutput << startstr << "<init_from>";
// URL encode image file name first, then XML encode on top
std::stringstream imageUrlEncoded;
for (std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it) {
if (isalnum_C((unsigned char)*it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\')
imageUrlEncoded << *it;
else
imageUrlEncoded << '%' << std::hex << size_t((unsigned char)*it) << std::dec;
}
mOutput << XMLEscape(imageUrlEncoded.str());
mOutput << "</init_from>" << endstr;
PopTag();
mOutput << startstr << "</image>" << endstr;
if (pSurface.texture.empty()) {
return;
}
mOutput << startstr << "<image id=\"" << imageId << "\">" << endstr;
PushTag();
mOutput << startstr << "<init_from>";
// URL encode image file name first, then XML encode on top
std::stringstream imageUrlEncoded;
for (std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it) {
if (isalnum_C((unsigned char)*it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\')
imageUrlEncoded << *it;
else
imageUrlEncoded << '%' << std::hex << size_t((unsigned char)*it) << std::dec;
}
mOutput << XMLEscape(imageUrlEncoded.str());
mOutput << "</init_from>" << endstr;
PopTag();
mOutput << startstr << "</image>" << endstr;
}
// ------------------------------------------------------------------------------------------------
// Writes a color-or-texture entry into an effect definition
void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &imageId) {
if (pSurface.exist) {
mOutput << startstr << "<" << pTypeName << ">" << endstr;
PushTag();
if (pSurface.texture.empty()) {
mOutput << startstr << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "</color>" << endstr;
} else {
mOutput << startstr << "<texture texture=\"" << imageId << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
}
PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr;
if (!pSurface.exist) {
return;
}
mOutput << startstr << "<" << pTypeName << ">" << endstr;
PushTag();
if (pSurface.texture.empty()) {
mOutput << startstr << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "</color>" << endstr;
} else {
mOutput << startstr << "<texture texture=\"" << imageId << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
}
PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr;
}
// ------------------------------------------------------------------------------------------------
// Writes the two parameters necessary for referencing a texture in an effect entry
void ColladaExporter::WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &materialId) {
// if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
if (!pSurface.texture.empty()) {
mOutput << startstr << "<newparam sid=\"" << materialId << "-" << pTypeName << "-surface\">" << endstr;
PushTag();
mOutput << startstr << "<surface type=\"2D\">" << endstr;
PushTag();
mOutput << startstr << "<init_from>" << materialId << "-" << pTypeName << "-image</init_from>" << endstr;
PopTag();
mOutput << startstr << "</surface>" << endstr;
PopTag();
mOutput << startstr << "</newparam>" << endstr;
mOutput << startstr << "<newparam sid=\"" << materialId << "-" << pTypeName << "-sampler\">" << endstr;
PushTag();
mOutput << startstr << "<sampler2D>" << endstr;
PushTag();
mOutput << startstr << "<source>" << materialId << "-" << pTypeName << "-surface</source>" << endstr;
PopTag();
mOutput << startstr << "</sampler2D>" << endstr;
PopTag();
mOutput << startstr << "</newparam>" << endstr;
if (pSurface.texture.empty()) {
return;
}
mOutput << startstr << "<newparam sid=\"" << materialId << "-" << pTypeName << "-surface\">" << endstr;
PushTag();
mOutput << startstr << "<surface type=\"2D\">" << endstr;
PushTag();
mOutput << startstr << "<init_from>" << materialId << "-" << pTypeName << "-image</init_from>" << endstr;
PopTag();
mOutput << startstr << "</surface>" << endstr;
PopTag();
mOutput << startstr << "</newparam>" << endstr;
mOutput << startstr << "<newparam sid=\"" << materialId << "-" << pTypeName << "-sampler\">" << endstr;
PushTag();
mOutput << startstr << "<sampler2D>" << endstr;
PushTag();
mOutput << startstr << "<source>" << materialId << "-" << pTypeName << "-surface</source>" << endstr;
PopTag();
mOutput << startstr << "</sampler2D>" << endstr;
PopTag();
mOutput << startstr << "</newparam>" << endstr;
}
// ------------------------------------------------------------------------------------------------
// Writes a scalar property
void ColladaExporter::WriteFloatEntry(const Property &pProperty, const std::string &pTypeName) {
if (pProperty.exist) {
mOutput << startstr << "<" << pTypeName << ">" << endstr;
PushTag();
mOutput << startstr << "<float sid=\"" << pTypeName << "\">" << pProperty.value << "</float>" << endstr;
PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr;
if (!pProperty.exist) {
return;
}
mOutput << startstr << "<" << pTypeName << ">" << endstr;
PushTag();
mOutput << startstr << "<float sid=\"" << pTypeName << "\">" << pProperty.value << "</float>" << endstr;
PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr;
}
// ------------------------------------------------------------------------------------------------
@ -832,8 +877,9 @@ void ColladaExporter::WriteControllerLibrary() {
void ColladaExporter::WriteController(size_t pIndex) {
const aiMesh *mesh = mScene->mMeshes[pIndex];
// Is there a skin controller?
if (mesh->mNumBones == 0 || mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
if (mesh->mNumBones == 0 || mesh->mNumFaces == 0 || mesh->mNumVertices == 0) {
return;
}
const std::string idstr = GetObjectUniqueId(AiObjectType::Mesh, pIndex);
const std::string namestr = GetObjectName(AiObjectType::Mesh, pIndex);
@ -864,8 +910,9 @@ void ColladaExporter::WriteController(size_t pIndex) {
mOutput << startstr << "<Name_array id=\"" << idstr << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\">";
for (size_t i = 0; i < mesh->mNumBones; ++i)
for (size_t i = 0; i < mesh->mNumBones; ++i) {
mOutput << GetBoneUniqueId(mesh->mBones[i]) << ' ';
}
mOutput << "</Name_array>" << endstr;
@ -888,9 +935,11 @@ void ColladaExporter::WriteController(size_t pIndex) {
std::vector<ai_real> bind_poses;
bind_poses.reserve(mesh->mNumBones * 16);
for (unsigned int i = 0; i < mesh->mNumBones; ++i)
for (unsigned int j = 0; j < 4; ++j)
for (unsigned int i = 0; i < mesh->mNumBones; ++i) {
for (unsigned int j = 0; j < 4; ++j) {
bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4);
}
}
WriteFloatArray(idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real *)bind_poses.data(), bind_poses.size() / 16);
@ -898,9 +947,11 @@ void ColladaExporter::WriteController(size_t pIndex) {
std::vector<ai_real> skin_weights;
skin_weights.reserve(mesh->mNumVertices * mesh->mNumBones);
for (size_t i = 0; i < mesh->mNumBones; ++i)
for (size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
for (size_t i = 0; i < mesh->mNumBones; ++i) {
for (size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) {
skin_weights.push_back(mesh->mBones[i]->mWeights[j].mWeight);
}
}
WriteFloatArray(idstr + "-skin-weights", FloatType_Weight, (const ai_real *)skin_weights.data(), skin_weights.size());
@ -924,12 +975,15 @@ void ColladaExporter::WriteController(size_t pIndex) {
mOutput << startstr << "<vcount>";
std::vector<ai_uint> num_influences(mesh->mNumVertices, (ai_uint)0);
for (size_t i = 0; i < mesh->mNumBones; ++i)
for (size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
for (size_t i = 0; i < mesh->mNumBones; ++i) {
for (size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) {
++num_influences[mesh->mBones[i]->mWeights[j].mVertexId];
}
}
for (size_t i = 0; i < mesh->mNumVertices; ++i)
for (size_t i = 0; i < mesh->mNumVertices; ++i) {
mOutput << num_influences[i] << " ";
}
mOutput << "</vcount>" << endstr;
@ -945,7 +999,7 @@ void ColladaExporter::WriteController(size_t pIndex) {
ai_uint weight_index = 0;
std::vector<ai_int> joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1);
for (unsigned int i = 0; i < mesh->mNumBones; ++i)
for (unsigned int i = 0; i < mesh->mNumBones; ++i) {
for (unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j) {
unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId;
for (ai_uint k = 0; k < num_influences[vId]; ++k) {
@ -957,9 +1011,11 @@ void ColladaExporter::WriteController(size_t pIndex) {
}
++weight_index;
}
}
for (size_t i = 0; i < joint_weight_indices.size(); ++i)
for (size_t i = 0; i < joint_weight_indices.size(); ++i) {
mOutput << joint_weight_indices[i] << " ";
}
num_influences.clear();
accum_influences.clear();
@ -983,8 +1039,9 @@ void ColladaExporter::WriteGeometryLibrary() {
mOutput << startstr << "<library_geometries>" << endstr;
PushTag();
for (size_t a = 0; a < mScene->mNumMeshes; ++a)
for (size_t a = 0; a < mScene->mNumMeshes; ++a) {
WriteGeometry(a);
}
PopTag();
mOutput << startstr << "</library_geometries>" << endstr;
@ -997,8 +1054,9 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
const std::string geometryId = GetObjectUniqueId(AiObjectType::Mesh, pIndex);
const std::string geometryName = GetObjectName(AiObjectType::Mesh, pIndex);
if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) {
return;
}
// opening tag
mOutput << startstr << "<geometry id=\"" << geometryId << "\" name=\"" << geometryName << "\" >" << endstr;
@ -1010,8 +1068,9 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
// Positions
WriteFloatArray(geometryId + "-positions", FloatType_Vector, (ai_real *)mesh->mVertices, mesh->mNumVertices);
// Normals, if any
if (mesh->HasNormals())
if (mesh->HasNormals()) {
WriteFloatArray(geometryId + "-normals", FloatType_Vector, (ai_real *)mesh->mNormals, mesh->mNumVertices);
}
// texture coords
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
@ -1040,10 +1099,11 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
int countLines = 0;
int countPoly = 0;
for (size_t a = 0; a < mesh->mNumFaces; ++a) {
if (mesh->mFaces[a].mNumIndices == 2)
if (mesh->mFaces[a].mNumIndices == 2) {
countLines++;
else if (mesh->mFaces[a].mNumIndices >= 3)
} else if (mesh->mFaces[a].mNumIndices >= 3) {
countPoly++;
}
}
// lines
@ -1051,13 +1111,18 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
PushTag();
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << geometryId << "-vertices\" />" << endstr;
if (mesh->HasNormals())
if (mesh->HasNormals()) {
mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << geometryId << "-normals\" />" << endstr;
}
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (mesh->HasTextureCoords(static_cast<unsigned int>(a)))
mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << geometryId << "-tex" << a << "\" "
if (mesh->HasTextureCoords(static_cast<unsigned int>(a))) {
mOutput << startstr
<< "<input semantic=\"TEXCOORD\" source=\"#"
<< geometryId
<< "-tex" << a << "\" "
<< "set=\"" << a << "\""
<< " />" << endstr;
}
}
for (size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) {
if (mesh->HasVertexColors(static_cast<unsigned int>(a)))
@ -1070,8 +1135,9 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
for (size_t a = 0; a < mesh->mNumFaces; ++a) {
const aiFace &face = mesh->mFaces[a];
if (face.mNumIndices != 2) continue;
for (size_t b = 0; b < face.mNumIndices; ++b)
for (size_t b = 0; b < face.mNumIndices; ++b) {
mOutput << face.mIndices[b] << " ";
}
}
mOutput << "</p>" << endstr;
PopTag();
@ -1085,8 +1151,9 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr;
PushTag();
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << geometryId << "-vertices\" />" << endstr;
if (mesh->HasNormals())
if (mesh->HasNormals()) {
mOutput << startstr << "<input offset=\"0\" semantic=\"NORMAL\" source=\"#" << geometryId << "-normals\" />" << endstr;
}
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (mesh->HasTextureCoords(static_cast<unsigned int>(a)))
mOutput << startstr << "<input offset=\"0\" semantic=\"TEXCOORD\" source=\"#" << geometryId << "-tex" << a << "\" "
@ -1111,8 +1178,9 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
for (size_t a = 0; a < mesh->mNumFaces; ++a) {
const aiFace &face = mesh->mFaces[a];
if (face.mNumIndices < 3) continue;
for (size_t b = 0; b < face.mNumIndices; ++b)
for (size_t b = 0; b < face.mNumIndices; ++b) {
mOutput << face.mIndices[b] << " ";
}
}
mOutput << "</p>" << endstr;
PopTag();
@ -1131,13 +1199,27 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
void ColladaExporter::WriteFloatArray(const std::string &pIdString, FloatDataType pType, const ai_real *pData, size_t pElementCount) {
size_t floatsPerElement = 0;
switch (pType) {
case FloatType_Vector: floatsPerElement = 3; break;
case FloatType_TexCoord2: floatsPerElement = 2; break;
case FloatType_TexCoord3: floatsPerElement = 3; break;
case FloatType_Color: floatsPerElement = 3; break;
case FloatType_Mat4x4: floatsPerElement = 16; break;
case FloatType_Weight: floatsPerElement = 1; break;
case FloatType_Time: floatsPerElement = 1; break;
case FloatType_Vector:
floatsPerElement = 3;
break;
case FloatType_TexCoord2:
floatsPerElement = 2;
break;
case FloatType_TexCoord3:
floatsPerElement = 3;
break;
case FloatType_Color:
floatsPerElement = 3;
break;
case FloatType_Mat4x4:
floatsPerElement = 16;
break;
case FloatType_Weight:
floatsPerElement = 1;
break;
case FloatType_Time:
floatsPerElement = 1;
break;
default:
return;
}
@ -1163,8 +1245,9 @@ void ColladaExporter::WriteFloatArray(const std::string &pIdString, FloatDataTyp
mOutput << pData[a * 4 + 2] << " ";
}
} else {
for (size_t a = 0; a < pElementCount * floatsPerElement; ++a)
for (size_t a = 0; a < pElementCount * floatsPerElement; ++a) {
mOutput << pData[a] << " ";
}
}
mOutput << "</float_array>" << endstr;
PopTag();
@ -1256,9 +1339,13 @@ void ColladaExporter::WriteSceneLibrary() {
// ------------------------------------------------------------------------------------------------
void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
const aiAnimation *anim = mScene->mAnimations[pIndex];
if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0)
if (anim == nullptr) {
return;
}
if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0) {
return;
}
const std::string animationNameEscaped = GetObjectName(AiObjectType::Animation, pIndex);
const std::string idstrEscaped = GetObjectUniqueId(AiObjectType::Animation, pIndex);
@ -1269,8 +1356,11 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
std::string cur_node_idstr;
for (size_t a = 0; a < anim->mNumChannels; ++a) {
const aiNodeAnim *nodeAnim = anim->mChannels[a];
if (nodeAnim == nullptr) {
continue;
}
// sanity check
// sanity checks
if (nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys) {
continue;
}
@ -1369,6 +1459,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
for (size_t a = 0; a < anim->mNumChannels; ++a) {
const aiNodeAnim *nodeAnim = anim->mChannels[a];
if (nodeAnim == nullptr) {
continue;
}
{
// samplers
@ -1387,97 +1480,42 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
for (size_t a = 0; a < anim->mNumChannels; ++a) {
const aiNodeAnim *nodeAnim = anim->mChannels[a];
if (nodeAnim == nullptr) {
continue;
}
{
// channels
mOutput << startstr << "<channel source=\"#" << XMLIDEncode(nodeAnim->mNodeName.data + std::string("_matrix-sampler")) << "\" target=\"" << XMLIDEncode(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr;
mOutput << startstr
<< "<channel source=\"#"
<< XMLIDEncode(nodeAnim->mNodeName.data + std::string("_matrix-sampler"))
<< "\" target=\""
<< XMLIDEncode(nodeAnim->mNodeName.data)
<< "/matrix\"/>"
<< endstr;
}
}
PopTag();
mOutput << startstr << "</animation>" << endstr;
}
// ------------------------------------------------------------------------------------------------
void ColladaExporter::WriteAnimationsLibrary() {
if (mScene->mNumAnimations > 0) {
mOutput << startstr << "<library_animations>" << endstr;
PushTag();
// start recursive write at the root node
for (size_t a = 0; a < mScene->mNumAnimations; ++a)
WriteAnimationLibrary(a);
PopTag();
mOutput << startstr << "</library_animations>" << endstr;
}
}
// ------------------------------------------------------------------------------------------------
// Helper to find a bone by name in the scene
aiBone *findBone(const aiScene *scene, const aiString &name) {
for (size_t m = 0; m < scene->mNumMeshes; m++) {
aiMesh *mesh = scene->mMeshes[m];
for (size_t b = 0; b < mesh->mNumBones; b++) {
aiBone *bone = mesh->mBones[b];
if (name == bone->mName) {
return bone;
}
}
}
return nullptr;
}
// ------------------------------------------------------------------------------------------------
// Helper to find the node associated with a bone in the scene
const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) {
if (aNode && bone && aNode->mName == bone->mName) {
return aNode;
if (mScene->mNumAnimations == 0) {
return;
}
if (aNode && bone) {
for (unsigned int i = 0; i < aNode->mNumChildren; ++i) {
aiNode *aChild = aNode->mChildren[i];
const aiNode *foundFromChild = nullptr;
if (aChild) {
foundFromChild = findBoneNode(aChild, bone);
if (foundFromChild) {
return foundFromChild;
}
}
}
mOutput << startstr << "<library_animations>" << endstr;
PushTag();
// start recursive write at the root node
for (size_t a = 0; a < mScene->mNumAnimations; ++a) {
WriteAnimationLibrary(a);
}
return nullptr;
}
const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) {
std::set<const aiNode *> topParentBoneNodes;
if (mesh && mesh->mNumBones > 0) {
for (unsigned int i = 0; i < mesh->mNumBones; ++i) {
aiBone *bone = mesh->mBones[i];
const aiNode *node = findBoneNode(scene->mRootNode, bone);
if (node) {
while (node->mParent && findBone(scene, node->mParent->mName) != nullptr) {
node = node->mParent;
}
topParentBoneNodes.insert(node);
}
}
}
if (!topParentBoneNodes.empty()) {
const aiNode *parentBoneNode = *topParentBoneNodes.begin();
if (topParentBoneNodes.size() == 1) {
return parentBoneNode;
} else {
for (auto it : topParentBoneNodes) {
if (it->mParent) return it->mParent;
}
return parentBoneNode;
}
}
return nullptr;
PopTag();
mOutput << startstr << "</library_animations>" << endstr;
}
// ------------------------------------------------------------------------------------------------
@ -1488,13 +1526,13 @@ void ColladaExporter::WriteNode(const aiNode *pNode) {
// Assimp-specific: nodes with no name cannot be associated with bones
const char *node_type;
bool is_joint, is_skeleton_root = false;
if (pNode->mName.length == 0 || nullptr == findBone(mScene, pNode->mName)) {
if (pNode->mName.length == 0 || nullptr == mScene->findBone(pNode->mName)) {
node_type = "NODE";
is_joint = false;
} else {
node_type = "JOINT";
is_joint = true;
if (!pNode->mParent || nullptr == findBone(mScene, pNode->mParent->mName)) {
if (!pNode->mParent || nullptr == mScene->findBone(pNode->mParent->mName)) {
is_skeleton_root = true;
}
}
@ -1532,7 +1570,6 @@ void ColladaExporter::WriteNode(const aiNode *pNode) {
}
// customized, sid should be 'matrix' to match with loader code.
//mOutput << startstr << "<matrix sid=\"transform\">";
mOutput << startstr << "<matrix sid=\"matrix\">";
mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " ";
@ -1556,7 +1593,6 @@ void ColladaExporter::WriteNode(const aiNode *pNode) {
break;
}
}
} else
// instance every geometry
for (size_t a = 0; a < pNode->mNumMeshes; ++a) {
@ -1612,8 +1648,9 @@ void ColladaExporter::WriteNode(const aiNode *pNode) {
}
// recurse into subnodes
for (size_t a = 0; a < pNode->mNumChildren; ++a)
for (size_t a = 0; a < pNode->mNumChildren; ++a) {
WriteNode(pNode->mChildren[a]);
}
PopTag();
mOutput << startstr << "</node>" << endstr;
@ -1628,8 +1665,9 @@ void ColladaExporter::CreateNodeIds(const aiNode *node) {
std::string ColladaExporter::GetNodeUniqueId(const aiNode *node) {
// Use the pointer as the key. This is safe because the scene is immutable.
auto idIt = mNodeIdMap.find(node);
if (idIt != mNodeIdMap.cend())
if (idIt != mNodeIdMap.cend()) {
return idIt->second;
}
// Prefer the requested Collada Id if extant
std::string idStr;
@ -1640,36 +1678,42 @@ std::string ColladaExporter::GetNodeUniqueId(const aiNode *node) {
idStr = node->mName.C_Str();
}
// Make sure the requested id is valid
if (idStr.empty())
if (idStr.empty()) {
idStr = "node";
else
} else {
idStr = XMLIDEncode(idStr);
}
// Ensure it's unique
idStr = MakeUniqueId(mUniqueIds, idStr, std::string());
mUniqueIds.insert(idStr);
mNodeIdMap.insert(std::make_pair(node, idStr));
return idStr;
}
std::string ColladaExporter::GetNodeName(const aiNode *node) {
if (node == nullptr) {
return std::string();
}
return XMLEscape(node->mName.C_Str());
}
std::string ColladaExporter::GetBoneUniqueId(const aiBone *bone) {
// Find the Node that is this Bone
const aiNode *boneNode = findBoneNode(mScene->mRootNode, bone);
if (boneNode == nullptr)
const aiNode *boneNode = mScene->mRootNode->findBoneNode(bone);
if (boneNode == nullptr) {
return std::string();
}
return GetNodeUniqueId(boneNode);
}
std::string ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t pIndex) {
auto idIt = GetObjectIdMap(type).find(pIndex);
if (idIt != GetObjectIdMap(type).cend())
if (idIt != GetObjectIdMap(type).cend()) {
return idIt->second;
}
// Not seen this object before, create and add
NameIdPair result = AddObjectIndexToMaps(type, pIndex);
@ -1678,8 +1722,9 @@ std::string ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t pIndex)
std::string ColladaExporter::GetObjectName(AiObjectType type, size_t pIndex) {
auto objectName = GetObjectNameMap(type).find(pIndex);
if (objectName != GetObjectNameMap(type).cend())
if (objectName != GetObjectNameMap(type).cend()) {
return objectName->second;
}
// Not seen this object before, create and add
NameIdPair result = AddObjectIndexToMaps(type, pIndex);
@ -1699,9 +1744,15 @@ ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType t
// Get the name and id postfix
switch (type) {
case AiObjectType::Mesh: name = mScene->mMeshes[index]->mName.C_Str(); break;
case AiObjectType::Material: name = mScene->mMaterials[index]->GetName().C_Str(); break;
case AiObjectType::Animation: name = mScene->mAnimations[index]->mName.C_Str(); break;
case AiObjectType::Mesh:
name = mScene->mMeshes[index]->mName.C_Str();
break;
case AiObjectType::Material:
name = mScene->mMaterials[index]->GetName().C_Str();
break;
case AiObjectType::Animation:
name = mScene->mAnimations[index]->mName.C_Str();
break;
case AiObjectType::Light:
name = mScene->mLights[index]->mName.C_Str();
idPostfix = "-light";
@ -1710,7 +1761,8 @@ ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType t
name = mScene->mCameras[index]->mName.C_Str();
idPostfix = "-camera";
break;
case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type");
case AiObjectType::Count:
throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type");
}
if (name.empty()) {
@ -1728,8 +1780,9 @@ ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType t
idStr = XMLIDEncode(name);
}
if (!name.empty())
if (!name.empty()) {
name = XMLEscape(name);
}
idStr = MakeUniqueId(mUniqueIds, idStr, idPostfix);
@ -1743,5 +1796,5 @@ ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType t
} // end of namespace Assimp
#endif
#endif
#endif // ASSIMP_BUILD_NO_COLLADA_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -66,13 +65,13 @@ class IOSystem;
/// Helper class to export a given scene to a Collada file. Just for my personal
/// comfort when implementing it.
class ColladaExporter {
class ColladaExporter final {
public:
/// Constructor for a specific scene to export
ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file);
/// Destructor
virtual ~ColladaExporter();
virtual ~ColladaExporter() = default;
protected:
/// Starts writing the contents

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -341,7 +341,7 @@ struct SubMesh {
/// Contains data for a single mesh
struct Mesh {
Mesh(const std::string &id) :
explicit Mesh(const std::string &id) :
mId(id) {
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
mNumUVComponents[i] = 2;

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -77,18 +77,26 @@ static constexpr aiImporterDesc desc = {
"dae xml zae"
};
static const float kMillisecondsFromSeconds = 1000.f;
static constexpr float kMillisecondsFromSeconds = 1000.f;
// Add an item of metadata to a node
// Assumes the key is not already in the list
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) {
node->mMetaData = new aiMetadata();
}
node->mMetaData->Add(key, value);
}
// ------------------------------------------------------------------------------------------------
// 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) {
const size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size());
return pData.mValues[pos];
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ColladaLoader::ColladaLoader() :
@ -152,7 +160,7 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
throw DeadlyImportError("Collada: File came out empty. Something is wrong here.");
}
// reserve some storage to avoid unnecessary reallocs
// reserve some storage to avoid unnecessary reallocates
newMats.reserve(parser.mMaterialLibrary.size() * 2u);
mMeshes.reserve(parser.mMeshLibrary.size() * 2u);
@ -176,7 +184,7 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
0, 0, parser.mUnitSize, 0,
0, 0, 0, 1);
}
if (!ignoreUpDirection) {
// Convert to Y_UP, if different orientation
if (parser.mUpDirection == ColladaParser::UP_X) {
@ -224,7 +232,7 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
// Recursively constructs a scene node for the given parser node and returns it.
aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collada::Node *pNode) {
// create a node for it
aiNode *node = new aiNode();
auto *node = new aiNode();
// find a name for the new node. It's more complicated than you might think
node->mName.Set(FindNameForNode(pNode));
@ -272,24 +280,24 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
// ------------------------------------------------------------------------------------------------
// Resolve node instances
void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Node *pNode,
std::vector<const Node*> &resolved) {
std::vector<const Node*> &resolved) const {
// reserve enough storage
resolved.reserve(pNode->mNodeInstances.size());
// ... and iterate through all nodes to be instanced as children of pNode
for (const auto &nodeInst : pNode->mNodeInstances) {
for (const auto &[mNode] : pNode->mNodeInstances) {
// find the corresponding node in the library
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
const auto itt = pParser.mNodeLibrary.find(mNode);
const Node *nd = itt == pParser.mNodeLibrary.end() ? nullptr : (*itt).second;
// FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
// need to check for both name and ID to catch all. To avoid breaking valid files,
// the workaround is only enabled when the first attempt to resolve the node has failed.
if (nullptr == nd) {
nd = FindNode(pParser.mRootNode, nodeInst.mNode);
nd = FindNode(pParser.mRootNode, mNode);
}
if (nullptr == nd) {
ASSIMP_LOG_ERROR("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
ASSIMP_LOG_ERROR("Collada: Unable to resolve reference to instanced node ", mNode);
} else {
// attach this node to the list of children
resolved.push_back(nd);
@ -299,8 +307,8 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Nod
// ------------------------------------------------------------------------------------------------
// Resolve UV channels
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Sampler &sampler, const SemanticMappingTable &table) {
SemanticMappingTable::InputSemanticMap::const_iterator it = table.mMap.find(sampler.mUVChannel);
static void ApplyVertexToEffectSemanticMapping(Sampler &sampler, const SemanticMappingTable &table) {
const auto it = table.mMap.find(sampler.mUVChannel);
if (it == table.mMap.end()) {
return;
}
@ -317,7 +325,7 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Sampler &sampler, const S
void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node *pNode, aiNode *pTarget) {
for (const LightInstance &lid : pNode->mLights) {
// find the referred light
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find(lid.mLight);
auto srcLightIt = pParser.mLightLibrary.find(lid.mLight);
if (srcLightIt == pParser.mLightLibrary.end()) {
ASSIMP_LOG_WARN("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping.");
continue;
@ -325,7 +333,7 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
const Collada::Light *srcLight = &srcLightIt->second;
// now fill our ai data structure
aiLight *out = new aiLight();
auto out = new aiLight();
out->mName = pTarget->mName;
out->mType = (aiLightSourceType)srcLight->mType;
@ -382,7 +390,7 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Node *pNode, aiNode *pTarget) {
for (const CameraInstance &cid : pNode->mCameras) {
// find the referred light
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera);
auto srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera);
if (srcCameraIt == pParser.mCameraLibrary.end()) {
ASSIMP_LOG_WARN("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping.");
continue;
@ -395,7 +403,7 @@ void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Node
}
// now fill our ai data structure
aiCamera *out = new aiCamera();
auto *out = new aiCamera();
out->mName = pTarget->mName;
// collada cameras point in -Z by default, rest is specified in node transform
@ -445,10 +453,10 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
const Controller *srcController = nullptr;
// find the referred mesh
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find(mid.mMeshOrController);
auto srcMeshIt = pParser.mMeshLibrary.find(mid.mMeshOrController);
if (srcMeshIt == pParser.mMeshLibrary.end()) {
// if not found in the mesh-library, it might also be a controller referring to a mesh
ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find(mid.mMeshOrController);
auto srcContrIt = pParser.mControllerLibrary.find(mid.mMeshOrController);
if (srcContrIt != pParser.mControllerLibrary.end()) {
srcController = &srcContrIt->second;
srcMeshIt = pParser.mMeshLibrary.find(srcController->mMeshId);
@ -462,7 +470,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
continue;
}
} else {
// ID found in the mesh library -> direct reference to an unskinned mesh
// ID found in the mesh library -> direct reference to a not skinned mesh
srcMesh = srcMeshIt->second;
}
@ -476,7 +484,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
// find material assigned to this submesh
std::string meshMaterial;
std::map<std::string, SemanticMappingTable>::const_iterator meshMatIt = mid.mMaterials.find(submesh.mMaterial);
auto meshMatIt = mid.mMaterials.find(submesh.mMaterial);
const Collada::SemanticMappingTable *table = nullptr;
if (meshMatIt != mid.mMaterials.end()) {
@ -492,30 +500,34 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
// OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table
// given. The only mapping stuff which we do actually support is the UV channel.
std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find(meshMaterial);
auto matIt = mMaterialIndexByName.find(meshMaterial);
unsigned int matIdx = 0;
if (matIt != mMaterialIndexByName.end()) {
matIdx = static_cast<unsigned int>(matIt->second);
}
if (table && !table->mMap.empty()) {
std::pair<Collada::Effect *, aiMaterial *> &mat = newMats[matIdx];
if (matIdx < newMats.size()) {
std::pair<Collada::Effect *, aiMaterial *> &mat = newMats[matIdx];
// Iterate through all texture channels assigned to the effect and
// check whether we have mapping information for it.
ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
// Iterate through all texture channels assigned to the effect and
// check whether we have mapping information for it.
ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
} else {
ASSIMP_LOG_WARN("Collada: Ignoring material mapping for mesh \"", mid.mMeshOrController, "\". Material index ", matIdx, " is out of bounds (newMats.size()=", newMats.size(), ").");
}
}
// built lookup index of the Mesh-Submesh-Material combination
ColladaMeshIndex index(mid.mMeshOrController, sm, meshMaterial);
// if we already have the mesh at the library, just add its index to the node's array
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find(index);
auto dstMeshIt = mMeshIndexByID.find(index);
if (dstMeshIt != mMeshIndexByID.end()) {
newMeshRefs.push_back(dstMeshIt->second);
} else {
@ -530,7 +542,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
faceStart += submesh.mNumFaces;
// assign the material index
std::map<std::string, size_t>::const_iterator subMatIt = mMaterialIndexByName.find(submesh.mMaterial);
auto subMatIt = mMaterialIndexByName.find(submesh.mMaterial);
if (subMatIt != mMaterialIndexByName.end()) {
dstMesh->mMaterialIndex = static_cast<unsigned int>(subMatIt->second);
} else {
@ -618,7 +630,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
std::copy(pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() + pStartVertex + numVertices, dstMesh->mTangents);
}
// bitangents, if given.
// bi-tangents, if given.
if (pSrcMesh->mBitangents.size() >= pStartVertex + numVertices) {
dstMesh->mBitangents = new aiVector3D[numVertices];
std::copy(pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() + pStartVertex + numVertices, dstMesh->mBitangents);
@ -664,7 +676,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
std::vector<float> targetWeights;
Collada::MorphMethod method = Normalized;
for (std::map<std::string, Controller>::const_iterator it = pParser.mControllerLibrary.begin();
for (auto it = pParser.mControllerLibrary.begin();
it != pParser.mControllerLibrary.end(); ++it) {
const Controller &c = it->second;
const Collada::Mesh *baseMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, c.mMeshId);
@ -754,7 +766,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
std::vector<IndexPairVector::const_iterator> weightStartPerVertex;
weightStartPerVertex.resize(pSrcController->mWeightCounts.size(), pSrcController->mWeights.end());
IndexPairVector::const_iterator pit = pSrcController->mWeights.begin();
auto pit = pSrcController->mWeights.begin();
for (size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a) {
weightStartPerVertex[a] = pit;
pit += pSrcController->mWeightCounts[a];
@ -766,7 +778,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
// the controller assigns the vertex weights
size_t orgIndex = pSrcMesh->mFacePosIndices[a];
// find the vertex weights for this vertex
IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex];
auto iit = weightStartPerVertex[orgIndex];
size_t pairCount = pSrcController->mWeightCounts[orgIndex];
for (size_t b = 0; b < pairCount; ++b, ++iit) {
@ -807,7 +819,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
}
// create bone with its weights
aiBone *bone = new aiBone;
auto bone = new aiBone;
bone->mName = ReadString(jointNamesAcc, jointNames, a);
bone->mOffsetMatrix.a1 = ReadFloat(jointMatrixAcc, jointMatrices, a, 0);
bone->mOffsetMatrix.a2 = ReadFloat(jointMatrixAcc, jointMatrices, a, 1);
@ -973,7 +985,7 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse
// if there are other animations which fit the template anim, combine all channels into a single anim
if (!collectedAnimIndices.empty()) {
aiAnimation *combinedAnim = new aiAnimation();
auto *combinedAnim = new aiAnimation();
combinedAnim->mName = aiString(std::string("combinedAnim_") + char('0' + a));
combinedAnim->mDuration = templateAnim->mDuration;
combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond;
@ -1040,7 +1052,7 @@ struct MorphTimeValues {
};
void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, float weight, unsigned int value) {
MorphTimeValues::key k;
MorphTimeValues::key k{};
k.mValue = value;
k.mWeight = weight;
if (values.empty() || time < values[0].mTime) {
@ -1077,6 +1089,7 @@ static float getWeightAtKey(const std::vector<MorphTimeValues> &values, int key,
return mKey.mWeight;
}
}
// no value at key found, try to interpolate if present at other keys. if not, return zero
// TODO: interpolation
return 0.0f;
@ -1105,7 +1118,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// now check all channels if they affect the current node
std::string targetID, subElement;
for (std::vector<AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
for (auto cit = pSrcAnim->mChannels.begin();
cit != pSrcAnim->mChannels.end(); ++cit) {
const AnimationChannel &srcChannel = *cit;
ChannelEntry entry;
@ -1348,7 +1361,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// build an animation channel for the given node out of these trafo keys
if (!resultTrafos.empty()) {
aiNodeAnim *dstAnim = new aiNodeAnim;
auto *dstAnim = new aiNodeAnim;
dstAnim->mNodeName = nodeName;
dstAnim->mNumPositionKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mNumRotationKeys = static_cast<unsigned int>(resultTrafos.size());
@ -1390,7 +1403,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// or 2) one channel with morph target count arrays
// assume first
aiMeshMorphAnim *morphAnim = new aiMeshMorphAnim;
auto *morphAnim = new aiMeshMorphAnim;
morphAnim->mName.Set(nodeName);
std::vector<MorphTimeValues> morphTimeValues;
@ -1433,7 +1446,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
}
if (!anims.empty() || !morphAnims.empty()) {
aiAnimation *anim = new aiAnimation;
auto anim = new aiAnimation;
anim->mName.Set(pName);
anim->mNumChannels = static_cast<unsigned int>(anims.size());
if (anim->mNumChannels > 0) {
@ -1513,7 +1526,7 @@ void ColladaLoader::AddTexture(aiMaterial &mat,
map = sampler.mUVId;
} else {
map = -1;
for (std::string::const_iterator it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
for (auto it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
if (IsNumeric(*it)) {
map = strtoul10(&(*it));
break;
@ -1531,7 +1544,7 @@ void ColladaLoader::AddTexture(aiMaterial &mat,
// Fills materials from the collada material definitions
void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pScene*/) {
for (auto &elem : newMats) {
aiMaterial &mat = (aiMaterial &)*elem.second;
auto &mat = (aiMaterial &)*elem.second;
Collada::Effect &effect = *elem.first;
// resolve shading mode
@ -1641,17 +1654,17 @@ void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pSce
void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/) {
newMats.reserve(pParser.mMaterialLibrary.size());
for (ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin();
for (auto matIt = pParser.mMaterialLibrary.begin();
matIt != pParser.mMaterialLibrary.end(); ++matIt) {
const Material &material = matIt->second;
// a material is only a reference to an effect
ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find(material.mEffect);
auto effIt = pParser.mEffectLibrary.find(material.mEffect);
if (effIt == pParser.mEffectLibrary.end())
continue;
Effect &effect = effIt->second;
// create material
aiMaterial *mat = new aiMaterial;
auto *mat = new aiMaterial;
aiString name(material.mName.empty() ? matIt->first : material.mName);
mat->AddProperty(&name, AI_MATKEY_NAME);
@ -1674,7 +1687,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
std::string name = pName;
while (true) {
// the given string is a param entry. Find it
Effect::ParamLibrary::const_iterator it = pEffect.mParams.find(name);
auto it = pEffect.mParams.find(name);
// if not found, we're at the end of the recursion. The resulting string should be the image ID
if (it == pEffect.mParams.end())
break;
@ -1684,7 +1697,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
}
// find the image referred by this name in the image library of the scene
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find(name);
auto imIt = pParser.mImageLibrary.find(name);
if (imIt == pParser.mImageLibrary.end()) {
ASSIMP_LOG_WARN("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\".");
@ -1696,7 +1709,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
// if this is an embedded texture image setup an aiTexture for it
if (!imIt->second.mImageData.empty()) {
aiTexture *tex = new aiTexture();
auto *tex = new aiTexture();
// Store embedded texture name reference
tex->mFilename.Set(imIt->second.mFileName.c_str());
@ -1728,14 +1741,6 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
return result;
}
// ------------------------------------------------------------------------------------------------
// Reads a float value from an accessor and its data array.
ai_real ColladaLoader::ReadFloat(const Accessor &pAccessor, const Data &pData, size_t pIndex, size_t pOffset) const {
size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size());
return pData.mValues[pos];
}
// ------------------------------------------------------------------------------------------------
// Reads a string value from an accessor and its data array.
const std::string &ColladaLoader::ReadString(const Accessor &pAccessor, const Data &pData, size_t pIndex) const {
@ -1818,4 +1823,4 @@ std::string ColladaLoader::FindNameForNode(const Node *pNode) {
} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER
#endif // !! ASSIMP_BUILD_NO_COLLADA_IMPORTER

View file

@ -4,8 +4,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -77,10 +76,13 @@ struct ColladaMeshIndex {
}
};
/** Loader class to read Collada scenes. 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.
/**
* @brief Loader class to read Collada scenes.
*
* 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.
*/
class ColladaLoader : public BaseImporter {
class ColladaLoader final : public BaseImporter {
public:
/// The class constructor.
ColladaLoader();
@ -102,50 +104,51 @@ protected:
/// See #BaseImporter::InternReadFile for the details
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
/** Recursively constructs a scene node for the given parser node and returns it. */
/// Recursively constructs a scene node for the given parser node and returns it.
aiNode *BuildHierarchy(const ColladaParser &pParser, const Collada::Node *pNode);
/** Resolve node instances */
/// Resolve node instances
void ResolveNodeInstances(const ColladaParser &pParser, const Collada::Node *pNode,
std::vector<const Collada::Node *> &resolved);
std::vector<const Collada::Node *> &resolved) const;
/** Builds meshes for the given node and references them */
/// Builds meshes for the given node and references them
void BuildMeshesForNode(const ColladaParser &pParser, const Collada::Node *pNode,
aiNode *pTarget);
/// Lookup for meshes by their name
aiMesh *findMesh(const std::string &meshid);
/** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */
/// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
aiMesh *CreateMesh(const ColladaParser &pParser, const Collada::Mesh *pSrcMesh, const Collada::SubMesh &pSubMesh,
const Collada::Controller *pSrcController, size_t pStartVertex, size_t pStartFace);
/** Builds cameras for the given node and references them */
/// Builds cameras for the given node and references them
void BuildCamerasForNode(const ColladaParser &pParser, const Collada::Node *pNode,
aiNode *pTarget);
/** Builds lights for the given node and references them */
/// Builds lights for the given node and references them
void BuildLightsForNode(const ColladaParser &pParser, const Collada::Node *pNode,
aiNode *pTarget);
/** Stores all meshes in the given scene */
/// Stores all meshes in the given scene
void StoreSceneMeshes(aiScene *pScene);
/** Stores all materials in the given scene */
/// Stores all materials in the given scene
void StoreSceneMaterials(aiScene *pScene);
/** Stores all lights in the given scene */
/// Stores all lights in the given scene
void StoreSceneLights(aiScene *pScene);
/** Stores all cameras in the given scene */
/// Stores all cameras in the given scene
void StoreSceneCameras(aiScene *pScene);
/** Stores all textures in the given scene */
/// Stores all textures in the given scene
void StoreSceneTextures(aiScene *pScene);
/** Stores all animations
* @param pScene target scene to store the anims
*/
void StoreAnimations(aiScene *pScene, const ColladaParser &pParser);
/// Stores all animations
/// @param pScene Target scene to store the anims
/// @param parser The collada parser
void StoreAnimations(aiScene *pScene, const ColladaParser &parser);
/** Stores all animations for the given source anim and its nested child animations
* @param pScene target scene to store the anims
@ -163,10 +166,6 @@ protected:
/** Fill materials from the collada material definitions */
void FillMaterials(const ColladaParser &pParser, aiScene *pScene);
/** Resolve UV channel mappings*/
void ApplyVertexToEffectSemanticMapping(Collada::Sampler &sampler,
const Collada::SemanticMappingTable &table);
/** Add a texture and all of its sampling properties to a material*/
void AddTexture(aiMaterial &mat, const ColladaParser &pParser,
const Collada::Effect &effect,
@ -177,22 +176,13 @@ protected:
aiString FindFilenameForEffectTexture(const ColladaParser &pParser,
const Collada::Effect &pEffect, const std::string &pName);
/** Reads a float value from an accessor and its data array.
* @param pAccessor The accessor to use for reading
* @param pData The data array to read from
* @param pIndex The index of the element to retrieve
* @param pOffset Offset into the element, for multipart elements such as vectors or matrices
* @return the specified value
*/
ai_real ReadFloat(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex, size_t pOffset) const;
/** Reads a string value from an accessor and its data array.
* @param pAccessor The accessor to use for reading
* @param pData The data array to read from
* @param pIndex The index of the element to retrieve
* @return the specified value
*/
const std::string &ReadString(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex) const;
[[nodiscard]] const std::string &ReadString(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex) const;
/** Recursively collects all nodes into the given array */
void CollectNodes(const aiNode *pNode, std::vector<const aiNode *> &poNodes) const;
@ -205,7 +195,7 @@ protected:
/** Finds a proper name for a node derived from the collada-node's properties */
std::string FindNameForNode(const Collada::Node *pNode);
protected:
private:
/** Filename, for a verbose error message */
std::string mFileName;

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -48,7 +48,6 @@
#define AI_COLLADAPARSER_H_INC
#include "ColladaHelper.h"
#include <assimp/TinyFormatter.h>
#include <assimp/ai_assert.h>
#include <assimp/XmlParser.h>
@ -67,268 +66,240 @@ class ZipArchiveIOSystem;
class ColladaParser {
friend class ColladaLoader;
/** Converts a path read from a collada file to the usual representation */
static void UriDecodePath(aiString &ss);
public:
/// Map for generic metadata as aiString.
using StringMetaData = std::map<std::string, aiString>;
protected:
/** Map for generic metadata as aiString */
typedef std::map<std::string, aiString> StringMetaData;
/** Constructor from XML file */
/// Constructor from XML file.
ColladaParser(IOSystem *pIOHandler, const std::string &pFile);
/** Destructor */
/// Destructor
~ColladaParser();
/** Attempts to read the ZAE manifest and returns the DAE to open */
/// Attempts to read the ZAE manifest and returns the DAE to open
static std::string ReadZaeManifest(ZipArchiveIOSystem &zip_archive);
/** Reads the contents of the file */
/// Reads the contents of the file
void ReadContents(XmlNode &node);
/** Reads the structure of the file */
/// Reads the structure of the file
void ReadStructure(XmlNode &node);
/** Reads asset information such as coordinate system information and legal blah */
/// Reads asset information such as coordinate system information and legal blah
void ReadAssetInfo(XmlNode &node);
/** Reads contributor information such as author and legal blah */
/// Reads contributor information such as author and legal blah
void ReadContributorInfo(XmlNode &node);
/** Reads generic metadata into provided map and renames keys for Assimp */
void ReadMetaDataItem(XmlNode &node, StringMetaData &metadata);
/** Reads the animation library */
/// Reads the animation library
void ReadAnimationLibrary(XmlNode &node);
/** Reads the animation clip library */
/// Reads the animation clip library
void ReadAnimationClipLibrary(XmlNode &node);
/** Unwrap controllers dependency hierarchy */
/// Unwrap controllers dependency hierarchy
void PostProcessControllers();
/** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */
/// Re-build animations from animation clip library, if present, otherwise combine single-channel animations
void PostProcessRootAnimations();
/** Reads an animation into the given parent structure */
/// Reads an animation into the given parent structure
void ReadAnimation(XmlNode &node, Collada::Animation *pParent);
/** Reads an animation sampler into the given anim channel */
void ReadAnimationSampler(XmlNode &node, Collada::AnimationChannel &pChannel);
/** Reads the skeleton controller library */
/// Reads the skeleton controller library
void ReadControllerLibrary(XmlNode &node);
/** Reads a controller into the given mesh structure */
/// Reads a controller into the given mesh structure
void ReadController(XmlNode &node, Collada::Controller &pController);
/** Reads the joint definitions for the given controller */
void ReadControllerJoints(XmlNode &node, Collada::Controller &pController);
/// Reads the image library contents
void ReadImageLibrary(const XmlNode &node);
/** Reads the joint weights for the given controller */
void ReadControllerWeights(XmlNode &node, Collada::Controller &pController);
/// Reads an image entry into the given image
void ReadImage(const XmlNode &node, Collada::Image &pImage) const;
/** Reads the image library contents */
void ReadImageLibrary(XmlNode &node);
/** Reads an image entry into the given image */
void ReadImage(XmlNode &node, Collada::Image &pImage);
/** Reads the material library */
/// Reads the material library
void ReadMaterialLibrary(XmlNode &node);
/** Reads a material entry into the given material */
void ReadMaterial(XmlNode &node, Collada::Material &pMaterial);
/** Reads the camera library */
/// Reads the camera library
void ReadCameraLibrary(XmlNode &node);
/** Reads a camera entry into the given camera */
void ReadCamera(XmlNode &node, Collada::Camera &pCamera);
/** Reads the light library */
/// Reads the light library
void ReadLightLibrary(XmlNode &node);
/** Reads a light entry into the given light */
void ReadLight(XmlNode &node, Collada::Light &pLight);
/** Reads the effect library */
/// Reads the effect library
void ReadEffectLibrary(XmlNode &node);
/** Reads an effect entry into the given effect*/
/// Reads an effect entry into the given effect
void ReadEffect(XmlNode &node, Collada::Effect &pEffect);
/** Reads an COMMON effect profile */
/// Reads an COMMON effect profile
void ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEffect);
/** Read sampler properties */
/// Read sampler properties
void ReadSamplerProperties(XmlNode &node, Collada::Sampler &pSampler);
/** Reads an effect entry containing a color or a texture defining that color */
/// Reads an effect entry containing a color or a texture defining that color
void ReadEffectColor(XmlNode &node, aiColor4D &pColor, Collada::Sampler &pSampler);
/** Reads an effect entry containing a float */
/// Reads an effect entry containing a float
void ReadEffectFloat(XmlNode &node, ai_real &pFloat);
/** Reads an effect parameter specification of any kind */
/// Reads an effect parameter specification of any kind
void ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam);
/** Reads the geometry library contents */
/// Reads the geometry library contents
void ReadGeometryLibrary(XmlNode &node);
/** Reads a geometry from the geometry library. */
/// Reads a geometry from the geometry library.
void ReadGeometry(XmlNode &node, Collada::Mesh &pMesh);
/** Reads a mesh from the geometry library */
/// Reads a mesh from the geometry library
void ReadMesh(XmlNode &node, Collada::Mesh &pMesh);
/** Reads a source element - a combination of raw data and an accessor defining
* things that should not be redefinable. Yes, that's another rant.
*/
/// Reads a source element - a combination of raw data and an accessor defining
///things that should not be definable. Yes, that's another rant.
void ReadSource(XmlNode &node);
/** Reads a data array holding a number of elements, and stores it in the global library.
* Currently supported are array of floats and arrays of strings.
*/
/// Reads a data array holding a number of elements, and stores it in the global library.
/// Currently supported are array of floats and arrays of strings.
void ReadDataArray(XmlNode &node);
/** Reads an accessor and stores it in the global library under the given ID -
* accessors use the ID of the parent <source> element
*/
/// Reads an accessor and stores it in the global library under the given ID -
/// accessors use the ID of the parent <source> element
void ReadAccessor(XmlNode &node, const std::string &pID);
/** Reads input declarations of per-vertex mesh data into the given mesh */
/// Reads input declarations of per-vertex mesh data into the given mesh
void ReadVertexData(XmlNode &node, Collada::Mesh &pMesh);
/** Reads input declarations of per-index mesh data into the given mesh */
/// Reads input declarations of per-index mesh data into the given mesh
void ReadIndexData(XmlNode &node, Collada::Mesh &pMesh);
/** Reads a single input channel element and stores it in the given array, if valid */
/// Reads a single input channel element and stores it in the given array, if valid
void ReadInputChannel(XmlNode &node, std::vector<Collada::InputChannel> &poChannels);
/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
/// Reads a <p> primitive index list and assembles the mesh data into the given mesh
size_t ReadPrimitives(XmlNode &node, Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
size_t pNumPrimitives, const std::vector<size_t> &pVCount, Collada::PrimitiveType pPrimType);
/** Copies the data for a single primitive into the mesh, based on the InputChannels */
/// Copies the data for a single primitive into the mesh, based on the InputChannels
void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
size_t currentPrimitive, const std::vector<size_t> &indices);
/** Reads one triangle of a tristrip into the mesh */
/// Reads one triangle of a tristrip into the mesh
void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh &pMesh,
std::vector<Collada::InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices);
/** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
/// Extracts a single object from an input channel and stores it in the appropriate mesh data array
void ExtractDataObjectFromChannel(const Collada::InputChannel &pInput, size_t pLocalIndex, Collada::Mesh &pMesh);
/** Reads the library of node hierarchies and scene parts */
/// Reads the library of node hierarchies and scene parts
void ReadSceneLibrary(XmlNode &node);
/** Reads a scene node's contents including children and stores it in the given node */
/// Reads a scene node's contents including children and stores it in the given node
void ReadSceneNode(XmlNode &node, Collada::Node *pNode);
/** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
void ReadNodeTransformation(XmlNode &node, Collada::Node *pNode, Collada::TransformType pType);
/** Reads a mesh reference in a node and adds it to the node's mesh list */
/// Reads a mesh reference in a node and adds it to the node's mesh list
void ReadNodeGeometry(XmlNode &node, Collada::Node *pNode);
/** Reads the collada scene */
/// Reads the collada scene
void ReadScene(XmlNode &node);
// Processes bind_vertex_input and bind elements
/// Processes bind_vertex_input and bind elements
void ReadMaterialVertexInputBinding(XmlNode &node, Collada::SemanticMappingTable &tbl);
/** Reads embedded textures from a ZAE archive*/
/// Reads embedded textures from a ZAE archive
void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
protected:
/** Calculates the resulting transformation from all the given transform steps */
/// Converts a path read from a collada file to the usual representation
static void UriDecodePath(aiString &ss);
/// Calculates the resulting transformation from all the given transform steps
aiMatrix4x4 CalculateResultTransform(const std::vector<Collada::Transform> &pTransforms) const;
/** Determines the input data type for the given semantic string */
/// Determines the input data type for the given semantic string
Collada::InputType GetTypeForSemantic(const std::string &pSemantic);
/** Finds the item in the given library by its reference, throws if not found */
/// Finds the item in the given library by its reference, throws if not found
template <typename Type>
const Type &ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const;
protected:
// Filename, for a verbose error message
private:
/// Filename, for a verbose error message
std::string mFileName;
// XML reader, member for everyday use
/// XML reader, member for everyday use
XmlParser mXmlParser;
/** All data arrays found in the file by ID. Might be referred to by actually
everyone. Collada, you are a steaming pile of indirection. */
/// All data arrays found in the file by ID. Might be referred to by actually
/// everyone. Collada, you are a steaming pile of indirection.
using DataLibrary = std::map<std::string, Collada::Data> ;
DataLibrary mDataLibrary;
/** Same for accessors which define how the data in a data array is accessed. */
/// Same for accessors which define how the data in a data array is accessed.
using AccessorLibrary = std::map<std::string, Collada::Accessor> ;
AccessorLibrary mAccessorLibrary;
/** Mesh library: mesh by ID */
/// Mesh library: mesh by ID
using MeshLibrary = std::map<std::string, Collada::Mesh *>;
MeshLibrary mMeshLibrary;
/** node library: root node of the hierarchy part by ID */
/// node library: root node of the hierarchy part by ID
using NodeLibrary = std::map<std::string, Collada::Node *>;
NodeLibrary mNodeLibrary;
/** Image library: stores texture properties by ID */
/// Image library: stores texture properties by ID
using ImageLibrary = std::map<std::string, Collada::Image> ;
ImageLibrary mImageLibrary;
/** Effect library: surface attributes by ID */
/// Effect library: surface attributes by ID
using EffectLibrary = std::map<std::string, Collada::Effect> ;
EffectLibrary mEffectLibrary;
/** Material library: surface material by ID */
/// Material library: surface material by ID
using MaterialLibrary = std::map<std::string, Collada::Material> ;
MaterialLibrary mMaterialLibrary;
/** Light library: surface light by ID */
/// Light library: surface light by ID
using LightLibrary = std::map<std::string, Collada::Light> ;
LightLibrary mLightLibrary;
/** Camera library: surface material by ID */
/// Camera library: surface material by ID
using CameraLibrary = std::map<std::string, Collada::Camera> ;
CameraLibrary mCameraLibrary;
/** Controller library: joint controllers by ID */
/// Controller library: joint controllers by ID
using ControllerLibrary = std::map<std::string, Collada::Controller> ;
ControllerLibrary mControllerLibrary;
/** Animation library: animation references by ID */
/// Animation library: animation references by ID
using AnimationLibrary = std::map<std::string, Collada::Animation *> ;
AnimationLibrary mAnimationLibrary;
/** Animation clip library: clip animation references by ID */
/// Animation clip library: clip animation references by ID
using AnimationClipLibrary = std::vector<std::pair<std::string, std::vector<std::string>>> ;
AnimationClipLibrary mAnimationClipLibrary;
/** Pointer to the root node. Don't delete, it just points to one of
the nodes in the node library. */
/// Pointer to the root node. Don't delete, it just points to one of the nodes in the node library.
Collada::Node *mRootNode;
/** Root animation container */
/// Root animation container
Collada::Animation mAnims;
/** Size unit: how large compared to a meter */
/// Size unit: how large compared to a meter
ai_real mUnitSize;
/** Which is the up vector */
/// Which is the up vector
enum { UP_X,
UP_Y,
UP_Z } mUpDirection;
/** Asset metadata (global for scene) */
/// Asset metadata (global for scene)
StringMetaData mAssetMetaData;
/** Collada file format version */
/// Collada file format version
Collada::FormatVersion mFormat;
};

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -54,18 +53,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <assimp/DefaultLogger.hpp>
namespace Assimp {
namespace DXF {
namespace Assimp::DXF {
// read pairs of lines, parse group code and value and provide utilities
// to convert the data to the target data type.
// do NOT skip empty lines. In DXF files, they count as valid data.
class LineReader {
public:
LineReader(StreamReaderLE& reader)
: splitter(reader,false,true)
, groupcode( 0 )
, end() {
explicit LineReader(StreamReaderLE& reader) : splitter(reader,false,true), groupcode( 0 ), end() {
// empty
}
@ -105,7 +100,7 @@ public:
}
// -----------------------------------------
float ValueAsFloat() const {
ai_real ValueAsFloat() const {
return fast_atof(value.c_str());
}
@ -165,8 +160,7 @@ private:
// represents a POLYLINE or a LWPOLYLINE. or even a 3DFACE The data is converted as needed.
struct PolyLine {
PolyLine()
: flags() {
PolyLine() : flags() {
// empty
}
@ -182,10 +176,7 @@ struct PolyLine {
// reference to a BLOCK. Specifies its own coordinate system.
struct InsertBlock {
InsertBlock()
: pos()
, scale(1.f,1.f,1.f)
, angle() {
InsertBlock() : pos(0.f, 0.f, 0.f), scale(1.f,1.f,1.f), angle(0.0f) {
// empty
}
@ -198,8 +189,7 @@ struct InsertBlock {
// keeps track of all geometry in a single BLOCK.
struct Block
{
struct Block {
std::vector< std::shared_ptr<PolyLine> > lines;
std::vector<InsertBlock> insertions;
@ -207,14 +197,11 @@ struct Block
aiVector3D base;
};
struct FileData
{
struct FileData {
// note: the LAST block always contains the stuff from ENTITIES.
std::vector<Block> blocks;
};
}
} // Namespace Assimp
} // namespace Assimp::DXF
#endif
#endif // INCLUDED_DXFHELPER_H

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -45,8 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
#include "AssetLib/DXF/DXFLoader.h"
#include "AssetLib/DXF/DXFHelper.h"
#include "DXFLoader.h"
#include "DXFHelper.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include <assimp/ParsingUtils.h>

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h>
#include <map>
namespace Assimp {
namespace Assimp {
// Forward declarations
namespace DXF {
@ -66,7 +66,7 @@ namespace DXF {
/**
* @brief DXF importer implementation.
*/
class DXFImporter : public BaseImporter {
class DXFImporter final : public BaseImporter {
public:
DXFImporter() = default;
~DXFImporter() override = default;

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -143,31 +143,33 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, cons
// ------------------------------------------------------------------------------------------------
const AnimationCurveMap &AnimationCurveNode::Curves() const {
if (curves.empty()) {
// resolve attached animation curves
const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationCurve");
if (!curves.empty()) {
return curves;
}
for (const Connection *con : conns) {
// resolve attached animation curves
const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationCurve");
// link should go for a property
if (!con->PropertyName().length()) {
continue;
}
for (const Connection *con : conns) {
const Object *const ob = con->SourceObject();
if (nullptr == ob) {
DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring", &element);
continue;
}
const AnimationCurve *const anim = dynamic_cast<const AnimationCurve *>(ob);
if (nullptr == anim) {
DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve", &element);
continue;
}
curves[con->PropertyName()] = anim;
// link should go for a property
if (!con->PropertyName().length()) {
continue;
}
const Object *const ob = con->SourceObject();
if (nullptr == ob) {
DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring", &element);
continue;
}
const AnimationCurve *const anim = dynamic_cast<const AnimationCurve *>(ob);
if (nullptr == anim) {
DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve", &element);
continue;
}
curves[con->PropertyName()] = anim;
}
return curves;

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -60,58 +59,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
//enum Flag
//{
// e_unknown_0 = 1 << 0,
// e_unknown_1 = 1 << 1,
// e_unknown_2 = 1 << 2,
// e_unknown_3 = 1 << 3,
// e_unknown_4 = 1 << 4,
// e_unknown_5 = 1 << 5,
// e_unknown_6 = 1 << 6,
// e_unknown_7 = 1 << 7,
// e_unknown_8 = 1 << 8,
// e_unknown_9 = 1 << 9,
// e_unknown_10 = 1 << 10,
// e_unknown_11 = 1 << 11,
// e_unknown_12 = 1 << 12,
// e_unknown_13 = 1 << 13,
// e_unknown_14 = 1 << 14,
// e_unknown_15 = 1 << 15,
// e_unknown_16 = 1 << 16,
// e_unknown_17 = 1 << 17,
// e_unknown_18 = 1 << 18,
// e_unknown_19 = 1 << 19,
// e_unknown_20 = 1 << 20,
// e_unknown_21 = 1 << 21,
// e_unknown_22 = 1 << 22,
// e_unknown_23 = 1 << 23,
// e_flag_field_size_64_bit = 1 << 24, // Not sure what is
// e_unknown_25 = 1 << 25,
// e_unknown_26 = 1 << 26,
// e_unknown_27 = 1 << 27,
// e_unknown_28 = 1 << 28,
// e_unknown_29 = 1 << 29,
// e_unknown_30 = 1 << 30,
// e_unknown_31 = 1 << 31
//};
//
//bool check_flag(uint32_t flags, Flag to_check)
//{
// return (flags & to_check) != 0;
//}
// ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, size_t offset)
:
#ifdef DEBUG
contents(sbegin, static_cast<size_t>(send-sbegin)),
#endif
sbegin(sbegin)
, send(send)
, type(type)
, line(offset)
, column(BINARY_MARKER)
{
Token::Token(const char* sbegin, const char* send, TokenType type, size_t offset) :
#ifdef DEBUG
contents(sbegin, static_cast<size_t>(send-sbegin)),
#endif
sbegin(sbegin),
send(send),
type(type),
line(offset),
column(BINARY_MARKER) {
ai_assert(sbegin);
ai_assert(send);
@ -134,7 +91,9 @@ AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset)
// ------------------------------------------------------------------------------------------------
size_t Offset(const char* begin, const char* cursor) {
ai_assert(begin <= cursor);
if (begin > cursor) {
return 0;
}
return cursor - begin;
}

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -47,11 +47,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
namespace Assimp {
namespace FBX {
namespace Assimp::FBX {
static constexpr size_t NumNullRecords = 25;
const char NULL_RECORD[NumNullRecords] = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
constexpr char NULL_RECORD[NumNullRecords] = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
}; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
@ -83,8 +83,7 @@ enum TransformInheritance {
TransformInheritance_MAX // end-of-enum sentinel
};
} // namespace FBX
} // namespace Assimp
} // namespace Assimp::FBX
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <set>
//
#if _MSC_VER > 1500 || (defined __GNUC___)
#if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
# else
# define fbx_unordered_map map

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -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.
struct FBXConverter::PotentialNode {
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; }
std::unique_ptr<aiNode> mOwnership;
aiNode* mNode;
@ -438,7 +438,8 @@ void FBXConverter::ConvertLight(const Light &light, const std::string &orig_name
out_light->mType = aiLightSource_UNDEFINED;
break;
default:
ai_assert(false);
FBXImporter::LogError("Not handled light type: ", light.LightType());
break;
}
float decay = light.DecayStart();
@ -463,7 +464,7 @@ void FBXConverter::ConvertLight(const Light &light, const std::string &orig_name
out_light->mAttenuationQuadratic = 1.0f;
break;
default:
ai_assert(false);
FBXImporter::LogError("Not handled light decay type: ", light.DecayType());
break;
}
}
@ -601,7 +602,7 @@ const char *FBXConverter::NameTransformationCompProperty(TransformationComp comp
return "GeometricRotationInverse";
case TransformationComp_GeometricTranslationInverse:
return "GeometricTranslationInverse";
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
case TransformationComp_MAXIMUM:
break;
}
@ -2957,7 +2958,7 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
// be invoked _later_ (animations come first). If this node has only rotation,
// scaling and translation _and_ there are no animated other components either,
// we can use a single node and also a single node animation channel.
if( !has_complex && !NeedsComplexTransformationChain(target)) {
if (!doc.Settings().preservePivots || (!has_complex && !NeedsComplexTransformationChain(target))) {
aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain,
node_property_map.end(),
start, stop,
@ -3415,7 +3416,7 @@ FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::
KeyFrameListList inputs;
inputs.reserve(nodes.size() * 3);
//give some breathing room for rounding errors
// give some breathing room for rounding errors
const int64_t adj_start = start - 10000;
const int64_t adj_stop = stop + 10000;
@ -3441,7 +3442,7 @@ FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::
ai_assert(curve->GetKeys().size() == curve->GetValues().size());
ai_assert(curve->GetKeys().size());
//get values within the start/stop time window
// get values within the start/stop time window
std::shared_ptr<KeyTimeList> Keys(new KeyTimeList());
std::shared_ptr<KeyValueList> Values(new KeyValueList());
const size_t count = curve->GetKeys().size();
@ -3461,8 +3462,7 @@ FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::
if (tnew >= adj_start && tnew <= adj_stop) {
Keys->push_back(tnew);
Values->push_back(vnew);
}
else {
} else {
// Something broke
break;
}

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