Compare commits

..
Author SHA1 Message Date
Kim Kulling 676ef9637b glFT2: Fix texture size in export. 2025-03-11 13:04:10 +01:00
381 changed files with 2848 additions and 6198 deletions
+1 -1
View File
@@ -70,7 +70,7 @@ IncludeCategories:
- Regex: '^<.*'
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentCaseLabels: false
#IndentPPDirectives: AfterHash
IndentWidth: 4
# IndentWrappedFunctionNames: false
-4
View File
@@ -23,10 +23,6 @@ jobs:
os: windows-latest
cxx: cl.exe
cc: cl.exe
- name: windows-hunter-latest-cl.exe
os: windows-latest
cxx: cl.exe
cc: cl.exe
- name: ubuntu-latest-clang++
os: ubuntu-latest
cxx: clang++
+2 -4
View File
@@ -4,9 +4,7 @@
### Install prerequisites
You need to install
* cmake
* Your compiler (must support C++17 and C99 at least)
* For Windows
* DX-SDK 9 if you want to use our 3D-Viewer
* Your compiler
### Get the source
Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via:
@@ -41,7 +39,7 @@ This will generate the project files for the visual studio. All dependencies use
See <https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app>
### Build instructions for MinGW
Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag
Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag
required to compile some of assimp's files, especially for debug builds.
Version 7.3.0 of g++-mingw-w64 & gcc-mingw-w64 appears to work.
+7 -7
View File
@@ -290,7 +290,7 @@ FEATURES:
- Added support for 64 bit version header introduced in FbxSdk2016
- Travis: enable coverall support.
- PyAssimp: New version of the pyASSIMP 3D viewer, with much improved 3D controls
- Morph animation support for collada
- Morph animation support for collada
- Added support for parameters Ni and Tf in OBJ/MTL file format
- aiScene: add method to add children
- Added new option to IFC importer to control tessellation angle + removed unused IFC option
@@ -300,7 +300,7 @@ FEATURES:
- travis ci: enable sudo support.
- openddlparser: integrate release v0.4.0
- aiMetaData: Added support for metadata in assbin format
FIXES/HOUSEKEEPING:
- Introduce usage of #pragma statement
- Put cmake-scripts into their own folder
@@ -352,7 +352,7 @@ FIXES/HOUSEKEEPING:
- add vertex color export support ( issue 809 )
- Fix memory leak in Collada importer ( issue 1169 )
- add stp to the list of supported extensions for step-files ( issue 1183 )
- fix clang build ( Issue-1169 )
- fix clang build ( Issue-1169 )
- fix for FreeBSD
- Import FindPkgMacros to main CMake Configuration
- Extended support for tessellation parameter to more IFC shapes
@@ -375,7 +375,7 @@ FIXES/HOUSEKEEPING:
- Obj-Importer: do not break when detecting an overflow ( issue 1244 )
- Obj-Importer: fix parsing of multible line data definitions
- Fixed bug where IFC models with multiple IFCSite only loaded 1 site instead of the complete model
- PLYImporter: - optimize memory and speed on ply importer / change parser to use a file stream - manage texture path in ply
- PLYImporter: - optimize memory and speed on ply importer / change parser to use a file stream - manage texture path in ply
import - manage texture coords on faces in ply import - correction on point cloud faces generation
- Utf8: integrate new lib ( issue 1158 )
- fixed CMAKE_MODULE_PATH overwriting previous values
@@ -400,7 +400,7 @@ FIXES/HOUSEKEEPING:
- Remove std functions deprecated by C++11.
- X-Importer: make it deal with lines
- use correct path for compilers ( issue 1335 )
- Collada: add workaround to deal with polygon with holes
- Collada: add workaround to deal with polygon with holes
- update python readme
- Use unique node names when loading Collada files
- Fixed many FBX bugs
@@ -429,7 +429,7 @@ FEATURES:
- C4D: update to latest Melange-SDK
- Add a gitter channel
- Coverity check enabled
- Switch to <...> include brackets for public headers
- Switch to <...> include brackets for public headers
- Enable export by pyAssimp
- CI: check windows build
- Add functionality to perform a singlepost-processing step
@@ -564,7 +564,7 @@ API CHANGES:
currently used, however ...)
- Some Assimp::Importer methods are const now.
1.1 (2010-04-17)
This is the list of relevant changes from the 1.0 (r412) release to 1.1 (r700).
+2 -5
View File
@@ -347,11 +347,8 @@ ELSEIF(MSVC)
elseif((GENERATOR_IS_MULTI_CONFIG) OR (CMAKE_BUILD_TYPE MATCHES Release))
message("-- MSVC PDB generation disabled. Release binary will not be debuggable.")
endif()
if(NOT /utf-8 IN_LIST CMAKE_CXX_FLAGS)
# Source code is encoded in UTF-8
ADD_COMPILE_OPTIONS(/source-charset:utf-8)
endif ()
# Source code is encoded in UTF-8
ADD_COMPILE_OPTIONS(/source-charset:utf-8)
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
+2 -2
View File
@@ -60,7 +60,7 @@ The GUY who performed some of the CSM mocaps.
Contributed fixes for the documentation and the doxygen markup
- Zhao Lei
Contributed several bugfixes fixing memory leaks and improving float parsing
Contributed several bugfixes fixing memory leaks and improving float parsing
- sueastside
Updated PyAssimp to the latest Assimp data structures and provided a script to keep the Python binding up-to-date.
@@ -129,7 +129,7 @@ Contributed a patch to fix the VertexTriangleAdjacency postprocessing step.
Contributed the Debian build fixes ( architecture macro ).
- gellule
Several LWO and LWS fixes (pivoting).
Several LWO and LWS fixes (pivoting).
- Marcel Metz
GCC/Linux fixes for the SimpleOpenGL sample.
+1 -1
View File
@@ -1,6 +1,6 @@
FROM gcc:latest
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
WORKDIR /app
RUN apt install zlib1g-dev
+4 -4
View File
@@ -1,17 +1,17 @@
========================================================================
Open Asset Import Library (assimp) INSTALL
Open Asset Import Library (assimp) INSTALL
========================================================================
------------------------------
Getting the documentation
------------------------------
A regularly-updated copy is available at
A regularly-updated copy is available at
https://assimp-docs.readthedocs.io/en/latest/
------------------------------
Building Assimp
Building Assimp
------------------------------
Just check the build-instructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md
+2 -2
View File
@@ -3,7 +3,7 @@ Open Asset Import Library (assimp)
Open Asset Import Library is a library that loads various 3D file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
### Current project status ###
### Current project status ###
![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=assimp_assimp&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=assimp_assimp)
@@ -32,7 +32,7 @@ Clone [our model database](https://github.com/assimp/assimp-mdb).
- Ask questions at [the Assimp Discussion Board](https://github.com/assimp/assimp/discussions).
- Find us on [https://discord.gg/s9KJfaem](https://discord.gg/kKazXMXDy2)
- Ask [the Assimp community on Reddit](https://www.reddit.com/r/Assimp/).
- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
- Nothing has worked? File a question or an issue report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
#### Supported file formats ####
+1 -1
View File
@@ -11,6 +11,6 @@ currently being supported with security updates.
## Reporting a Vulnerability
If you have found any security vulnerability you can contact us via
If you have found any security vulnerability you can contact us via
kim.kulling@googlemail.com
+3 -2
View File
@@ -6,7 +6,7 @@
# Creates source debian files and manages library dependencies
#
# Features:
#
#
# - Automatically generates symbols and run-time dependencies from the build dependencies
# - Custom copy of source directory via CPACK_DEBIAN_PACKAGE_SOURCE_COPY
# - Simultaneous output of multiple debian source packages for each distribution
@@ -114,6 +114,7 @@ foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES})
endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n"
"Standards-Version: 3.8.4\n"
"Homepage: ${CPACK_PACKAGE_VENDOR}\n"
@@ -172,7 +173,7 @@ foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES})
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS})
endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n"
"Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n"
"${DEB_LONG_DESCRIPTION}"
+5 -5
View File
@@ -26,7 +26,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
getenv_path(DIRECTX_BASE)
# construct search paths
set(DirectX_PREFIX_PATH
set(DirectX_PREFIX_PATH
"${DXSDK_DIR}" "${ENV_DXSDK_DIR}"
"${DIRECTX_HOME}" "${ENV_DIRECTX_HOME}"
"${DIRECTX_ROOT}" "${ENV_DIRECTX_ROOT}"
@@ -66,7 +66,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
find_library(DirectX_D3DCOMPILER_LIBRARY NAMES d3dcompiler HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
findpkg_finish(DirectX)
set(DirectX_LIBRARIES ${DirectX_LIBRARIES}
set(DirectX_LIBRARIES ${DirectX_LIBRARIES}
${DirectX_D3DX9_LIBRARY}
${DirectX_DXERR_LIBRARY}
${DirectX_DXGUID_LIBRARY}
@@ -82,7 +82,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
get_filename_component(DirectX_LIBRARY_DIR "${DirectX_LIBRARY}" PATH)
message(STATUS "DX lib dir: ${DirectX_LIBRARY_DIR}")
find_library(DirectX_D3D11_LIBRARY NAMES d3d11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
if (DirectX_D3D11_INCLUDE_DIR AND DirectX_D3D11_LIBRARY)
set(DirectX_D3D11_FOUND TRUE)
set(DirectX_D3D11_INCLUDE_DIR ${DirectX_D3D11_INCLUDE_DIR})
@@ -92,8 +92,8 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
${DirectX_DXGI_LIBRARY}
${DirectX_DXERR_LIBRARY}
${DirectX_DXGUID_LIBRARY}
${DirectX_D3DCOMPILER_LIBRARY}
)
${DirectX_D3DCOMPILER_LIBRARY}
)
endif ()
mark_as_advanced(DirectX_D3D11_INCLUDE_DIR DirectX_D3D11_LIBRARY DirectX_D3DX11_LIBRARY)
endif ()
+12 -40
View File
@@ -3,7 +3,7 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ASSIMP_ARCHITECTURE "32")
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
if(WIN32)
set(ASSIMP_ROOT_DIR CACHE PATH "ASSIMP root directory")
@@ -17,29 +17,29 @@ if(WIN32)
if(MSVC12)
set(ASSIMP_MSVC_VERSION "vc120")
elseif(MSVC14)
elseif(MSVC14)
set(ASSIMP_MSVC_VERSION "vc140")
endif(MSVC12)
if(MSVC12 OR MSVC14)
find_path(ASSIMP_LIBRARY_DIR
NAMES
assimp-${ASSIMP_MSVC_VERSION}-mt.lib
HINTS
${ASSIMP_ROOT_DIR}/lib${ASSIMP_ARCHITECTURE}
)
find_library(ASSIMP_LIBRARY_RELEASE assimp-${ASSIMP_MSVC_VERSION}-mt.lib PATHS ${ASSIMP_LIBRARY_DIR})
find_library(ASSIMP_LIBRARY_DEBUG assimp-${ASSIMP_MSVC_VERSION}-mtd.lib PATHS ${ASSIMP_LIBRARY_DIR})
set(ASSIMP_LIBRARY
set(ASSIMP_LIBRARY
optimized ${ASSIMP_LIBRARY_RELEASE}
debug ${ASSIMP_LIBRARY_DEBUG}
)
set(ASSIMP_LIBRARIES "ASSIMP_LIBRARY_RELEASE" "ASSIMP_LIBRARY_DEBUG")
FUNCTION(ASSIMP_COPY_BINARIES TargetDirectory)
ADD_CUSTOM_TARGET(AssimpCopyBinaries
COMMAND ${CMAKE_COMMAND} -E copy ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE}/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${TargetDirectory}/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll
@@ -47,37 +47,9 @@ if(WIN32)
COMMENT "Copying Assimp binaries to '${TargetDirectory}'"
VERBATIM)
ENDFUNCTION(ASSIMP_COPY_BINARIES)
if (NOT TARGET ASSIMP)
set(INCLUDE_DIRS ${ASSIMP_ROOT_DIR}/include)
find_library(ASSIMP_LIB_DEBUG
NAMES assimp-${ASSIMP_MSVC_VERSION}-mtd.lib
PATHS ${ASSIMP_LIBRARY_DIR})
find_file(ASSIMP_DLL_DEBUG
NAMES assimp-${ASSIMP_MSVC_VERSION}-mtd.dll
PATHS ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE})
find_library(ASSIMP_LIB_RELEASE
NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.lib
PATHS ${ASSIMP_LIBRARY_DIR})
find_file(ASSIMP_DLL_RELEASE
NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.dll
PATHS ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE})
add_library(ASSIMP SHARED IMPORTED)
set_target_properties(ASSIMP PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${INCLUDE_DIRS}"
IMPORTED_IMPLIB_DEBUG ${ASSIMP_LIB_DEBUG}
IMPORTED_IMPLIB_RELEASE ${ASSIMP_LIB_RELEASE}
IMPORTED_LOCATION_DEBUG ${ASSIMP_DLL_DEBUG}
IMPORTED_LOCATION_RELEASE ${ASSIMP_DLL_RELEASE}
)
endif()
endif()
else(WIN32)
find_path(
@@ -109,5 +81,5 @@ else(WIN32)
message(FATAL_ERROR "Could not find asset importer library")
endif (assimp_FIND_REQUIRED)
endif (assimp_FOUND)
endif(WIN32)
+1 -1
View File
@@ -31,7 +31,7 @@ option(HUNTER_STATUS_PRINT "Print working status" ON)
option(HUNTER_STATUS_DEBUG "Print a lot info" OFF)
option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON)
set(HUNTER_ERROR_PAGE "https://hunter.readthedocs.io/en/latest/reference/errors")
set(HUNTER_ERROR_PAGE "https://docs.hunter.sh/en/latest/reference/errors")
function(hunter_gate_status_print)
if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG)
+3 -3
View File
@@ -9,14 +9,14 @@ MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar
OBJECT_OUTPUTS "${PrecompiledBinary}")
# Do not consider .c files
foreach(fname ${Sources})
foreach(fname ${Sources})
GET_FILENAME_COMPONENT(fext ${fname} EXT)
if(fext STREQUAL ".cpp")
SET_SOURCE_FILES_PROPERTIES(${fname}
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledBinary}\" /FI\"${PrecompiledBinary}\" /Fp\"${PrecompiledBinary}\""
OBJECT_DEPENDS "${PrecompiledBinary}")
OBJECT_DEPENDS "${PrecompiledBinary}")
endif(fext STREQUAL ".cpp")
endforeach(fname)
endforeach(fname)
ENDIF(MSVC)
# Add precompiled header to SourcesVar
+40 -33
View File
@@ -91,12 +91,15 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
// now iterate through all meshes and through all faces and
// find all faces that are using the default material
unsigned int cnt = 0;
for (auto i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) {
for (auto a = (*i).mFaceMaterials.begin(); a != (*i).mFaceMaterials.end(); ++a) {
for (std::vector<D3DS::Mesh>::iterator
i = mScene->mMeshes.begin();
i != mScene->mMeshes.end(); ++i) {
for (std::vector<unsigned int>::iterator
a = (*i).mFaceMaterials.begin();
a != (*i).mFaceMaterials.end(); ++a) {
// NOTE: The additional check seems to be necessary,
// some exporters seem to generate invalid data here
if (NotSet == (*a)) {
if (0xcdcdcdcd == (*a)) {
(*a) = idx;
++cnt;
} else if ((*a) >= mScene->mMaterials.size()) {
@@ -108,7 +111,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
}
if (cnt && idx == mScene->mMaterials.size()) {
// We need to create our own default material
Material sMat("%%%DEFAULT");
D3DS::Material sMat("%%%DEFAULT");
sMat.mDiffuse = aiColor3D(0.3f, 0.3f, 0.3f);
mScene->mMaterials.push_back(sMat);
@@ -118,17 +121,17 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
// ------------------------------------------------------------------------------------------------
// Check whether all indices are valid. Otherwise we'd crash before the validation step is reached
void Discreet3DSImporter::CheckIndices(Mesh &sMesh) {
for (auto i = sMesh.mFaces.begin(); i != sMesh.mFaces.end(); ++i) {
void Discreet3DSImporter::CheckIndices(D3DS::Mesh &sMesh) {
for (std::vector<D3DS::Face>::iterator i = sMesh.mFaces.begin(); i != sMesh.mFaces.end(); ++i) {
// check whether all indices are in range
for (unsigned int a = 0; a < 3; ++a) {
if ((*i).mIndices[a] >= sMesh.mPositions.size()) {
ASSIMP_LOG_WARN("3DS: Vertex index overflow)");
(*i).mIndices[a] = static_cast<uint32_t>(sMesh.mPositions.size() - 1);
(*i).mIndices[a] = (uint32_t)sMesh.mPositions.size() - 1;
}
if (!sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size()) {
ASSIMP_LOG_WARN("3DS: Texture coordinate index overflow)");
(*i).mIndices[a] = static_cast<uint32_t>(sMesh.mTexCoords.size() - 1);
(*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size() - 1;
}
}
}
@@ -136,7 +139,7 @@ void Discreet3DSImporter::CheckIndices(Mesh &sMesh) {
// ------------------------------------------------------------------------------------------------
// Generate out unique verbose format representation
void Discreet3DSImporter::MakeUnique(Mesh &sMesh) {
void Discreet3DSImporter::MakeUnique(D3DS::Mesh &sMesh) {
// TODO: really necessary? I don't think. Just a waste of memory and time
// to do it now in a separate buffer.
@@ -147,7 +150,7 @@ void Discreet3DSImporter::MakeUnique(Mesh &sMesh) {
vNew2.resize(sMesh.mFaces.size() * 3);
for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size(); ++i) {
Face &face = sMesh.mFaces[i];
D3DS::Face &face = sMesh.mFaces[i];
// Positions
for (unsigned int a = 0; a < 3; ++a, ++base) {
@@ -164,9 +167,10 @@ void Discreet3DSImporter::MakeUnique(Mesh &sMesh) {
// ------------------------------------------------------------------------------------------------
// Convert a 3DS texture to texture keys in an aiMaterial
void CopyTexture(aiMaterial &mat, Texture &texture, aiTextureType type) {
void CopyTexture(aiMaterial &mat, D3DS::Texture &texture, aiTextureType type) {
// Setup the texture name
aiString tex(texture.mMapName);
aiString tex;
tex.Set(texture.mMapName);
mat.AddProperty(&tex, AI_MATKEY_TEXTURE(type, 0));
// Setup the texture blend factor
@@ -193,11 +197,13 @@ void CopyTexture(aiMaterial &mat, Texture &texture, aiTextureType type) {
// ------------------------------------------------------------------------------------------------
// Convert a 3DS material to an aiMaterial
void Discreet3DSImporter::ConvertMaterial(Material &oldMat, aiMaterial &mat) {
void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
aiMaterial &mat) {
// NOTE: Pass the background image to the viewer by bypassing the
// material system. This is an evil hack, never do it again!
if (mBackgroundImage.empty() && bHasBG) {
aiString tex(mBackgroundImage);
if (0 != mBackgroundImage.length() && bHasBG) {
aiString tex;
tex.Set(mBackgroundImage);
mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
// Be sure this is only done for the first material
@@ -209,7 +215,8 @@ void Discreet3DSImporter::ConvertMaterial(Material &oldMat, aiMaterial &mat) {
oldMat.mAmbient.g += mClrAmbient.g;
oldMat.mAmbient.b += mClrAmbient.b;
aiString name(oldMat.mName);
aiString name;
name.Set(oldMat.mName);
mat.AddProperty(&name, AI_MATKEY_NAME);
// Material colors
@@ -219,9 +226,10 @@ void Discreet3DSImporter::ConvertMaterial(Material &oldMat, aiMaterial &mat) {
mat.AddProperty(&oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
// Phong shininess and shininess strength
if (Discreet3DS::Phong == oldMat.mShading || Discreet3DS::Metal == oldMat.mShading) {
if (D3DS::Discreet3DS::Phong == oldMat.mShading ||
D3DS::Discreet3DS::Metal == oldMat.mShading) {
if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength) {
oldMat.mShading = Discreet3DS::Gouraud;
oldMat.mShading = D3DS::Discreet3DS::Gouraud;
} else {
mat.AddProperty(&oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
mat.AddProperty(&oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
@@ -243,41 +251,40 @@ void Discreet3DSImporter::ConvertMaterial(Material &oldMat, aiMaterial &mat) {
// Shading mode
aiShadingMode eShading = aiShadingMode_NoShading;
switch (oldMat.mShading) {
case Discreet3DS::Flat:
case D3DS::Discreet3DS::Flat:
eShading = aiShadingMode_Flat;
break;
// I don't know what "Wire" shading should be,
// assume it is simple lambertian diffuse shading
case Discreet3DS::Wire: {
case D3DS::Discreet3DS::Wire: {
// Set the wireframe flag
unsigned int iWire = 1;
mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
[[fallthrough]];
case Discreet3DS::Gouraud:
case D3DS::Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud;
break;
// assume cook-torrance shading for metals.
case Discreet3DS::Phong:
case D3DS::Discreet3DS::Phong:
eShading = aiShadingMode_Phong;
break;
case Discreet3DS::Metal:
case D3DS::Discreet3DS::Metal:
eShading = aiShadingMode_CookTorrance;
break;
// FIX to workaround a warning with GCC 4 who complained
// about a missing case Blinn: here - Blinn isn't a valid
// value in the 3DS Loader, it is just needed for ASE
case Discreet3DS::Blinn:
case D3DS::Discreet3DS::Blinn:
eShading = aiShadingMode_Blinn;
break;
}
const int eShading_ = eShading;
int eShading_ = static_cast<int>(eShading);
mat.AddProperty<int>(&eShading_, 1, AI_MATKEY_SHADING_MODEL);
// DIFFUSE texture
@@ -646,7 +653,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
pcOut->mChildren = new aiNode *[pcIn->mChildren.size()];
// Recursively process all children
for (unsigned int i = 0; i < size; ++i) {
pcOut->mChildren[i] = new aiNode();
pcOut->mChildren[i]->mParent = pcOut;
@@ -776,7 +783,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Convert all meshes in the scene and generate the final output scene.
void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
// Allocate enough storage for all output materials
pcOut->mNumMaterials = static_cast<unsigned int>(mScene->mMaterials.size());
pcOut->mNumMaterials = (unsigned int)mScene->mMaterials.size();
pcOut->mMaterials = new aiMaterial *[pcOut->mNumMaterials];
// ... and convert the 3DS materials to aiMaterial's
@@ -790,17 +797,17 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
ConvertMeshes(pcOut);
// Now copy all light sources to the output scene
pcOut->mNumLights = static_cast<unsigned int>(mScene->mLights.size());
pcOut->mNumLights = (unsigned int)mScene->mLights.size();
if (pcOut->mNumLights) {
pcOut->mLights = new aiLight *[pcOut->mNumLights];
memcpy(pcOut->mLights, &mScene->mLights[0], sizeof(void *) * pcOut->mNumLights);
::memcpy(pcOut->mLights, &mScene->mLights[0], sizeof(void *) * pcOut->mNumLights);
}
// Now copy all cameras to the output scene
pcOut->mNumCameras = static_cast<unsigned int>(mScene->mCameras.size());
pcOut->mNumCameras = (unsigned int)mScene->mCameras.size();
if (pcOut->mNumCameras) {
pcOut->mCameras = new aiCamera *[pcOut->mNumCameras];
memcpy(pcOut->mCameras, &mScene->mCameras[0], sizeof(void *) * pcOut->mNumCameras);
::memcpy(pcOut->mCameras, &mScene->mCameras[0], sizeof(void *) * pcOut->mNumCameras);
}
}
+1
View File
@@ -4,6 +4,7 @@ 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,
+1 -1
View File
@@ -106,7 +106,7 @@ Discreet3DSImporter::Discreet3DSImporter() :
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static constexpr uint16_t token[] = { 0x4d4d, 0x3dc2 /*, 0x3daa */ };
static const uint16_t token[] = { 0x4d4d, 0x3dc2 /*, 0x3daa */ };
return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token), 0, sizeof token[0]);
}
+3 -1
View File
@@ -1,3 +1,4 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
@@ -55,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiNode;
namespace Assimp {
namespace Assimp {
using namespace D3DS;
@@ -124,6 +125,7 @@ protected:
void ParseColorChunk(aiColor3D* p_pcOut,
bool p_bAcceptPercent = true);
// -------------------------------------------------------------------
/** Skip a chunk in the file
*/
+1 -1
View File
@@ -85,7 +85,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
return false;
}
static constexpr char ModelRef[] = "3D/3dmodel.model";
static const char *const ModelRef = "3D/3dmodel.model";
ZipArchiveIOSystem archive(pIOHandler, filename);
if (!archive.Exists(ModelRef)) {
return false;
+1 -1
View File
@@ -147,7 +147,7 @@ AC3DImporter::AC3DImporter() :
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static constexpr uint32_t tokens[] = { AI_MAKE_MAGIC("AC3D") };
static const uint32_t tokens[] = { AI_MAKE_MAGIC("AC3D") };
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
+1 -1
View File
@@ -86,7 +86,7 @@ public:
AMFNodeElementBase *Parent; ///< Parent element. If nullptr then this node is root.
std::list<AMFNodeElementBase *> Child; ///< Child elements.
public:
public:
/// Destructor, virtual..
virtual ~AMFNodeElementBase() = default;
-4
View File
@@ -731,10 +731,6 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh &mesh) {
unsigned int iCurrent = 0, fi = 0;
for (std::vector<ASE::Face>::iterator i = mesh.mFaces.begin(); i != mesh.mFaces.end(); ++i, ++fi) {
for (unsigned int n = 0; n < 3; ++n, ++iCurrent) {
const uint32_t curIndex = (*i).mIndices[n];
if (curIndex >= mesh.mPositions.size()) {
throw DeadlyImportError("ASE: Invalid vertex index in face ", fi, ".");
}
mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]];
// add texture coordinates
+2 -5
View File
@@ -1406,13 +1406,10 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes
if (TokenMatch(mFilePtr, "MESH_BONE_VERTEX", 16)) {
// read the vertex index
unsigned int iIndex = strtoul10(mFilePtr, &mFilePtr);
if (mesh.mBoneVertices.empty()) {
SkipSection();
}
if (iIndex >= mesh.mBoneVertices.size() ) {
if (iIndex >= mesh.mPositions.size()) {
iIndex = (unsigned int)mesh.mPositions.size() - 1;
LogWarning("Bone vertex index is out of bounds. Using the largest valid "
"bone vertex index instead");
iIndex = (unsigned int)mesh.mBoneVertices.size() - 1;
}
// --- ignored
+2 -2
View File
@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
// internal headers
#include "AssbinLoader.h"
#include "AssetLib/Assbin/AssbinLoader.h"
#include "Common/assbin_chunks.h"
#include <assimp/MemoryIOWrapper.h>
#include <assimp/anim.h>
@@ -94,7 +94,7 @@ bool AssbinImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, boo
const size_t read = in->Read(s, sizeof(char), 32);
pIOHandler->Close(in);
if (read < 19) {
return false;
}
+2 -1
View File
@@ -1,3 +1,4 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
@@ -60,7 +61,7 @@ struct aiCamera;
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
namespace Assimp {
namespace Assimp {
// ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files
+2 -1
View File
@@ -4,6 +4,7 @@ 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,
@@ -49,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
namespace Assimp {
namespace Assimp {
void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{
+1
View File
@@ -4,6 +4,7 @@ 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,
+1 -1
View File
@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
// internal headers
#include "B3DImporter.h"
#include "AssetLib/B3D/B3DImporter.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include "PostProcessing/TextureTransform.h"
+1
View File
@@ -6,6 +6,7 @@ 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,
+1
View File
@@ -4,6 +4,7 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2025, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
+2 -2
View File
@@ -116,7 +116,7 @@ namespace Blender {
mywrap arr;
};
#if defined(_MSC_VER) && _MSC_VER < 1900
#ifdef _MSC_VER
# pragma warning(disable:4351)
#endif
@@ -171,7 +171,7 @@ namespace Blender {
// original file data
const FileDatabase& db;
};
#if defined(_MSC_VER) && _MSC_VER < 1900
#ifdef _MSC_VER
# pragma warning(default:4351)
#endif
+1 -1
View File
@@ -108,7 +108,7 @@ BlenderImporter::~BlenderImporter() {
delete modifier_cache;
}
static constexpr char Token[] = "BLENDER";
static const char Token[] = "BLENDER";
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
@@ -4,6 +4,7 @@ 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,
+1
View File
@@ -4,6 +4,7 @@ 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,
+1
View File
@@ -4,6 +4,7 @@ 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,
+1 -1
View File
@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h"
#include "BlenderScene.h"
namespace Assimp {
namespace Assimp {
namespace Blender {
template <> void Structure :: Convert<Object> (
+1 -1
View File
@@ -64,7 +64,7 @@ namespace {
aiString aiStringFrom(cineware::String const & cinestring) {
aiString result;
cinestring.GetCString(result.data, AI_MAXLEN - 1);
cinestring.GetCString(result.data, MAXLEN-1);
result.length = static_cast<ai_uint32>(cinestring.GetLength());
return result;
}
+1 -1
View File
@@ -63,7 +63,7 @@ namespace cineware {
class BaseShader;
}
namespace Assimp {
namespace Assimp {
// TinyFormatter.h
namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter;
+2 -2
View File
@@ -45,8 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
#include "COBLoader.h"
#include "COBScene.h"
#include "AssetLib/COB/COBLoader.h"
#include "AssetLib/COB/COBScene.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include <assimp/LineSplitter.h>
+1
View File
@@ -4,6 +4,7 @@ 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,
+4 -6
View File
@@ -118,11 +118,10 @@ void CSMImporter::InternReadFile( const std::string& pFile,
// now process the file and look out for '$' sections
while (true) {
SkipSpaces(&buffer, end);
if ('\0' == *buffer) {
if ('\0' == *buffer)
break;
}
if ('$' == *buffer) {
if ('$' == *buffer) {
++buffer;
if (TokenMatchI(buffer,"firstframe",10)) {
SkipSpaces(&buffer, end);
@@ -150,9 +149,8 @@ void CSMImporter::InternReadFile( const std::string& pFile,
anims_temp.push_back(new aiNodeAnim());
aiNodeAnim* nda = anims_temp.back();
char *ot = nda->mNodeName.data;
const char *ot_end = nda->mNodeName.data + AI_MAXLEN;
while (!IsSpaceOrNewLine(*buffer) && buffer != end && ot != ot_end) {
char* ot = nda->mNodeName.data;
while (!IsSpaceOrNewLine(*buffer)) {
*ot++ = *buffer++;
}
+33 -33
View File
@@ -1116,9 +1116,9 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
}
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (mesh->HasTextureCoords(static_cast<unsigned int>(a))) {
mOutput << startstr
<< "<input semantic=\"TEXCOORD\" source=\"#"
<< geometryId
mOutput << startstr
<< "<input semantic=\"TEXCOORD\" source=\"#"
<< geometryId
<< "-tex" << a << "\" "
<< "set=\"" << a << "\""
<< " />" << endstr;
@@ -1199,26 +1199,26 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
void ColladaExporter::WriteFloatArray(const std::string &pIdString, FloatDataType pType, const ai_real *pData, size_t pElementCount) {
size_t floatsPerElement = 0;
switch (pType) {
case FloatType_Vector:
floatsPerElement = 3;
case FloatType_Vector:
floatsPerElement = 3;
break;
case FloatType_TexCoord2:
floatsPerElement = 2;
case FloatType_TexCoord2:
floatsPerElement = 2;
break;
case FloatType_TexCoord3:
floatsPerElement = 3;
case FloatType_TexCoord3:
floatsPerElement = 3;
break;
case FloatType_Color:
floatsPerElement = 3;
case FloatType_Color:
floatsPerElement = 3;
break;
case FloatType_Mat4x4:
floatsPerElement = 16;
case FloatType_Mat4x4:
floatsPerElement = 16;
break;
case FloatType_Weight:
floatsPerElement = 1;
case FloatType_Weight:
floatsPerElement = 1;
break;
case FloatType_Time:
floatsPerElement = 1;
case FloatType_Time:
floatsPerElement = 1;
break;
default:
return;
@@ -1342,7 +1342,7 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
if (anim == nullptr) {
return;
}
if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0) {
return;
}
@@ -1486,12 +1486,12 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
{
// channels
mOutput << startstr
<< "<channel source=\"#"
<< XMLIDEncode(nodeAnim->mNodeName.data + std::string("_matrix-sampler"))
<< "\" target=\""
<< XMLIDEncode(nodeAnim->mNodeName.data)
<< "/matrix\"/>"
mOutput << startstr
<< "<channel source=\"#"
<< XMLIDEncode(nodeAnim->mNodeName.data + std::string("_matrix-sampler"))
<< "\" target=\""
<< XMLIDEncode(nodeAnim->mNodeName.data)
<< "/matrix\"/>"
<< endstr;
}
}
@@ -1505,7 +1505,7 @@ void ColladaExporter::WriteAnimationsLibrary() {
if (mScene->mNumAnimations == 0) {
return;
}
mOutput << startstr << "<library_animations>" << endstr;
PushTag();
@@ -1688,7 +1688,7 @@ std::string ColladaExporter::GetNodeUniqueId(const aiNode *node) {
idStr = MakeUniqueId(mUniqueIds, idStr, std::string());
mUniqueIds.insert(idStr);
mNodeIdMap.insert(std::make_pair(node, idStr));
return idStr;
}
@@ -1744,14 +1744,14 @@ ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType t
// Get the name and id postfix
switch (type) {
case AiObjectType::Mesh:
name = mScene->mMeshes[index]->mName.C_Str();
case AiObjectType::Mesh:
name = mScene->mMeshes[index]->mName.C_Str();
break;
case AiObjectType::Material:
name = mScene->mMaterials[index]->GetName().C_Str();
case AiObjectType::Material:
name = mScene->mMaterials[index]->GetName().C_Str();
break;
case AiObjectType::Animation:
name = mScene->mAnimations[index]->mName.C_Str();
case AiObjectType::Animation:
name = mScene->mAnimations[index]->mName.C_Str();
break;
case AiObjectType::Light:
name = mScene->mLights[index]->mName.C_Str();
@@ -1761,7 +1761,7 @@ ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType t
name = mScene->mCameras[index]->mName.C_Str();
idPostfix = "-camera";
break;
case AiObjectType::Count:
case AiObjectType::Count:
throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type");
}
+49 -49
View File
@@ -89,14 +89,6 @@ inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value
node->mMetaData->Add(key, value);
}
// ------------------------------------------------------------------------------------------------
// Reads a float value from an accessor and its data array.
static ai_real ReadFloat(const Accessor &pAccessor, const Data &pData, size_t pIndex, size_t pOffset) {
size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size());
return pData.mValues[pos];
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ColladaLoader::ColladaLoader() :
@@ -160,7 +152,7 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
throw DeadlyImportError("Collada: File came out empty. Something is wrong here.");
}
// reserve some storage to avoid unnecessary reallocates
// reserve some storage to avoid unnecessary reallocs
newMats.reserve(parser.mMaterialLibrary.size() * 2u);
mMeshes.reserve(parser.mMeshLibrary.size() * 2u);
@@ -184,7 +176,7 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
0, 0, parser.mUnitSize, 0,
0, 0, 0, 1);
}
if (!ignoreUpDirection) {
// Convert to Y_UP, if different orientation
if (parser.mUpDirection == ColladaParser::UP_X) {
@@ -232,7 +224,7 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
// Recursively constructs a scene node for the given parser node and returns it.
aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collada::Node *pNode) {
// create a node for it
auto *node = new aiNode();
aiNode *node = new aiNode();
// find a name for the new node. It's more complicated than you might think
node->mName.Set(FindNameForNode(pNode));
@@ -280,24 +272,24 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
// ------------------------------------------------------------------------------------------------
// Resolve node instances
void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Node *pNode,
std::vector<const Node*> &resolved) const {
std::vector<const Node*> &resolved) {
// reserve enough storage
resolved.reserve(pNode->mNodeInstances.size());
// ... and iterate through all nodes to be instanced as children of pNode
for (const auto &[mNode] : pNode->mNodeInstances) {
for (const auto &nodeInst : pNode->mNodeInstances) {
// find the corresponding node in the library
const auto itt = pParser.mNodeLibrary.find(mNode);
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
const Node *nd = itt == pParser.mNodeLibrary.end() ? nullptr : (*itt).second;
// FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
// need to check for both name and ID to catch all. To avoid breaking valid files,
// the workaround is only enabled when the first attempt to resolve the node has failed.
if (nullptr == nd) {
nd = FindNode(pParser.mRootNode, mNode);
nd = FindNode(pParser.mRootNode, nodeInst.mNode);
}
if (nullptr == nd) {
ASSIMP_LOG_ERROR("Collada: Unable to resolve reference to instanced node ", mNode);
ASSIMP_LOG_ERROR("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
} else {
// attach this node to the list of children
resolved.push_back(nd);
@@ -307,8 +299,8 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Nod
// ------------------------------------------------------------------------------------------------
// Resolve UV channels
static void ApplyVertexToEffectSemanticMapping(Sampler &sampler, const SemanticMappingTable &table) {
const auto it = table.mMap.find(sampler.mUVChannel);
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Sampler &sampler, const SemanticMappingTable &table) {
SemanticMappingTable::InputSemanticMap::const_iterator it = table.mMap.find(sampler.mUVChannel);
if (it == table.mMap.end()) {
return;
}
@@ -325,7 +317,7 @@ static void ApplyVertexToEffectSemanticMapping(Sampler &sampler, const SemanticM
void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node *pNode, aiNode *pTarget) {
for (const LightInstance &lid : pNode->mLights) {
// find the referred light
auto srcLightIt = pParser.mLightLibrary.find(lid.mLight);
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find(lid.mLight);
if (srcLightIt == pParser.mLightLibrary.end()) {
ASSIMP_LOG_WARN("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping.");
continue;
@@ -333,7 +325,7 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
const Collada::Light *srcLight = &srcLightIt->second;
// now fill our ai data structure
auto out = new aiLight();
aiLight *out = new aiLight();
out->mName = pTarget->mName;
out->mType = (aiLightSourceType)srcLight->mType;
@@ -390,7 +382,7 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Node *pNode, aiNode *pTarget) {
for (const CameraInstance &cid : pNode->mCameras) {
// find the referred light
auto srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera);
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera);
if (srcCameraIt == pParser.mCameraLibrary.end()) {
ASSIMP_LOG_WARN("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping.");
continue;
@@ -403,7 +395,7 @@ void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Node
}
// now fill our ai data structure
auto *out = new aiCamera();
aiCamera *out = new aiCamera();
out->mName = pTarget->mName;
// collada cameras point in -Z by default, rest is specified in node transform
@@ -453,10 +445,10 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
const Controller *srcController = nullptr;
// find the referred mesh
auto srcMeshIt = pParser.mMeshLibrary.find(mid.mMeshOrController);
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find(mid.mMeshOrController);
if (srcMeshIt == pParser.mMeshLibrary.end()) {
// if not found in the mesh-library, it might also be a controller referring to a mesh
auto srcContrIt = pParser.mControllerLibrary.find(mid.mMeshOrController);
ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find(mid.mMeshOrController);
if (srcContrIt != pParser.mControllerLibrary.end()) {
srcController = &srcContrIt->second;
srcMeshIt = pParser.mMeshLibrary.find(srcController->mMeshId);
@@ -470,7 +462,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
continue;
}
} else {
// ID found in the mesh library -> direct reference to a not skinned mesh
// ID found in the mesh library -> direct reference to an unskinned mesh
srcMesh = srcMeshIt->second;
}
@@ -484,7 +476,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
// find material assigned to this submesh
std::string meshMaterial;
auto meshMatIt = mid.mMaterials.find(submesh.mMaterial);
std::map<std::string, SemanticMappingTable>::const_iterator meshMatIt = mid.mMaterials.find(submesh.mMaterial);
const Collada::SemanticMappingTable *table = nullptr;
if (meshMatIt != mid.mMaterials.end()) {
@@ -500,7 +492,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
// OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table
// given. The only mapping stuff which we do actually support is the UV channel.
auto matIt = mMaterialIndexByName.find(meshMaterial);
std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find(meshMaterial);
unsigned int matIdx = 0;
if (matIt != mMaterialIndexByName.end()) {
matIdx = static_cast<unsigned int>(matIt->second);
@@ -523,7 +515,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
ColladaMeshIndex index(mid.mMeshOrController, sm, meshMaterial);
// if we already have the mesh at the library, just add its index to the node's array
auto dstMeshIt = mMeshIndexByID.find(index);
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find(index);
if (dstMeshIt != mMeshIndexByID.end()) {
newMeshRefs.push_back(dstMeshIt->second);
} else {
@@ -538,7 +530,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
faceStart += submesh.mNumFaces;
// assign the material index
auto subMatIt = mMaterialIndexByName.find(submesh.mMaterial);
std::map<std::string, size_t>::const_iterator subMatIt = mMaterialIndexByName.find(submesh.mMaterial);
if (subMatIt != mMaterialIndexByName.end()) {
dstMesh->mMaterialIndex = static_cast<unsigned int>(subMatIt->second);
} else {
@@ -626,7 +618,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
std::copy(pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() + pStartVertex + numVertices, dstMesh->mTangents);
}
// bi-tangents, if given.
// bitangents, if given.
if (pSrcMesh->mBitangents.size() >= pStartVertex + numVertices) {
dstMesh->mBitangents = new aiVector3D[numVertices];
std::copy(pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() + pStartVertex + numVertices, dstMesh->mBitangents);
@@ -672,7 +664,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
std::vector<float> targetWeights;
Collada::MorphMethod method = Normalized;
for (auto it = pParser.mControllerLibrary.begin();
for (std::map<std::string, Controller>::const_iterator it = pParser.mControllerLibrary.begin();
it != pParser.mControllerLibrary.end(); ++it) {
const Controller &c = it->second;
const Collada::Mesh *baseMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, c.mMeshId);
@@ -762,7 +754,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
std::vector<IndexPairVector::const_iterator> weightStartPerVertex;
weightStartPerVertex.resize(pSrcController->mWeightCounts.size(), pSrcController->mWeights.end());
auto pit = pSrcController->mWeights.begin();
IndexPairVector::const_iterator pit = pSrcController->mWeights.begin();
for (size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a) {
weightStartPerVertex[a] = pit;
pit += pSrcController->mWeightCounts[a];
@@ -774,7 +766,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
// the controller assigns the vertex weights
size_t orgIndex = pSrcMesh->mFacePosIndices[a];
// find the vertex weights for this vertex
auto iit = weightStartPerVertex[orgIndex];
IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex];
size_t pairCount = pSrcController->mWeightCounts[orgIndex];
for (size_t b = 0; b < pairCount; ++b, ++iit) {
@@ -815,7 +807,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
}
// create bone with its weights
auto bone = new aiBone;
aiBone *bone = new aiBone;
bone->mName = ReadString(jointNamesAcc, jointNames, a);
bone->mOffsetMatrix.a1 = ReadFloat(jointMatrixAcc, jointMatrices, a, 0);
bone->mOffsetMatrix.a2 = ReadFloat(jointMatrixAcc, jointMatrices, a, 1);
@@ -981,7 +973,7 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse
// if there are other animations which fit the template anim, combine all channels into a single anim
if (!collectedAnimIndices.empty()) {
auto *combinedAnim = new aiAnimation();
aiAnimation *combinedAnim = new aiAnimation();
combinedAnim->mName = aiString(std::string("combinedAnim_") + char('0' + a));
combinedAnim->mDuration = templateAnim->mDuration;
combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond;
@@ -1048,7 +1040,7 @@ struct MorphTimeValues {
};
void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, float weight, unsigned int value) {
MorphTimeValues::key k{};
MorphTimeValues::key k;
k.mValue = value;
k.mWeight = weight;
if (values.empty() || time < values[0].mTime) {
@@ -1085,7 +1077,7 @@ static float getWeightAtKey(const std::vector<MorphTimeValues> &values, int key,
return mKey.mWeight;
}
}
// no value at key found, try to interpolate if present at other keys. if not, return zero
// TODO: interpolation
return 0.0f;
@@ -1114,7 +1106,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// now check all channels if they affect the current node
std::string targetID, subElement;
for (auto cit = pSrcAnim->mChannels.begin();
for (std::vector<AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
cit != pSrcAnim->mChannels.end(); ++cit) {
const AnimationChannel &srcChannel = *cit;
ChannelEntry entry;
@@ -1357,7 +1349,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// build an animation channel for the given node out of these trafo keys
if (!resultTrafos.empty()) {
auto *dstAnim = new aiNodeAnim;
aiNodeAnim *dstAnim = new aiNodeAnim;
dstAnim->mNodeName = nodeName;
dstAnim->mNumPositionKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mNumRotationKeys = static_cast<unsigned int>(resultTrafos.size());
@@ -1399,7 +1391,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// or 2) one channel with morph target count arrays
// assume first
auto *morphAnim = new aiMeshMorphAnim;
aiMeshMorphAnim *morphAnim = new aiMeshMorphAnim;
morphAnim->mName.Set(nodeName);
std::vector<MorphTimeValues> morphTimeValues;
@@ -1442,7 +1434,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
}
if (!anims.empty() || !morphAnims.empty()) {
auto anim = new aiAnimation;
aiAnimation *anim = new aiAnimation;
anim->mName.Set(pName);
anim->mNumChannels = static_cast<unsigned int>(anims.size());
if (anim->mNumChannels > 0) {
@@ -1522,7 +1514,7 @@ void ColladaLoader::AddTexture(aiMaterial &mat,
map = sampler.mUVId;
} else {
map = -1;
for (auto it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
for (std::string::const_iterator it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
if (IsNumeric(*it)) {
map = strtoul10(&(*it));
break;
@@ -1540,7 +1532,7 @@ void ColladaLoader::AddTexture(aiMaterial &mat,
// Fills materials from the collada material definitions
void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pScene*/) {
for (auto &elem : newMats) {
auto &mat = (aiMaterial &)*elem.second;
aiMaterial &mat = (aiMaterial &)*elem.second;
Collada::Effect &effect = *elem.first;
// resolve shading mode
@@ -1650,17 +1642,17 @@ void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pSce
void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/) {
newMats.reserve(pParser.mMaterialLibrary.size());
for (auto matIt = pParser.mMaterialLibrary.begin();
for (ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin();
matIt != pParser.mMaterialLibrary.end(); ++matIt) {
const Material &material = matIt->second;
// a material is only a reference to an effect
auto effIt = pParser.mEffectLibrary.find(material.mEffect);
ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find(material.mEffect);
if (effIt == pParser.mEffectLibrary.end())
continue;
Effect &effect = effIt->second;
// create material
auto *mat = new aiMaterial;
aiMaterial *mat = new aiMaterial;
aiString name(material.mName.empty() ? matIt->first : material.mName);
mat->AddProperty(&name, AI_MATKEY_NAME);
@@ -1683,7 +1675,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
std::string name = pName;
while (true) {
// the given string is a param entry. Find it
auto it = pEffect.mParams.find(name);
Effect::ParamLibrary::const_iterator it = pEffect.mParams.find(name);
// if not found, we're at the end of the recursion. The resulting string should be the image ID
if (it == pEffect.mParams.end())
break;
@@ -1693,7 +1685,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
}
// find the image referred by this name in the image library of the scene
auto imIt = pParser.mImageLibrary.find(name);
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find(name);
if (imIt == pParser.mImageLibrary.end()) {
ASSIMP_LOG_WARN("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\".");
@@ -1705,7 +1697,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
// if this is an embedded texture image setup an aiTexture for it
if (!imIt->second.mImageData.empty()) {
auto *tex = new aiTexture();
aiTexture *tex = new aiTexture();
// Store embedded texture name reference
tex->mFilename.Set(imIt->second.mFileName.c_str());
@@ -1737,6 +1729,14 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
return result;
}
// ------------------------------------------------------------------------------------------------
// Reads a float value from an accessor and its data array.
ai_real ColladaLoader::ReadFloat(const Accessor &pAccessor, const Data &pData, size_t pIndex, size_t pOffset) const {
size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size());
return pData.mValues[pos];
}
// ------------------------------------------------------------------------------------------------
// Reads a string value from an accessor and its data array.
const std::string &ColladaLoader::ReadString(const Accessor &pAccessor, const Data &pData, size_t pIndex) const {
+20 -7
View File
@@ -76,10 +76,10 @@ struct ColladaMeshIndex {
}
};
/**
* @brief Loader class to read Collada scenes.
/**
* @brief Loader class to read Collada scenes.
*
* Collada is over-engineered to death, with every new iteration bringing more useless stuff,
* Collada is over-engineered to death, with every new iteration bringing more useless stuff,
* so I limited the data to what I think is useful for games.
*/
class ColladaLoader : public BaseImporter {
@@ -109,9 +109,9 @@ protected:
/// Resolve node instances
void ResolveNodeInstances(const ColladaParser &pParser, const Collada::Node *pNode,
std::vector<const Collada::Node *> &resolved) const;
std::vector<const Collada::Node *> &resolved);
/// Builds meshes for the given node and references them
/// Builds meshes for the given node and references them
void BuildMeshesForNode(const ColladaParser &pParser, const Collada::Node *pNode,
aiNode *pTarget);
@@ -166,6 +166,10 @@ protected:
/** Fill materials from the collada material definitions */
void FillMaterials(const ColladaParser &pParser, aiScene *pScene);
/** Resolve UV channel mappings*/
void ApplyVertexToEffectSemanticMapping(Collada::Sampler &sampler,
const Collada::SemanticMappingTable &table);
/** Add a texture and all of its sampling properties to a material*/
void AddTexture(aiMaterial &mat, const ColladaParser &pParser,
const Collada::Effect &effect,
@@ -176,13 +180,22 @@ protected:
aiString FindFilenameForEffectTexture(const ColladaParser &pParser,
const Collada::Effect &pEffect, const std::string &pName);
/** Reads a float value from an accessor and its data array.
* @param pAccessor The accessor to use for reading
* @param pData The data array to read from
* @param pIndex The index of the element to retrieve
* @param pOffset Offset into the element, for multipart elements such as vectors or matrices
* @return the specified value
*/
ai_real ReadFloat(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex, size_t pOffset) const;
/** Reads a string value from an accessor and its data array.
* @param pAccessor The accessor to use for reading
* @param pData The data array to read from
* @param pIndex The index of the element to retrieve
* @return the specified value
*/
[[nodiscard]] const std::string &ReadString(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex) const;
const std::string &ReadString(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex) const;
/** Recursively collects all nodes into the given array */
void CollectNodes(const aiNode *pNode, std::vector<const aiNode *> &poNodes) const;
@@ -195,7 +208,7 @@ protected:
/** Finds a proper name for a node derived from the collada-node's properties */
std::string FindNameForNode(const Collada::Node *pNode);
private:
protected:
/** Filename, for a verbose error message */
std::string mFileName;
+360 -357
View File
@@ -61,7 +61,6 @@ using namespace Assimp;
using namespace Assimp::Collada;
using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------
static void ReportWarning(const char *msg, ...) {
ai_assert(nullptr != msg);
@@ -76,7 +75,6 @@ static void ReportWarning(const char *msg, ...) {
ASSIMP_LOG_WARN("Validation warning: ", std::string(szBuffer, iLen));
}
// ------------------------------------------------------------------------------------------------
static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) {
for (size_t i = 0; i < key_renaming.size(); ++i) {
if (key_renaming[i].first == collada_key) {
@@ -89,7 +87,6 @@ static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVecto
return false;
}
// ------------------------------------------------------------------------------------------------
static void readUrlAttribute(XmlNode &node, std::string &url) {
url.clear();
if (!XmlParser::getStdStrAttribute(node, "url", url)) {
@@ -101,319 +98,23 @@ static void readUrlAttribute(XmlNode &node, std::string &url) {
url = url.c_str() + 1;
}
// ------------------------------------------------------------------------------------------------
// Reads a node transformation entry of the given type and adds it to the given node's transformation list.
static void ReadNodeTransformation(XmlNode &node, Node *pNode, TransformType pType) {
if (node.empty()) {
return;
}
std::string tagName = node.name();
Transform tf;
tf.mType = pType;
// read SID
if (XmlParser::hasAttribute(node, "sid")) {
XmlParser::getStdStrAttribute(node, "sid", tf.mID);
}
// how many parameters to read per transformation type
static constexpr unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 };
std::string value;
XmlParser::getValueAsString(node, value);
const char *content = value.c_str();
const char *end = value.c_str() + value.size();
// read as many parameters and store in the transformation
for (unsigned int a = 0; a < sNumParameters[pType]; a++) {
// skip whitespace before the number
SkipSpacesAndLineEnd(&content, end);
// read a number
content = fast_atoreal_move<ai_real>(content, tf.f[a]);
}
// place the transformation at the queue of the node
pNode->mTransforms.push_back(tf);
}
// ------------------------------------------------------------------------------------------------
// Reads a single string metadata item
static void ReadMetaDataItem(XmlNode &node, ColladaParser::StringMetaData &metadata) {
const MetaKeyPairVector &key_renaming = GetColladaAssimpMetaKeysCamelCase();
const std::string name = node.name();
if (name.empty()) {
return;
}
std::string v;
if (!XmlParser::getValueAsString(node, v)) {
return;
}
v = ai_trim(v);
aiString aistr;
aistr.Set(v);
std::string camel_key_str(name);
ToCamelCase(camel_key_str);
size_t found_index;
if (FindCommonKey(camel_key_str, key_renaming, found_index)) {
metadata.emplace(key_renaming[found_index].second, aistr);
} else {
metadata.emplace(camel_key_str, aistr);
}
}
// ------------------------------------------------------------------------------------------------
// Reads an animation sampler into the given anim channel
static void ReadAnimationSampler(const XmlNode &node, AnimationChannel &pChannel) {
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "input") {
if (XmlParser::hasAttribute(currentNode, "semantic")) {
std::string semantic, sourceAttr;
XmlParser::getStdStrAttribute(currentNode, "semantic", semantic);
if (XmlParser::hasAttribute(currentNode, "source")) {
XmlParser::getStdStrAttribute(currentNode, "source", sourceAttr);
const char *source = sourceAttr.c_str();
if (source[0] != '#') {
throw DeadlyImportError("Unsupported URL format");
}
source++;
if (semantic == "INPUT") {
pChannel.mSourceTimes = source;
} else if (semantic == "OUTPUT") {
pChannel.mSourceValues = source;
} else if (semantic == "IN_TANGENT") {
pChannel.mInTanValues = source;
} else if (semantic == "OUT_TANGENT") {
pChannel.mOutTanValues = source;
} else if (semantic == "INTERPOLATION") {
pChannel.mInterpolationValues = source;
}
}
}
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads the joint definitions for the given controller
static void ReadControllerJoints(const XmlNode &node, Controller &pController) {
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "input") {
const char *attrSemantic = currentNode.attribute("semantic").as_string();
const char *attrSource = currentNode.attribute("source").as_string();
if (attrSource[0] != '#') {
throw DeadlyImportError("Unsupported URL format in \"", attrSource, "\" in source attribute of <joints> data <input> element");
}
++attrSource;
// parse source URL to corresponding source
if (strcmp(attrSemantic, "JOINT") == 0) {
pController.mJointNameSource = attrSource;
} else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) {
pController.mJointOffsetMatrixSource = attrSource;
} else {
throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <joints> data <input> element");
}
}
}
}
// ------------------------------------------------------------------------------------------------
static void ReadControllerWeightsInput(const XmlNode &currentNode, Controller &pController) {
InputChannel channel;
const char *attrSemantic = currentNode.attribute("semantic").as_string();
const char *attrSource = currentNode.attribute("source").as_string();
channel.mOffset = currentNode.attribute("offset").as_int();
// local URLS always start with a '#'. We don't support global URLs
if (attrSource[0] != '#') {
throw DeadlyImportError("Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element");
}
channel.mAccessor = attrSource + 1;
// parse source URL to corresponding source
if (strcmp(attrSemantic, "JOINT") == 0) {
pController.mWeightInputJoints = channel;
} else if (strcmp(attrSemantic, "WEIGHT") == 0) {
pController.mWeightInputWeights = channel;
} else {
throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <vertex_weights> data <input> element");
}
}
// ------------------------------------------------------------------------------------------------
static void ReadControllerWeightsVCount(const XmlNode &currentNode, Controller &pController) {
const std::string stdText = currentNode.text().as_string();
const char *text = stdText.c_str();
const char *end = text + stdText.size();
size_t numWeights = 0;
for (auto it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) {
if (*text == 0) {
throw DeadlyImportError("Out of data while reading <vcount>");
}
*it = strtoul10(text, &text);
numWeights += *it;
SkipSpacesAndLineEnd(&text, end);
}
// reserve weight count
pController.mWeights.resize(numWeights);
}
// ------------------------------------------------------------------------------------------------
static void ReadControllerWeightsJoint2verts(XmlNode &currentNode, Controller &pController) {
// read JointIndex - WeightIndex pairs
std::string stdText;
XmlParser::getValueAsString(currentNode, stdText);
const char *text = stdText.c_str();
const char *end = text + stdText.size();
for (auto it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) {
if (text == nullptr) {
throw DeadlyImportError("Out of data while reading <vertex_weights>");
}
SkipSpacesAndLineEnd(&text, end);
it->first = strtoul10(text, &text);
SkipSpacesAndLineEnd(&text, end);
if (*text == 0) {
throw DeadlyImportError("Out of data while reading <vertex_weights>");
}
it->second = strtoul10(text, &text);
SkipSpacesAndLineEnd(&text, end);
}
}
// ------------------------------------------------------------------------------------------------
// Reads the joint weights for the given controller
static void ReadControllerWeights(XmlNode &node, Controller &pController) {
// Read vertex count from attributes and resize the array accordingly
int vertexCount = 0;
XmlParser::getIntAttribute(node, "count", vertexCount);
pController.mWeightCounts.resize(vertexCount);
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "input") {
ReadControllerWeightsInput(currentNode, pController);
} else if (currentName == "vcount" && vertexCount > 0) {
ReadControllerWeightsVCount(currentNode, pController);
} else if (currentName == "v" && vertexCount > 0) {
ReadControllerWeightsJoint2verts(currentNode, pController);
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a material entry into the given material
static void ReadMaterial(const XmlNode &node, Material &pMaterial) {
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "instance_effect") {
std::string url;
readUrlAttribute(currentNode, url);
pMaterial.mEffect = url;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a light entry into the given light
static void ReadLight(XmlNode &node, Light &pLight) {
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
// TODO: Check the current technique and skip over unsupported extra techniques
while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name();
if (currentName == "spot") {
pLight.mType = aiLightSource_SPOT;
} else if (currentName == "ambient") {
pLight.mType = aiLightSource_AMBIENT;
} else if (currentName == "directional") {
pLight.mType = aiLightSource_DIRECTIONAL;
} else if (currentName == "point") {
pLight.mType = aiLightSource_POINT;
} else if (currentName == "color") {
// text content contains 3 floats
std::string v;
XmlParser::getValueAsString(currentNode, v);
const char *content = v.c_str();
const char *end = content + v.size();
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.r);
SkipSpacesAndLineEnd(&content, end);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.g);
SkipSpacesAndLineEnd(&content, end);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b);
SkipSpacesAndLineEnd(&content, end);
} else if (currentName == "constant_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttConstant);
} else if (currentName == "linear_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttLinear);
} else if (currentName == "quadratic_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttQuadratic);
} else if (currentName == "falloff_angle") {
XmlParser::getValueAsReal(currentNode, pLight.mFalloffAngle);
} else if (currentName == "falloff_exponent") {
XmlParser::getValueAsReal(currentNode, pLight.mFalloffExponent);
}
// FCOLLADA extensions
// -------------------------------------------------------
else if (currentName == "outer_cone") {
XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle);
} else if (currentName == "penumbra_angle") { // this one is deprecated, now calculated using outer_cone
XmlParser::getValueAsReal(currentNode, pLight.mPenumbraAngle);
} else if (currentName == "intensity") {
XmlParser::getValueAsReal(currentNode, pLight.mIntensity);
} else if (currentName == "falloff") {
XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle);
} else if (currentName == "hotspot_beam") {
XmlParser::getValueAsReal(currentNode, pLight.mFalloffAngle);
}
// OpenCOLLADA extensions
// -------------------------------------------------------
else if (currentName == "decay_falloff") {
XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle);
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a camera entry into the given light
static void ReadCamera(XmlNode &node, Camera &camera) {
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name();
if (currentName == "orthographic") {
camera.mOrtho = true;
} else if (currentName == "xfov" || currentName == "xmag") {
XmlParser::getValueAsReal(currentNode, camera.mHorFov);
} else if (currentName == "yfov" || currentName == "ymag") {
XmlParser::getValueAsReal(currentNode, camera.mVerFov);
} else if (currentName == "aspect_ratio") {
XmlParser::getValueAsReal(currentNode, camera.mAspect);
} else if (currentName == "znear") {
XmlParser::getValueAsReal(currentNode, camera.mZNear);
} else if (currentName == "zfar") {
XmlParser::getValueAsReal(currentNode, camera.mZFar);
}
}
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
mFileName(pFile),
mXmlParser(),
mDataLibrary(),
mAccessorLibrary(),
mMeshLibrary(),
mNodeLibrary(),
mImageLibrary(),
mEffectLibrary(),
mMaterialLibrary(),
mLightLibrary(),
mCameraLibrary(),
mControllerLibrary(),
mRootNode(nullptr),
mAnims(),
mUnitSize(1.0f),
mUpDirection(UP_Y),
mFormat(FV_1_5_n) {
@@ -421,13 +122,13 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
throw DeadlyImportError("IOSystem is nullptr.");
}
std::unique_ptr<IOStream> daeFile;
std::unique_ptr<IOStream> daefile;
std::unique_ptr<ZipArchiveIOSystem> zip_archive;
// Determine type
const std::string extension = BaseImporter::GetExtension(pFile);
std::string extension = BaseImporter::GetExtension(pFile);
if (extension != "dae") {
zip_archive = std::make_unique<ZipArchiveIOSystem>(pIOHandler, pFile);
zip_archive.reset(new ZipArchiveIOSystem(pIOHandler, pFile));
}
if (zip_archive && zip_archive->isOpen()) {
@@ -437,24 +138,24 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
throw DeadlyImportError("Invalid ZAE");
}
daeFile.reset(zip_archive->Open(dae_filename.c_str()));
if (daeFile == nullptr) {
daefile.reset(zip_archive->Open(dae_filename.c_str()));
if (daefile == nullptr) {
throw DeadlyImportError("Invalid ZAE manifest: '", dae_filename, "' is missing");
}
} else {
// attempt to open the file directly
daeFile.reset(pIOHandler->Open(pFile));
if (daeFile == nullptr) {
daefile.reset(pIOHandler->Open(pFile));
if (daefile == nullptr) {
throw DeadlyImportError("Failed to open file '", pFile, "'.");
}
}
// generate a XML reader for it
if (!mXmlParser.parse(daeFile.get())) {
if (!mXmlParser.parse(daefile.get())) {
throw DeadlyImportError("Unable to read file, malformed XML");
}
// start reading
const XmlNode node = mXmlParser.getRootNode();
XmlNode node = mXmlParser.getRootNode();
XmlNode colladaNode = node.child("COLLADA");
if (colladaNode.empty()) {
return;
@@ -489,14 +190,14 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) {
zip_archive.getFileListExtension(file_list, "dae");
if (file_list.empty()) {
return {};
return std::string();
}
return file_list.front();
}
XmlParser manifestParser;
if (!manifestParser.parse(manifestfile.get())) {
return {};
return std::string();
}
XmlNode root = manifestParser.getRootNode();
@@ -504,7 +205,7 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) {
if (name != "dae_root") {
root = *manifestParser.findNode("dae_root");
if (nullptr == root) {
return {};
return std::string();
}
std::string v;
XmlParser::getValueAsString(root, v);
@@ -513,7 +214,7 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) {
return std::string(ai_str.C_Str());
}
return {};
return std::string();
}
// ------------------------------------------------------------------------------------------------
@@ -545,7 +246,7 @@ void ColladaParser::UriDecodePath(aiString &ss) {
char mychar[3] = { it[1], it[2], 0 };
size_t nbr = strtoul16(mychar);
it += 3;
*out++ = static_cast<char>(nbr & 0xFF);
*out++ = (char)(nbr & 0xFF);
} else {
*out++ = *it++;
}
@@ -560,11 +261,12 @@ void ColladaParser::UriDecodePath(aiString &ss) {
// ------------------------------------------------------------------------------------------------
// Reads the contents of the file
void ColladaParser::ReadContents(XmlNode &node) {
if (const std::string name = node.name(); name == "COLLADA") {
const std::string name = node.name();
if (name == "COLLADA") {
std::string version;
if (XmlParser::getStdStrAttribute(node, "version", version)) {
aiString v;
v.Set(version);
v.Set(version.c_str());
mAssetMetaData.emplace(AI_METADATA_SOURCE_FORMAT_VERSION, v);
if (!::strncmp(version.c_str(), "1.5", 3)) {
mFormat = FV_1_5_n;
@@ -585,7 +287,8 @@ void ColladaParser::ReadContents(XmlNode &node) {
// Reads the structure of the file
void ColladaParser::ReadStructure(XmlNode &node) {
for (XmlNode &currentNode : node.children()) {
if (const std::string &currentName = currentNode.name(); currentName == "asset") {
const std::string &currentName = currentNode.name();
if (currentName == "asset") {
ReadAssetInfo(currentNode);
} else if (currentName == "library_animations") {
ReadAnimationLibrary(currentNode);
@@ -626,7 +329,8 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
}
for (XmlNode &currentNode : node.children()) {
if (const std::string &currentName = currentNode.name(); currentName == "unit") {
const std::string &currentName = currentNode.name();
if (currentName == "unit") {
mUnitSize = 1.f;
std::string tUnitSizeString;
if (XmlParser::getStdStrAttribute(currentNode, "meter", tUnitSizeString)) {
@@ -660,6 +364,35 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
}
}
// ------------------------------------------------------------------------------------------------
// Reads a single string metadata item
void ColladaParser::ReadMetaDataItem(XmlNode &node, StringMetaData &metadata) {
const Collada::MetaKeyPairVector &key_renaming = GetColladaAssimpMetaKeysCamelCase();
const std::string name = node.name();
if (name.empty()) {
return;
}
std::string v;
if (!XmlParser::getValueAsString(node, v)) {
return;
}
v = ai_trim(v);
aiString aistr;
aistr.Set(v);
std::string camel_key_str(name);
ToCamelCase(camel_key_str);
size_t found_index;
if (FindCommonKey(camel_key_str, key_renaming, found_index)) {
metadata.emplace(key_renaming[found_index].second, aistr);
} else {
metadata.emplace(camel_key_str, aistr);
}
}
// ------------------------------------------------------------------------------------------------
// Reads the animation clips
void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
@@ -691,16 +424,15 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
}
}
// ------------------------------------------------------------------------------------------------
// The controller post processing step
void ColladaParser::PostProcessControllers() {
std::string meshId;
for (auto &it : mControllerLibrary) {
std::string meshId = it.second.mMeshId;
meshId = it.second.mMeshId;
if (meshId.empty()) {
continue;
}
auto findItr = mControllerLibrary.find(meshId);
ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId);
while (findItr != mControllerLibrary.end()) {
meshId = findItr->second.mMeshId;
findItr = mControllerLibrary.find(meshId);
@@ -722,13 +454,13 @@ void ColladaParser::PostProcessRootAnimations() {
for (auto &it : mAnimationClipLibrary) {
std::string clipName = it.first;
auto *clip = new Animation();
Animation *clip = new Animation();
clip->mName = clipName;
temp.mSubAnims.push_back(clip);
for (const std::string &animationID : it.second) {
auto animation = mAnimationLibrary.find(animationID);
AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID);
if (animation != mAnimationLibrary.end()) {
Animation *pSourceAnimation = animation->second;
@@ -801,7 +533,7 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
std::string id;
if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
// have it read into a channel
auto newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
ReadAnimationSampler(currentNode, newChannel->second);
}
} else if (currentName == "channel") {
@@ -811,7 +543,7 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
if (source_name[0] == '#') {
source_name = source_name.substr(1, source_name.size() - 1);
}
auto cit = channels.find(source_name);
ChannelMap::iterator cit = channels.find(source_name);
if (cit != channels.end()) {
cit->second.mTarget = target;
}
@@ -836,6 +568,40 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
}
}
// ------------------------------------------------------------------------------------------------
// Reads an animation sampler into the given anim channel
void ColladaParser::ReadAnimationSampler(XmlNode &node, Collada::AnimationChannel &pChannel) {
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "input") {
if (XmlParser::hasAttribute(currentNode, "semantic")) {
std::string semantic, sourceAttr;
XmlParser::getStdStrAttribute(currentNode, "semantic", semantic);
if (XmlParser::hasAttribute(currentNode, "source")) {
XmlParser::getStdStrAttribute(currentNode, "source", sourceAttr);
const char *source = sourceAttr.c_str();
if (source[0] != '#') {
throw DeadlyImportError("Unsupported URL format");
}
source++;
if (semantic == "INPUT") {
pChannel.mSourceTimes = source;
} else if (semantic == "OUTPUT") {
pChannel.mSourceValues = source;
} else if (semantic == "IN_TANGENT") {
pChannel.mInTanValues = source;
} else if (semantic == "OUT_TANGENT") {
pChannel.mOutTanValues = source;
} else if (semantic == "INTERPOLATION") {
pChannel.mInterpolationValues = source;
}
}
}
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads the skeleton controller library
void ColladaParser::ReadControllerLibrary(XmlNode &node) {
@@ -848,7 +614,8 @@ void ColladaParser::ReadControllerLibrary(XmlNode &node) {
if (currentName != "controller") {
continue;
}
if (std::string id; XmlParser::getStdStrAttribute(currentNode, "id", id)) {
std::string id;
if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
mControllerLibrary[id] = Controller();
ReadController(currentNode, mControllerLibrary[id]);
}
@@ -865,11 +632,13 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
while (xmlIt.getNext(currentNode)) {
if (const std::string &currentName = currentNode.name(); currentName == "morph") {
const std::string &currentName = currentNode.name();
if (currentName == "morph") {
controller.mType = Morph;
std::string id = currentNode.attribute("source").as_string();
controller.mMeshId = id.substr(1, id.size() - 1);
if (const int methodIndex = currentNode.attribute("method").as_int(); methodIndex > 0) {
int methodIndex = currentNode.attribute("method").as_int();
if (methodIndex > 0) {
std::string method;
XmlParser::getValueAsString(currentNode, method);
@@ -878,7 +647,8 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
}
}
} else if (currentName == "skin") {
if (std::string id; XmlParser::getStdStrAttribute(currentNode, "source", id)) {
std::string id;
if (XmlParser::getStdStrAttribute(currentNode, "source", id)) {
controller.mMeshId = id.substr(1, id.size() - 1);
}
} else if (currentName == "bind_shape_matrix") {
@@ -886,10 +656,10 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
XmlParser::getValueAsString(currentNode, v);
const char *content = v.c_str();
const char *end = content + v.size();
for (float & a : controller.mBindShapeMatrix) {
for (unsigned int a = 0; a < 16; a++) {
SkipSpacesAndLineEnd(&content, end);
// read a number
content = fast_atoreal_move<ai_real>(content, a);
content = fast_atoreal_move<ai_real>(content, controller.mBindShapeMatrix[a]);
// skip whitespace after it
SkipSpacesAndLineEnd(&content, end);
}
@@ -916,13 +686,108 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
}
}
// ------------------------------------------------------------------------------------------------
// Reads the joint definitions for the given controller
void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pController) {
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "input") {
const char *attrSemantic = currentNode.attribute("semantic").as_string();
const char *attrSource = currentNode.attribute("source").as_string();
if (attrSource[0] != '#') {
throw DeadlyImportError("Unsupported URL format in \"", attrSource, "\" in source attribute of <joints> data <input> element");
}
++attrSource;
// parse source URL to corresponding source
if (strcmp(attrSemantic, "JOINT") == 0) {
pController.mJointNameSource = attrSource;
} else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) {
pController.mJointOffsetMatrixSource = attrSource;
} else {
throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <joints> data <input> element");
}
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads the joint weights for the given controller
void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) {
// Read vertex count from attributes and resize the array accordingly
int vertexCount = 0;
XmlParser::getIntAttribute(node, "count", vertexCount);
pController.mWeightCounts.resize(vertexCount);
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "input") {
InputChannel channel;
const char *attrSemantic = currentNode.attribute("semantic").as_string();
const char *attrSource = currentNode.attribute("source").as_string();
channel.mOffset = currentNode.attribute("offset").as_int();
// local URLS always start with a '#'. We don't support global URLs
if (attrSource[0] != '#') {
throw DeadlyImportError("Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element");
}
channel.mAccessor = attrSource + 1;
// parse source URL to corresponding source
if (strcmp(attrSemantic, "JOINT") == 0) {
pController.mWeightInputJoints = channel;
} else if (strcmp(attrSemantic, "WEIGHT") == 0) {
pController.mWeightInputWeights = channel;
} else {
throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <vertex_weights> data <input> element");
}
} else if (currentName == "vcount" && vertexCount > 0) {
const std::string stdText = currentNode.text().as_string();
const char *text = stdText.c_str();
const char *end = text + stdText.size();
size_t numWeights = 0;
for (std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) {
if (*text == 0) {
throw DeadlyImportError("Out of data while reading <vcount>");
}
*it = strtoul10(text, &text);
numWeights += *it;
SkipSpacesAndLineEnd(&text, end);
}
// reserve weight count
pController.mWeights.resize(numWeights);
} else if (currentName == "v" && vertexCount > 0) {
// read JointIndex - WeightIndex pairs
std::string stdText;
XmlParser::getValueAsString(currentNode, stdText);
const char *text = stdText.c_str();
const char *end = text + stdText.size();
for (std::vector<std::pair<size_t, size_t>>::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) {
if (text == nullptr) {
throw DeadlyImportError("Out of data while reading <vertex_weights>");
}
SkipSpacesAndLineEnd(&text, end);
it->first = strtoul10(text, &text);
SkipSpacesAndLineEnd(&text, end);
if (*text == 0) {
throw DeadlyImportError("Out of data while reading <vertex_weights>");
}
it->second = strtoul10(text, &text);
SkipSpacesAndLineEnd(&text, end);
}
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads the image library contents
void ColladaParser::ReadImageLibrary(const XmlNode &node) {
void ColladaParser::ReadImageLibrary(XmlNode &node) {
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "image") {
if (std::basic_string<char> id; XmlParser::getStdStrAttribute(currentNode, "id", id)) {
std::string id;
if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
mImageLibrary[id] = Image();
// read on from there
ReadImage(currentNode, mImageLibrary[id]);
@@ -933,7 +798,7 @@ void ColladaParser::ReadImageLibrary(const XmlNode &node) {
// ------------------------------------------------------------------------------------------------
// Reads an image entry into the given image
void ColladaParser::ReadImage(const XmlNode &node, Collada::Image &pImage) const {
void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == "image") {
@@ -996,13 +861,13 @@ void ColladaParser::ReadImage(const XmlNode &node, Collada::Image &pImage) const
// Reads the material library
void ColladaParser::ReadMaterialLibrary(XmlNode &node) {
std::map<std::string, int> names;
for (const XmlNode &currentNode : node.children()) {
for (XmlNode &currentNode : node.children()) {
std::string id = currentNode.attribute("id").as_string();
std::string name = currentNode.attribute("name").as_string();
mMaterialLibrary[id] = Material();
if (!name.empty()) {
auto it = names.find(name);
std::map<std::string, int>::iterator it = names.find(name);
if (it != names.end()) {
std::ostringstream strStream;
strStream << ++it->second;
@@ -1057,6 +922,107 @@ void ColladaParser::ReadCameraLibrary(XmlNode &node) {
}
}
// ------------------------------------------------------------------------------------------------
// Reads a material entry into the given material
void ColladaParser::ReadMaterial(XmlNode &node, Collada::Material &pMaterial) {
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "instance_effect") {
std::string url;
readUrlAttribute(currentNode, url);
pMaterial.mEffect = url;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a light entry into the given light
void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
// TODO: Check the current technique and skip over unsupported extra techniques
while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name();
if (currentName == "spot") {
pLight.mType = aiLightSource_SPOT;
} else if (currentName == "ambient") {
pLight.mType = aiLightSource_AMBIENT;
} else if (currentName == "directional") {
pLight.mType = aiLightSource_DIRECTIONAL;
} else if (currentName == "point") {
pLight.mType = aiLightSource_POINT;
} else if (currentName == "color") {
// text content contains 3 floats
std::string v;
XmlParser::getValueAsString(currentNode, v);
const char *content = v.c_str();
const char *end = content + v.size();
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.r);
SkipSpacesAndLineEnd(&content, end);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.g);
SkipSpacesAndLineEnd(&content, end);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b);
SkipSpacesAndLineEnd(&content, end);
} else if (currentName == "constant_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttConstant);
} else if (currentName == "linear_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttLinear);
} else if (currentName == "quadratic_attenuation") {
XmlParser::getValueAsReal(currentNode, pLight.mAttQuadratic);
} else if (currentName == "falloff_angle") {
XmlParser::getValueAsReal(currentNode, pLight.mFalloffAngle);
} else if (currentName == "falloff_exponent") {
XmlParser::getValueAsReal(currentNode, pLight.mFalloffExponent);
}
// FCOLLADA extensions
// -------------------------------------------------------
else if (currentName == "outer_cone") {
XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle);
} else if (currentName == "penumbra_angle") { // this one is deprecated, now calculated using outer_cone
XmlParser::getValueAsReal(currentNode, pLight.mPenumbraAngle);
} else if (currentName == "intensity") {
XmlParser::getValueAsReal(currentNode, pLight.mIntensity);
}
else if (currentName == "falloff") {
XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle);
} else if (currentName == "hotspot_beam") {
XmlParser::getValueAsReal(currentNode, pLight.mFalloffAngle);
}
// OpenCOLLADA extensions
// -------------------------------------------------------
else if (currentName == "decay_falloff") {
XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle);
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a camera entry into the given light
void ColladaParser::ReadCamera(XmlNode &node, Collada::Camera &camera) {
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name();
if (currentName == "orthographic") {
camera.mOrtho = true;
} else if (currentName == "xfov" || currentName == "xmag") {
XmlParser::getValueAsReal(currentNode, camera.mHorFov);
} else if (currentName == "yfov" || currentName == "ymag") {
XmlParser::getValueAsReal(currentNode, camera.mVerFov);
} else if (currentName == "aspect_ratio") {
XmlParser::getValueAsReal(currentNode, camera.mAspect);
} else if (currentName == "znear") {
XmlParser::getValueAsReal(currentNode, camera.mZNear);
} else if (currentName == "zfar") {
XmlParser::getValueAsReal(currentNode, camera.mZFar);
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads the effect library
void ColladaParser::ReadEffectLibrary(XmlNode &node) {
@@ -1260,7 +1226,7 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
std::string v;
XmlParser::getValueAsString(currentNode, v);
const char *content = v.c_str();
const char *end = v.c_str() + v.size() + 1;
const char *end = v.c_str() + v.size() + 1;
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.r);
SkipSpacesAndLineEnd(&content, end);
@@ -1386,7 +1352,7 @@ void ColladaParser::ReadGeometry(XmlNode &node, Collada::Mesh &pMesh) {
if (node.empty()) {
return;
}
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "mesh") {
@@ -1767,6 +1733,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
expectedPointCount = 3 * pNumPrimitives;
break;
default:
// other primitive types don't state the index count upfront... we need to guess
break;
}
@@ -1808,7 +1775,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
}
// find the data for all sources
for (auto it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) {
for (std::vector<InputChannel>::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) {
InputChannel &input = *it;
if (input.mResolved) {
continue;
@@ -1827,7 +1794,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
}
}
// and the same for the per-index channels
for (auto it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) {
for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) {
InputChannel &input = *it;
if (input.mResolved) {
continue;
@@ -1935,11 +1902,11 @@ void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t n
ai_assert((baseOffset + numOffsets - 1) < indices.size());
// extract per-vertex channels using the global per-vertex offset
for (auto it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) {
for (std::vector<InputChannel>::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) {
ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh);
}
// and extract per-index channels using there specified offset
for (auto it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) {
for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) {
ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh);
}
@@ -2206,6 +2173,40 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
}
}
// ------------------------------------------------------------------------------------------------
// Reads a node transformation entry of the given type and adds it to the given node's transformation list.
void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, TransformType pType) {
if (node.empty()) {
return;
}
std::string tagName = node.name();
Transform tf;
tf.mType = pType;
// read SID
if (XmlParser::hasAttribute(node, "sid")) {
XmlParser::getStdStrAttribute(node, "sid", tf.mID);
}
// how many parameters to read per transformation type
static constexpr unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 };
std::string value;
XmlParser::getValueAsString(node, value);
const char *content = value.c_str();
const char *end = value.c_str() + value.size();
// read as many parameters and store in the transformation
for (unsigned int a = 0; a < sNumParameters[pType]; a++) {
// skip whitespace before the number
SkipSpacesAndLineEnd(&content, end);
// read a number
content = fast_atoreal_move<ai_real>(content, tf.f[a]);
}
// place the transformation at the queue of the node
pNode->mTransforms.push_back(tf);
}
// ------------------------------------------------------------------------------------------------
// Processes bind_vertex_input and bind elements
@@ -2243,7 +2244,9 @@ void ColladaParser::ReadMaterialVertexInputBinding(XmlNode &node, Collada::Seman
void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive) {
// Attempt to load any undefined Collada::Image in ImageLibrary
for (auto &it : mImageLibrary) {
if (Image &image = it.second; image.mImageData.empty()) {
Collada::Image &image = it.second;
if (image.mImageData.empty()) {
std::unique_ptr<IOStream> image_file(zip_archive.Open(image.mFileName.c_str()));
if (image_file) {
image.mImageData.resize(image_file->FileSize());
@@ -2326,7 +2329,7 @@ void ColladaParser::ReadScene(XmlNode &node) {
}
// find the referred scene, skip the leading #
auto sit = mNodeLibrary.find(url.c_str() + 1);
NodeLibrary::const_iterator sit = mNodeLibrary.find(url.c_str() + 1);
if (sit == mNodeLibrary.end()) {
throw DeadlyImportError("Unable to resolve visual_scene reference \"", std::string(std::move(url)), "\" in <instance_visual_scene> element.");
}
@@ -2398,7 +2401,7 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector<Transform>
// ------------------------------------------------------------------------------------------------
// Determines the input data type for the given semantic string
InputType ColladaParser::GetTypeForSemantic(const std::string &semantic) {
Collada::InputType ColladaParser::GetTypeForSemantic(const std::string &semantic) {
if (semantic.empty()) {
ASSIMP_LOG_WARN("Vertex input type is empty.");
return IT_Invalid;
+111 -82
View File
@@ -48,6 +48,7 @@
#define AI_COLLADAPARSER_H_INC
#include "ColladaHelper.h"
#include <assimp/TinyFormatter.h>
#include <assimp/ai_assert.h>
#include <assimp/XmlParser.h>
@@ -66,240 +67,268 @@ class ZipArchiveIOSystem;
class ColladaParser {
friend class ColladaLoader;
public:
/// Map for generic metadata as aiString.
using StringMetaData = std::map<std::string, aiString>;
/** Converts a path read from a collada file to the usual representation */
static void UriDecodePath(aiString &ss);
/// Constructor from XML file.
protected:
/** Map for generic metadata as aiString */
typedef std::map<std::string, aiString> StringMetaData;
/** Constructor from XML file */
ColladaParser(IOSystem *pIOHandler, const std::string &pFile);
/// Destructor
/** Destructor */
~ColladaParser();
/// Attempts to read the ZAE manifest and returns the DAE to open
/** Attempts to read the ZAE manifest and returns the DAE to open */
static std::string ReadZaeManifest(ZipArchiveIOSystem &zip_archive);
/// Reads the contents of the file
/** Reads the contents of the file */
void ReadContents(XmlNode &node);
/// Reads the structure of the file
/** Reads the structure of the file */
void ReadStructure(XmlNode &node);
/// Reads asset information such as coordinate system information and legal blah
/** Reads asset information such as coordinate system information and legal blah */
void ReadAssetInfo(XmlNode &node);
/// Reads contributor information such as author and legal blah
/** Reads contributor information such as author and legal blah */
void ReadContributorInfo(XmlNode &node);
/// Reads the animation library
/** Reads generic metadata into provided map and renames keys for Assimp */
void ReadMetaDataItem(XmlNode &node, StringMetaData &metadata);
/** Reads the animation library */
void ReadAnimationLibrary(XmlNode &node);
/// Reads the animation clip library
/** Reads the animation clip library */
void ReadAnimationClipLibrary(XmlNode &node);
/// Unwrap controllers dependency hierarchy
/** Unwrap controllers dependency hierarchy */
void PostProcessControllers();
/// Re-build animations from animation clip library, if present, otherwise combine single-channel animations
/** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */
void PostProcessRootAnimations();
/// Reads an animation into the given parent structure
/** Reads an animation into the given parent structure */
void ReadAnimation(XmlNode &node, Collada::Animation *pParent);
/// Reads the skeleton controller library
/** Reads an animation sampler into the given anim channel */
void ReadAnimationSampler(XmlNode &node, Collada::AnimationChannel &pChannel);
/** Reads the skeleton controller library */
void ReadControllerLibrary(XmlNode &node);
/// Reads a controller into the given mesh structure
/** Reads a controller into the given mesh structure */
void ReadController(XmlNode &node, Collada::Controller &pController);
/// Reads the image library contents
void ReadImageLibrary(const XmlNode &node);
/** Reads the joint definitions for the given controller */
void ReadControllerJoints(XmlNode &node, Collada::Controller &pController);
/// Reads an image entry into the given image
void ReadImage(const XmlNode &node, Collada::Image &pImage) const;
/** Reads the joint weights for the given controller */
void ReadControllerWeights(XmlNode &node, Collada::Controller &pController);
/// Reads the material library
/** Reads the image library contents */
void ReadImageLibrary(XmlNode &node);
/** Reads an image entry into the given image */
void ReadImage(XmlNode &node, Collada::Image &pImage);
/** Reads the material library */
void ReadMaterialLibrary(XmlNode &node);
/// Reads the camera library
/** Reads a material entry into the given material */
void ReadMaterial(XmlNode &node, Collada::Material &pMaterial);
/** Reads the camera library */
void ReadCameraLibrary(XmlNode &node);
/// Reads the light library
/** Reads a camera entry into the given camera */
void ReadCamera(XmlNode &node, Collada::Camera &pCamera);
/** Reads the light library */
void ReadLightLibrary(XmlNode &node);
/// Reads the effect library
/** Reads a light entry into the given light */
void ReadLight(XmlNode &node, Collada::Light &pLight);
/** Reads the effect library */
void ReadEffectLibrary(XmlNode &node);
/// Reads an effect entry into the given effect
/** Reads an effect entry into the given effect*/
void ReadEffect(XmlNode &node, Collada::Effect &pEffect);
/// Reads an COMMON effect profile
/** Reads an COMMON effect profile */
void ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEffect);
/// Read sampler properties
/** Read sampler properties */
void ReadSamplerProperties(XmlNode &node, Collada::Sampler &pSampler);
/// Reads an effect entry containing a color or a texture defining that color
/** Reads an effect entry containing a color or a texture defining that color */
void ReadEffectColor(XmlNode &node, aiColor4D &pColor, Collada::Sampler &pSampler);
/// Reads an effect entry containing a float
/** Reads an effect entry containing a float */
void ReadEffectFloat(XmlNode &node, ai_real &pFloat);
/// Reads an effect parameter specification of any kind
/** Reads an effect parameter specification of any kind */
void ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam);
/// Reads the geometry library contents
/** Reads the geometry library contents */
void ReadGeometryLibrary(XmlNode &node);
/// Reads a geometry from the geometry library.
/** Reads a geometry from the geometry library. */
void ReadGeometry(XmlNode &node, Collada::Mesh &pMesh);
/// Reads a mesh from the geometry library
/** Reads a mesh from the geometry library */
void ReadMesh(XmlNode &node, Collada::Mesh &pMesh);
/// Reads a source element - a combination of raw data and an accessor defining
///things that should not be definable. Yes, that's another rant.
/** Reads a source element - a combination of raw data and an accessor defining
* things that should not be redefinable. Yes, that's another rant.
*/
void ReadSource(XmlNode &node);
/// Reads a data array holding a number of elements, and stores it in the global library.
/// Currently supported are array of floats and arrays of strings.
/** Reads a data array holding a number of elements, and stores it in the global library.
* Currently supported are array of floats and arrays of strings.
*/
void ReadDataArray(XmlNode &node);
/// Reads an accessor and stores it in the global library under the given ID -
/// accessors use the ID of the parent <source> element
/** Reads an accessor and stores it in the global library under the given ID -
* accessors use the ID of the parent <source> element
*/
void ReadAccessor(XmlNode &node, const std::string &pID);
/// Reads input declarations of per-vertex mesh data into the given mesh
/** Reads input declarations of per-vertex mesh data into the given mesh */
void ReadVertexData(XmlNode &node, Collada::Mesh &pMesh);
/// Reads input declarations of per-index mesh data into the given mesh
/** Reads input declarations of per-index mesh data into the given mesh */
void ReadIndexData(XmlNode &node, Collada::Mesh &pMesh);
/// Reads a single input channel element and stores it in the given array, if valid
/** Reads a single input channel element and stores it in the given array, if valid */
void ReadInputChannel(XmlNode &node, std::vector<Collada::InputChannel> &poChannels);
/// Reads a <p> primitive index list and assembles the mesh data into the given mesh
/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
size_t ReadPrimitives(XmlNode &node, Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
size_t pNumPrimitives, const std::vector<size_t> &pVCount, Collada::PrimitiveType pPrimType);
/// Copies the data for a single primitive into the mesh, based on the InputChannels
/** Copies the data for a single primitive into the mesh, based on the InputChannels */
void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
size_t currentPrimitive, const std::vector<size_t> &indices);
/// Reads one triangle of a tristrip into the mesh
/** Reads one triangle of a tristrip into the mesh */
void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh &pMesh,
std::vector<Collada::InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices);
/// Extracts a single object from an input channel and stores it in the appropriate mesh data array
/** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
void ExtractDataObjectFromChannel(const Collada::InputChannel &pInput, size_t pLocalIndex, Collada::Mesh &pMesh);
/// Reads the library of node hierarchies and scene parts
/** Reads the library of node hierarchies and scene parts */
void ReadSceneLibrary(XmlNode &node);
/// Reads a scene node's contents including children and stores it in the given node
/** Reads a scene node's contents including children and stores it in the given node */
void ReadSceneNode(XmlNode &node, Collada::Node *pNode);
/// Reads a mesh reference in a node and adds it to the node's mesh list
/** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
void ReadNodeTransformation(XmlNode &node, Collada::Node *pNode, Collada::TransformType pType);
/** Reads a mesh reference in a node and adds it to the node's mesh list */
void ReadNodeGeometry(XmlNode &node, Collada::Node *pNode);
/// Reads the collada scene
/** Reads the collada scene */
void ReadScene(XmlNode &node);
/// Processes bind_vertex_input and bind elements
// Processes bind_vertex_input and bind elements
void ReadMaterialVertexInputBinding(XmlNode &node, Collada::SemanticMappingTable &tbl);
/// Reads embedded textures from a ZAE archive
/** Reads embedded textures from a ZAE archive*/
void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
protected:
/// Converts a path read from a collada file to the usual representation
static void UriDecodePath(aiString &ss);
/// Calculates the resulting transformation from all the given transform steps
/** Calculates the resulting transformation from all the given transform steps */
aiMatrix4x4 CalculateResultTransform(const std::vector<Collada::Transform> &pTransforms) const;
/// Determines the input data type for the given semantic string
/** Determines the input data type for the given semantic string */
Collada::InputType GetTypeForSemantic(const std::string &pSemantic);
/// Finds the item in the given library by its reference, throws if not found
/** Finds the item in the given library by its reference, throws if not found */
template <typename Type>
const Type &ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const;
private:
/// Filename, for a verbose error message
protected:
// Filename, for a verbose error message
std::string mFileName;
/// XML reader, member for everyday use
// XML reader, member for everyday use
XmlParser mXmlParser;
/// All data arrays found in the file by ID. Might be referred to by actually
/// everyone. Collada, you are a steaming pile of indirection.
/** All data arrays found in the file by ID. Might be referred to by actually
everyone. Collada, you are a steaming pile of indirection. */
using DataLibrary = std::map<std::string, Collada::Data> ;
DataLibrary mDataLibrary;
/// Same for accessors which define how the data in a data array is accessed.
/** Same for accessors which define how the data in a data array is accessed. */
using AccessorLibrary = std::map<std::string, Collada::Accessor> ;
AccessorLibrary mAccessorLibrary;
/// Mesh library: mesh by ID
/** Mesh library: mesh by ID */
using MeshLibrary = std::map<std::string, Collada::Mesh *>;
MeshLibrary mMeshLibrary;
/// node library: root node of the hierarchy part by ID
/** node library: root node of the hierarchy part by ID */
using NodeLibrary = std::map<std::string, Collada::Node *>;
NodeLibrary mNodeLibrary;
/// Image library: stores texture properties by ID
/** Image library: stores texture properties by ID */
using ImageLibrary = std::map<std::string, Collada::Image> ;
ImageLibrary mImageLibrary;
/// Effect library: surface attributes by ID
/** Effect library: surface attributes by ID */
using EffectLibrary = std::map<std::string, Collada::Effect> ;
EffectLibrary mEffectLibrary;
/// Material library: surface material by ID
/** Material library: surface material by ID */
using MaterialLibrary = std::map<std::string, Collada::Material> ;
MaterialLibrary mMaterialLibrary;
/// Light library: surface light by ID
/** Light library: surface light by ID */
using LightLibrary = std::map<std::string, Collada::Light> ;
LightLibrary mLightLibrary;
/// Camera library: surface material by ID
/** Camera library: surface material by ID */
using CameraLibrary = std::map<std::string, Collada::Camera> ;
CameraLibrary mCameraLibrary;
/// Controller library: joint controllers by ID
/** Controller library: joint controllers by ID */
using ControllerLibrary = std::map<std::string, Collada::Controller> ;
ControllerLibrary mControllerLibrary;
/// Animation library: animation references by ID
/** Animation library: animation references by ID */
using AnimationLibrary = std::map<std::string, Collada::Animation *> ;
AnimationLibrary mAnimationLibrary;
/// Animation clip library: clip animation references by ID
/** Animation clip library: clip animation references by ID */
using AnimationClipLibrary = std::vector<std::pair<std::string, std::vector<std::string>>> ;
AnimationClipLibrary mAnimationClipLibrary;
/// Pointer to the root node. Don't delete, it just points to one of the nodes in the node library.
/** Pointer to the root node. Don't delete, it just points to one of
the nodes in the node library. */
Collada::Node *mRootNode;
/// Root animation container
/** Root animation container */
Collada::Animation mAnims;
/// Size unit: how large compared to a meter
/** Size unit: how large compared to a meter */
ai_real mUnitSize;
/// Which is the up vector
/** Which is the up vector */
enum { UP_X,
UP_Y,
UP_Z } mUpDirection;
/// Asset metadata (global for scene)
/** Asset metadata (global for scene) */
StringMetaData mAssetMetaData;
/// Collada file format version
/** Collada file format version */
Collada::FormatVersion mFormat;
};
+2 -2
View File
@@ -45,8 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
#include "DXFLoader.h"
#include "DXFHelper.h"
#include "AssetLib/DXF/DXFLoader.h"
#include "AssetLib/DXF/DXFHelper.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include <assimp/ParsingUtils.h>
+1 -1
View File
@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h>
#include <map>
namespace Assimp {
namespace Assimp {
// Forward declarations
namespace DXF {
+1 -1
View File
@@ -146,7 +146,7 @@ const AnimationCurveMap &AnimationCurveNode::Curves() const {
if (!curves.empty()) {
return curves;
}
// resolve attached animation curves
const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationCurve");
+1 -1
View File
@@ -2958,7 +2958,7 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
// be invoked _later_ (animations come first). If this node has only rotation,
// scaling and translation _and_ there are no animated other components either,
// we can use a single node and also a single node animation channel.
if (!doc.Settings().preservePivots || (!has_complex && !NeedsComplexTransformationChain(target))) {
if( !has_complex && !NeedsComplexTransformationChain(target)) {
aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain,
node_property_map.end(),
start, stop,
+1 -1
View File
@@ -269,7 +269,7 @@ Document::~Document()
{
// The document does not own the memory for the following objects, but we need to call their d'tor
// so they can properly free memory like string members:
for (ObjectMap::value_type &v : objects) {
delete_LazyObject(v.second);
}
+1 -1
View File
@@ -221,7 +221,7 @@ private: // internal functions used for writing
void BeginChildrenAscii(std::ostream &s, int indent);
void DumpChildrenAscii(std::ostream &s, int indent);
void EndAscii(std::ostream &s, int indent, bool has_children);
// static helper functions
static void WritePropertyNodeAscii(
const std::string& name,
-2
View File
@@ -286,8 +286,6 @@ void FBXExportProperty::DumpAscii(std::ostream& s, int indent) {
break;
}
}
// assimp issue #6112; fallthrough confirmed by @mesilliac
[[fallthrough]];
case 'R':
s << '"';
// we might as well check this now,
+71 -100
View File
@@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Logger.hpp>
#include <assimp/StreamWriter.h> // StreamWriterLE
#include <assimp/Exceptional.h> // DeadlyExportError
#include <assimp/material.h> // aiTextureType
@@ -1043,40 +1042,14 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) {
}
inline int64_t to_ktime(double ticks, const aiAnimation* anim) {
// Defensive: handle zero or near-zero mTicksPerSecond
double tps = anim->mTicksPerSecond;
double timeVal;
if (FP_ZERO == std::fpclassify(tps)) {
timeVal = ticks;
} else {
timeVal = ticks / tps;
if (FP_ZERO == std::fpclassify(anim->mTicksPerSecond)) {
return static_cast<int64_t>(ticks) * FBX::SECOND;
}
// Clamp to prevent overflow
const double kMax = static_cast<double>(INT64_MAX) / static_cast<double>(FBX::SECOND);
const double kMin = static_cast<double>(INT64_MIN) / static_cast<double>(FBX::SECOND);
if (timeVal > kMax) {
return INT64_MAX;
}
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) {
// Clamp to prevent overflow
const double kMax = static_cast<double>(INT64_MAX) / static_cast<double>(FBX::SECOND);
const double kMin = static_cast<double>(INT64_MIN) / static_cast<double>(FBX::SECOND);
if (time > kMax) {
return INT64_MAX;
}
if (time < kMin) {
return INT64_MIN;
}
return static_cast<int64_t>(time * FBX::SECOND);
return (static_cast<int64_t>(time * FBX::SECOND));
}
void FBXExporter::WriteObjects () {
@@ -1095,6 +1068,8 @@ void FBXExporter::WriteObjects () {
// 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);
// geometry (aiMesh)
@@ -1132,6 +1107,9 @@ void FBXExporter::WriteObjects () {
std::vector<std::vector<double>> uv_data;
std::vector<std::vector<int32_t>> uv_indices;
std::map<aiVector3D, int32_t> index_by_uv;
std::vector<int32_t> offsets = { 0 };
indent = 2;
@@ -1140,10 +1118,11 @@ 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;
if (bJoinIdenticalVertices) {
if(bJoinIdenticalVertices){
int32_t index = 0;
for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
aiVector3D vtx = m->mVertices[vi];
@@ -1159,7 +1138,7 @@ void FBXExporter::WriteObjects () {
}
} else { // do not join vertex, respect the export flag
vertex_indices.resize(v_offset + m->mNumVertices);
std::iota(vertex_indices.begin() + v_offset, vertex_indices.end(), 0);
std::iota(vertex_indices.begin() + v_offset, vertex_indices.end(), (int)v_offset);
for(unsigned int v = 0; v < m->mNumVertices; ++ v) {
aiVector3D vtx = m->mVertices[v];
flattened_vertices.insert(flattened_vertices.end(), {vtx.x, vtx.y, vtx.z});
@@ -1167,8 +1146,8 @@ void FBXExporter::WriteObjects () {
}
vVertexIndice[mi].insert(
// TODO test whether this can be end or not
vVertexIndice[mi].end(),
vertex_indices.begin() + v_offset,
vVertexIndice[mi].begin(),
vertex_indices.begin(),
vertex_indices.end()
);
@@ -1179,14 +1158,19 @@ void FBXExporter::WriteObjects () {
// the last vertex index of each polygon is negated and - 1
for (size_t fi = 0; fi < m->mNumFaces; fi++) {
const aiFace &f = m->mFaces[fi];
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++) {
@@ -1213,12 +1197,10 @@ void FBXExporter::WriteObjects () {
const auto num_uv = static_cast<size_t>(m->GetNumUVChannels());
uv_indices.resize(std::max(num_uv, uv_indices.size()));
uv_data.resize(std::max(num_uv, uv_data.size()));
std::map<aiVector3D, int32_t> index_by_uv;
// uvs, if any
for (size_t uvi = 0; uvi < m->GetNumUVChannels(); uvi++) {
const auto nc = m->mNumUVComponents[uvi];
if (nc > 2) {
if (m->mNumUVComponents[uvi] > 2) {
// FBX only supports 2-channel UV maps...
// or at least i'm not sure how to indicate a different number
std::stringstream err;
@@ -1234,7 +1216,7 @@ void FBXExporter::WriteObjects () {
ASSIMP_LOG_WARN(err.str());
}
int32_t index = static_cast<int32_t>(uv_data[uvi].size()) / nc;
int32_t index = 0;
for (size_t fi = 0; fi < m->mNumFaces; fi++) {
const aiFace &f = m->mFaces[fi];
for (size_t pvi = 0; pvi < f.mNumIndices; pvi++) {
@@ -1243,7 +1225,7 @@ void FBXExporter::WriteObjects () {
if (elem == index_by_uv.end()) {
index_by_uv[curUv] = index;
uv_indices[uvi].push_back(index);
for (uint32_t x = 0; x < nc; ++x) {
for (uint32_t x = 0; x < m->mNumUVComponents[uvi]; ++x) {
uv_data[uvi].push_back(curUv[x]);
}
++index;
@@ -1253,6 +1235,8 @@ void FBXExporter::WriteObjects () {
}
}
}
offsets.push_back((int32_t)polygon_data.size());
}
@@ -1260,42 +1244,38 @@ void FBXExporter::WriteObjects () {
FBX::Node::WritePropertyNode("PolygonVertexIndex", polygon_data, outstream, binary, indent);
FBX::Node::WritePropertyNode("GeometryVersion", int32_t(124), outstream, binary, indent);
if (!normal_data.empty()) {
FBX::Node normals("LayerElementNormal", int32_t(0));
normals.Begin(outstream, binary, indent);
normals.DumpProperties(outstream, binary, indent);
normals.EndProperties(outstream, binary, indent);
normals.BeginChildren(outstream, binary, indent);
indent = 3;
FBX::Node::WritePropertyNode("Version", int32_t(101), outstream, binary, indent);
FBX::Node::WritePropertyNode("Name", "", outstream, binary, indent);
FBX::Node::WritePropertyNode("MappingInformationType", "ByPolygonVertex", outstream, binary, indent);
FBX::Node::WritePropertyNode("ReferenceInformationType", "Direct", outstream, binary, indent);
FBX::Node::WritePropertyNode("Normals", normal_data, outstream, binary, indent);
// note: version 102 has a NormalsW also... not sure what it is,
// so stick with version 101 for now.
indent = 2;
normals.End(outstream, binary, indent, true);
}
FBX::Node normals("LayerElementNormal", int32_t(0));
normals.Begin(outstream, binary, indent);
normals.DumpProperties(outstream, binary, indent);
normals.EndProperties(outstream, binary, indent);
normals.BeginChildren(outstream, binary, indent);
indent = 3;
FBX::Node::WritePropertyNode("Version", int32_t(101),outstream,binary,indent);
FBX::Node::WritePropertyNode("Name", "",outstream,binary,indent);
FBX::Node::WritePropertyNode("MappingInformationType", "ByPolygonVertex",outstream,binary,indent);
FBX::Node::WritePropertyNode("ReferenceInformationType", "Direct",outstream,binary,indent);
FBX::Node::WritePropertyNode("Normals", normal_data,outstream,binary,indent);
// note: version 102 has a NormalsW also... not sure what it is,
// so stick with version 101 for now.
indent = 2;
normals.End(outstream,binary,indent,true);
if (!color_data.empty()) {
const auto colorChannelIndex = 0;
FBX::Node vertexcolors("LayerElementColor", int32_t(colorChannelIndex));
vertexcolors.Begin(outstream, binary, indent);
vertexcolors.DumpProperties(outstream, binary, indent);
vertexcolors.EndProperties(outstream, binary, indent);
vertexcolors.BeginChildren(outstream, binary, indent);
indent = 3;
FBX::Node::WritePropertyNode("Version", int32_t(101), outstream, binary, indent);
char layerName[8];
snprintf(layerName, sizeof(layerName), "COLOR_%d", colorChannelIndex);
FBX::Node::WritePropertyNode("Name", (const char *)layerName, outstream, binary, indent);
FBX::Node::WritePropertyNode("MappingInformationType", "ByPolygonVertex", outstream, binary, indent);
FBX::Node::WritePropertyNode("ReferenceInformationType", "Direct", outstream, binary, indent);
FBX::Node::WritePropertyNode("Colors", color_data, outstream, binary, indent);
indent = 2;
vertexcolors.End(outstream, binary, indent, true);
}
const auto colorChannelIndex = 0;
FBX::Node vertexcolors("LayerElementColor", int32_t(colorChannelIndex));
vertexcolors.Begin(outstream, binary, indent);
vertexcolors.DumpProperties(outstream, binary, indent);
vertexcolors.EndProperties(outstream, binary, indent);
vertexcolors.BeginChildren(outstream, binary, indent);
indent = 3;
FBX::Node::WritePropertyNode("Version", int32_t(101), outstream, binary, indent);
char layerName[8];
snprintf(layerName, sizeof(layerName), "COLOR_%d", colorChannelIndex);
FBX::Node::WritePropertyNode("Name", (const char *)layerName, outstream, binary, indent);
FBX::Node::WritePropertyNode("MappingInformationType", "ByPolygonVertex", outstream, binary, indent);
FBX::Node::WritePropertyNode("ReferenceInformationType", "Direct", outstream, binary, indent);
FBX::Node::WritePropertyNode("Colors", color_data, outstream, binary, indent);
indent = 2;
vertexcolors.End(outstream, binary, indent, true);
for (uint32_t uvi = 0; uvi < uv_data.size(); uvi++) {
FBX::Node uv("LayerElementUV", int32_t(uvi));
@@ -1306,7 +1286,7 @@ void FBXExporter::WriteObjects () {
indent = 3;
FBX::Node::WritePropertyNode("Version", int32_t(101), outstream, binary, indent);
FBX::Node::WritePropertyNode("Name", "", outstream, binary, indent);
FBX::Node::WritePropertyNode("MappingInformationType", "ByPolygonVertex", outstream, binary, indent);
FBX::Node::WritePropertyNode("MappingInformationType", "ByPolgonVertex", outstream, binary, indent);
FBX::Node::WritePropertyNode("ReferenceInformationType", "IndexToDirect", outstream, binary, indent);
FBX::Node::WritePropertyNode("UV", uv_data[uvi], outstream, binary, indent);
FBX::Node::WritePropertyNode("UVIndex", uv_indices[uvi], outstream, binary, indent);
@@ -1347,21 +1327,15 @@ void FBXExporter::WriteObjects () {
// TODO: handle multiple uv sets correctly?
FBX::Node layer("Layer", int32_t(0));
layer.AddChild("Version", int32_t(100));
FBX::Node le;
FBX::Node le("LayerElement");
le.AddChild("Type", "LayerElementNormal");
le.AddChild("TypedIndex", int32_t(0));
layer.AddChild(le);
if (!normal_data.empty()) {
le = FBX::Node("LayerElement");
le.AddChild("Type", "LayerElementNormal");
le.AddChild("TypedIndex", int32_t(0));
layer.AddChild(le);
}
if (!color_data.empty()) {
le = FBX::Node("LayerElement");
le.AddChild("Type", "LayerElementColor");
le.AddChild("TypedIndex", int32_t(0));
layer.AddChild(le);
}
le = FBX::Node("LayerElement");
le.AddChild("Type", "LayerElementColor");
le.AddChild("TypedIndex", int32_t(0));
layer.AddChild(le);
le = FBX::Node("LayerElement");
le.AddChild("Type", "LayerElementMaterial");
@@ -2055,11 +2029,8 @@ void FBXExporter::WriteObjects () {
std::vector<double> subdef_weights;
int32_t last_index = -1;
for (size_t wi = 0; wi < b->mNumWeights; ++wi) {
if (b->mWeights[wi].mVertexId >= vVertexIndice[mi].size()) {
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
@@ -2539,9 +2510,9 @@ void add_meta(FBX::Node& fbx_node, const aiNode* node){
default:
break;
}
}
}
// write a single model node to the stream
+1
View File
@@ -4,6 +4,7 @@ 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,
+1 -1
View File
@@ -82,7 +82,7 @@ using ElementCollection = std::pair<ElementMap::const_iterator,ElementMap::const
* @endverbatim
*
* As can be seen in this sample, elements can contain nested #Scope
* as their trailing member.
* as their trailing member.
**/
class Element {
public:
+1
View File
@@ -4,6 +4,7 @@ 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,
+1
View File
@@ -4,6 +4,7 @@ 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,
+1
View File
@@ -4,6 +4,7 @@ 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,
+3 -2
View File
@@ -4,6 +4,7 @@ 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,
@@ -42,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//! @file Data structures for the 3D Game Studio Heightmap format (HMP)
//!
namespace Assimp {
namespace HMP {
namespace Assimp {
namespace HMP {
#include <assimp/Compiler/pushpack1.h>
#include <stdint.h>
+2 -2
View File
@@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
// internal headers
#include "HMPLoader.h"
#include "AssetLib/HMP/HMPLoader.h"
#include "AssetLib/MD2/MD2FileData.h"
#include <assimp/StringUtils.h>
@@ -81,7 +81,7 @@ HMPImporter::~HMPImporter() = default;
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool HMPImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static constexpr uint32_t tokens[] = {
static const uint32_t tokens[] = {
AI_HMP_MAGIC_NUMBER_LE_4,
AI_HMP_MAGIC_NUMBER_LE_5,
AI_HMP_MAGIC_NUMBER_LE_7
+1 -1
View File
@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h>
// internal headers
#include "HMPFileData.h"
#include "AssetLib/HMP/HMPFileData.h"
#include "AssetLib/MDL/MDLLoader.h"
namespace Assimp {
+3 -2
View File
@@ -4,6 +4,7 @@ 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,
@@ -52,8 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Compiler/pushpack1.h>
namespace Assimp {
namespace MDL {
namespace Assimp {
namespace MDL {
// magic bytes used in Half Life 2 MDL models
#define AI_MDL_MAGIC_NUMBER_BE_HL2a AI_MAKE_MAGIC("IDST")
+2 -2
View File
@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
#include "AssetLib/IFC/IFCUtil.h"
#include "Common/PolyTools.h"
#include "PostProcessing/ProcessHelper.h"
@@ -669,7 +669,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
}
// ------------------------------------------------------------------------------------------------
void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedAreaSolid *as,
void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedAreaSolid *as,
TempMesh &result,
const TempMesh &first_operand,
ConversionData &conv) {
+2 -2
View File
@@ -102,10 +102,10 @@ class Circle : public Conic {
public:
// --------------------------------------------------
Circle(const Schema_2x3::IfcCircle& entity, ConversionData& conv) : Conic(entity,conv) , entity(entity) {}
// --------------------------------------------------
~Circle() override = default;
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const override {
u = -conv.angle_scale * u;
+12 -12
View File
@@ -127,7 +127,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
}
}
}
if (outer_polygon_it == end) {
return;
}
@@ -234,7 +234,7 @@ void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, Tem
return;
}
const unsigned int cnt_segments =
const unsigned int cnt_segments =
std::max(2u,static_cast<unsigned int>(conv.settings.cylindricalTessellation * std::fabs(max_angle)/AI_MATH_HALF_PI_F));
const IfcFloat delta = max_angle/cnt_segments;
@@ -294,8 +294,8 @@ void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, Tem
}
// ------------------------------------------------------------------------------------------------
void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid,
TempMesh& result,
void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid,
TempMesh& result,
ConversionData& conv) {
const Curve* const curve = Curve::Convert(*solid.Directrix, conv);
if(!curve) {
@@ -687,9 +687,9 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
}
// ------------------------------------------------------------------------------------------------
void ProcessExtrudedAreaSolid(const Schema_2x3::IfcExtrudedAreaSolid& solid,
void ProcessExtrudedAreaSolid(const Schema_2x3::IfcExtrudedAreaSolid& solid,
TempMesh& result,
ConversionData& conv,
ConversionData& conv,
bool collect_openings) {
TempMesh meshout;
@@ -728,7 +728,7 @@ void ProcessExtrudedAreaSolid(const Schema_2x3::IfcExtrudedAreaSolid& solid,
}
// ------------------------------------------------------------------------------------------------
void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept,
void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept,
TempMesh& meshout,
ConversionData& conv) {
if(const Schema_2x3::IfcExtrudedAreaSolid* const solid = swept.ToPtr<Schema_2x3::IfcExtrudedAreaSolid>()) {
@@ -741,8 +741,8 @@ void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept,
}
// ------------------------------------------------------------------------------------------------
bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo,
unsigned int matid,
bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo,
unsigned int matid,
std::set<unsigned int>& mesh_indices,
ConversionData& conv) {
bool fix_orientation = false;
@@ -841,7 +841,7 @@ void AssignAddedMeshes(std::set<unsigned int>& mesh_indices,aiNode* nd, Conversi
// ------------------------------------------------------------------------------------------------
bool TryQueryMeshCache(const Schema_2x3::IfcRepresentationItem& item,
std::set<unsigned int>& mesh_indices,
std::set<unsigned int>& mesh_indices,
unsigned int mat_index,
ConversionData& conv) {
ConversionData::MeshCacheIndex idx(&item, mat_index);
@@ -855,7 +855,7 @@ bool TryQueryMeshCache(const Schema_2x3::IfcRepresentationItem& item,
// ------------------------------------------------------------------------------------------------
void PopulateMeshCache(const Schema_2x3::IfcRepresentationItem& item,
const std::set<unsigned int>& mesh_indices,
const std::set<unsigned int>& mesh_indices,
unsigned int mat_index,
ConversionData& conv) {
ConversionData::MeshCacheIndex idx(&item, mat_index);
@@ -863,7 +863,7 @@ void PopulateMeshCache(const Schema_2x3::IfcRepresentationItem& item,
}
// ------------------------------------------------------------------------------------------------
bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item,
bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item,
unsigned int matid,
std::set<unsigned int>& mesh_indices,
ConversionData& conv) {
+7 -5
View File
@@ -245,11 +245,11 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// tell the reader for which types we need to simulate STEPs reverse indices
static const char *const inverse_indices_to_track[] = {
"ifcrelcontainedinspatialstructure",
"ifcrelaggregates",
"ifcrelvoidselement",
"ifcreldefinesbyproperties",
"ifcpropertyset",
"ifcrelcontainedinspatialstructure",
"ifcrelaggregates",
"ifcrelvoidselement",
"ifcreldefinesbyproperties",
"ifcpropertyset",
"ifcstyleditem"
};
@@ -260,6 +260,8 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
ThrowException("missing IfcProject entity");
}
ConversionData conv(*db, proj->To<Schema_2x3::IfcProject>(), pScene, settings);
SetUnits(conv);
SetCoordinateSpace(conv);
+1
View File
@@ -4,6 +4,7 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2025, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
+7 -7
View File
@@ -69,7 +69,7 @@ AI_FORCE_INLINE ulong64 to_int64(IfcFloat p) {
AI_FORCE_INLINE IfcFloat from_int64(ulong64 p) {
return (static_cast<IfcFloat>((p)) / max_ulong64);
}
}
AI_FORCE_INLINE void fillRectangle(const IfcVector2& pmin, const IfcVector2& pmax, std::vector<IfcVector2>& out) {
out.emplace_back(pmin.x, pmin.y);
@@ -176,7 +176,7 @@ struct ProjectedWindowContour {
SkipList skiplist;
bool is_rectangular;
ProjectedWindowContour(const Contour& contour, const BoundingBox& bb, bool is_rectangular)
ProjectedWindowContour(const Contour& contour, const BoundingBox& bb, bool is_rectangular)
: contour(contour), bb(bb) , is_rectangular(is_rectangular) {}
~ProjectedWindowContour() = default;
@@ -215,7 +215,7 @@ static bool IsDuplicateVertex(const IfcVector2& vv, const std::vector<IfcVector2
}
// ------------------------------------------------------------------------------------------------
void ExtractVerticesFromClipper(const ClipperLib::Path& poly, std::vector<IfcVector2>& temp_contour,
void ExtractVerticesFromClipper(const ClipperLib::Path& poly, std::vector<IfcVector2>& temp_contour,
bool filter_duplicates = false) {
temp_contour.clear();
for(const ClipperLib::IntPoint& point : poly) {
@@ -362,7 +362,7 @@ void InsertWindowContours(const ContourVector& contours, const std::vector<TempO
}
// ------------------------------------------------------------------------------------------------
void MergeWindowContours (const std::vector<IfcVector2>& a, const std::vector<IfcVector2>& b,
void MergeWindowContours (const std::vector<IfcVector2>& a, const std::vector<IfcVector2>& b,
ClipperLib::Paths& out) {
out.clear();
@@ -988,16 +988,16 @@ void Quadrify(const ContourVector& contours, TempMesh& curmesh) {
}
// ------------------------------------------------------------------------------------------------
IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour,
IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour,
const TempMesh& in_mesh,
bool &ok,
bool &ok,
IfcVector3& nor_out) {
const std::vector<IfcVector3>& in_verts = in_mesh.mVerts;
if (in_verts.empty()){
ok = false;
return IfcMatrix4();
}
ok = true;
IfcMatrix4 m = IfcMatrix4(DerivePlaneCoordinateSpace(in_mesh, ok, nor_out));
if(!ok) {
+10 -10
View File
@@ -50,8 +50,8 @@ namespace Assimp {
namespace IFC {
// ------------------------------------------------------------------------------------------------
void ProcessPolyLine(const Schema_2x3::IfcPolyline& def,
TempMesh& meshout,
void ProcessPolyLine(const Schema_2x3::IfcPolyline& def,
TempMesh& meshout,
ConversionData& /*conv*/) {
// this won't produce a valid mesh, it just spits out a list of vertices
IfcVector3 t;
@@ -63,8 +63,8 @@ void ProcessPolyLine(const Schema_2x3::IfcPolyline& def,
}
// ------------------------------------------------------------------------------------------------
bool ProcessCurve(const Schema_2x3::IfcCurve& curve,
TempMesh& meshout,
bool ProcessCurve(const Schema_2x3::IfcCurve& curve,
TempMesh& meshout,
ConversionData& conv) {
std::unique_ptr<const Curve> cv(Curve::Convert(curve,conv));
if (!cv) {
@@ -90,22 +90,22 @@ bool ProcessCurve(const Schema_2x3::IfcCurve& curve,
}
// ------------------------------------------------------------------------------------------------
void ProcessClosedProfile(const Schema_2x3::IfcArbitraryClosedProfileDef& def,
TempMesh& meshout,
void ProcessClosedProfile(const Schema_2x3::IfcArbitraryClosedProfileDef& def,
TempMesh& meshout,
ConversionData& conv) {
ProcessCurve(def.OuterCurve,meshout,conv);
}
// ------------------------------------------------------------------------------------------------
void ProcessOpenProfile(const Schema_2x3::IfcArbitraryOpenProfileDef& def,
TempMesh& meshout,
void ProcessOpenProfile(const Schema_2x3::IfcArbitraryOpenProfileDef& def,
TempMesh& meshout,
ConversionData& conv) {
ProcessCurve(def.Curve,meshout,conv);
}
// ------------------------------------------------------------------------------------------------
void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& def,
TempMesh& meshout,
void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& def,
TempMesh& meshout,
ConversionData& conv) {
if(const Schema_2x3::IfcRectangleProfileDef* const cprofile = def.ToPtr<Schema_2x3::IfcRectangleProfileDef>()) {
const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
+3 -3
View File
@@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
#include "AssetLib/IFC/IFCUtil.h"
#include "Common/PolyTools.h"
#include "Geometry/GeometryUtils.h"
#include "PostProcessing/ProcessHelper.h"
@@ -375,7 +375,7 @@ void TempMesh::RemoveAdjacentDuplicates() {
ArrayBounds(&*base, cnt ,vmin,vmax);
const IfcFloat epsilon = (vmax-vmin).SquareLength() / static_cast<IfcFloat>(1e9);
// drop any identical, adjacent vertices. this pass will collect the dropouts
// of the previous pass as a side-effect.
FuzzyVectorCompare fz(epsilon);
@@ -461,7 +461,7 @@ void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourRgb& in) {
}
// ------------------------------------------------------------------------------------------------
void ConvertColor(aiColor4D& out,
void ConvertColor(aiColor4D& out,
const Schema_2x3::IfcColourOrFactor& in,
ConversionData& conv,
const aiColor4D* base) {
+3 -2
View File
@@ -4,6 +4,7 @@ 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,
@@ -46,8 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_IFCUTIL_H
#define INCLUDED_IFCUTIL_H
#include "IFCReaderGen_2x3.h"
#include "IFCLoader.h"
#include "AssetLib/IFC/IFCReaderGen_2x3.h"
#include "AssetLib/IFC/IFCLoader.h"
#include "AssetLib/Step/STEPFile.h"
#include <assimp/mesh.h>
+1 -1
View File
@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "assimp/StringComparison.h"
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
#include "IRRLoader.h"
#include "AssetLib/Irr/IRRLoader.h"
#include "Common/Importer.h"
#include <assimp/GenericProperty.h>
+1 -1
View File
@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_IRRLOADER_H_INCLUDED
#define AI_IRRLOADER_H_INCLUDED
#include "IRRShared.h"
#include "AssetLib/Irr/IRRShared.h"
#include "Common/Importer.h"
#include <assimp/SceneCombiner.h>
+2 -2
View File
@@ -322,7 +322,7 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
// NOTE this might explode for UTF-16 and wchars
const char *sz = indicesNode.text().get();
const char *end = sz + std::strlen(sz);
// For each index loop over aiMesh faces
while (SkipSpacesAndLineEnd(&sz, end)) {
if (curFace >= faceEnd) {
@@ -380,7 +380,7 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
aiMaterial *mat = (aiMaterial *)curMat;
mat->AddProperty(&curColors[0].a, 1, AI_MATKEY_OPACITY);
}
// end of previous buffer. A material and a mesh should be there
if (!curMat || !curMesh) {
ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material");
+1
View File
@@ -4,6 +4,7 @@ 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,
+1 -1
View File
@@ -78,7 +78,7 @@ void LWOImporter::LoadLWOBFile() {
else
LoadLWOBPolygons(head.length);
} break;
case AI_LWO_SRFS: // list of tags
{
if (!mTags->empty())
+2 -2
View File
@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
// internal headers
#include "LWOLoader.h"
#include "AssetLib/LWO/LWOLoader.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include "PostProcessing/ProcessHelper.h"
#include "Geometry/GeometryUtils.h"
@@ -104,7 +104,7 @@ LWOImporter::~LWOImporter() = default;
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool LWOImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const {
static constexpr uint32_t tokens[] = {
static const uint32_t tokens[] = {
AI_LWO_FOURCC_LWOB,
AI_LWO_FOURCC_LWO2,
AI_LWO_FOURCC_LXOB
+1
View File
@@ -4,6 +4,7 @@ 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,
+4 -4
View File
@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
#include "LWSLoader.h"
#include "AssetLib/LWS/LWSLoader.h"
#include "Common/Importer.h"
#include "PostProcessing/ConvertToLHProcess.h"
@@ -149,7 +149,7 @@ LWSImporter::LWSImporter() :
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static constexpr uint32_t tokens[] = {
static const uint32_t tokens[] = {
AI_MAKE_MAGIC("LWSC"),
AI_MAKE_MAGIC("LWMO")
};
@@ -255,7 +255,7 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
// ------------------------------------------------------------------------------------------------
// Read animation channels in the old LightWave animation format
void LWSImporter::ReadEnvelope_Old(std::list<LWS::Element>::const_iterator &it,const std::list<LWS::Element>::const_iterator &endIt,
void LWSImporter::ReadEnvelope_Old(std::list<LWS::Element>::const_iterator &it,const std::list<LWS::Element>::const_iterator &endIt,
LWS::NodeDesc &nodes, unsigned int) {
if (++it == endIt) {
ASSIMP_LOG_ERROR("LWS: Encountered unexpected end of file while parsing object motion");
@@ -274,7 +274,7 @@ void LWSImporter::ReadEnvelope_Old(std::list<LWS::Element>::const_iterator &it,c
ASSIMP_LOG_ERROR("LWS: Encountered unexpected end of file while parsing object motion");
return;
}
const unsigned int sub_num = strtoul10((*it).tokens[0].c_str());
for (unsigned int n = 0; n < sub_num; ++n) {
if (++it == endIt) {
+3 -2
View File
@@ -4,6 +4,7 @@ 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,
@@ -51,8 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Compiler/pushpack1.h>
namespace Assimp {
namespace MD2 {
namespace Assimp {
namespace MD2 {
// to make it easier for us, we test the magic word against both "endiannesses"
#define AI_MD2_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP2")
+4 -10
View File
@@ -101,7 +101,7 @@ MD2Importer::MD2Importer()
// Returns whether the class can handle the format of the given file.
bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const
{
static constexpr uint32_t tokens[] = { AI_MD2_MAGIC_NUMBER_LE };
static const uint32_t tokens[] = { AI_MD2_MAGIC_NUMBER_LE };
return CheckMagicToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens));
}
@@ -319,22 +319,16 @@ void MD2Importer::InternReadFile( const std::string& pFile,
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
const ai_uint32 MaxNameLength = AI_MAXLEN - 1; // one byte reserved for \0
ai_uint32 iLen = static_cast<ai_uint32>(::strlen(pcSkins->name));
bool nameTooLong = iLen > MaxNameLength;
if (pcSkins->name[0] && !nameTooLong)
if (pcSkins->name[0])
{
aiString szString;
::memcpy(szString.data, pcSkins->name, iLen);
const ai_uint32 iLen = (ai_uint32) ::strlen(pcSkins->name);
::memcpy(szString.data,pcSkins->name,iLen);
szString.data[iLen] = '\0';
szString.length = iLen;
pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else if (nameTooLong) {
ASSIMP_LOG_WARN("Texture file name is too long. It will be skipped.");
}
else{
ASSIMP_LOG_WARN("Texture file name has zero length. It will be skipped.");
}
+1
View File
@@ -4,6 +4,7 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2025, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
+2 -1
View File
@@ -4,6 +4,7 @@ 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,
@@ -59,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Compiler/pushpack1.h>
namespace Assimp {
namespace MD3 {
namespace MD3 {
// to make it easier for us, we test the magic word against both "endiannesses"
#define AI_MD3_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP3")
+4 -2
View File
@@ -5,6 +5,8 @@ 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,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
#include "MD3Loader.h"
#include "AssetLib/MD3/MD3Loader.h"
#include "Common/Importer.h"
#include <assimp/GenericProperty.h>
@@ -350,7 +352,7 @@ MD3Importer::~MD3Importer() = default;
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MD3Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static constexpr uint32_t tokens[] = { AI_MD3_MAGIC_NUMBER_LE };
static const uint32_t tokens[] = { AI_MD3_MAGIC_NUMBER_LE };
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
+4 -4
View File
@@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// internal headers
#include "MD5Loader.h"
#include "AssetLib/MD5/MD5Loader.h"
#include "Material/MaterialSystem.h"
#include <assimp/ParsingUtils.h>
@@ -127,7 +127,7 @@ void MD5Parser::ParseHeader() {
if (buffer == bufferEnd) {
return;
}
ASSIMP_LOG_INFO(std::string(sz, std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer - sz))));
SkipSpacesAndLineEnd();
}
@@ -291,7 +291,7 @@ inline void AI_MD5_PARSE_STRING_IN_QUOTATION(const char **sz, const char *buffer
}
if ('\0' != **sz) {
const char *szStart = ++(*sz);
while (('\"' != **sz && '\0' != **sz) && *sz != bufferEnd) {
++*sz;
}
@@ -324,7 +324,7 @@ MD5MeshParser::MD5MeshParser(SectionArray &mSections) {
const char *sz = elem.szStart;
AI_MD5_PARSE_STRING_IN_QUOTATION(&sz, elem.end, desc.mName);
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
// negative values, at least -1, is allowed here
+1 -1
View File
@@ -422,7 +422,7 @@ inline bool MD5Parser::SkipSpacesAndLineEnd( const char* in, const char** out) {
*out = in;
return false;
}
bool bHad = false, running = true;
while (running) {
if( *in == '\r' || *in == '\n') {
+1
View File
@@ -4,6 +4,7 @@ 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,
+3 -3
View File
@@ -44,9 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
// internal headers
#include "MDCLoader.h"
#include "AssetLib/MDC/MDCLoader.h"
#include "AssetLib/MD3/MD3FileData.h"
#include "MDCNormalTable.h" // shouldn't be included by other units
#include "AssetLib/MDC/MDCNormalTable.h" // shouldn't be included by other units
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
@@ -106,7 +106,7 @@ MDCImporter::MDCImporter() :
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static constexpr uint32_t tokens[] = { AI_MDC_MAGIC_NUMBER_LE };
static const uint32_t tokens[] = { AI_MDC_MAGIC_NUMBER_LE };
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
+1
View File
@@ -4,6 +4,7 @@ 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,
+1
View File
@@ -4,6 +4,7 @@ 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,
+4 -3
View File
@@ -4,6 +4,7 @@ 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,
@@ -62,8 +63,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiMaterial;
namespace Assimp {
namespace MDL {
namespace Assimp {
namespace MDL {
// -------------------------------------------------------------------------------------
// to make it easier for us, we test the magic word against both "endiannesses"
@@ -602,7 +603,7 @@ struct Vertex_MDL7
union {
uint8_t norm162index;
float norm[3];
} PACK_STRUCT;
};
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
+6 -6
View File
@@ -48,10 +48,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
#include "MDLLoader.h"
#include "AssetLib/MDL/MDLLoader.h"
#include "AssetLib/MD2/MD2FileData.h"
#include "HalfLife/HL1MDLLoader.h"
#include "MDLDefaultColorMap.h"
#include "AssetLib/MDL/HalfLife/HL1MDLLoader.h"
#include "AssetLib/MDL/MDLDefaultColorMap.h"
#include <assimp/StringUtils.h>
#include <assimp/importerdesc.h>
@@ -268,8 +268,8 @@ void MDLImporter::InternReadFile(const std::string &pFile,
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(
1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f);
}
@@ -420,7 +420,7 @@ void MDLImporter::InternReadFile_Quake1() {
}
// go to the end of the skin section / the beginning of the next skin
bool overflow = false;
if (pcHeader->skinwidth != 0 && pcHeader->skinheight != 0) {
if (pcHeader->skinwidth != 0 || pcHeader->skinheight != 0) {
if ((pcHeader->skinheight > INT_MAX / pcHeader->skinwidth) || (pcHeader->skinwidth > INT_MAX / pcHeader->skinheight)){
overflow = true;
}
+1 -1
View File
@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h>
#include "MDLFileData.h"
#include "AssetLib/HMP/HalfLifeFileData.h"
#include "HalfLife/HL1ImportSettings.h"
#include "AssetLib/MDL/HalfLife/HL1ImportSettings.h"
struct aiNode;
struct aiTexture;
-7
View File
@@ -209,8 +209,6 @@ void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char *szData,
return;
}
static const uint32_t MaxTextureSize = 4096;
// ------------------------------------------------------------------------------------------------
// Load color data of a texture and convert it to our output format
void MDLImporter::ParseTextureColorData(const unsigned char *szData,
@@ -221,11 +219,6 @@ void MDLImporter::ParseTextureColorData(const unsigned char *szData,
// allocate storage for the texture image
if (do_read) {
// check for max texture sizes
if (pcNew->mWidth > MaxTextureSize || pcNew->mHeight > MaxTextureSize) {
throw DeadlyImportError("Invalid MDL file. A texture is too big.");
}
if(pcNew->mWidth != 0 && pcNew->mHeight > UINT_MAX/pcNew->mWidth) {
throw DeadlyImportError("Invalid MDL file. A texture is too big.");
}
+1
View File
@@ -4,6 +4,7 @@ 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,
+4 -4
View File
@@ -41,10 +41,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
#include "MMDImporter.h"
#include "MMDPmdParser.h"
#include "MMDPmxParser.h"
#include "MMDVmdParser.h"
#include "AssetLib/MMD/MMDImporter.h"
#include "AssetLib/MMD/MMDPmdParser.h"
#include "AssetLib/MMD/MMDPmxParser.h"
#include "AssetLib/MMD/MMDVmdParser.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include <assimp/DefaultIOSystem.h>
+1
View File
@@ -4,6 +4,7 @@ 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,
+1
View File
@@ -4,6 +4,7 @@ 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,

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