Compare commits
40
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30b20e07e7 | ||
|
|
fa18d3dde6 | ||
|
|
709fe3c3d0 | ||
|
|
489c8d565b | ||
|
|
0581ed5f11 | ||
|
|
5c568616ec | ||
|
|
45cb880835 | ||
|
|
dd98d4aea3 | ||
|
|
01ac320de8 | ||
|
|
a815a78433 | ||
|
|
69f8eb21fd | ||
|
|
72b9939b9f | ||
|
|
4c8a3bd39c | ||
|
|
8ef3838beb | ||
|
|
441884387f | ||
|
|
f7bbf6dc15 | ||
|
|
aadd49311a | ||
|
|
3f107bebf2 | ||
|
|
a38ec50fd3 | ||
|
|
4c42db1805 | ||
|
|
26e2372882 | ||
|
|
36b004e286 | ||
|
|
3a0ee8792f | ||
|
|
e3f9cf5564 | ||
|
|
6d7ea78792 | ||
|
|
13316790aa | ||
|
|
9255412906 | ||
|
|
8355e0c4bc | ||
|
|
6fa9d09a97 | ||
|
|
9f4e7c6d8d | ||
|
|
59bc03d931 | ||
|
|
edcb350129 | ||
|
|
a79dc358cf | ||
|
|
db0bde758e | ||
|
|
b447485c06 | ||
|
|
4c61ca3af5 | ||
|
|
4b6cc8c28a | ||
|
|
d99f9bd2f7 | ||
|
|
b2afe717d3 | ||
|
|
ad6e8e210a |
@@ -16,9 +16,13 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++]
|
||||
name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, windows-latest-clang.exe, ubuntu-latest-clang++]
|
||||
# For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
|
||||
include:
|
||||
- name: windows-latest-clang.exe
|
||||
os: windows-latest
|
||||
cxx: clang++.exe
|
||||
cc: clang.exe
|
||||
- name: windows-latest-cl.exe
|
||||
os: windows-latest
|
||||
cxx: cl.exe
|
||||
@@ -44,7 +48,7 @@ jobs:
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -69,13 +73,13 @@ jobs:
|
||||
${{ runner.os }}-DX_SDK
|
||||
|
||||
- name: Download DXSetup
|
||||
if: contains(matrix.name, 'windows') && steps.dxcache.outputs.cache-hit != 'true'
|
||||
if: contains(matrix.name, 'windows-latest-cl.exe') && steps.dxcache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
curl -s -o DXSDK_Jun10.exe --location https://download.microsoft.com/download/A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe
|
||||
cmd.exe /c start /wait .\DXSDK_Jun10.exe /U /O /F /S /P "${{ github.workspace }}\DX_SDK"
|
||||
|
||||
- name: Set Windows specific CMake arguments
|
||||
if: contains(matrix.name, 'windows')
|
||||
if: contains(matrix.name, 'windows-latest-cl.exe')
|
||||
id: windows_extra_cmake_args
|
||||
run: echo ":set-output name=args::=-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1" >> $GITHUB_OUTPUT
|
||||
|
||||
@@ -184,7 +188,7 @@ jobs:
|
||||
- id: upload-url
|
||||
run: |
|
||||
echo "url=$(cat create-release/release_upload_url.txt)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'
|
||||
- uses: actions/upload-release-asset@v1
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: lukka/get-cmake@latest
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
name: adress-sanitizer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: lukka/get-cmake@latest
|
||||
- uses: lukka/set-shell-env@v1
|
||||
with:
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
name: undefined-behavior-sanitizer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: lukka/get-cmake@latest
|
||||
- uses: lukka/set-shell-env@v1
|
||||
with:
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
name: printf-sanitizer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: run scan_printf script
|
||||
run: ./scripts/scan_printf.sh
|
||||
|
||||
@@ -67,7 +67,7 @@ The cmake-build-environment provides options to configure the build. The followi
|
||||
- **ASSIMP_NO_EXPORT (default OFF)**: Disable Assimp's export functionality.
|
||||
- **ASSIMP_BUILD_ZLIB (default OFF)**: Build our own zlib.
|
||||
- **ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all exporters enabled.
|
||||
- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all importers enabled.
|
||||
- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with (most) importers enabled. Currently, USD importer is not included. See ASSIMP_BUILD_USD_IMPORTER.
|
||||
- **ASSIMP_BUILD_ASSIMP_TOOLS (default OFF)**: If the supplementary tools for Assimp are built in addition to the library.
|
||||
- **ASSIMP_BUILD_SAMPLES (default OFF)**: If the official samples are built as well (needs Glut).
|
||||
- **ASSIMP_BUILD_TESTS (default ON)**: If the test suite for Assimp is built in addition to the library.
|
||||
@@ -83,6 +83,7 @@ The cmake-build-environment provides options to configure the build. The followi
|
||||
- **USE_STATIC_CRT (default OFF)**: Link against the static MSVC runtime libraries.
|
||||
- **ASSIMP_BUILD_DRACO (default OFF)**: Build Draco libraries. Primarily for glTF.
|
||||
- **ASSIMP_BUILD_ASSIMP_VIEW (default ON, if DirectX found, OFF otherwise)**: Build Assimp view tool (requires DirectX).
|
||||
- **ASSIMP_BUILD_USD_IMPORTER (default OFF, requires ASSIMP_WARNINGS_AS_ERRORS to be OFF)**: Build USD importer, defaults to off for CI purposes
|
||||
|
||||
### Install prebuild binaries
|
||||
## Install on all platforms using vcpkg
|
||||
@@ -109,5 +110,5 @@ You need to have pip installed:
|
||||
pip install pyassimp
|
||||
```
|
||||
|
||||
### Get the SDK from itchi.io
|
||||
Just check [itchi.io](https://kimkulling.itch.io/the-asset-importer-lib)
|
||||
### Get the SDK from itch.io
|
||||
Just check [itch.io](https://kimkulling.itch.io/the-asset-importer-lib)
|
||||
|
||||
+15
-5
@@ -309,6 +309,17 @@ IF( UNIX )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND WIN32)
|
||||
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
|
||||
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
|
||||
ENDIF()
|
||||
|
||||
IF( MSVC OR "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") # clang with MSVC ABI
|
||||
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
|
||||
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
|
||||
endif ()
|
||||
|
||||
|
||||
# Grouped compiler settings ########################################
|
||||
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU)
|
||||
IF(NOT ASSIMP_HUNTER_ENABLED)
|
||||
@@ -354,14 +365,13 @@ ELSEIF(MSVC)
|
||||
if(NOT /utf-8 IN_LIST CMAKE_CXX_FLAGS)
|
||||
# Source code is encoded in UTF-8
|
||||
ADD_COMPILE_OPTIONS(/source-charset:utf-8)
|
||||
endif ()
|
||||
|
||||
endif()
|
||||
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||
IF(NOT ASSIMP_HUNTER_ENABLED)
|
||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
ENDIF()
|
||||
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
|
||||
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS "-Wno-deprecated-non-prototype -fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
|
||||
SET(CMAKE_C_FLAGS "-Wno-deprecated-non-prototype -fno-strict-aliasing ${CMAKE_C_FLAGS}")
|
||||
ELSEIF( MINGW )
|
||||
IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
|
||||
message(FATAL_ERROR "MinGW is too old to be supported. Please update MinGW and try again.")
|
||||
@@ -581,7 +591,7 @@ ELSE()
|
||||
SET(ASSIMP_BUILD_MINIZIP 1)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
|
||||
SET(ZLIB_LIBRARIES_LINKED -lz)
|
||||
SET(ZLIB_LIBRARIES_LINKED -l${ZLIB_LIBRARIES})
|
||||
ENDIF()
|
||||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
|
||||
ENDIF()
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 20,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "assimp_with_tools",
|
||||
"binaryDir": "${sourceDir}",
|
||||
"cacheVariables": {
|
||||
"ASSIMP_BUILD_ASSIMP_TOOLS" : "ON"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
FROM gcc:latest
|
||||
FROM gcc:1.5.1.0
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y ninja-build cmake
|
||||
RUN apt-get update \
|
||||
apt-get install --no-install-recommends -y ninja-build cmake zlib1g-dev
|
||||
|
||||
WORKDIR /app
|
||||
RUN apt install zlib1g-dev
|
||||
|
||||
COPY . .
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2021, assimp team
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
||||
@@ -20,17 +20,17 @@ Additionally, assimp features various __mesh post-processing tools__: normals an
|
||||

|
||||
|
||||
### Documentation ###
|
||||
Read [our latest documentation](https://assimp-docs.readthedocs.io/en/latest/).
|
||||
Read [our latest documentation](https://the-asset-importer-lib-documentation.readthedocs.io/en/latest/).
|
||||
|
||||
### Pre-built binaries ###
|
||||
Download binaries from [our Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib).
|
||||
Download binaries from [our Itch Projectspace](https://kimkulling.itch.io/the-asset-importer-lib).
|
||||
|
||||
### Test data ###
|
||||
Clone [our model database](https://github.com/assimp/assimp-mdb).
|
||||
Clone [our model database for testing purposes](https://github.com/assimp/assimp-mdb).
|
||||
|
||||
### Communities ###
|
||||
- Ask questions at [the Assimp Discussion Board](https://github.com/assimp/assimp/discussions).
|
||||
- Find us on [https://discord.gg/s9KJfaem](https://discord.gg/kKazXMXDy2)
|
||||
- Find us on [discord](https://discord.gg/kKazXMXDy2)
|
||||
- Ask [the Assimp community on Reddit](https://www.reddit.com/r/Assimp/).
|
||||
- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
|
||||
- Nothing has worked? File a question or an issue report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
|
||||
@@ -83,7 +83,7 @@ The source code is organized in the following way:
|
||||
code/AssetLib/<FormatName> Implementation for import and export of the format
|
||||
|
||||
### Contributing ###
|
||||
I would greatly appreciate contributing to assimp. The easiest way to get involved is to submit
|
||||
We would greatly appreciate for you to contribute to assimp. The easiest way to get involved is to submit
|
||||
a pull request with your changes against the main repository's `master` branch.
|
||||
|
||||
## Contributors
|
||||
|
||||
+1
-2
@@ -2,8 +2,7 @@
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
The current version of Assimp that's being supported with security updates:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
|
||||
@@ -319,7 +319,7 @@ void Discreet3DSImporter::ConvertMaterial(Material &oldMat, aiMaterial &mat) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Split meshes by their materials and generate output aiMesh'es
|
||||
void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
|
||||
std::vector<aiMesh *> avOutMeshes;
|
||||
MeshArray avOutMeshes;
|
||||
avOutMeshes.reserve(mScene->mMeshes.size() * 2);
|
||||
|
||||
unsigned int iFaceCnt = 0, num = 0;
|
||||
|
||||
@@ -157,7 +157,7 @@ struct Component {
|
||||
|
||||
class Object : public Resource {
|
||||
public:
|
||||
std::vector<aiMesh *> mMeshes;
|
||||
MeshArray mMeshes;
|
||||
std::vector<unsigned int> mMeshIndex;
|
||||
std::vector<Component> mComponents;
|
||||
std::string mName;
|
||||
|
||||
@@ -58,9 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Assimp::D3MF {
|
||||
|
||||
namespace D3MF {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
|
||||
@@ -132,9 +131,11 @@ static bool IsEmbeddedTexture( const std::string &filename ) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
||||
mRootStream(nullptr),
|
||||
mZipArchive() {
|
||||
mZipArchive(nullptr) {
|
||||
mZipArchive = new ZipArchiveIOSystem(pIOHandler, rFile);
|
||||
if (!mZipArchive->isOpen()) {
|
||||
delete mZipArchive;
|
||||
mZipArchive = nullptr;
|
||||
throw DeadlyImportError("Failed to open file ", rFile, ".");
|
||||
}
|
||||
|
||||
@@ -184,7 +185,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
||||
}
|
||||
|
||||
D3MFOpcPackage::~D3MFOpcPackage() {
|
||||
mZipArchive->Close(mRootStream);
|
||||
if (mRootStream && mZipArchive) {
|
||||
mZipArchive->Close(mRootStream);
|
||||
}
|
||||
delete mZipArchive;
|
||||
}
|
||||
|
||||
@@ -250,7 +253,6 @@ void D3MFOpcPackage::LoadEmbeddedTextures(IOStream *fileStream, const std::strin
|
||||
mEmbeddedTextures.emplace_back(texture);
|
||||
}
|
||||
|
||||
} // Namespace D3MF
|
||||
} // Namespace Assimp
|
||||
} // Namespace Assimp::D3MF
|
||||
|
||||
#endif //ASSIMP_BUILD_NO_3MF_IMPORTER
|
||||
|
||||
@@ -495,13 +495,16 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||
}
|
||||
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
|
||||
for (unsigned int vertex_index = 0; vertex_index < mesh->mNumVertices; vertex_index++) {
|
||||
mesh->mTextureCoords[0][vertex_index].z = IdNotSet;//mark not set
|
||||
mesh->mTextureCoords[0][vertex_index].z = IdNotSet; //mark not set
|
||||
}
|
||||
}
|
||||
|
||||
auto update_texture = [&](int idx) {
|
||||
if (pindex[idx] != IdNotSet) {
|
||||
size_t vertex_index = face.mIndices[idx];
|
||||
if (vertex_index >= mesh->mNumVertices) {
|
||||
return;
|
||||
}
|
||||
mesh->mTextureCoords[0][vertex_index] =
|
||||
aiVector3D(group->mTex2dCoords[pindex[idx]].x, group->mTex2dCoords[pindex[idx]].y, 0.0f);
|
||||
}
|
||||
@@ -521,6 +524,9 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||
auto update_color = [&](int idx) {
|
||||
if (pindex[idx] != IdNotSet) {
|
||||
size_t vertex_index = face.mIndices[idx];
|
||||
if (vertex_index >= mesh->mNumVertices) {
|
||||
return;
|
||||
}
|
||||
mesh->mColors[0][vertex_index] = group->mColors[pindex[idx]];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,6 +75,8 @@ static constexpr aiImporterDesc desc = {
|
||||
"ac acc ac3d"
|
||||
};
|
||||
|
||||
static constexpr auto ACDoubleSidedFlag = 0x20;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// skip to the next token
|
||||
inline const char *AcSkipToNextToken(const char *buffer, const char *end) {
|
||||
@@ -123,12 +125,36 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *end,
|
||||
}
|
||||
for (unsigned int _i = 0; _i < num; ++_i) {
|
||||
buffer = AcSkipToNextToken(buffer, end);
|
||||
buffer = fast_atoreal_move<float>(buffer, ((float *)out)[_i]);
|
||||
buffer = fast_atoreal_move(buffer, ((float *)out)[_i]);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Reverses vertex indices in a face.
|
||||
static void flipWindingOrder(aiFace &f) {
|
||||
std::reverse(f.mIndices, f.mIndices + f.mNumIndices);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Duplicates a face and inverts it. Also duplicates all vertices (so the new face gets its own
|
||||
// set of normals and isn’t smoothed against the original).
|
||||
static void buildBacksideOfFace(const aiFace &origFace, aiFace *&outFaces, aiVector3D *&outVertices, const aiVector3D *allVertices,
|
||||
aiVector3D *&outUV, const aiVector3D *allUV, unsigned &curIdx) {
|
||||
auto &newFace = *outFaces++;
|
||||
newFace = origFace;
|
||||
flipWindingOrder(newFace);
|
||||
for (unsigned f = 0; f < newFace.mNumIndices; ++f) {
|
||||
*outVertices++ = allVertices[newFace.mIndices[f]];
|
||||
if (outUV) {
|
||||
*outUV = allUV[newFace.mIndices[f]];
|
||||
outUV++;
|
||||
}
|
||||
newFace.mIndices[f] = curIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
AC3DImporter::AC3DImporter() :
|
||||
@@ -392,7 +418,7 @@ void AC3DImporter::ConvertMaterial(const Object &object,
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts the loaded data to the internal verbose representation
|
||||
aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
std::vector<aiMesh *> &meshes,
|
||||
MeshArray &meshes,
|
||||
std::vector<aiMaterial *> &outMaterials,
|
||||
const std::vector<Material> &materials,
|
||||
aiNode *parent) {
|
||||
@@ -451,6 +477,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
if ((*it).entries.empty()) {
|
||||
ASSIMP_LOG_WARN("AC3D: surface has zero vertex references");
|
||||
}
|
||||
const bool isDoubleSided = ACDoubleSidedFlag == (it->flags & ACDoubleSidedFlag);
|
||||
const int doubleSidedFactor = isDoubleSided ? 2 : 1;
|
||||
|
||||
// validate all vertex indices to make sure we won't crash here
|
||||
for (it2 = (*it).entries.begin(),
|
||||
@@ -480,8 +508,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
|
||||
// triangle strip
|
||||
case Surface::TriangleStrip:
|
||||
needMat[idx].first += (unsigned int)(*it).entries.size() - 2;
|
||||
needMat[idx].second += ((unsigned int)(*it).entries.size() - 2) * 3;
|
||||
needMat[idx].first += static_cast<unsigned int>(it->entries.size() - 2) * doubleSidedFactor;
|
||||
needMat[idx].second += static_cast<unsigned int>(it->entries.size() - 2) * 3 * doubleSidedFactor;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -494,8 +522,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
case Surface::Polygon:
|
||||
// the number of faces increments by one, the number
|
||||
// of vertices by surface.numref.
|
||||
needMat[idx].first++;
|
||||
needMat[idx].second += (unsigned int)(*it).entries.size();
|
||||
needMat[idx].first += doubleSidedFactor;
|
||||
needMat[idx].second += static_cast<unsigned int>(it->entries.size()) * doubleSidedFactor;
|
||||
};
|
||||
}
|
||||
unsigned int *pip = node->mMeshes = new unsigned int[node->mNumMeshes];
|
||||
@@ -545,6 +573,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
for (it = object.surfaces.begin(); it != end; ++it) {
|
||||
if (mat == (*it).mat) {
|
||||
const Surface &src = *it;
|
||||
const bool isDoubleSided = ACDoubleSidedFlag == (src.flags & ACDoubleSidedFlag);
|
||||
|
||||
// closed polygon
|
||||
uint8_t type = (*it).GetType();
|
||||
@@ -570,6 +599,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
++uv;
|
||||
}
|
||||
}
|
||||
if(isDoubleSided) // Need a backface?
|
||||
buildBacksideOfFace(faces[-1], faces, vertices, mesh->mVertices, uv, mesh->mTextureCoords[0], cur);
|
||||
}
|
||||
} else if (type == Surface::TriangleStrip) {
|
||||
for (unsigned int i = 0; i < (unsigned int)src.entries.size() - 2; ++i) {
|
||||
@@ -619,6 +650,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
uv->y = entry3.second.y;
|
||||
++uv;
|
||||
}
|
||||
if(isDoubleSided) // Need a backface?
|
||||
buildBacksideOfFace(faces[-1], faces, vertices, mesh->mVertices, uv, mesh->mTextureCoords[0], cur);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -677,7 +710,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
||||
std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
|
||||
ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: ", object.name);
|
||||
|
||||
std::vector<aiMesh *> cpy(meshes.size() - oldm, nullptr);
|
||||
MeshArray cpy(meshes.size() - oldm, nullptr);
|
||||
div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true);
|
||||
std::copy(cpy.begin(), cpy.end(), meshes.begin() + oldm);
|
||||
|
||||
@@ -813,7 +846,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
|
||||
}
|
||||
|
||||
mNumMeshes += (mNumMeshes >> 2u) + 1;
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
meshes.reserve(mNumMeshes);
|
||||
|
||||
std::vector<aiMaterial *> omaterials;
|
||||
|
||||
@@ -226,7 +226,7 @@ private:
|
||||
* @param materials Material list
|
||||
* @param Scenegraph node for the object */
|
||||
aiNode *ConvertObjectSection(Object &object,
|
||||
std::vector<aiMesh *> &meshes,
|
||||
MeshArray &meshes,
|
||||
std::vector<aiMaterial *> &outMaterials,
|
||||
const std::vector<Material> &materials,
|
||||
aiNode *parent = nullptr);
|
||||
|
||||
@@ -99,8 +99,6 @@ namespace Assimp {
|
||||
///
|
||||
class AMFImporter : public BaseImporter {
|
||||
using AMFMetaDataArray = std::vector<AMFMetadata *>;
|
||||
using MeshArray = std::vector<aiMesh *>;
|
||||
using NodeArray = std::vector<aiNode *>;
|
||||
|
||||
public:
|
||||
struct SPP_Material;
|
||||
|
||||
@@ -162,7 +162,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
|
||||
|
||||
// process all meshes
|
||||
bool tookNormals = false;
|
||||
std::vector<aiMesh *> avOutMeshes;
|
||||
MeshArray avOutMeshes;
|
||||
avOutMeshes.reserve(mParser->m_vMeshes.size() * 2);
|
||||
for (std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin(); i != mParser->m_vMeshes.end(); ++i) {
|
||||
if ((*i).bSkip) {
|
||||
@@ -187,7 +187,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
|
||||
// Now build the output mesh list. Remove dummies
|
||||
pScene->mNumMeshes = (unsigned int)avOutMeshes.size();
|
||||
aiMesh **pp = pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
||||
for (std::vector<aiMesh *>::const_iterator i = avOutMeshes.begin(); i != avOutMeshes.end(); ++i) {
|
||||
for (MeshArray::const_iterator i = avOutMeshes.begin(); i != avOutMeshes.end(); ++i) {
|
||||
if (!(*i)->mNumFaces) {
|
||||
continue;
|
||||
}
|
||||
@@ -902,7 +902,7 @@ void ASEImporter::ConvertMaterial(ASE::Material &mat) {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build output meshes
|
||||
void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, std::vector<aiMesh *> &avOutMeshes) {
|
||||
void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, MeshArray &avOutMeshes) {
|
||||
// validate the material index of the mesh
|
||||
if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) {
|
||||
mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size() - 1;
|
||||
|
||||
@@ -1427,7 +1427,7 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes
|
||||
|
||||
// then parse the vertex weight
|
||||
if (!SkipSpaces(&mFilePtr, mEnd)) break;
|
||||
mFilePtr = fast_atoreal_move<float>(mFilePtr, pairOut.second);
|
||||
mFilePtr = fast_atoreal_move(mFilePtr, pairOut.second);
|
||||
|
||||
// -1 marks unused entries
|
||||
if (-1 != pairOut.first) {
|
||||
@@ -1893,7 +1893,7 @@ void Parser::ParseLV4MeshReal(ai_real &fOut) {
|
||||
return;
|
||||
}
|
||||
// parse the first float
|
||||
mFilePtr = fast_atoreal_move<ai_real>(mFilePtr, fOut);
|
||||
mFilePtr = fast_atoreal_move(mFilePtr, fOut);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Parser::ParseLV4MeshFloat(float &fOut) {
|
||||
@@ -1906,7 +1906,7 @@ void Parser::ParseLV4MeshFloat(float &fOut) {
|
||||
return;
|
||||
}
|
||||
// parse the first float
|
||||
mFilePtr = fast_atoreal_move<float>(mFilePtr, fOut);
|
||||
mFilePtr = fast_atoreal_move(mFilePtr, fOut);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Parser::ParseLV4MeshLong(unsigned int &iOut) {
|
||||
|
||||
@@ -385,7 +385,7 @@ float BVHLoader::GetNextTokenAsFloat() {
|
||||
// check if the float is valid by testing if the atof() function consumed every char of the token
|
||||
const char *ctoken = token.c_str();
|
||||
float result = 0.0f;
|
||||
ctoken = fast_atoreal_move<float>(ctoken, result);
|
||||
ctoken = fast_atoreal_move(ctoken, result);
|
||||
|
||||
if (ctoken != token.c_str() + token.length())
|
||||
ThrowException("Expected a floating point number, but found \"", token, "\".");
|
||||
|
||||
@@ -961,7 +961,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
|
||||
if (mesh->totface > static_cast<int>(mesh->mtface.size())) {
|
||||
ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)");
|
||||
}
|
||||
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
for (MeshArray::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
ai_assert(0 != (*it)->mNumVertices);
|
||||
ai_assert(0 != (*it)->mNumFaces);
|
||||
const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
|
||||
@@ -1030,7 +1030,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
|
||||
if (mesh->totface > static_cast<int>(mesh->tface.size())) {
|
||||
ThrowException("Number of faces is larger than the corresponding UV face array (#2)");
|
||||
}
|
||||
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
for (MeshArray::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
ai_assert(0 != (*it)->mNumVertices);
|
||||
ai_assert(0 != (*it)->mNumFaces);
|
||||
|
||||
@@ -1057,7 +1057,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
|
||||
if (mesh->totface > static_cast<int>((mesh->mcol.size() / 4))) {
|
||||
ThrowException("Number of faces is larger than the corresponding color face array");
|
||||
}
|
||||
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
for (MeshArray::iterator it = temp->begin() + old; it != temp->end(); ++it) {
|
||||
ai_assert(0 != (*it)->mNumVertices);
|
||||
ai_assert(0 != (*it)->mNumFaces);
|
||||
|
||||
|
||||
@@ -166,10 +166,10 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
||||
// copy meshes over
|
||||
pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
|
||||
std::copy(meshes.begin(), meshes.end(), pScene->mMeshes);
|
||||
std::copy(mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
|
||||
|
||||
// copy materials over, adding a default material if necessary
|
||||
unsigned int mat_count = static_cast<unsigned int>(materials.size());
|
||||
unsigned int mat_count = static_cast<unsigned int>(mMaterials.size());
|
||||
for(aiMesh* mesh : meshes) {
|
||||
ai_assert(mesh->mMaterialIndex <= mat_count);
|
||||
if(mesh->mMaterialIndex >= mat_count) {
|
||||
@@ -179,14 +179,14 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
||||
const aiString name(AI_DEFAULT_MATERIAL_NAME);
|
||||
def_material->AddProperty(&name, AI_MATKEY_NAME);
|
||||
|
||||
materials.push_back(def_material.release());
|
||||
mMaterials.push_back(def_material.release());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pScene->mNumMaterials = static_cast<unsigned int>(materials.size());
|
||||
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
|
||||
std::copy(materials.begin(), materials.end(), pScene->mMaterials);
|
||||
std::copy(mMaterials.begin(), mMaterials.end(), pScene->mMaterials);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -251,8 +251,8 @@ void C4DImporter::ReadMaterials(BaseMaterial* mat) {
|
||||
while (mat) {
|
||||
if (mat->GetType() == Mmaterial) {
|
||||
aiMaterial* out = new aiMaterial();
|
||||
material_mapping[mat] = static_cast<unsigned int>(materials.size());
|
||||
materials.push_back(out);
|
||||
mMaterialMapping[mat] = static_cast<unsigned int>(mMaterials.size());
|
||||
mMaterials.push_back(out);
|
||||
|
||||
auto const ai_name = aiStringFrom(mat->GetName());
|
||||
out->AddProperty(&ai_name, AI_MATKEY_NAME);
|
||||
@@ -289,7 +289,7 @@ void C4DImporter::ReadMaterials(BaseMaterial* mat) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
|
||||
ai_assert(parent != nullptr );
|
||||
std::vector<aiNode*> nodes;
|
||||
NodeArray nodes;
|
||||
|
||||
// based on Cineware sample code
|
||||
while (object) {
|
||||
@@ -577,7 +577,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
|
||||
unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) {
|
||||
ai_assert(obj != nullptr);
|
||||
|
||||
const unsigned int mat_count = static_cast<unsigned int>(materials.size());
|
||||
const unsigned int mat_count = static_cast<unsigned int>(mMaterials.size());
|
||||
|
||||
BaseTag* tag = obj->GetTag(Ttexture);
|
||||
if(tag == nullptr) {
|
||||
|
||||
@@ -97,11 +97,12 @@ private:
|
||||
|
||||
bool ReadShader(aiMaterial* out, cineware::BaseShader* shader);
|
||||
|
||||
std::vector<aiMesh*> meshes;
|
||||
std::vector<aiMaterial*> materials;
|
||||
private:
|
||||
MeshArray mMeshes;
|
||||
MaterialArray materials;
|
||||
|
||||
typedef std::map<cineware::BaseMaterial*, unsigned int> MaterialMap;
|
||||
MaterialMap material_mapping;
|
||||
using MaterialMap = std::map<cineware::BaseMaterial*, unsigned int> ;
|
||||
MaterialMap mMaterialMapping;
|
||||
|
||||
}; // !class C4DImporter
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
|
||||
else if (TokenMatchI(buffer,"rate",4)) {
|
||||
SkipSpaces(&buffer, end);
|
||||
float d = { 0.0f };
|
||||
buffer = fast_atoreal_move<float>(buffer,d);
|
||||
buffer = fast_atoreal_move(buffer,d);
|
||||
anim->mTicksPerSecond = d;
|
||||
}
|
||||
else if (TokenMatchI(buffer,"order",5)) {
|
||||
@@ -226,17 +226,17 @@ void CSMImporter::InternReadFile( const std::string& pFile,
|
||||
} else {
|
||||
aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
|
||||
sub->mTime = (double)frame;
|
||||
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
|
||||
buffer = fast_atoreal_move(buffer, sub->mValue.x);
|
||||
|
||||
if (!SkipSpacesAndLineEnd(&buffer, end)) {
|
||||
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample y coord");
|
||||
}
|
||||
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
|
||||
buffer = fast_atoreal_move(buffer, sub->mValue.y);
|
||||
|
||||
if (!SkipSpacesAndLineEnd(&buffer, end)) {
|
||||
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample z coord");
|
||||
}
|
||||
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
|
||||
buffer = fast_atoreal_move(buffer, sub->mValue.z);
|
||||
|
||||
++s->mNumPositionKeys;
|
||||
}
|
||||
|
||||
@@ -668,7 +668,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
|
||||
}
|
||||
|
||||
// create morph target meshes if any
|
||||
std::vector<aiMesh *> targetMeshes;
|
||||
MeshArray targetMeshes;
|
||||
std::vector<float> targetWeights;
|
||||
Collada::MorphMethod method = Normalized;
|
||||
|
||||
|
||||
@@ -206,10 +206,10 @@ private:
|
||||
std::map<std::string, size_t> mMaterialIndexByName;
|
||||
|
||||
/** Accumulated meshes for the target scene */
|
||||
std::vector<aiMesh *> mMeshes;
|
||||
MeshArray mMeshes;
|
||||
|
||||
/** Accumulated morph target meshes */
|
||||
std::vector<aiMesh *> mTargetMeshes;
|
||||
MeshArray mTargetMeshes;
|
||||
|
||||
/** Temporary material list */
|
||||
std::vector<std::pair<Collada::Effect *, aiMaterial *>> newMats;
|
||||
|
||||
@@ -129,7 +129,7 @@ static void ReadNodeTransformation(XmlNode &node, Node *pNode, TransformType pTy
|
||||
// skip whitespace before the number
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
// read a number
|
||||
content = fast_atoreal_move<ai_real>(content, tf.f[a]);
|
||||
content = fast_atoreal_move(content, tf.f[a]);
|
||||
}
|
||||
|
||||
// place the transformation at the queue of the node
|
||||
@@ -346,13 +346,13 @@ static void ReadLight(XmlNode &node, Light &pLight) {
|
||||
const char *content = v.c_str();
|
||||
const char *end = content + v.size();
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.r);
|
||||
content = fast_atoreal_move(content, pLight.mColor.r);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.g);
|
||||
content = fast_atoreal_move(content, pLight.mColor.g);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b);
|
||||
content = fast_atoreal_move(content, pLight.mColor.b);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
} else if (currentName == "constant_attenuation") {
|
||||
XmlParser::getValueAsReal(currentNode, pLight.mAttConstant);
|
||||
@@ -631,7 +631,7 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
|
||||
std::string tUnitSizeString;
|
||||
if (XmlParser::getStdStrAttribute(currentNode, "meter", tUnitSizeString)) {
|
||||
try {
|
||||
fast_atoreal_move<ai_real>(tUnitSizeString.data(), mUnitSize);
|
||||
fast_atoreal_move(tUnitSizeString.data(), mUnitSize);
|
||||
} catch (const DeadlyImportError& die) {
|
||||
std::string warning("Collada: Failed to parse meter parameter to real number. Exception:\n");
|
||||
warning.append(die.what());
|
||||
@@ -889,7 +889,7 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
|
||||
for (auto & a : controller.mBindShapeMatrix) {
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
// read a number
|
||||
content = fast_atoreal_move<ai_real>(content, a);
|
||||
content = fast_atoreal_move(content, a);
|
||||
// skip whitespace after it
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
}
|
||||
@@ -1262,16 +1262,16 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
|
||||
const char *content = v.c_str();
|
||||
const char *end = v.c_str() + v.size() + 1;
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.r);
|
||||
content = fast_atoreal_move(content, pColor.r);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.g);
|
||||
content = fast_atoreal_move(content, pColor.g);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.b);
|
||||
content = fast_atoreal_move(content, pColor.b);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.a);
|
||||
content = fast_atoreal_move(content, pColor.a);
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
} else if (currentName == "texture") {
|
||||
// get name of source texture/sampler
|
||||
@@ -1494,7 +1494,7 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
|
||||
|
||||
// read a number
|
||||
ai_real value;
|
||||
content = fast_atoreal_move<ai_real>(content, value);
|
||||
content = fast_atoreal_move(content, value);
|
||||
data.mValues.push_back(value);
|
||||
// skip whitespace after it
|
||||
SkipSpacesAndLineEnd(&content, end);
|
||||
|
||||
@@ -91,7 +91,9 @@ AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
size_t Offset(const char* begin, const char* cursor) {
|
||||
ai_assert(begin <= cursor);
|
||||
if (begin > cursor) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cursor - begin;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace FBX {
|
||||
|
||||
using namespace Util;
|
||||
|
||||
#define MAGIC_NODE_TAG "_$AssimpFbx$"
|
||||
static constexpr char MAGIC_NODE_TAG[] = "_$AssimpFbx$";
|
||||
|
||||
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL
|
||||
|
||||
@@ -125,21 +125,10 @@ static void correctRootTransform(const aiScene *scene) {
|
||||
|
||||
FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) :
|
||||
defaultMaterialIndex(),
|
||||
mMeshes(),
|
||||
lights(),
|
||||
cameras(),
|
||||
textures(),
|
||||
materials_converted(),
|
||||
textures_converted(),
|
||||
meshes_converted(),
|
||||
node_anim_chain_bits(),
|
||||
mNodeNames(),
|
||||
anim_fps(),
|
||||
mSceneOut(out),
|
||||
doc(doc),
|
||||
mRemoveEmptyBones(removeEmptyBones) {
|
||||
|
||||
|
||||
// animations need to be converted first since this will
|
||||
// populate the node_anim_chain_bits map, which is needed
|
||||
// to determine which nodes need to be generated.
|
||||
@@ -162,7 +151,7 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
|
||||
continue;
|
||||
}
|
||||
|
||||
const Material *mat = dynamic_cast<const Material *>(ob);
|
||||
auto mat = dynamic_cast<const Material *>(ob);
|
||||
if (mat) {
|
||||
|
||||
if (materials_converted.find(mat) == materials_converted.end()) {
|
||||
@@ -222,7 +211,6 @@ static std::string getAncestorBaseName(const aiNode *node) {
|
||||
return std::string(nodeName, length);
|
||||
}
|
||||
|
||||
// Make unique name
|
||||
std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiNode &parent) {
|
||||
std::string original_name = FixNodeName(model->Name());
|
||||
if (original_name.empty()) {
|
||||
@@ -236,9 +224,18 @@ std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiN
|
||||
/// This struct manages nodes which may or may not end up in the node hierarchy.
|
||||
/// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
|
||||
struct FBXConverter::PotentialNode {
|
||||
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
|
||||
PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
|
||||
aiNode* operator->() { return mNode; }
|
||||
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {
|
||||
// empty
|
||||
}
|
||||
|
||||
explicit PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {
|
||||
// empty
|
||||
}
|
||||
|
||||
aiNode* operator->() {
|
||||
return mNode;
|
||||
}
|
||||
|
||||
std::unique_ptr<aiNode> mOwnership;
|
||||
aiNode* mNode;
|
||||
};
|
||||
@@ -1092,14 +1089,14 @@ aiMesh *FBXConverter::SetupEmptyMesh(const Geometry &mesh, aiNode *parent) {
|
||||
}
|
||||
|
||||
static aiSkeleton *createAiSkeleton(SkeletonBoneContainer &sbc) {
|
||||
if (sbc.MeshArray.empty() || sbc.SkeletonBoneToMeshLookup.empty()) {
|
||||
if (sbc.meshArray.empty() || sbc.skeletonBoneToMeshLookup.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
aiSkeleton *skeleton = new aiSkeleton;
|
||||
for (auto *mesh : sbc.MeshArray) {
|
||||
auto it = sbc.SkeletonBoneToMeshLookup.find(mesh);
|
||||
if (it == sbc.SkeletonBoneToMeshLookup.end()) {
|
||||
for (auto *mesh : sbc.meshArray) {
|
||||
auto it = sbc.skeletonBoneToMeshLookup.find(mesh);
|
||||
if (it == sbc.skeletonBoneToMeshLookup.end()) {
|
||||
continue;
|
||||
}
|
||||
SkeletonBoneArray *ba = it->second;
|
||||
@@ -1547,12 +1544,12 @@ static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *s
|
||||
void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent, unsigned int materialIndex,
|
||||
std::vector<unsigned int> *outputVertStartIndices, SkeletonBoneContainer &skeletonContainer) {
|
||||
|
||||
if (skeletonContainer.SkeletonBoneToMeshLookup.find(out) != skeletonContainer.SkeletonBoneToMeshLookup.end()) {
|
||||
if (skeletonContainer.skeletonBoneToMeshLookup.find(out) != skeletonContainer.skeletonBoneToMeshLookup.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConvertWeights(out, geo, absolute_transform, parent, materialIndex, outputVertStartIndices);
|
||||
skeletonContainer.MeshArray.emplace_back(out);
|
||||
skeletonContainer.meshArray.emplace_back(out);
|
||||
SkeletonBoneArray *ba = new SkeletonBoneArray;
|
||||
for (size_t i = 0; i < out->mNumBones; ++i) {
|
||||
aiBone *bone = out->mBones[i];
|
||||
@@ -1563,7 +1560,7 @@ void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo
|
||||
copyBoneToSkeletonBone(out, bone, skeletonBone);
|
||||
ba->emplace_back(skeletonBone);
|
||||
}
|
||||
skeletonContainer.SkeletonBoneToMeshLookup[out] = ba;
|
||||
skeletonContainer.skeletonBoneToMeshLookup[out] = ba;
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
|
||||
@@ -1571,8 +1568,6 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
|
||||
std::vector<unsigned int> *outputVertStartIndices) {
|
||||
ai_assert(geo.DeformerSkin());
|
||||
|
||||
std::vector<size_t> out_indices, index_out_indices, count_out_indices;
|
||||
|
||||
const Skin &sk = *geo.DeformerSkin();
|
||||
|
||||
std::vector<aiBone*> bones;
|
||||
@@ -1580,6 +1575,10 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
|
||||
ai_assert(no_mat_check || outputVertStartIndices);
|
||||
|
||||
try {
|
||||
std::vector<size_t> count_out_indices;
|
||||
std::vector<size_t> index_out_indices;
|
||||
std::vector<size_t> out_indices;
|
||||
|
||||
// iterate over the sub deformers
|
||||
for (const Cluster *cluster : sk.Clusters()) {
|
||||
ai_assert(cluster);
|
||||
@@ -1751,10 +1750,10 @@ unsigned int FBXConverter::GetDefaultMaterial() {
|
||||
return defaultMaterialIndex - 1;
|
||||
}
|
||||
|
||||
aiMaterial *out_mat = new aiMaterial();
|
||||
auto out_mat = new aiMaterial();
|
||||
materials.push_back(out_mat);
|
||||
|
||||
const aiColor3D diffuse = aiColor3D(0.8f, 0.8f, 0.8f);
|
||||
const auto diffuse = aiColor3D(0.8f, 0.8f, 0.8f);
|
||||
out_mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
|
||||
aiString s;
|
||||
@@ -1770,7 +1769,7 @@ unsigned int FBXConverter::ConvertMaterial(const Material &material, const MeshG
|
||||
const PropertyTable &props = material.Props();
|
||||
|
||||
// generate empty output material
|
||||
aiMaterial *out_mat = new aiMaterial();
|
||||
auto out_mat = new aiMaterial();
|
||||
materials_converted[&material] = static_cast<unsigned int>(materials.size());
|
||||
|
||||
materials.push_back(out_mat);
|
||||
@@ -1809,7 +1808,7 @@ unsigned int FBXConverter::ConvertMaterial(const Material &material, const MeshG
|
||||
|
||||
unsigned int FBXConverter::ConvertVideo(const Video &video) {
|
||||
// generate empty output texture
|
||||
aiTexture *out_tex = new aiTexture();
|
||||
auto out_tex = new aiTexture();
|
||||
textures.push_back(out_tex);
|
||||
|
||||
// assuming the texture is compressed
|
||||
|
||||
@@ -80,8 +80,8 @@ using SkeletonBoneArray = std::vector<aiSkeletonBone *>;
|
||||
using SkeletonBoneToMesh = std::map<aiMesh*, SkeletonBoneArray*>;
|
||||
|
||||
struct SkeletonBoneContainer {
|
||||
std::vector<aiMesh *> MeshArray;
|
||||
SkeletonBoneToMesh SkeletonBoneToMeshLookup;
|
||||
MeshArray meshArray;
|
||||
SkeletonBoneToMesh skeletonBoneToMeshLookup;
|
||||
};
|
||||
|
||||
class Document;
|
||||
|
||||
@@ -1043,6 +1043,10 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) {
|
||||
}
|
||||
|
||||
inline int64_t to_ktime(double ticks, const aiAnimation* anim) {
|
||||
if (FP_ZERO == std::fpclassify(anim->mTicksPerSecond)) {
|
||||
return static_cast<int64_t>(ticks * FBX::SECOND);
|
||||
}
|
||||
|
||||
// Defensive: handle zero or near-zero mTicksPerSecond
|
||||
double tps = anim->mTicksPerSecond;
|
||||
double timeVal;
|
||||
@@ -1062,7 +1066,7 @@ inline int64_t to_ktime(double ticks, const aiAnimation* anim) {
|
||||
if (timeVal < kMin) {
|
||||
return INT64_MIN;
|
||||
}
|
||||
return static_cast<int64_t>(timeVal * FBX::SECOND);
|
||||
return static_cast<int64_t>((ticks / anim->mTicksPerSecond) * FBX::SECOND);
|
||||
}
|
||||
|
||||
inline int64_t to_ktime(double time) {
|
||||
@@ -1094,6 +1098,7 @@ void FBXExporter::WriteObjects () {
|
||||
bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true);
|
||||
// save vertex_indices as it is needed later
|
||||
std::vector<std::vector<int32_t>> vVertexIndice(mScene->mNumMeshes);
|
||||
std::vector<uint32_t> uniq_v_before_mi;
|
||||
|
||||
const auto bTransparencyFactorReferencedToOpacity = mProperties->GetPropertyBool(AI_CONFIG_EXPORT_FBX_TRANSPARENCY_FACTOR_REFER_TO_OPACITY, false);
|
||||
|
||||
@@ -1140,6 +1145,7 @@ void FBXExporter::WriteObjects () {
|
||||
const aiMesh *m = mScene->mMeshes[mi];
|
||||
|
||||
size_t v_offset = vertex_indices.size();
|
||||
size_t uniq_v_before = flattened_vertices.size() / 3;
|
||||
|
||||
// map of vertex value to its index in the data vector
|
||||
std::map<aiVector3D,size_t> index_by_vertex_value;
|
||||
@@ -1182,11 +1188,17 @@ void FBXExporter::WriteObjects () {
|
||||
if (f.mNumIndices == 0) continue;
|
||||
size_t pvi = 0;
|
||||
for (; pvi < f.mNumIndices - 1; pvi++) {
|
||||
polygon_data.push_back(vertex_indices[v_offset + f.mIndices[pvi]]);
|
||||
polygon_data.push_back(
|
||||
static_cast<int32_t>(uniq_v_before + vertex_indices[v_offset + f.mIndices[pvi]])
|
||||
);
|
||||
}
|
||||
polygon_data.push_back(-1 - vertex_indices[v_offset+f.mIndices[pvi]]);
|
||||
polygon_data.push_back(
|
||||
static_cast<int32_t>(-1 ^ (uniq_v_before + vertex_indices[v_offset+f.mIndices[pvi]]))
|
||||
);
|
||||
}
|
||||
|
||||
uniq_v_before_mi.push_back(static_cast<uint32_t>(uniq_v_before));
|
||||
|
||||
if (m->HasNormals()) {
|
||||
normal_data.reserve(3 * polygon_data.size());
|
||||
for (size_t fi = 0; fi < m->mNumFaces; fi++) {
|
||||
@@ -2058,7 +2070,8 @@ void FBXExporter::WriteObjects () {
|
||||
ASSIMP_LOG_ERROR("UNREAL: Skipping vertex index to prevent buffer overflow.");
|
||||
continue;
|
||||
}
|
||||
int32_t vi = vVertexIndice[mi][b->mWeights[wi].mVertexId];
|
||||
int32_t vi = vVertexIndice[mi][b->mWeights[wi].mVertexId]
|
||||
+ uniq_v_before_mi[mi];
|
||||
bool bIsWeightedAlready = (setWeightedVertex.find(vi) != setWeightedVertex.end());
|
||||
if (vi == last_index || bIsWeightedAlready) {
|
||||
// only for vertices we exported to fbx
|
||||
|
||||
@@ -365,10 +365,14 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
|
||||
}
|
||||
|
||||
if (data[0] == 'F') {
|
||||
return SafeParse<float>(data+1, t.end());
|
||||
BE_NCONST float id = SafeParse<float>(data+1, t.end());
|
||||
AI_SWAP4(id);
|
||||
return id;
|
||||
}
|
||||
else {
|
||||
return static_cast<float>( SafeParse<double>(data+1, t.end()) );
|
||||
BE_NCONST double id = SafeParse<double>(data+1, t.end());
|
||||
AI_SWAP8(id);
|
||||
return static_cast<float>(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,9 +641,15 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
|
||||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count3; ++i, d += 3) {
|
||||
out.emplace_back(static_cast<ai_real>(d[0]),
|
||||
static_cast<ai_real>(d[1]),
|
||||
static_cast<ai_real>(d[2]));
|
||||
BE_NCONST double val1 = d[0];
|
||||
BE_NCONST double val2 = d[1];
|
||||
BE_NCONST double val3 = d[2];
|
||||
AI_SWAP8(val1);
|
||||
AI_SWAP8(val2);
|
||||
AI_SWAP8(val3);
|
||||
out.emplace_back(static_cast<ai_real>(val1),
|
||||
static_cast<ai_real>(val2),
|
||||
static_cast<ai_real>(val3));
|
||||
}
|
||||
// for debugging
|
||||
/*for ( size_t i = 0; i < out.size(); i++ ) {
|
||||
@@ -652,7 +662,13 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
|
||||
else if (type == 'f') {
|
||||
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count3; ++i, f += 3) {
|
||||
out.emplace_back(f[0],f[1],f[2]);
|
||||
BE_NCONST float val1 = f[0];
|
||||
BE_NCONST float val2 = f[1];
|
||||
BE_NCONST float val3 = f[2];
|
||||
AI_SWAP4(val1);
|
||||
AI_SWAP4(val2);
|
||||
AI_SWAP4(val3);
|
||||
out.emplace_back(val1,val2,val3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -726,16 +742,32 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
|
||||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count4; ++i, d += 4) {
|
||||
out.emplace_back(static_cast<float>(d[0]),
|
||||
static_cast<float>(d[1]),
|
||||
static_cast<float>(d[2]),
|
||||
static_cast<float>(d[3]));
|
||||
BE_NCONST double val1 = d[0];
|
||||
BE_NCONST double val2 = d[1];
|
||||
BE_NCONST double val3 = d[2];
|
||||
BE_NCONST double val4 = d[3];
|
||||
AI_SWAP8(val1);
|
||||
AI_SWAP8(val2);
|
||||
AI_SWAP8(val3);
|
||||
AI_SWAP8(val4);
|
||||
out.emplace_back(static_cast<float>(val1),
|
||||
static_cast<float>(val2),
|
||||
static_cast<float>(val3),
|
||||
static_cast<float>(val4));
|
||||
}
|
||||
}
|
||||
else if (type == 'f') {
|
||||
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count4; ++i, f += 4) {
|
||||
out.emplace_back(f[0],f[1],f[2],f[3]);
|
||||
BE_NCONST float val1 = f[0];
|
||||
BE_NCONST float val2 = f[1];
|
||||
BE_NCONST float val3 = f[2];
|
||||
BE_NCONST float val4 = f[3];
|
||||
AI_SWAP4(val1);
|
||||
AI_SWAP4(val2);
|
||||
AI_SWAP4(val3);
|
||||
AI_SWAP4(val4);
|
||||
out.emplace_back(val1,val2,val3,val4);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -807,13 +839,21 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el) {
|
||||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count2; ++i, d += 2) {
|
||||
out.emplace_back(static_cast<float>(d[0]),
|
||||
static_cast<float>(d[1]));
|
||||
BE_NCONST double val1 = d[0];
|
||||
BE_NCONST double val2 = d[1];
|
||||
AI_SWAP8(val1);
|
||||
AI_SWAP8(val2);
|
||||
out.emplace_back(static_cast<float>(val1),
|
||||
static_cast<float>(val2));
|
||||
}
|
||||
} else if (type == 'f') {
|
||||
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count2; ++i, f += 2) {
|
||||
out.emplace_back(f[0],f[1]);
|
||||
BE_NCONST float val1 = f[0];
|
||||
BE_NCONST float val2 = f[1];
|
||||
AI_SWAP4(val1);
|
||||
AI_SWAP4(val2);
|
||||
out.emplace_back(val1,val2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -938,13 +978,17 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
|
||||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count; ++i, ++d) {
|
||||
out.push_back(static_cast<float>(*d));
|
||||
BE_NCONST double val = *d;
|
||||
AI_SWAP8(val);
|
||||
out.push_back(static_cast<float>(val));
|
||||
}
|
||||
}
|
||||
else if (type == 'f') {
|
||||
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count; ++i, ++f) {
|
||||
out.push_back(*f);
|
||||
BE_NCONST float val = *f;
|
||||
AI_SWAP4(val);
|
||||
out.push_back(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ aiMesh *IRRImporter::BuildSingleQuadMesh(const SkyboxVertex &v1,
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void IRRImporter::BuildSkybox(std::vector<aiMesh *> &meshes, std::vector<aiMaterial *> materials) {
|
||||
void IRRImporter::BuildSkybox(MeshArray &meshes, std::vector<aiMaterial *> materials) {
|
||||
// Update the material of the skybox - replace the name and disable shading for skyboxes.
|
||||
for (unsigned int i = 0; i < 6; ++i) {
|
||||
aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i)));
|
||||
@@ -602,7 +602,7 @@ void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
|
||||
BatchLoader &batch,
|
||||
std::vector<aiMesh *> &meshes,
|
||||
MeshArray &meshes,
|
||||
std::vector<aiNodeAnim *> &anims,
|
||||
std::vector<AttachmentInfo> &attach,
|
||||
std::vector<aiMaterial *> &materials,
|
||||
@@ -1283,7 +1283,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
std::vector<aiNodeAnim *> anims;
|
||||
std::vector<aiMaterial *> materials;
|
||||
std::vector<AttachmentInfo> attach;
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
|
||||
// try to guess how much storage we'll need
|
||||
anims.reserve(guessedAnimCnt + (guessedAnimCnt >> 2));
|
||||
|
||||
@@ -229,7 +229,7 @@ private:
|
||||
/// Fill the scene-graph recursively
|
||||
void GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
|
||||
BatchLoader &batch,
|
||||
std::vector<aiMesh *> &meshes,
|
||||
MeshArray &meshes,
|
||||
std::vector<aiNodeAnim *> &anims,
|
||||
std::vector<AttachmentInfo> &attach,
|
||||
std::vector<aiMaterial *> &materials,
|
||||
@@ -248,7 +248,7 @@ private:
|
||||
/// @param meshes Receives 6 output meshes
|
||||
/// @param materials The last 6 materials are assigned to the newly
|
||||
/// created meshes. The names of the materials are adjusted.
|
||||
void BuildSkybox(std::vector<aiMesh *> &meshes,
|
||||
void BuildSkybox(MeshArray &meshes,
|
||||
std::vector<aiMaterial *> materials);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@@ -121,7 +121,7 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
|
||||
|
||||
// final data
|
||||
std::vector<aiMaterial *> materials;
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
materials.reserve(5);
|
||||
meshes.reserve(5);
|
||||
|
||||
@@ -433,24 +433,24 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, const char *end, Verte
|
||||
aiColor4D c;
|
||||
|
||||
// Read the vertex position
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.z);
|
||||
sz = fast_atoreal_move(sz, temp.z);
|
||||
SkipSpaces(&sz, end);
|
||||
vertices.push_back(temp);
|
||||
|
||||
// Read the vertex normals
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.z);
|
||||
sz = fast_atoreal_move(sz, temp.z);
|
||||
SkipSpaces(&sz, end);
|
||||
normals.push_back(temp);
|
||||
|
||||
@@ -466,10 +466,10 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, const char *end, Verte
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
// read the first UV coordinate set
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
temp.z = 0.f;
|
||||
temp.y = 1.f - temp.y; // DX to OGL
|
||||
@@ -479,35 +479,35 @@ void IRRMeshImporter::ParseBufferVertices(const char *sz, const char *end, Verte
|
||||
// So by definition, all buffers have either UV2 or tangents or neither
|
||||
// read the (optional) second UV coordinate set
|
||||
if (vertexFormat == VertexFormat::t2coord) {
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
temp.y = 1.f - temp.y; // DX to OGL
|
||||
UV2s.push_back(temp);
|
||||
}
|
||||
// read optional tangent and bitangent vectors
|
||||
else if (vertexFormat == VertexFormat::tangent) {
|
||||
// tangents
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.z);
|
||||
sz = fast_atoreal_move(sz, temp.z);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
temp.y *= -1.0f;
|
||||
tangents.push_back(temp);
|
||||
|
||||
// bitangents
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.x);
|
||||
sz = fast_atoreal_move(sz, temp.x);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.z);
|
||||
sz = fast_atoreal_move(sz, temp.z);
|
||||
SkipSpaces(&sz, end);
|
||||
|
||||
sz = fast_atoreal_move<float>(sz, (float &)temp.y);
|
||||
sz = fast_atoreal_move(sz, temp.y);
|
||||
SkipSpaces(&sz, end);
|
||||
temp.y *= -1.0f;
|
||||
bitangents.push_back(temp);
|
||||
|
||||
@@ -139,21 +139,21 @@ void IrrlichtBase::ReadVectorProperty(VectorProperty &out, pugi::xml_node& vecto
|
||||
const char *end = ptr + len;
|
||||
|
||||
SkipSpaces(&ptr, end);
|
||||
ptr = fast_atoreal_move<float>(ptr, (float &)out.value.x);
|
||||
ptr = fast_atoreal_move(ptr, out.value.x);
|
||||
SkipSpaces(&ptr, end);
|
||||
if (',' != *ptr) {
|
||||
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
|
||||
} else {
|
||||
SkipSpaces(ptr + 1, &ptr, end);
|
||||
}
|
||||
ptr = fast_atoreal_move<float>(ptr, (float &)out.value.y);
|
||||
ptr = fast_atoreal_move(ptr, out.value.y);
|
||||
SkipSpaces(&ptr, end);
|
||||
if (',' != *ptr) {
|
||||
ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
|
||||
} else {
|
||||
SkipSpaces(ptr + 1, &ptr, end);
|
||||
}
|
||||
ptr = fast_atoreal_move<float>(ptr, (float &)out.value.z);
|
||||
ptr = fast_atoreal_move(ptr, out.value.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
|
||||
ResolveClips();
|
||||
|
||||
// now process all layers and build meshes and nodes
|
||||
std::vector<aiMesh *> apcMeshes;
|
||||
MeshArray apcMeshes;
|
||||
std::map<uint16_t, aiNode *> apcNodes;
|
||||
|
||||
apcMeshes.reserve(mLayers->size() * std::min(((unsigned int)mSurfaces->size() / 2u), 1u));
|
||||
|
||||
@@ -208,9 +208,9 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
|
||||
|
||||
float f;
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, key.value);
|
||||
c = fast_atoreal_move(c, key.value);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, f);
|
||||
c = fast_atoreal_move(c, f);
|
||||
|
||||
key.time = f;
|
||||
|
||||
@@ -242,7 +242,7 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
|
||||
}
|
||||
for (unsigned int i = 0; i < num; ++i) {
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, key.params[i]);
|
||||
c = fast_atoreal_move(c, key.params[i]);
|
||||
}
|
||||
} else if ((*it).tokens[0] == "Behaviors") {
|
||||
SkipSpaces(&c, end);
|
||||
@@ -284,11 +284,11 @@ void LWSImporter::ReadEnvelope_Old(std::list<LWS::Element>::const_iterator &it,c
|
||||
|
||||
// parse value and time, skip the rest for the moment.
|
||||
LWO::Key key;
|
||||
const char *c = fast_atoreal_move<float>((*it).tokens[0].c_str(), key.value);
|
||||
const char *c = fast_atoreal_move((*it).tokens[0].c_str(), key.value);
|
||||
const char *end = c + (*it).tokens[0].size();
|
||||
SkipSpaces(&c, end);
|
||||
float f;
|
||||
fast_atoreal_move<float>((*it).tokens[0].c_str(), f);
|
||||
fast_atoreal_move((*it).tokens[0].c_str(), f);
|
||||
key.time = f;
|
||||
|
||||
envl.keys.emplace_back(key);
|
||||
@@ -775,7 +775,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
ASSIMP_LOG_ERROR("LWS: envelopes for LightIntensity not supported, set to 1.0");
|
||||
nodes.back().lightIntensity = (ai_real)1.0;
|
||||
} else {
|
||||
fast_atoreal_move<float>(c, nodes.back().lightIntensity);
|
||||
fast_atoreal_move(c, nodes.back().lightIntensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -816,11 +816,11 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) {
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'");
|
||||
} else {
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.r);
|
||||
c = fast_atoreal_move(c, nodes.back().lightColor.r);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.g);
|
||||
c = fast_atoreal_move(c, nodes.back().lightColor.g);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().lightColor.b);
|
||||
c = fast_atoreal_move(c, nodes.back().lightColor.b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,11 +829,11 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (nodes.empty()) {
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'");
|
||||
} else {
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.x);
|
||||
c = fast_atoreal_move(c, nodes.back().pivotPos.x);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.y);
|
||||
c = fast_atoreal_move(c, nodes.back().pivotPos.y);
|
||||
SkipSpaces(&c, end);
|
||||
c = fast_atoreal_move<float>(c, (float &)nodes.back().pivotPos.z);
|
||||
c = fast_atoreal_move(c, nodes.back().pivotPos.z);
|
||||
// Mark pivotPos as set
|
||||
nodes.back().isPivotSet = true;
|
||||
}
|
||||
|
||||
@@ -246,11 +246,11 @@ inline void AI_MD5_READ_TRIPLE(aiVector3D &vec, const char **sz, const char *buf
|
||||
return;
|
||||
++*sz;
|
||||
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
|
||||
*sz = fast_atoreal_move<float>(*sz, (float &)vec.x);
|
||||
*sz = fast_atoreal_move(*sz, vec.x);
|
||||
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
|
||||
*sz = fast_atoreal_move<float>(*sz, (float &)vec.y);
|
||||
*sz = fast_atoreal_move(*sz, vec.y);
|
||||
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
|
||||
*sz = fast_atoreal_move<float>(*sz, (float &)vec.z);
|
||||
*sz = fast_atoreal_move(*sz, vec.z);
|
||||
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
|
||||
if (')' != **sz) {
|
||||
MD5Parser::ReportWarning("Unexpected token: ) was expected", linenumber);
|
||||
@@ -377,9 +377,9 @@ MD5MeshParser::MD5MeshParser(SectionArray &mSections) {
|
||||
if ('(' != *sz++)
|
||||
MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber);
|
||||
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
|
||||
sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.x);
|
||||
sz = fast_atoreal_move(sz, vert.mUV.x);
|
||||
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
|
||||
sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.y);
|
||||
sz = fast_atoreal_move(sz, vert.mUV.y);
|
||||
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
|
||||
if (')' != *sz++)
|
||||
MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber);
|
||||
@@ -415,7 +415,7 @@ MD5MeshParser::MD5MeshParser(SectionArray &mSections) {
|
||||
WeightDesc &weight = desc.mWeights[idx];
|
||||
weight.mBone = strtoul10(sz, &sz);
|
||||
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
|
||||
sz = fast_atoreal_move<float>(sz, weight.mWeight);
|
||||
sz = fast_atoreal_move(sz, weight.mWeight);
|
||||
AI_MD5_READ_TRIPLE(weight.vOffsetPosition, &sz, elem.end, elem.iLineNumber);
|
||||
}
|
||||
}
|
||||
@@ -486,7 +486,7 @@ MD5AnimParser::MD5AnimParser(SectionArray &mSections) {
|
||||
const char *sz = elem.szStart;
|
||||
while (SkipSpacesAndLineEnd(&sz, elem.end)) {
|
||||
float f;
|
||||
sz = fast_atoreal_move<float>(sz, f);
|
||||
sz = fast_atoreal_move(sz, f);
|
||||
desc.mValues.push_back(f);
|
||||
}
|
||||
}
|
||||
@@ -503,7 +503,7 @@ MD5AnimParser::MD5AnimParser(SectionArray &mSections) {
|
||||
} else if ((*iter).mName == "numAnimatedComponents") {
|
||||
mAnimatedBones.reserve(strtoul10((*iter).mGlobalValue.c_str()));
|
||||
} else if ((*iter).mName == "frameRate") {
|
||||
fast_atoreal_move<float>((*iter).mGlobalValue.c_str(), fFrameRate);
|
||||
fast_atoreal_move((*iter).mGlobalValue.c_str(), fFrameRate);
|
||||
}
|
||||
}
|
||||
ASSIMP_LOG_DEBUG("MD5AnimParser end");
|
||||
|
||||
@@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "MDLLoader.h"
|
||||
#include "AssetLib/MD2/MD2FileData.h"
|
||||
#include "HalfLife/HL1MDLLoader.h"
|
||||
#include "HalfLife/HL1FileData.h"
|
||||
#include "MDLDefaultColorMap.h"
|
||||
|
||||
#include <assimp/StringUtils.h>
|
||||
@@ -1404,10 +1405,10 @@ void MDLImporter::InternReadFile_3DGS_MDL7() {
|
||||
sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
|
||||
|
||||
// vector to held all created meshes
|
||||
std::vector<aiMesh *> *avOutList;
|
||||
MeshArray *avOutList;
|
||||
|
||||
// 3 meshes per group - that should be OK for most models
|
||||
avOutList = new std::vector<aiMesh *>[pcHeader->groups_num];
|
||||
avOutList = new MeshArray[pcHeader->groups_num];
|
||||
for (uint32_t i = 0; i < pcHeader->groups_num; ++i)
|
||||
avOutList[i].reserve(3);
|
||||
|
||||
@@ -1980,6 +1981,11 @@ void MDLImporter::InternReadFile_HL1(const std::string &pFile, const uint32_t iM
|
||||
if (iMagicWord == AI_MDL_MAGIC_NUMBER_BE_HL2b || iMagicWord == AI_MDL_MAGIC_NUMBER_LE_HL2b)
|
||||
throw DeadlyImportError("Impossible to properly load a model from an MDL sequence file.");
|
||||
|
||||
// Check if the buffer is large enough to hold the header
|
||||
if (iFileSize < sizeof(HalfLife::Header_HL1)) {
|
||||
throw DeadlyImportError("HL1 MDL file is too small to contain header.");
|
||||
}
|
||||
|
||||
// Read the MDL file.
|
||||
HalfLife::HL1MDLLoader loader(
|
||||
pScene,
|
||||
|
||||
@@ -86,7 +86,7 @@ const aiImporterDesc *NFFImporter::GetInfo() const {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#define AI_NFF_PARSE_FLOAT(f) \
|
||||
SkipSpaces(&sz, lineEnd); \
|
||||
if (!IsLineEnd(*sz)) sz = fast_atoreal_move<ai_real>(sz, (ai_real &)f);
|
||||
if (!IsLineEnd(*sz)) sz = fast_atoreal_move(sz, (ai_real &)f);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#define AI_NFF_PARSE_TRIPLE(v) \
|
||||
|
||||
@@ -212,14 +212,14 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
// stop at dimensions: this allows loading 1D or 2D coordinate vertices
|
||||
for (unsigned int dim = 0; dim < dimensions; ++dim) {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, *vec[dim]);
|
||||
sz = fast_atoreal_move(sz, *vec[dim]);
|
||||
}
|
||||
|
||||
// if has homogeneous coordinate, divide others by this one
|
||||
if (hasHomogenous) {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
ai_real w = 1.;
|
||||
sz = fast_atoreal_move<ai_real>(sz, w);
|
||||
sz = fast_atoreal_move(sz, w);
|
||||
for (unsigned int dim = 0; dim < dimensions; ++dim) {
|
||||
*(vec[dim]) /= w;
|
||||
}
|
||||
@@ -229,11 +229,11 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (hasNormals) {
|
||||
aiVector3D &n = mesh->mNormals[i];
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.x);
|
||||
sz = fast_atoreal_move(sz, n.x);
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.y);
|
||||
sz = fast_atoreal_move(sz, n.y);
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
fast_atoreal_move<ai_real>(sz, (ai_real &)n.z);
|
||||
fast_atoreal_move(sz, n.z);
|
||||
}
|
||||
|
||||
// reading colors is a pain because the specification says it can be
|
||||
@@ -243,22 +243,22 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (hasColors) {
|
||||
aiColor4D &c = mesh->mColors[0][i];
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.r);
|
||||
sz = fast_atoreal_move(sz, c.r);
|
||||
if (*sz != '#' && *sz != '\n' && *sz != '\r') {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.g);
|
||||
sz = fast_atoreal_move(sz, c.g);
|
||||
} else {
|
||||
c.g = 0.;
|
||||
}
|
||||
if (*sz != '#' && *sz != '\n' && *sz != '\r') {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.b);
|
||||
sz = fast_atoreal_move(sz, c.b);
|
||||
} else {
|
||||
c.b = 0.;
|
||||
}
|
||||
if (*sz != '#' && *sz != '\n' && *sz != '\r') {
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.a);
|
||||
sz = fast_atoreal_move(sz, c.a);
|
||||
} else {
|
||||
c.a = 1.;
|
||||
}
|
||||
@@ -266,9 +266,9 @@ void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
if (hasTexCoord) {
|
||||
aiVector3D &t = mesh->mTextureCoords[0][i];
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)t.x);
|
||||
sz = fast_atoreal_move(sz, t.x);
|
||||
SkipSpaces(&sz, lineEnd);
|
||||
fast_atoreal_move<ai_real>(sz, (ai_real &)t.y);
|
||||
fast_atoreal_move(sz, t.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -396,9 +395,12 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices) {
|
||||
if (nd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
|
||||
|
||||
aiMesh *cm( nullptr );
|
||||
aiMesh *cm{nullptr};
|
||||
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
|
||||
cm = pScene->mMeshes[nd->mMeshes[i]];
|
||||
if (nullptr != cm) {
|
||||
|
||||
@@ -165,21 +165,23 @@ struct Material {
|
||||
//! Ambient color
|
||||
aiColor3D ambient;
|
||||
//! Diffuse color
|
||||
aiColor3D diffuse;
|
||||
aiColor3D diffuse = aiColor3D(0.6f, 0.6f, 0.6f);
|
||||
//! Specular color
|
||||
aiColor3D specular;
|
||||
//! Emissive color
|
||||
aiColor3D emissive;
|
||||
//! Alpha value
|
||||
ai_real alpha;
|
||||
ai_real alpha = ai_real(1.0);
|
||||
//! Shineness factor
|
||||
ai_real shineness;
|
||||
ai_real shineness = ai_real(0.0);
|
||||
//! Illumination model
|
||||
int illumination_model;
|
||||
int illumination_model = 1;
|
||||
//! Index of refraction
|
||||
ai_real ior;
|
||||
ai_real ior = ai_real(1.0);
|
||||
//! Transparency color
|
||||
aiColor3D transparent;
|
||||
aiColor3D transparent = aiColor3D(1.0f, 1.0f, 1.0f);
|
||||
//! Ambient occlusion
|
||||
Maybe<ai_real> ambient_occlusion;
|
||||
|
||||
//! PBR Roughness
|
||||
Maybe<ai_real> roughness;
|
||||
@@ -187,31 +189,33 @@ struct Material {
|
||||
Maybe<ai_real> metallic;
|
||||
//! PBR Metallic
|
||||
Maybe<aiColor3D> sheen;
|
||||
//! PBR Sheen: an additional grazing component, primarily intended for cloth.
|
||||
Maybe<ai_real> sheen_grazing;
|
||||
//! PBR Sheen Tint: amount to tint sheen towards base color.
|
||||
Maybe<ai_real> sheen_tint;
|
||||
//! PBR Clearcoat
|
||||
Maybe<ai_real> clearcoat;
|
||||
//! PBR Clearcoat Thickness
|
||||
Maybe<ai_real> clearcoat_thickness;
|
||||
//! PBR Clearcoat Rougness
|
||||
Maybe<ai_real> clearcoat_roughness;
|
||||
//! PBR clearcoatGloss: controls clearcoat glossiness (0 = a “satin” appearance, 1 = a “gloss” appearance).
|
||||
Maybe<ai_real> clearcoat_gloss;
|
||||
//! PBR Anisotropy
|
||||
ai_real anisotropy;
|
||||
ai_real anisotropy = ai_real(0.0);
|
||||
//! PBR Anisotropy Rotation
|
||||
Maybe<ai_real> anisotropy_rotation;
|
||||
//! PBR Subsurface Scattering
|
||||
Maybe<ai_real> subsurface_scattering;
|
||||
//! PBR Specular Tint: a concession for artistic control that tints incident specular towards the base color.
|
||||
Maybe<ai_real> specular_tint;
|
||||
// See: https://disneyanimation.com/publications/physically-based-shading-at-disney/
|
||||
|
||||
//! bump map multipler (normal map scalar)(-bm)
|
||||
ai_real bump_multiplier;
|
||||
//! bump map multiplier (normal map scalar)(-bm)
|
||||
ai_real bump_multiplier = ai_real(1.0);
|
||||
|
||||
//! Constructor
|
||||
Material() :
|
||||
diffuse(0.6f, 0.6f, 0.6f),
|
||||
alpha(ai_real(1.0)),
|
||||
shineness(ai_real(0.0)),
|
||||
illumination_model(1),
|
||||
ior(ai_real(1.0)),
|
||||
transparent(1.0f, 1.0, 1.0),
|
||||
roughness(),
|
||||
metallic(),
|
||||
sheen(),
|
||||
clearcoat_thickness(),
|
||||
clearcoat_roughness(),
|
||||
anisotropy(ai_real(0.0)),
|
||||
bump_multiplier(ai_real(1.0)) {
|
||||
Material() {
|
||||
std::fill_n(clamp, static_cast<unsigned int>(TextureTypeCount), false);
|
||||
}
|
||||
|
||||
|
||||
@@ -235,24 +235,64 @@ void ObjFileMtlImporter::load() {
|
||||
++m_DataIt;
|
||||
if (m_pModel->mCurrentMaterial != nullptr)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->clearcoat_roughness);
|
||||
} else {
|
||||
} else if (*m_DataIt == 't') {
|
||||
++m_DataIt;
|
||||
if (m_pModel->mCurrentMaterial != nullptr)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->clearcoat_thickness);
|
||||
} else {
|
||||
if (m_pModel->mCurrentMaterial != nullptr)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->clearcoat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm': // Texture or metallic
|
||||
{
|
||||
// Save start of token (after 'm')
|
||||
auto tokenStart = m_DataIt; // points to 'm'
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd); // move iterator to end of token
|
||||
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd; // advance iterator
|
||||
|
||||
if (keyword.compare(0, 3, "map") == 0) {
|
||||
// starts with "map", treat as texture map
|
||||
m_DataIt = tokenStart;
|
||||
getTexture();
|
||||
} else if (keyword == "metallic" || keyword == "metal" || keyword == "metalness") {
|
||||
// parse metallic float value instead of texture
|
||||
getFloatIfMaterialValid(&ObjFile::Material::metallic);
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'm': // Texture
|
||||
case 'b': // quick'n'dirty - for 'bump' sections
|
||||
case 'r': // quick'n'dirty - for 'refl' sections
|
||||
{
|
||||
getTexture();
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'r': // refl (map) or roughness (float)
|
||||
{
|
||||
auto tokenStart = m_DataIt; // points to 'r'
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd);
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd;
|
||||
|
||||
if (keyword == "roughness" || keyword == "rough") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::roughness);
|
||||
} else if (keyword == "refl" || keyword == "reflection") {
|
||||
m_DataIt = tokenStart;
|
||||
getTexture();
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'i': // Illumination model
|
||||
{
|
||||
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||
@@ -261,11 +301,60 @@ void ObjFileMtlImporter::load() {
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'a': // Anisotropy
|
||||
{
|
||||
++m_DataIt;
|
||||
if (m_pModel->mCurrentMaterial != nullptr)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->anisotropy);
|
||||
case 'a': {
|
||||
auto tokenStart = m_DataIt;
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd);
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd;
|
||||
|
||||
if (keyword == "aniso" || keyword == "anisotropy") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::anisotropy);
|
||||
} else if (keyword == "ao") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::ambient_occlusion);
|
||||
} else if (keyword == "anisor" || ai_stdStrToLower(keyword) == "anisotropicrotation") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::anisotropy_rotation);
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("Unhandled keyword: ", keyword );
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 's': {
|
||||
auto tokenStart = m_DataIt;
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd);
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd;
|
||||
|
||||
if (keyword == "subsurface" || keyword == "scattering") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::subsurface_scattering);
|
||||
} else if (ai_stdStrToLower(keyword) == "speculartint") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::specular_tint);
|
||||
} else if (keyword == "sheen") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::sheen_grazing);
|
||||
} else if (ai_stdStrToLower(keyword) == "sheentint") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::sheen_tint);
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("Unhandled keyword: ", keyword );
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
case 'c': {
|
||||
auto tokenStart = m_DataIt;
|
||||
auto tokenEnd = getNextToken(m_DataIt, m_DataItEnd);
|
||||
std::string keyword(tokenStart, tokenEnd);
|
||||
m_DataIt = tokenEnd;
|
||||
|
||||
if (ai_stdStrToLower(keyword) == "clearcoat") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::clearcoat);
|
||||
} else if (ai_stdStrToLower(keyword) == "clearcoatgloss") {
|
||||
getFloatIfMaterialValid(&ObjFile::Material::clearcoat_gloss);
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("Unhandled keyword: ", keyword );
|
||||
}
|
||||
|
||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||
} break;
|
||||
|
||||
@@ -332,6 +421,23 @@ void ObjFileMtlImporter::getFloatValue(Maybe<ai_real> &value) {
|
||||
value = Maybe<ai_real>();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Writes a loaded single float value if material not null
|
||||
void ObjFileMtlImporter::getFloatIfMaterialValid(ai_real ObjFile::Material::*member) {
|
||||
if (m_pModel != nullptr && m_pModel->mCurrentMaterial != nullptr) {
|
||||
// This will call getFloatValue(ai_real&)
|
||||
getFloatValue(m_pModel->mCurrentMaterial->*member);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void ObjFileMtlImporter::getFloatIfMaterialValid(Maybe<ai_real> ObjFile::Material::*member) {
|
||||
// It can directly access `m_pModel` because it's part of the class
|
||||
if (m_pModel != nullptr && m_pModel->mCurrentMaterial != nullptr) {
|
||||
getFloatValue(m_pModel->mCurrentMaterial->*member);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Creates a material from loaded data.
|
||||
void ObjFileMtlImporter::createMaterial() {
|
||||
|
||||
@@ -87,6 +87,8 @@ private:
|
||||
/// Gets a float value from data.
|
||||
void getFloatValue(ai_real &value);
|
||||
void getFloatValue(Maybe<ai_real> &value);
|
||||
void getFloatIfMaterialValid(ai_real ObjFile::Material::*member);
|
||||
void getFloatIfMaterialValid(Maybe<ai_real> ObjFile::Material::*member);
|
||||
/// Creates a new material from loaded data.
|
||||
void createMaterial();
|
||||
/// Get texture name from loaded data.
|
||||
|
||||
@@ -121,6 +121,13 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
|
||||
m_DataItEnd = buffer.end();
|
||||
mEnd = &buffer[buffer.size() - 1] + 1;
|
||||
|
||||
if (processed == 0 && std::distance(m_DataIt, m_DataItEnd) >= 3 &&
|
||||
static_cast<unsigned char>(*m_DataIt) == 0xEF &&
|
||||
static_cast<unsigned char>(*(m_DataIt + 1)) == 0xBB &&
|
||||
static_cast<unsigned char>(*(m_DataIt + 2)) == 0xBF) {
|
||||
m_DataIt += 3; // skip BOM
|
||||
}
|
||||
|
||||
// Handle progress reporting
|
||||
const size_t filePos(streamBuffer.getFilePos());
|
||||
if (lastFilePos < filePos) {
|
||||
|
||||
@@ -828,13 +828,13 @@ bool PLY::PropertyInstance::ParseValue(const char *&pCur,
|
||||
// technically this should cast to float, but people tend to use float descriptors for double data
|
||||
// this is the best way to not risk losing precision on import and it doesn't hurt to do this
|
||||
ai_real f;
|
||||
pCur = fast_atoreal_move<ai_real>(pCur, f);
|
||||
pCur = fast_atoreal_move(pCur, f);
|
||||
out->fFloat = (ai_real)f;
|
||||
break;
|
||||
|
||||
case EDT_Double:
|
||||
double d;
|
||||
pCur = fast_atoreal_move<double>(pCur, d);
|
||||
pCur = fast_atoreal_move(pCur, d);
|
||||
out->fDouble = (double)d;
|
||||
break;
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ void Q3BSPFileImporter::CreateNodes(const Q3BSP::Q3BSPModel *pModel, aiScene *pS
|
||||
}
|
||||
|
||||
unsigned int matIdx(0);
|
||||
std::vector<aiMesh *> MeshArray;
|
||||
MeshArray MeshArray;
|
||||
std::vector<aiNode *> NodeArray;
|
||||
for (FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) {
|
||||
std::vector<Q3BSP::sQ3BSPFace *> *pArray = (*it).second;
|
||||
|
||||
@@ -136,7 +136,7 @@ void RAWImporter::InternReadFile(const std::string &pFile,
|
||||
unsigned int num;
|
||||
for (num = 0; num < 12; ++num) {
|
||||
if (!SkipSpaces(&sz, end) || !IsNumeric(*sz)) break;
|
||||
sz = fast_atoreal_move<float>(sz, data[num]);
|
||||
sz = fast_atoreal_move(sz, data[num]);
|
||||
}
|
||||
if (num != 12 && num != 9) {
|
||||
ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture");
|
||||
|
||||
@@ -116,7 +116,7 @@ struct SIBObject {
|
||||
|
||||
struct SIB {
|
||||
std::vector<aiMaterial *> mtls;
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
std::vector<aiLight *> lights;
|
||||
std::vector<SIBObject> objs, insts;
|
||||
};
|
||||
|
||||
@@ -982,7 +982,7 @@ bool SMDImporter::ParseFloat(const char *szCurrent, const char **szCurrentOut, c
|
||||
return false;
|
||||
}
|
||||
|
||||
*szCurrentOut = fast_atoreal_move<float>(szCurrent,out);
|
||||
*szCurrentOut = fast_atoreal_move(szCurrent,out);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -404,7 +404,7 @@ std::shared_ptr<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*& i
|
||||
for(;*cur && *cur != ',' && *cur != ')' && !IsSpace(*cur);++cur) {
|
||||
if (*cur == '.') {
|
||||
double f;
|
||||
inout = fast_atoreal_move<double>(start,f);
|
||||
inout = fast_atoreal_move(start,f);
|
||||
return std::make_shared<EXPRESS::REAL>(f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Read an ASCII STL file
|
||||
void STLImporter::LoadASCIIFile(aiNode *root) {
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
std::vector<aiNode *> nodes;
|
||||
const char *sz = mBuffer;
|
||||
const char *bufferEnd = mBuffer + mFileSize;
|
||||
@@ -294,11 +294,11 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
|
||||
aiVector3D vn;
|
||||
sz += 7;
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.x);
|
||||
sz = fast_atoreal_move(sz, vn.x);
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.y);
|
||||
sz = fast_atoreal_move(sz, vn.y);
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.z);
|
||||
sz = fast_atoreal_move(sz, vn.z);
|
||||
normalBuffer.emplace_back(vn);
|
||||
normalBuffer.emplace_back(vn);
|
||||
normalBuffer.emplace_back(vn);
|
||||
@@ -315,11 +315,11 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
positionBuffer.emplace_back();
|
||||
aiVector3D *vn = &positionBuffer.back();
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->x);
|
||||
sz = fast_atoreal_move(sz, vn->x);
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->y);
|
||||
sz = fast_atoreal_move(sz, vn->y);
|
||||
SkipSpaces(&sz, bufferEnd);
|
||||
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->z);
|
||||
sz = fast_atoreal_move(sz, vn->z);
|
||||
faceVertexCounter++;
|
||||
}
|
||||
} else if (!::strncmp(sz, "endsolid", 8)) {
|
||||
|
||||
@@ -383,11 +383,11 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
|
||||
|
||||
for (; !IsLineEnd(*data); ++data) {
|
||||
if (data[0] == 'X' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.a1);
|
||||
data = fast_atoreal_move(data + 2, nd->mTransformation.a1);
|
||||
} else if (data[0] == 'Y' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.b2);
|
||||
data = fast_atoreal_move(data + 2, nd->mTransformation.b2);
|
||||
} else if (data[0] == 'Z' && data[1] == '=') {
|
||||
data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.c3);
|
||||
data = fast_atoreal_move(data + 2, nd->mTransformation.c3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ void XFileImporter::CreateMeshes(aiScene *pScene, aiNode *pNode, const std::vect
|
||||
}
|
||||
|
||||
// create a mesh for each mesh-material combination in the source node
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
for (unsigned int a = 0; a < pMeshes.size(); ++a) {
|
||||
XFile::Mesh *sourceMesh = pMeshes[a];
|
||||
if (nullptr == sourceMesh) {
|
||||
|
||||
@@ -1277,7 +1277,7 @@ ai_real XFileParser::ReadFloat() {
|
||||
}
|
||||
|
||||
ai_real result = 0.0;
|
||||
mP = fast_atoreal_move<ai_real>(mP, result);
|
||||
mP = fast_atoreal_move(mP, result);
|
||||
|
||||
CheckForSeparator();
|
||||
|
||||
|
||||
@@ -128,13 +128,17 @@ void X3DGeoHelper::rect_parallel_epiped(const aiVector3D &pSize, std::list<aiVec
|
||||
|
||||
#undef MESH_RectParallelepiped_CREATE_VERT
|
||||
|
||||
static constexpr int InvalidIndex = -1;
|
||||
|
||||
void X3DGeoHelper::coordIdx_str2faces_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces, unsigned int &pPrimitiveTypes) {
|
||||
std::vector<int32_t> f_data(pCoordIdx);
|
||||
std::vector<unsigned int> inds;
|
||||
unsigned int prim_type = 0;
|
||||
|
||||
if (f_data.back() != (-1)) {
|
||||
f_data.push_back(-1);
|
||||
if (!f_data.empty()) {
|
||||
if (f_data.back() != InvalidIndex) {
|
||||
f_data.push_back(InvalidIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// reserve average size.
|
||||
@@ -191,8 +195,10 @@ mg_m_err:
|
||||
void X3DGeoHelper::coordIdx_str2lines_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces) {
|
||||
std::vector<int32_t> f_data(pCoordIdx);
|
||||
|
||||
if (f_data.back() != (-1)) {
|
||||
f_data.push_back(-1);
|
||||
if (!f_data.empty()) {
|
||||
if (f_data.back() != InvalidIndex) {
|
||||
f_data.push_back(InvalidIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// reserve average size.
|
||||
|
||||
@@ -139,7 +139,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||
ReadWorld(*worldNode, scope);
|
||||
}
|
||||
|
||||
std::vector<aiMesh *> &meshes = scope.meshes_linear;
|
||||
MeshArray &meshes = scope.meshes_linear;
|
||||
std::vector<aiMaterial *> &materials = scope.materials_linear;
|
||||
if (meshes.empty() || materials.empty()) {
|
||||
ThrowException("failed to extract data from XGL file, no meshes loaded");
|
||||
|
||||
@@ -192,7 +192,7 @@ static bool CheckValidFacesIndices(const aiFace *faces, unsigned nFaces, unsigne
|
||||
}
|
||||
|
||||
void glTFImporter::ImportMeshes(Asset &r) {
|
||||
std::vector<aiMesh *> meshes;
|
||||
MeshArray meshes;
|
||||
|
||||
unsigned int k = 0;
|
||||
meshOffsets.clear();
|
||||
|
||||
@@ -59,6 +59,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Header files, standard library.
|
||||
#include <cinttypes>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
@@ -1238,13 +1239,25 @@ void glTF2Exporter::ExportMeshes() {
|
||||
}
|
||||
|
||||
/******************** Tangents ********************/
|
||||
if (nullptr != aim->mTangents) {
|
||||
if (nullptr != aim->mTangents && nullptr != aim->mBitangents) {
|
||||
// Find the handedness by calculating the bitangent without the handedness factor,
|
||||
// the use a dot product to find out if the original bitangent was inverted (multiplied
|
||||
// by a factor of -1.0) or not (multiplied by 1.0)
|
||||
std::vector<ai_real> tangentsWithHandedness(aim->mNumVertices * 4);
|
||||
for (uint32_t i = 0; i < aim->mNumVertices; ++i) {
|
||||
aiVector3D calculatedBitangent = aim->mNormals[i] ^ aim->mTangents[i];
|
||||
ai_real bitangentDotProduct = calculatedBitangent * aim->mBitangents[i];
|
||||
ai_real handedness = std::copysign(1.0, bitangentDotProduct);
|
||||
aim->mTangents[i].NormalizeSafe();
|
||||
tangentsWithHandedness[i * 4] = aim->mTangents[i][0];
|
||||
tangentsWithHandedness[i * 4 + 1] = aim->mTangents[i][1];
|
||||
tangentsWithHandedness[i * 4 + 2] = aim->mTangents[i][2];
|
||||
tangentsWithHandedness[i * 4 + 3] = handedness;
|
||||
}
|
||||
|
||||
Ref<Accessor> t = ExportData(
|
||||
*mAsset, meshId, b, aim->mNumVertices, aim->mTangents, AttribType::VEC3,
|
||||
AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER
|
||||
*mAsset, meshId, b, aim->mNumVertices, &tangentsWithHandedness[0], AttribType::VEC4,
|
||||
AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER
|
||||
);
|
||||
if (t) {
|
||||
p.attributes.tangent.push_back(t);
|
||||
|
||||
@@ -347,6 +347,21 @@ struct ReadHelper<int64_t> {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
// On Mac size_t and uint64_t are not the same, so we need a specialized version
|
||||
// here to properly parse byteOffset and other parameters > 2^31
|
||||
// On Windows and Linux the types match andno additional specialization is required
|
||||
|
||||
template <>
|
||||
struct ReadHelper<size_t> {
|
||||
static bool Read(Value &val, size_t &out) {
|
||||
return val.IsInt64() ? out = val.GetInt64(), true : false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline static bool ReadValue(Value &val, T &out) {
|
||||
return ReadHelper<T>::Read(val, out);
|
||||
|
||||
@@ -1318,11 +1318,6 @@ if(MSVC10)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
IF( MSVC OR "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") # clang with MSVC ABI
|
||||
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
|
||||
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
|
||||
endif ()
|
||||
|
||||
IF(NOT ASSIMP_HUNTER_ENABLED)
|
||||
if (UNZIP_FOUND)
|
||||
SET (unzip_compile_SRCS "")
|
||||
@@ -1415,7 +1410,6 @@ add_compile_options(
|
||||
IF (ASSIMP_WARNINGS_AS_ERRORS)
|
||||
MESSAGE(STATUS "Treating all warnings as errors (for assimp library only)")
|
||||
IF (MSVC)
|
||||
|
||||
IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
|
||||
TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror
|
||||
-Wno-microsoft-enum-value
|
||||
|
||||
@@ -678,8 +678,8 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build a list of unique bones
|
||||
void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash> &asBones,
|
||||
std::vector<aiMesh *>::const_iterator it,
|
||||
std::vector<aiMesh *>::const_iterator end) {
|
||||
MeshArray::const_iterator it,
|
||||
MeshArray::const_iterator end) {
|
||||
unsigned int iOffset = 0;
|
||||
for (; it != end; ++it) {
|
||||
for (unsigned int l = 0; l < (*it)->mNumBones; ++l) {
|
||||
@@ -712,8 +712,7 @@ void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash> &asBones,
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Merge a list of bones
|
||||
void SceneCombiner::MergeBones(aiMesh *out, std::vector<aiMesh *>::const_iterator it,
|
||||
std::vector<aiMesh *>::const_iterator end) {
|
||||
void SceneCombiner::MergeBones(aiMesh *out, MeshArray::const_iterator it, MeshArray::const_iterator end) {
|
||||
if (nullptr == out || out->mNumBones == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -771,8 +770,8 @@ void SceneCombiner::MergeBones(aiMesh *out, std::vector<aiMesh *>::const_iterato
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Merge a list of meshes
|
||||
void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
std::vector<aiMesh *>::const_iterator begin,
|
||||
std::vector<aiMesh *>::const_iterator end) {
|
||||
MeshArray::const_iterator begin,
|
||||
MeshArray::const_iterator end) {
|
||||
if (nullptr == _out) {
|
||||
return;
|
||||
}
|
||||
@@ -788,7 +787,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
|
||||
std::string name;
|
||||
// Find out how much output storage we'll need
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
const char *meshName((*it)->mName.C_Str());
|
||||
name += std::string(meshName);
|
||||
if (it != end - 1) {
|
||||
@@ -810,7 +809,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
if ((**begin).HasPositions()) {
|
||||
|
||||
pv2 = out->mVertices = new aiVector3D[out->mNumVertices];
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mVertices) {
|
||||
::memcpy(pv2, (*it)->mVertices, (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
} else
|
||||
@@ -822,7 +821,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
if ((**begin).HasNormals()) {
|
||||
|
||||
pv2 = out->mNormals = new aiVector3D[out->mNumVertices];
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mNormals) {
|
||||
::memcpy(pv2, (*it)->mNormals, (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
} else {
|
||||
@@ -837,7 +836,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
pv2 = out->mTangents = new aiVector3D[out->mNumVertices];
|
||||
aiVector3D *pv2b = out->mBitangents = new aiVector3D[out->mNumVertices];
|
||||
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mTangents) {
|
||||
::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
::memcpy(pv2b, (*it)->mBitangents, (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
@@ -854,7 +853,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n];
|
||||
|
||||
pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices];
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mTextureCoords[n]) {
|
||||
::memcpy(pv2, (*it)->mTextureCoords[n], (*it)->mNumVertices * sizeof(aiVector3D));
|
||||
} else {
|
||||
@@ -868,7 +867,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
n = 0;
|
||||
while ((**begin).HasVertexColors(n)) {
|
||||
aiColor4D *pVec2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
if ((*it)->mColors[n]) {
|
||||
::memcpy(pVec2, (*it)->mColors[n], (*it)->mNumVertices * sizeof(aiColor4D));
|
||||
} else {
|
||||
@@ -887,7 +886,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
aiFace *pf2 = out->mFaces;
|
||||
|
||||
unsigned int ofs = 0;
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it) {
|
||||
for (unsigned int m = 0; m < (*it)->mNumFaces; ++m, ++pf2) {
|
||||
aiFace &face = (*it)->mFaces[m];
|
||||
pf2->mNumIndices = face.mNumIndices;
|
||||
@@ -910,7 +909,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
|
||||
MergeBones(out, begin, end);
|
||||
|
||||
// delete all source meshes
|
||||
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it)
|
||||
for (MeshArray::const_iterator it = begin; it != end; ++it)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
|
||||
@@ -158,8 +158,8 @@ void CatmullClarkSubdivider::Subdivide(
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<aiMesh *> inmeshes;
|
||||
std::vector<aiMesh *> outmeshes;
|
||||
MeshArray inmeshes;
|
||||
MeshArray outmeshes;
|
||||
std::vector<unsigned int> maptbl;
|
||||
|
||||
inmeshes.reserve(nmesh);
|
||||
@@ -577,7 +577,7 @@ void CatmullClarkSubdivider::InternSubdivide(
|
||||
// 7. Apply the next subdivision step.
|
||||
// ---------------------------------------------------------------------
|
||||
if (num != 1) {
|
||||
std::vector<aiMesh *> tmp(nmesh);
|
||||
MeshArray tmp(nmesh);
|
||||
InternSubdivide(out, nmesh, &tmp.front(), num - 1);
|
||||
for (size_t i = 0; i < nmesh; ++i) {
|
||||
delete out[i];
|
||||
|
||||
@@ -47,8 +47,8 @@ namespace Assimp {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ai_real GeometryUtils::heron( ai_real a, ai_real b, ai_real c ) {
|
||||
const ai_real s = (a + b + c) / 2;
|
||||
const ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 );
|
||||
const ai_real s = (a + b + c) * 0.5;
|
||||
const ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), static_cast<ai_real>(0.5));
|
||||
return area;
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ ai_real GeometryUtils::distance3D( const aiVector3D &vA, const aiVector3D &vB )
|
||||
const ai_real lx = ( vB.x - vA.x );
|
||||
const ai_real ly = ( vB.y - vA.y );
|
||||
const ai_real lz = ( vB.z - vA.z );
|
||||
const ai_real a = lx*lx + ly*ly + lz*lz;
|
||||
const ai_real d = pow( a, (ai_real)0.5 );
|
||||
const ai_real a = lx*lx + ly*ly + lz*lz;
|
||||
const ai_real d = pow( a, static_cast<ai_real>(0.5));
|
||||
|
||||
return d;
|
||||
}
|
||||
@@ -66,6 +66,9 @@ ai_real GeometryUtils::distance3D( const aiVector3D &vA, const aiVector3D &vB )
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ai_real GeometryUtils::calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
|
||||
ai_real area = 0;
|
||||
if (mesh == nullptr) {
|
||||
return area;
|
||||
}
|
||||
|
||||
const aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] );
|
||||
const aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] );
|
||||
@@ -81,8 +84,7 @@ ai_real GeometryUtils::calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Check whether a ray intersects a plane and find the intersection point
|
||||
bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
|
||||
const aiVector3D& planeNormal, aiVector3D& pos) {
|
||||
bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, const aiVector3D& planeNormal, aiVector3D& pos) {
|
||||
const ai_real b = planeNormal * (planePos - ray.pos);
|
||||
ai_real h = ray.dir * planeNormal;
|
||||
if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0)
|
||||
@@ -93,11 +95,14 @@ bool GeometryUtils::PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void GeometryUtils::normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut,
|
||||
size_t numVectors) {
|
||||
void GeometryUtils::normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors) {
|
||||
if (vectorArrayIn == nullptr || vectorArrayOut == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i=0; i<numVectors; ++i) {
|
||||
vectorArrayOut[i] = vectorArrayIn[i].Normalize();
|
||||
}
|
||||
vectorArrayOut[i] = vectorArrayIn[i].Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
@@ -159,7 +159,7 @@ aiReturn GetMaterialFloatArray(const aiMaterial *pMat,
|
||||
ai_assert(prop->mDataLength >= 5);
|
||||
ai_assert(!prop->mData[prop->mDataLength - 1]);
|
||||
for (unsigned int a = 0;; ++a) {
|
||||
cur = fast_atoreal_move<TReal>(cur, pOut[a]);
|
||||
cur = fast_atoreal_move(cur, pOut[a]);
|
||||
if (a == iWrite - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,65 @@ void JoinVerticesProcess::Execute( aiScene* pScene) {
|
||||
|
||||
namespace {
|
||||
|
||||
struct CompareVerticesAlmostEqual {
|
||||
bool operator () (const Vertex & a, const Vertex & b) const {
|
||||
static const float epsilon = 1e-5f;
|
||||
static const float squareEpsilon = epsilon * epsilon;
|
||||
|
||||
if ((a.position - b.position).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We just test the other attributes even if they're not present in the mesh.
|
||||
// In this case they're initialized to 0 so the comparison succeeds.
|
||||
// By this method the non-present attributes are effectively ignored in the comparison.
|
||||
|
||||
if ((a.normal - b.normal).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a.tangent - b.tangent).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a.bitangent - b.bitangent).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i ++) {
|
||||
if ((a.texcoords[i] - b.texcoords[i]).SquareLength() > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; i ++) {
|
||||
if (GetColorDifference(a.colors[i], b.colors[i]) > squareEpsilon) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If reached this point, they are ~equal
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct HashVertex {
|
||||
inline void hash_combine(std::size_t& seed, const ai_real& v) const {
|
||||
std::hash<ai_real> hasher;
|
||||
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
|
||||
size_t operator () (const Vertex & v) const {
|
||||
size_t hash = 0;
|
||||
|
||||
hash_combine(hash, v.position.x);
|
||||
hash_combine(hash, v.position.y);
|
||||
hash_combine(hash, v.position.z);
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
template<class XMesh>
|
||||
void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) {
|
||||
// replace vertex data with the unique data sets
|
||||
@@ -208,7 +267,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) {
|
||||
}
|
||||
}
|
||||
// a map that maps a vertex to its new index
|
||||
std::map<Vertex, int> vertex2Index = {};
|
||||
std::unordered_map<Vertex, int, HashVertex, CompareVerticesAlmostEqual> vertex2Index = {};
|
||||
// we can not end up with more vertices than we started with
|
||||
// Now check each vertex if it brings something new to the table
|
||||
int newIndex = 0;
|
||||
|
||||
@@ -332,7 +332,7 @@ void PretransformVertices::ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Simple routine to build meshes in worldspace, no further optimization
|
||||
void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh *> &out, aiMesh **in,
|
||||
void PretransformVertices::BuildWCSMeshes(MeshArray &out, aiMesh **in,
|
||||
unsigned int numIn, aiNode *node) const {
|
||||
// NOTE:
|
||||
// aiMesh::mNumBones store original source mesh, or UINT_MAX if not a copy
|
||||
@@ -459,7 +459,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
|
||||
}
|
||||
|
||||
// now build a list of output meshes
|
||||
std::vector<aiMesh *> apcOutMeshes;
|
||||
MeshArray apcOutMeshes;
|
||||
|
||||
// Keep scene hierarchy? It's an easy job in this case ...
|
||||
// we go on and transform all meshes, if one is referenced by nodes
|
||||
|
||||
@@ -139,7 +139,7 @@ private:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Simple routine to build meshes in worldspace, no further optimization
|
||||
void BuildWCSMeshes(std::vector<aiMesh *> &out, aiMesh **in,
|
||||
void BuildWCSMeshes(MeshArray &out, aiMesh **in,
|
||||
unsigned int numIn, aiNode *node) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@@ -126,7 +126,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
|
||||
|
||||
unsigned int aiNumMeshesPerPType[4] = { 0, 0, 0, 0 };
|
||||
|
||||
std::vector<aiMesh *> outMeshes;
|
||||
MeshArray outMeshes;
|
||||
outMeshes.reserve(static_cast<size_t>(pScene->mNumMeshes) << 1u);
|
||||
|
||||
bool bAnyChanges = false;
|
||||
@@ -165,6 +165,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
|
||||
if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) {
|
||||
*meshIdx = static_cast<unsigned int>(outMeshes.size());
|
||||
outMeshes.emplace_back(mesh);
|
||||
pScene->mMeshes[i] = nullptr; // Indicate ownership transfer
|
||||
} else {
|
||||
delete mesh;
|
||||
pScene->mMeshes[i] = nullptr;
|
||||
@@ -188,12 +189,15 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
|
||||
|
||||
unsigned int numPolyVerts = 0;
|
||||
for (; pFirstFace != pLastFace; ++pFirstFace) {
|
||||
if (pFirstFace->mNumIndices <= 3)
|
||||
if (pFirstFace->mNumIndices >= 1 && pFirstFace->mNumIndices <= 3)
|
||||
++aiNumPerPType[pFirstFace->mNumIndices - 1];
|
||||
else {
|
||||
++aiNumPerPType[3];
|
||||
numPolyVerts += pFirstFace->mNumIndices;
|
||||
}
|
||||
if (pFirstFace->mNumIndices == 0) {
|
||||
ASSIMP_LOG_WARN("Face with 0 indices treated as polygon");
|
||||
}
|
||||
}
|
||||
|
||||
VertexWeightTable *avw = ComputeVertexBoneWeightTable(mesh);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
All rights reserved.
|
||||
@@ -35,27 +34,20 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file A helper class that processes texture transformations */
|
||||
|
||||
#include "TextureTransform.h"
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
#include "TextureTransform.h"
|
||||
#include <assimp/StringUtils.h>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
TextureTransformStep::TextureTransformStep() : configFlags() {
|
||||
// nothing to do here
|
||||
}
|
||||
namespace Assimp {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
@@ -202,7 +194,6 @@ inline static const char* MappingModeToChar(aiTextureMapMode map) {
|
||||
void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
ASSIMP_LOG_DEBUG("TransformUVCoordsProcess begin");
|
||||
|
||||
|
||||
/* We build a per-mesh list of texture transformations we'll need
|
||||
* to apply. To achieve this, we iterate through all materials,
|
||||
* find all textures and get their transformations and UV indices.
|
||||
@@ -426,7 +417,6 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
// it shouldn't be too worse if we remove them.
|
||||
unsigned int size = (unsigned int)trafo.size();
|
||||
if (size > AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
||||
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_ERROR(static_cast<unsigned int>(trafo.size()), " UV channels required but just ",
|
||||
AI_MAX_NUMBER_OF_TEXTURECOORDS, " available");
|
||||
@@ -434,7 +424,6 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
size = AI_MAX_NUMBER_OF_TEXTURECOORDS;
|
||||
}
|
||||
|
||||
|
||||
aiVector3D* old[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
|
||||
old[n] = mesh->mTextureCoords[n];
|
||||
@@ -443,14 +432,13 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
// that we're not going to need later can be overridden.
|
||||
it = trafo.begin();
|
||||
for (unsigned int n = 0; n < trafo.size();++n,++it) {
|
||||
|
||||
if (n >= size) {
|
||||
// Try to use an untransformed channel for all channels we threw over board
|
||||
UpdateUVIndex((*it).updateList,untransformed);
|
||||
continue;
|
||||
}
|
||||
|
||||
outChannels++;
|
||||
++outChannels;
|
||||
|
||||
// Write to the log
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
@@ -470,15 +458,18 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
// Check whether we need a new buffer here
|
||||
if (mesh->mTextureCoords[n]) {
|
||||
|
||||
it2 = it;++it2;
|
||||
it2 = it;
|
||||
++it2;
|
||||
for (unsigned int m = n+1; m < size;++m, ++it2) {
|
||||
|
||||
if ((*it2).uvIndex == n){
|
||||
it2 = trafo.begin();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it2 == trafo.begin()){
|
||||
if (it2 == trafo.begin()) {
|
||||
{
|
||||
std::unique_ptr<aiVector3D[]> oldTextureCoords(mesh->mTextureCoords[n]);
|
||||
}
|
||||
mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
|
||||
}
|
||||
}
|
||||
@@ -536,13 +527,12 @@ void TextureTransformStep::Execute( aiScene* pScene) {
|
||||
|
||||
// Print some detailed statistics into the log
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
|
||||
if (transformedChannels) {
|
||||
ASSIMP_LOG_INFO("TransformUVCoordsProcess end: ", outChannels, " output channels (in: ", inChannels, ", modified: ", transformedChannels,")");
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("TransformUVCoordsProcess finished");
|
||||
ASSIMP_LOG_INFO("TransformUVCoordsProcess finished");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
All rights reserved.
|
||||
@@ -43,9 +42,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef AI_TEXTURE_TRANSFORM_H_INCLUDED
|
||||
#define AI_TEXTURE_TRANSFORM_H_INCLUDED
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include "Common/BaseProcess.h"
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/material.h>
|
||||
#include <list>
|
||||
|
||||
@@ -56,129 +55,103 @@ namespace Assimp {
|
||||
|
||||
#define AI_TT_UV_IDX_LOCK_TBD 0xffffffff
|
||||
#define AI_TT_UV_IDX_LOCK_NONE 0xeeeeeeee
|
||||
|
||||
|
||||
#define AI_TT_ROTATION_EPSILON ((float)AI_DEG_TO_RAD(0.5))
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Small helper structure representing a shortcut into the material list
|
||||
* to be able to update some values quickly.
|
||||
*/
|
||||
/**
|
||||
* @brief Small helper structure representing a shortcut into the material list
|
||||
* to be able to update some values quickly.
|
||||
*/
|
||||
struct TTUpdateInfo {
|
||||
TTUpdateInfo() AI_NO_EXCEPT
|
||||
: directShortcut(nullptr)
|
||||
, mat(nullptr)
|
||||
, semantic(0)
|
||||
, index(0) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Direct shortcut, if available
|
||||
unsigned int* directShortcut;
|
||||
unsigned int* directShortcut = nullptr;
|
||||
|
||||
//! Material
|
||||
aiMaterial *mat;
|
||||
aiMaterial *mat = nullptr;
|
||||
|
||||
//! Texture type and index
|
||||
unsigned int semantic, index;
|
||||
//! Texture type
|
||||
unsigned int semantic = 0;
|
||||
|
||||
//! Texture index
|
||||
unsigned int index = 0;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper class representing texture coordinate transformations
|
||||
*/
|
||||
/**
|
||||
* @brief Helper class representing texture coordinate transformations
|
||||
*/
|
||||
struct STransformVecInfo : public aiUVTransform {
|
||||
STransformVecInfo() AI_NO_EXCEPT
|
||||
: uvIndex(0)
|
||||
, mapU(aiTextureMapMode_Wrap)
|
||||
, mapV(aiTextureMapMode_Wrap)
|
||||
, lockedPos(AI_TT_UV_IDX_LOCK_NONE) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Source texture coordinate index
|
||||
unsigned int uvIndex;
|
||||
unsigned int uvIndex = 0;
|
||||
|
||||
//! Texture mapping mode in the u, v direction
|
||||
aiTextureMapMode mapU,mapV;
|
||||
//! Texture mapping mode in the u direction
|
||||
aiTextureMapMode mapU = aiTextureMapMode_Wrap;
|
||||
|
||||
//! Texture mapping mode in the v direction
|
||||
aiTextureMapMode mapV = aiTextureMapMode_Wrap;
|
||||
|
||||
//! Locked destination UV index
|
||||
//! AI_TT_UV_IDX_LOCK_TBD - to be determined
|
||||
//! AI_TT_UV_IDX_LOCK_NONE - none (default)
|
||||
unsigned int lockedPos;
|
||||
unsigned int lockedPos = AI_TT_UV_IDX_LOCK_NONE;
|
||||
|
||||
//! Update info - shortcuts into all materials
|
||||
//! that are referencing this transform setup
|
||||
std::list<TTUpdateInfo> updateList;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Compare two transform setups
|
||||
*/
|
||||
inline bool operator== (const STransformVecInfo& other) const
|
||||
{
|
||||
inline bool operator== (const STransformVecInfo& other) const {
|
||||
// We use a small epsilon here
|
||||
const static float epsilon = 0.05f;
|
||||
|
||||
if (std::fabs( mTranslation.x - other.mTranslation.x ) > epsilon ||
|
||||
std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon)
|
||||
{
|
||||
std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::fabs( mScaling.x - other.mScaling.x ) > epsilon ||
|
||||
std::fabs( mScaling.y - other.mScaling.y ) > epsilon)
|
||||
{
|
||||
std::fabs( mScaling.y - other.mScaling.y ) > epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::fabs( mRotation - other.mRotation) > epsilon)
|
||||
{
|
||||
if (std::fabs( mRotation - other.mRotation) > epsilon) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator!= (const STransformVecInfo& other) const
|
||||
{
|
||||
inline bool operator!= (const STransformVecInfo& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether this is an untransformed texture coordinate set
|
||||
*/
|
||||
inline bool IsUntransformed() const
|
||||
{
|
||||
/**
|
||||
* @brief Returns whether this is an untransformed texture coordinate set
|
||||
*/
|
||||
inline bool IsUntransformed() const {
|
||||
return (1.0f == mScaling.x && 1.f == mScaling.y &&
|
||||
!mTranslation.x && !mTranslation.y &&
|
||||
mRotation < AI_TT_ROTATION_EPSILON);
|
||||
!mTranslation.x && !mTranslation.y && mRotation < AI_TT_ROTATION_EPSILON);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Build a 3x3 matrix from the transformations
|
||||
*/
|
||||
inline void GetMatrix(aiMatrix3x3& mOut)
|
||||
{
|
||||
/**
|
||||
* @brief Build a 3x3 matrix from the transformations
|
||||
*/
|
||||
inline void GetMatrix(aiMatrix3x3& mOut) {
|
||||
mOut = aiMatrix3x3();
|
||||
|
||||
if (1.0f != mScaling.x || 1.0f != mScaling.y)
|
||||
{
|
||||
if (1.0f != mScaling.x || 1.0f != mScaling.y) {
|
||||
aiMatrix3x3 mScale;
|
||||
mScale.a1 = mScaling.x;
|
||||
mScale.b2 = mScaling.y;
|
||||
mOut = mScale;
|
||||
}
|
||||
if (mRotation)
|
||||
{
|
||||
if (mRotation) {
|
||||
aiMatrix3x3 mRot;
|
||||
mRot.a1 = mRot.b2 = std::cos(mRotation);
|
||||
mRot.a2 = mRot.b1 = std::sin(mRotation);
|
||||
mRot.a2 = -mRot.a2;
|
||||
mOut *= mRot;
|
||||
}
|
||||
if (mTranslation.x || mTranslation.y)
|
||||
{
|
||||
if (mTranslation.x || mTranslation.y) {
|
||||
aiMatrix3x3 mTrans;
|
||||
mTrans.a3 = mTranslation.x;
|
||||
mTrans.b3 = mTranslation.y;
|
||||
@@ -187,16 +160,18 @@ struct STransformVecInfo : public aiUVTransform {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper step to compute final UV coordinate sets if there are scalings
|
||||
/**
|
||||
* @brief Helper step to compute final UV coordinate sets if there are scalings
|
||||
* or rotations in the original data read from the file.
|
||||
*/
|
||||
class TextureTransformStep : public BaseProcess {
|
||||
*/
|
||||
class TextureTransformStep final : public BaseProcess {
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
/// The default class constructor / destructor.
|
||||
TextureTransformStep();
|
||||
/// The default class constructor. /
|
||||
TextureTransformStep() = default;
|
||||
|
||||
/// The default class destructor.
|
||||
~TextureTransformStep() override = default;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@@ -210,10 +185,11 @@ public:
|
||||
|
||||
protected:
|
||||
// -------------------------------------------------------------------
|
||||
/** Preprocess a specific UV transformation setup
|
||||
/**
|
||||
* @brief Preprocess a specific UV transformation setup
|
||||
*
|
||||
* @param info Transformation setup to be preprocessed.
|
||||
*/
|
||||
*/
|
||||
void PreProcessUVTransform(STransformVecInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
@@ -583,6 +583,9 @@ char *OpenDDLParser::parsePrimitiveDataType(char *in, char *end, Value::ValueTyp
|
||||
size_t prim_len(0);
|
||||
for (size_t i = 0; i < (size_t) Value::ValueType::ddl_types_max; i++) {
|
||||
prim_len = strlen(Grammar::PrimitiveTypeToken[i]);
|
||||
if (static_cast<size_t>(end - in) < prim_len) {
|
||||
continue;
|
||||
}
|
||||
if (0 == strncmp(in, Grammar::PrimitiveTypeToken[i], prim_len)) {
|
||||
type = static_cast<Value::ValueType>(i);
|
||||
break;
|
||||
@@ -595,6 +598,9 @@ char *OpenDDLParser::parsePrimitiveDataType(char *in, char *end, Value::ValueTyp
|
||||
} else {
|
||||
in += prim_len;
|
||||
}
|
||||
if (in >= end) {
|
||||
return in;
|
||||
}
|
||||
|
||||
bool ok(true);
|
||||
if (*in == Grammar::OpenArrayToken[0]) {
|
||||
@@ -602,13 +608,13 @@ char *OpenDDLParser::parsePrimitiveDataType(char *in, char *end, Value::ValueTyp
|
||||
++in;
|
||||
char *start(in);
|
||||
while (in != end) {
|
||||
++in;
|
||||
if (*in == Grammar::CloseArrayToken[0]) {
|
||||
len = ::atoi(start);
|
||||
ok = true;
|
||||
++in;
|
||||
break;
|
||||
}
|
||||
++in;
|
||||
}
|
||||
} else {
|
||||
len = 1;
|
||||
@@ -630,9 +636,9 @@ char *OpenDDLParser::parseReference(char *in, char *end, std::vector<Name *> &na
|
||||
if (nextName) {
|
||||
names.push_back(nextName);
|
||||
}
|
||||
while (Grammar::CommaSeparator[0] == *in) {
|
||||
while (in != end && Grammar::CommaSeparator[0] == *in) {
|
||||
in = getNextSeparator(in, end);
|
||||
if (Grammar::CommaSeparator[0] == *in) {
|
||||
if (in != end && Grammar::CommaSeparator[0] == *in) {
|
||||
in = parseName(in, end, &nextName);
|
||||
if (nextName) {
|
||||
names.push_back(nextName);
|
||||
@@ -655,7 +661,7 @@ char *OpenDDLParser::parseBooleanLiteral(char *in, char *end, Value **boolean) {
|
||||
char *start(in);
|
||||
|
||||
size_t len(0);
|
||||
while (!isSeparator(*in) && in != end) {
|
||||
while (in != end && !isSeparator(*in)) {
|
||||
++in;
|
||||
++len;
|
||||
}
|
||||
@@ -688,7 +694,7 @@ char *OpenDDLParser::parseIntegerLiteral(char *in, char *end, Value **integer, V
|
||||
|
||||
in = lookForNextToken(in, end);
|
||||
char *start(in);
|
||||
while (!isSeparator(*in) && in != end) {
|
||||
while (in != end && !isSeparator(*in)) {
|
||||
++in;
|
||||
}
|
||||
|
||||
@@ -831,7 +837,7 @@ char *OpenDDLParser::parseHexaLiteral(char *in, char *end, Value **data) {
|
||||
bool ok(true);
|
||||
char *start(in);
|
||||
int pos(0);
|
||||
while (!isSeparator(*in) && in != end) {
|
||||
while (in != end && !isSeparator(*in)) {
|
||||
if ((*in < '0' && *in > '9') || (*in < 'a' && *in > 'f') || (*in < 'A' && *in > 'F')) {
|
||||
ok = false;
|
||||
break;
|
||||
|
||||
@@ -12,6 +12,15 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef _CRT_SECURE_NO_WARNINGS
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
# endif // _CRT_SECURE_NO_WARNINGS
|
||||
# ifndef _CRT_NONSTDC_NO_DEPRECATE
|
||||
# define _CRT_NONSTDC_NO_DEPRECATE
|
||||
# endif // _CRT_NONSTDC_NO_DEPRECATE
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef _CRT_NONSTDC_NO_DEPRECATE
|
||||
# define _CRT_NONSTDC_NO_DEPRECATE
|
||||
# endif
|
||||
# ifndef _CRT_SECURE_NO_WARNINGS
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
# endif //_CRT_SECURE_NO_WARNINGS
|
||||
#endif // _WIN32
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__BORLANDC__)
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef _CRT_SECURE_NO_WARNINGS
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
# endif // _CRT_SECURE_NO_WARNINGS
|
||||
# ifndef _CRT_NONSTDC_NO_DEPRECATE
|
||||
# define _CRT_NONSTDC_NO_DEPRECATE
|
||||
# endif // _CRT_NONSTDC_NO_DEPRECATE
|
||||
#endif // _WIN32
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Copyright (C) 2004-2019 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
|
||||
@@ -23,7 +23,6 @@ z_const char * const z_errmsg[10] = {
|
||||
(z_const char *)""
|
||||
};
|
||||
|
||||
|
||||
const char * ZEXPORT zlibVersion()
|
||||
{
|
||||
return ZLIB_VERSION;
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <assimp/types.h>
|
||||
|
||||
#include <exception>
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
// =======================================================================
|
||||
@@ -67,6 +68,7 @@ class IOStream;
|
||||
class IOSystem;
|
||||
class ProgressHandler;
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Plugin development
|
||||
//
|
||||
@@ -108,6 +110,10 @@ namespace Assimp {
|
||||
* allocations and may take some time, so it's better to reuse them as often as
|
||||
* possible.
|
||||
*
|
||||
* If you want to let assimp deal with OutOfMemory-exception make sure that
|
||||
* ASSIMP_CATCH_GLOBAL_EXCEPTIONS is set.
|
||||
* If this is not the case you need to catch the exception by yourself.
|
||||
*
|
||||
* If you need the Importer to do custom file handling to access the files,
|
||||
* implement IOSystem and IOStream and supply an instance of your custom
|
||||
* IOSystem implementation by calling SetIOHandler() before calling ReadFile().
|
||||
|
||||
@@ -240,8 +240,8 @@ public:
|
||||
* @param end Points to the mesh after the last mesh to be processed
|
||||
*/
|
||||
static void MergeMeshes(aiMesh **dest, unsigned int flags,
|
||||
std::vector<aiMesh *>::const_iterator begin,
|
||||
std::vector<aiMesh *>::const_iterator end);
|
||||
MeshArray::const_iterator begin,
|
||||
MeshArray::const_iterator end);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Merges two or more bones
|
||||
@@ -251,8 +251,8 @@ public:
|
||||
* @param begin First mesh to be processed
|
||||
* @param end Points to the mesh after the last mesh to be processed
|
||||
*/
|
||||
static void MergeBones(aiMesh *out, std::vector<aiMesh *>::const_iterator it,
|
||||
std::vector<aiMesh *>::const_iterator end);
|
||||
static void MergeBones(aiMesh *out, MeshArray::const_iterator it,
|
||||
MeshArray::const_iterator end);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Merges two or more materials
|
||||
@@ -277,8 +277,8 @@ public:
|
||||
* @param end Last mesh to be processed
|
||||
*/
|
||||
static void BuildUniqueBoneList(std::list<BoneWithHash> &asBones,
|
||||
std::vector<aiMesh *>::const_iterator it,
|
||||
std::vector<aiMesh *>::const_iterator end);
|
||||
MeshArray::const_iterator it,
|
||||
MeshArray::const_iterator end);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Add a name prefix to all nodes in a scene.
|
||||
|
||||
@@ -183,29 +183,6 @@ struct Vertex {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator < (const Vertex & o) const {
|
||||
if (position < o.position) return true;
|
||||
if (position != o.position) return false;
|
||||
|
||||
if (normal < o.normal) return true;
|
||||
if (normal != o.normal) return false;
|
||||
|
||||
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i ++) {
|
||||
if (texcoords[i] < o.texcoords[i]) return true;
|
||||
if (texcoords[i] != o.texcoords[i]) return false;
|
||||
}
|
||||
|
||||
// note that tangent/bitangent are not checked since they are optional
|
||||
|
||||
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; i ++) {
|
||||
if (colors[i] < o.colors[i]) return true;
|
||||
if (colors[i] != o.colors[i]) return false;
|
||||
}
|
||||
|
||||
// if reached this point, they are equal
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/// Convert back to non-interleaved storage
|
||||
void SortBack(aiMesh* out, unsigned int idx) const {
|
||||
|
||||
@@ -70,9 +70,15 @@ union _IEEESingle {
|
||||
float Float;
|
||||
struct
|
||||
{
|
||||
#if (defined AI_BUILD_BIG_ENDIAN)
|
||||
uint32_t Sign : 1;
|
||||
uint32_t Exp : 8;
|
||||
uint32_t Frac : 23;
|
||||
#else
|
||||
uint32_t Frac : 23;
|
||||
uint32_t Exp : 8;
|
||||
uint32_t Sign : 1;
|
||||
#endif
|
||||
} IEEE;
|
||||
};
|
||||
|
||||
@@ -83,9 +89,15 @@ union _IEEEDouble {
|
||||
double Double;
|
||||
struct
|
||||
{
|
||||
#if (defined AI_BUILD_BIG_ENDIAN)
|
||||
uint64_t Sign : 1;
|
||||
uint64_t Exp : 11;
|
||||
uint64_t Frac : 52;
|
||||
#else
|
||||
uint64_t Frac : 52;
|
||||
uint64_t Exp : 11;
|
||||
uint64_t Sign : 1;
|
||||
#endif
|
||||
} IEEE;
|
||||
};
|
||||
|
||||
|
||||
+12
-1
@@ -77,6 +77,17 @@ typedef uint32_t ai_uint32;
|
||||
#include <new> // for std::nothrow_t
|
||||
#include <string> // for aiString::Set(const std::string&)
|
||||
|
||||
struct aiNode;
|
||||
struct aiMesh;
|
||||
struct aiMaterial;
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
using MeshArray = std::vector<aiMesh *>;
|
||||
using NodeArray = std::vector<aiNode *>;
|
||||
using MaterialArray = std::vector<aiMaterial*>;
|
||||
|
||||
namespace Assimp {
|
||||
//! @cond never
|
||||
namespace Intern {
|
||||
@@ -118,7 +129,7 @@ extern "C" {
|
||||
|
||||
/** Maximum dimension for strings, ASSIMP strings are zero terminated. */
|
||||
#ifdef __cplusplus
|
||||
static const size_t AI_MAXLEN = 1024;
|
||||
static constexpr size_t AI_MAXLEN = 1024;
|
||||
#else
|
||||
#define AI_MAXLEN 1024
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[Setup]
|
||||
AppName=Open Asset Import Library - SDK
|
||||
AppVerName=Open Asset Import Library - SDK (v5.4.3)
|
||||
AppVerName=Open Asset Import Library - SDK (v6.0.2)
|
||||
DefaultDirName={pf}\Assimp
|
||||
DefaultGroupName=Assimp
|
||||
UninstallDisplayIcon={app}\bin\x64\assimp.exe
|
||||
@@ -12,9 +12,9 @@ SetupIconFile=..\..\tools\shared\assimp_tools_icon.ico
|
||||
WizardImageFile=..\..\tools\shared\assimp_tools_icon.bmp
|
||||
WizardSmallImageFile=..\..\tools\shared\assimp_tools_icon.bmp
|
||||
LicenseFile=License.rtf
|
||||
OutputBaseFileName=assimp-sdk-5.4.3-setup
|
||||
VersionInfoVersion=5.4.3.0
|
||||
VersionInfoTextVersion=5.4.3
|
||||
OutputBaseFileName=assimp-sdk-6.0.2-setup
|
||||
VersionInfoVersion=6.0.2.0
|
||||
VersionInfoTextVersion=6.0.2
|
||||
VersionInfoCompany=Assimp Development Team
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
|
||||
@@ -43,7 +43,7 @@ Source: "vc_redist.x64.exe"; DestDir: "{app}\stub\"; Check: IsWin64
|
||||
; Common stuff
|
||||
Source: "..\..\CREDITS"; DestDir: "{app}"
|
||||
Source: "..\..\LICENSE"; DestDir: "{app}"
|
||||
Source: "..\..\README"; DestDir: "{app}"
|
||||
Source: "..\..\README.md"; DestDir: "{app}"
|
||||
Source: "WEB"; DestDir: "{app}"
|
||||
|
||||
Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs
|
||||
|
||||
@@ -36,13 +36,21 @@ aiProcess_JoinIdenticalVertices = 0x2
|
||||
#
|
||||
aiProcess_MakeLeftHanded = 0x4
|
||||
|
||||
## <hr>Triangulates all faces of all meshes.
|
||||
## <hr>Triangulates all faces of all meshes.
|
||||
#
|
||||
# By default the imported mesh data might contain faces with more than 3
|
||||
# indices. For rendering you'll usually want all faces to be triangles.
|
||||
# This post processing stepaiProcess_ForceGenNormals
|
||||
## <hr>Removes some parts of the data structure (animations, materials,
|
||||
# light sources, cameras, textures, vertex components).
|
||||
# indices. For rendering you'll usually want all faces to be triangles.
|
||||
# This post processing step splits up faces with more than 3 indices into
|
||||
# triangles. Line and point primitives are *not* modified! If you want
|
||||
# 'triangles only' with no other kinds of primitives, try the following
|
||||
# solution:
|
||||
# - Specify both #aiProcess_Triangulate and #aiProcess_SortByPType
|
||||
# - Ignore all point and line meshes when you process assimp's output
|
||||
#
|
||||
aiProcess_Triangulate = 0x8
|
||||
|
||||
# <hr>Removes some parts of the data structure (animations, materials,
|
||||
# light sources, cameras, textures, vertex components).
|
||||
#
|
||||
# The components to be removed are specified in a separate
|
||||
# configuration option, <tt>#AI_CONFIG_PP_RVC_FLAGS<tt>. This is quite useful
|
||||
|
||||
@@ -314,7 +314,7 @@ public final class AiMesh {
|
||||
* @return true if tangents and bitangents are available
|
||||
*/
|
||||
public boolean hasTangentsAndBitangents() {
|
||||
return m_tangents != null && m_tangents != null;
|
||||
return m_tangents != null && m_bitangents != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+8
-2
@@ -59,6 +59,10 @@ endif()
|
||||
# Assimp library can be found, even if it is not installed system-wide yet.
|
||||
LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib )
|
||||
|
||||
SET(TOOLS
|
||||
unit/Tools/TestTools.h
|
||||
)
|
||||
|
||||
SET( COMMON
|
||||
unit/utSimd.cpp
|
||||
unit/utIOSystem.cpp
|
||||
@@ -219,6 +223,7 @@ SOURCE_GROUP( UnitTests\\GeometryTools FILES ${Geometry} )
|
||||
SOURCE_GROUP( UnitTests\\ImportExport FILES ${IMPORTERS} )
|
||||
SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} )
|
||||
SOURCE_GROUP( UnitTests\\Math FILES ${MATH} )
|
||||
SOURCE_GROUP( UnitTests\\Tools FILES ${TOOLS} )
|
||||
SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES})
|
||||
|
||||
add_executable( unit
|
||||
@@ -227,11 +232,12 @@ add_executable( unit
|
||||
../code/Common/Version.cpp
|
||||
../code/Common/Base64.cpp
|
||||
${COMMON}
|
||||
${Geometry}
|
||||
${Geometry}
|
||||
${IMPORTERS}
|
||||
${MATERIAL}
|
||||
${MATH}
|
||||
${POST_PROCESSES}
|
||||
${POST_PROCESSES}
|
||||
${TOOLS}
|
||||
)
|
||||
|
||||
if(ASSIMP_HUNTER_ENABLED)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
AC3Db
|
||||
MATERIAL "" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10 trans 0
|
||||
OBJECT world
|
||||
kids 1
|
||||
OBJECT poly
|
||||
name "rect"
|
||||
loc 1 0.5 0
|
||||
numvert 4
|
||||
-1 0.5 0
|
||||
1 0.5 0
|
||||
1 -0.5 0
|
||||
-1 -0.5 0
|
||||
numsurf 1
|
||||
SURF 0x20
|
||||
mat 0
|
||||
refs 4
|
||||
3 0 0
|
||||
2 1 0
|
||||
1 1 1
|
||||
0 0 1
|
||||
kids 0
|
||||
@@ -2,7 +2,7 @@
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -43,20 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
using namespace ::Assimp;
|
||||
|
||||
class TestDefaultIOStream : public DefaultIOStream {
|
||||
class TestDefaultIOStream final : public DefaultIOStream {
|
||||
public:
|
||||
TestDefaultIOStream()
|
||||
: DefaultIOStream() {
|
||||
// empty
|
||||
}
|
||||
|
||||
TestDefaultIOStream( FILE* pFile, const std::string &strFilename )
|
||||
: DefaultIOStream( pFile, strFilename ) {
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ~TestDefaultIOStream() {
|
||||
// empty
|
||||
}
|
||||
TestDefaultIOStream() = default;
|
||||
TestDefaultIOStream(FILE* pFile, const std::string &strFilename) : DefaultIOStream(pFile, strFilename) {}
|
||||
~TestDefaultIOStream() override = default;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace Assimp::Unittest {
|
||||
|
||||
class TestTools final {
|
||||
public:
|
||||
TestTools() = default;
|
||||
~TestTools() = default;
|
||||
static bool openFilestream(FILE **pFile, const char *filename, const char *mode);
|
||||
};
|
||||
|
||||
inline bool TestTools::openFilestream(FILE **fs, const char *filename, const char *mode) {
|
||||
#if defined(_WIN32)
|
||||
errno_t err{ 0 };
|
||||
err = fopen_s(fs, filename, mode);
|
||||
EXPECT_EQ(err, 0);
|
||||
#else
|
||||
*fs = fopen(filename, mode);
|
||||
#endif
|
||||
return fs != nullptr;
|
||||
}
|
||||
|
||||
} // namespace Assimp::Unittest
|
||||
@@ -3,7 +3,7 @@
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
@@ -39,42 +39,60 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
#pragma once
|
||||
#ifdef _WIN32
|
||||
# ifndef _CRT_NONSTDC_NO_DEPRECATE
|
||||
# define _CRT_NONSTDC_NO_DEPRECATE
|
||||
# endif // _CRT_NONSTDC_NO_DEPRECATE
|
||||
# ifndef _CRT_SECURE_NO_WARNINGS
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__)
|
||||
#define TMP_PATH "./"
|
||||
# define TMP_PATH "./"
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define TMP_PATH "/tmp/"
|
||||
# define TMP_PATH "/var/tmp/"
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#include <io.h>
|
||||
inline FILE* MakeTmpFile(char* tmplate)
|
||||
{
|
||||
auto pathtemplate = _mktemp(tmplate);
|
||||
inline FILE* MakeTmpFile(char* tmplate, size_t len, std::string &tmpName) {
|
||||
size_t tmpLen = len + 1;
|
||||
char *pathtemplate = new char[tmpLen];
|
||||
strcpy_s(pathtemplate, tmpLen, tmplate);
|
||||
int err_code = _mktemp_s(pathtemplate, tmpLen);
|
||||
EXPECT_EQ(err_code, 0);
|
||||
EXPECT_NE(pathtemplate, nullptr);
|
||||
if(pathtemplate == nullptr)
|
||||
{
|
||||
if(pathtemplate == nullptr) {
|
||||
delete[] pathtemplate;
|
||||
return nullptr;
|
||||
}
|
||||
auto* fs = std::fopen(pathtemplate, "w+");
|
||||
errno_t err;
|
||||
FILE *fs{nullptr};
|
||||
err = fopen_s(&fs, pathtemplate, "w+");
|
||||
EXPECT_EQ(0, err);
|
||||
tmpName = pathtemplate;
|
||||
EXPECT_NE(fs, nullptr);
|
||||
delete[] pathtemplate;
|
||||
|
||||
return fs;
|
||||
}
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
inline FILE* MakeTmpFile(char* tmplate)
|
||||
{
|
||||
inline FILE *MakeTmpFile(char *tmplate, size_t len, std::string &tmpName) {
|
||||
auto fd = mkstemp(tmplate);
|
||||
EXPECT_NE(-1, fd);
|
||||
if(fd == -1)
|
||||
{
|
||||
if(fd == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
auto fs = fdopen(fd, "w+");
|
||||
EXPECT_NE(nullptr, fs);
|
||||
tmpName += tmplate;
|
||||
|
||||
return fs;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -141,3 +141,14 @@ TEST(utACImportExport, testFormatDetection) {
|
||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/AC/TestFormatDetection", aiProcess_ValidateDataStructure);
|
||||
ASSERT_NE(nullptr, scene);
|
||||
}
|
||||
|
||||
TEST(utACImportExport, importDobuleSidedFaces) {
|
||||
Assimp::Importer importer;
|
||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/AC/doubleSidedFace.ac", aiProcess_ValidateDataStructure);
|
||||
ASSERT_NE(nullptr, scene);
|
||||
// The scene contains one double-sided, rectangular AC surface. It should resolve to two quads (front + back) with eight
|
||||
// vertices (one per side to guarantee proper normal vectors).
|
||||
ASSERT_EQ(scene->mNumMeshes, 1u);
|
||||
ASSERT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
||||
ASSERT_EQ(scene->mMeshes[0]->mNumVertices, 8u);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
||||
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
||||
@@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <gtest/gtest.h>
|
||||
#include "TestIOStream.h"
|
||||
#include "UnitTestFileGenerator.h"
|
||||
#include "Tools/TestTools.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
@@ -60,8 +61,9 @@ TEST_F( utDefaultIOStream, FileSizeTest ) {
|
||||
const auto dataSize = sizeof(data);
|
||||
const auto dataCount = dataSize / sizeof(*data);
|
||||
|
||||
char fpath[] = { TMP_PATH"rndfp.XXXXXX" };
|
||||
auto* fs = MakeTmpFile(fpath);
|
||||
char fpath[] = { TMP_PATH"rndfp.XXXXXX\0" };
|
||||
std::string tmpName;
|
||||
auto *fs = MakeTmpFile(fpath, std::strlen(fpath), tmpName);
|
||||
ASSERT_NE(nullptr, fs);
|
||||
{
|
||||
auto written = std::fwrite(data, sizeof(*data), dataCount, fs );
|
||||
@@ -71,13 +73,13 @@ TEST_F( utDefaultIOStream, FileSizeTest ) {
|
||||
ASSERT_EQ(vflush, 0);
|
||||
|
||||
std::fclose(fs);
|
||||
fs = std::fopen(fpath, "r");
|
||||
|
||||
ASSERT_NE(nullptr, fs);
|
||||
EXPECT_TRUE(Unittest::TestTools::openFilestream(&fs, tmpName.c_str(), "r"));
|
||||
ASSERT_NE(nullptr, fs);
|
||||
|
||||
TestDefaultIOStream myStream( fs, fpath);
|
||||
size_t size = myStream.FileSize();
|
||||
EXPECT_EQ( size, dataSize);
|
||||
}
|
||||
remove(fpath);
|
||||
remove(tmpName.c_str());
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -44,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "UnitTestPCH.h"
|
||||
#include <assimp/IOStreamBuffer.h>
|
||||
#include "TestIOStream.h"
|
||||
#include "Tools/TestTools.h"
|
||||
#include "UnitTestFileGenerator.h"
|
||||
|
||||
class IOStreamBufferTest : public ::testing::Test {
|
||||
@@ -86,18 +85,21 @@ TEST_F( IOStreamBufferTest, open_close_Test ) {
|
||||
const auto dataCount = dataSize / sizeof(*data);
|
||||
|
||||
char fname[]={ "octest.XXXXXX" };
|
||||
auto* fs = MakeTmpFile(fname);
|
||||
std::string tmpName;
|
||||
auto* fs = MakeTmpFile(fname, std::strlen(fname), tmpName);
|
||||
ASSERT_NE(nullptr, fs);
|
||||
|
||||
auto written = std::fwrite( data, sizeof(*data), dataCount, fs );
|
||||
auto written = std::fwrite(data, sizeof(*data), dataCount, fs);
|
||||
EXPECT_NE( 0U, written );
|
||||
auto flushResult = std::fflush( fs );
|
||||
ASSERT_EQ(0, flushResult);
|
||||
std::fclose( fs );
|
||||
fs = std::fopen(fname, "r");
|
||||
ASSERT_NE(nullptr, fs);
|
||||
fclose(fs);
|
||||
|
||||
FILE *new_fs{ nullptr };
|
||||
EXPECT_TRUE(Unittest::TestTools::openFilestream(&new_fs, tmpName.c_str(), "r"));
|
||||
ASSERT_NE(nullptr, new_fs);
|
||||
{
|
||||
TestDefaultIOStream myStream( fs, fname );
|
||||
TestDefaultIOStream myStream(new_fs, fname);
|
||||
|
||||
EXPECT_TRUE( myBuffer.open( &myStream ) );
|
||||
EXPECT_FALSE( myBuffer.open( &myStream ) );
|
||||
@@ -111,8 +113,9 @@ TEST_F( IOStreamBufferTest, readlineTest ) {
|
||||
const auto dataSize = sizeof(data);
|
||||
const auto dataCount = dataSize / sizeof(*data);
|
||||
|
||||
char fname[]={ "readlinetest.XXXXXX" };
|
||||
auto* fs = MakeTmpFile(fname);
|
||||
char fname[]={ "readlinetest.XXXXXX\0" };
|
||||
std::string tmpName;
|
||||
auto* fs = MakeTmpFile(fname, std::strlen(fname), tmpName);
|
||||
ASSERT_NE(nullptr, fs);
|
||||
|
||||
auto written = std::fwrite( data, sizeof(*data), dataCount, fs );
|
||||
@@ -121,23 +124,25 @@ TEST_F( IOStreamBufferTest, readlineTest ) {
|
||||
auto flushResult = std::fflush(fs);
|
||||
ASSERT_EQ(0, flushResult);
|
||||
std::fclose(fs);
|
||||
fs = std::fopen(fname, "r");
|
||||
ASSERT_NE(nullptr, fs);
|
||||
|
||||
FILE *new_fs{ nullptr };
|
||||
EXPECT_TRUE(Unittest::TestTools::openFilestream(&new_fs, tmpName.c_str(), "r"));
|
||||
ASSERT_NE(nullptr, new_fs);
|
||||
|
||||
const auto tCacheSize = 26u;
|
||||
|
||||
IOStreamBuffer<char> myBuffer( tCacheSize );
|
||||
EXPECT_EQ(tCacheSize, myBuffer.cacheSize() );
|
||||
IOStreamBuffer<char> myBuffer(tCacheSize);
|
||||
EXPECT_EQ(tCacheSize, myBuffer.cacheSize());
|
||||
|
||||
TestDefaultIOStream myStream( fs, fname );
|
||||
TestDefaultIOStream myStream(new_fs, fname);
|
||||
auto size = myStream.FileSize();
|
||||
auto numBlocks = size / myBuffer.cacheSize();
|
||||
if ( size % myBuffer.cacheSize() > 0 ) {
|
||||
numBlocks++;
|
||||
}
|
||||
EXPECT_TRUE( myBuffer.open( &myStream ) );
|
||||
EXPECT_EQ( numBlocks, myBuffer.getNumBlocks() );
|
||||
EXPECT_TRUE( myBuffer.close() );
|
||||
EXPECT_TRUE(myBuffer.open(&myStream));
|
||||
EXPECT_EQ(numBlocks, myBuffer.getNumBlocks() );
|
||||
EXPECT_TRUE(myBuffer.close() );
|
||||
}
|
||||
|
||||
TEST_F( IOStreamBufferTest, accessBlockIndexTest ) {
|
||||
|
||||
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2025, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -50,18 +48,7 @@ using namespace ::Assimp::Profiling;
|
||||
|
||||
class utProfiler : public ::testing::Test {
|
||||
public:
|
||||
LogStream *m_stream;
|
||||
|
||||
/*virtual void SetUp() {
|
||||
m_stream = new UTLogStream;
|
||||
DefaultLogger::create();
|
||||
DefaultLogger::get()->attachStream( m_stream );
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
DefaultLogger::get()->detatchStream( m_stream );
|
||||
m_stream = nullptr;
|
||||
}*/
|
||||
LogStream *mStream = nullptr;
|
||||
};
|
||||
|
||||
TEST_F( utProfiler, addRegion_success ) {
|
||||
@@ -70,8 +57,7 @@ TEST_F( utProfiler, addRegion_success ) {
|
||||
for ( int i=0; i<10; i++ ) {
|
||||
volatile int j=0;
|
||||
j++;
|
||||
(void)j; /* avoid gcc-16 warnings about unused variable */
|
||||
}
|
||||
myProfiler.EndRegion( "t1" );
|
||||
//UTLogStream *stream( (UTLogStream*) m_stream );
|
||||
//EXPECT_FALSE( stream->m_messages.empty() );
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class utSceneCombiner : public ::testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(utSceneCombiner, MergeMeshes_ValidNames_Test) {
|
||||
std::vector<aiMesh *> merge_list;
|
||||
MeshArray merge_list;
|
||||
aiMesh *mesh1 = new aiMesh;
|
||||
mesh1->mName.Set("mesh_1");
|
||||
merge_list.push_back(mesh1);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user