Compare commits

..

3 Commits

Author SHA1 Message Date
Kim Kulling 25759eaffa
Update USDLoader.h
Fix review finding,
2024-07-18 21:06:03 +02:00
Kim Kulling 6362f86a7c
Update USDLoader.cpp
Fix review finding
2024-07-18 21:05:02 +02:00
Kim Kulling a52aabaf67
Merge branch 'master' into kimkulling/introduce_anim_interpolation_mode 2024-07-18 19:11:58 +02:00
70 changed files with 561 additions and 1456 deletions

View File

@ -7,10 +7,10 @@ on:
branches: [ master ] branches: [ master ]
permissions: permissions:
contents: write # to fetch code (actions/checkout),and release contents: read # to fetch code (actions/checkout)
jobs: jobs:
build: job:
name: ${{ matrix.name }}-build-and-test name: ${{ matrix.name }}-build-and-test
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
@ -37,9 +37,6 @@ jobs:
cc: gcc cc: gcc
steps: steps:
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
submodules: true submodules: true
@ -73,12 +70,12 @@ jobs:
- name: Set Windows specific CMake arguments - name: Set Windows specific CMake arguments
if: contains(matrix.name, 'windows') if: contains(matrix.name, 'windows')
id: windows_extra_cmake_args id: windows_extra_cmake_args
run: echo ":set-output name=args::=-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1" >> $GITHUB_OUTPUT run: echo "::set-output name=args::-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1 -DASSIMP_BUILD_ZLIB=1"
- name: Set Hunter specific CMake arguments - name: Set Hunter specific CMake arguments
if: contains(matrix.name, 'hunter') if: contains(matrix.name, 'hunter')
id: hunter_extra_cmake_args id: hunter_extra_cmake_args
run: echo "args=-DBUILD_SHARED_LIBS=OFF -DASSIMP_HUNTER_ENABLED=ON -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/cmake/polly/${{ matrix.toolchain }}.cmake" >> $GITHUB_OUTPUT run: echo "::set-output name=args::-DBUILD_SHARED_LIBS=OFF -DASSIMP_HUNTER_ENABLED=ON -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/cmake/polly/${{ matrix.toolchain }}.cmake"
- name: configure and build - name: configure and build
uses: lukka/run-cmake@v3 uses: lukka/run-cmake@v3
@ -95,7 +92,7 @@ jobs:
- name: Exclude certain tests in Hunter specific builds - name: Exclude certain tests in Hunter specific builds
if: contains(matrix.name, 'hunter') if: contains(matrix.name, 'hunter')
id: hunter_extra_test_args id: hunter_extra_test_args
run: echo "args=--gtest_filter=-utOpenGEXImportExport.Importissue1340_EmptyCameraObject:utColladaZaeImportExport.importBlenFromFileTest" >> $GITHUB_OUTPUT run: echo "::set-output name=args::--gtest_filter=-utOpenGEXImportExport.Importissue1340_EmptyCameraObject:utColladaZaeImportExport.importBlenFromFileTest"
- name: test - name: test
run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }} run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }}
@ -104,89 +101,5 @@ jobs:
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
if: matrix.name == 'windows-msvc' if: matrix.name == 'windows-msvc'
with: with:
name: 'assimp-bins-${{ matrix.name }}' name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'
path: build/bin/assimp*.exe path: build/bin
- uses: marvinpinto/action-automatic-releases@latest
if: contains(matrix.name, 'windows-msvc-hunter')
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "master"
prerelease: true
title: "AutoRelease"
files: |
build/bin/assimp*.exe
create-release:
needs: [build]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- id: create-release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: '${{secrets.GITHUB_TOKEN}}'
with:
tag_name: '${{github.ref}}'
release_name: 'Release ${{github.ref}}'
draft: false
prerelease: true
- run: |
echo '${{steps.create-release.outputs.upload_url}}' > release_upload_url.txt
- uses: actions/upload-artifact@v4
with:
name: create-release
path: release_upload_url.txt
upload-release:
strategy:
matrix:
name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++, ubuntu-gcc-hunter, macos-clang-hunter, windows-msvc-hunter]
# For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
include:
- name: windows-latest-cl.exe
os: windows-latest
cxx: cl.exe
cc: cl.exe
- name: ubuntu-latest-clang++
os: ubuntu-latest
cxx: clang++
cc: clang
- name: macos-latest-clang++
os: macos-latest
cxx: clang++
cc: clang
- name: ubuntu-latest-g++
os: ubuntu-latest
cxx: g++
cc: gcc
- name: ubuntu-gcc-hunter
os: ubuntu-latest
toolchain: ninja-gcc-cxx17-fpic
- name: macos-clang-hunter
os: macos-latest
toolchain: ninja-clang-cxx17-fpic
- name: windows-msvc-hunter
os: windows-latest
toolchain: ninja-vs-win64-cxx17
needs: [create-release]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- uses: softprops/action-gh-release@v2
with:
name: create-release
- id: upload-url
run: |
echo "url=$(cat create-release/release_upload_url.txt)" >> $GITHUB_OUTPUT
- uses: actions/download-artifact@v4
with:
name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'
- uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: '${{secrets.GITHUB_TOKEN}}'
with:
files: |
*.zip

View File

@ -46,15 +46,6 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.22 )
# auto-cloned during build; so MUST disable the feature or the PR will be rejected # auto-cloned during build; so MUST disable the feature or the PR will be rejected
option(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off) option(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off)
option(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off) option(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off)
option(ASSIMP_BUILD_USE_CCACHE "Use ccache to speed up compilation." on)
if(ASSIMP_BUILD_USE_CCACHE)
find_program(CCACHE_PATH ccache)
if (CCACHE_PATH)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH})
endif()
endif()
# Disabled importers: m3d for 5.1 or later # Disabled importers: m3d for 5.1 or later
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER)
@ -71,7 +62,7 @@ IF(ASSIMP_HUNTER_ENABLED)
add_definitions(-DASSIMP_USE_HUNTER) add_definitions(-DASSIMP_USE_HUNTER)
ENDIF() ENDIF()
PROJECT(Assimp VERSION 5.4.3) PROJECT(Assimp VERSION 5.4.1)
# All supported options ############################################### # All supported options ###############################################
@ -163,7 +154,7 @@ IF (WIN32)
IF(MSVC) IF(MSVC)
OPTION( ASSIMP_INSTALL_PDB OPTION( ASSIMP_INSTALL_PDB
"Create MSVC debug symbol files and add to Install target." "Install MSVC debug files."
ON ) ON )
IF(NOT (MSVC_VERSION LESS 1900)) IF(NOT (MSVC_VERSION LESS 1900))
# Multibyte character set has been deprecated since at least MSVC2015 (possibly earlier) # Multibyte character set has been deprecated since at least MSVC2015 (possibly earlier)
@ -308,15 +299,8 @@ ELSEIF(MSVC)
# supress warning for double to float conversion if Double precision is activated # supress warning for double to float conversion if Double precision is activated
ADD_COMPILE_OPTIONS(/wd4244) ADD_COMPILE_OPTIONS(/wd4244)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
# Allow user to disable PDBs SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
if(ASSIMP_INSTALL_PDB) SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
elseif((GENERATOR_IS_MULTI_CONFIG) OR (CMAKE_BUILD_TYPE MATCHES Release))
message("-- MSVC PDB generation disabled. Release binary will not be debuggable.")
endif()
# Source code is encoded in UTF-8
ADD_COMPILE_OPTIONS(/source-charset:utf-8)
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON) SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
@ -659,7 +643,7 @@ ELSE()
IF ( ASSIMP_BUILD_DRACO ) IF ( ASSIMP_BUILD_DRACO )
# Primarily for glTF v2 # Primarily for glTF v2
# Enable Draco glTF feature set # Enable Draco glTF feature set
set(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE) set(DRACO_GLTF ON CACHE BOOL "" FORCE)
# Disable unnecessary or omitted components # Disable unnecessary or omitted components
set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE) set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
set(DRACO_WASM OFF CACHE BOOL "" FORCE) set(DRACO_WASM OFF CACHE BOOL "" FORCE)

View File

@ -643,17 +643,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
} }
// Allocate storage for children // Allocate storage for children
const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size()); pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
pcOut->mNumChildren = size;
if (size == 0) {
return;
}
pcOut->mChildren = new aiNode *[pcIn->mChildren.size()]; pcOut->mChildren = new aiNode *[pcIn->mChildren.size()];
// Recursively process all children // Recursively process all children
const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
for (unsigned int i = 0; i < size; ++i) { for (unsigned int i = 0; i < size; ++i) {
pcOut->mChildren[i] = new aiNode(); pcOut->mChildren[i] = new aiNode();
pcOut->mChildren[i]->mParent = pcOut; pcOut->mChildren[i]->mParent = pcOut;

View File

@ -52,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/Exporter.hpp> #include <assimp/Exporter.hpp>
#include <assimp/Exceptional.h>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <memory> #include <memory>

View File

@ -249,10 +249,10 @@ void D3MFExporter::writeBaseMaterials() {
if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) { if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) {
hexDiffuseColor = ai_rgba2hex( hexDiffuseColor = ai_rgba2hex(
(int)(((ai_real)color.r) * 255), (int)((ai_real)color.r) * 255,
(int)(((ai_real)color.g) * 255), (int)((ai_real)color.g) * 255,
(int)(((ai_real)color.b) * 255), (int)((ai_real)color.b) * 255,
(int)(((ai_real)color.a) * 255), (int)((ai_real)color.a) * 255,
true); true);
} else { } else {

View File

@ -372,11 +372,9 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
} }
// add children recursively // add children recursively
if (!root.temp_children.empty()) { nd->mChildren = new aiNode *[root.temp_children.size()]();
nd->mChildren = new aiNode *[root.temp_children.size()](); for (const Node *n : root.temp_children) {
for (const Node *n : root.temp_children) { (nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd;
(nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd;
}
} }
return nd; return nd;

View File

@ -181,9 +181,7 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
if (out->mNumMeshes == 0) { if (out->mNumMeshes == 0) {
out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
} else { } else {
// Apply the FBX axis metadata unless requested not to correctRootTransform(mSceneOut);
if (!doc.Settings().ignoreUpDirection)
correctRootTransform(mSceneOut);
} }
} }
@ -312,8 +310,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
child->mParent = last_parent; child->mParent = last_parent;
last_parent = child.mNode; last_parent = child.mNode;
new_abs_transform *= child->mTransformation;
} }
// attach geometry // attach geometry
@ -336,8 +332,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
postnode->mParent = last_parent; postnode->mParent = last_parent;
last_parent = postnode.mNode; last_parent = postnode.mNode;
new_abs_transform *= postnode->mTransformation;
} }
} else { } else {
// free the nodes we allocated as we don't need them // free the nodes we allocated as we don't need them
@ -363,12 +357,12 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
if (nodes.empty()) { if (nodes.empty()) {
parent->mNumChildren = 0; parent->mNumChildren = 0;
parent->mChildren = nullptr; parent->mChildren = nullptr;
} else { }
parent->mChildren = new aiNode *[nodes.size()]();
parent->mNumChildren = static_cast<unsigned int>(nodes.size()); parent->mChildren = new aiNode *[nodes.size()]();
for (unsigned int i = 0; i < nodes.size(); ++i) { parent->mNumChildren = static_cast<unsigned int>(nodes.size());
parent->mChildren[i] = nodes[i].mOwnership.release(); for (unsigned int i = 0; i < nodes.size(); ++i) {
} parent->mChildren[i] = nodes[i].mOwnership.release();
} }
} }
@ -2134,10 +2128,6 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_
TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor", aiTextureType_EMISSION_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor", aiTextureType_EMISSION_COLOR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|metalness", aiTextureType_METALNESS, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|metalness", aiTextureType_METALNESS, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness", aiTextureType_DIFFUSE_ROUGHNESS, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|base", aiTextureType_MAYA_BASE, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|specular", aiTextureType_MAYA_SPECULAR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|specularColor", aiTextureType_MAYA_SPECULAR_COLOR, mesh);
TrySetTextureProperties(out_mat, _textures, "Maya|specularRoughness", aiTextureType_MAYA_SPECULAR_ROUGHNESS, mesh);
// Maya stingray // Maya stingray
TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map", aiTextureType_BASE_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map", aiTextureType_BASE_COLOR, mesh);

View File

@ -1217,8 +1217,10 @@ void FBXExporter::WriteObjects ()
} }
// colors, if any // colors, if any
for (size_t ci = 0; ci < m->GetNumColorChannels(); ++ci) { // TODO only one color channel currently
FBX::Node vertexcolors("LayerElementColor", int32_t(ci)); const int32_t colorChannelIndex = 0;
if (m->HasVertexColors(colorChannelIndex)) {
FBX::Node vertexcolors("LayerElementColor", int32_t(colorChannelIndex));
vertexcolors.Begin(outstream, binary, indent); vertexcolors.Begin(outstream, binary, indent);
vertexcolors.DumpProperties(outstream, binary, indent); vertexcolors.DumpProperties(outstream, binary, indent);
vertexcolors.EndProperties(outstream, binary, indent); vertexcolors.EndProperties(outstream, binary, indent);
@ -1228,7 +1230,7 @@ void FBXExporter::WriteObjects ()
"Version", int32_t(101), outstream, binary, indent "Version", int32_t(101), outstream, binary, indent
); );
char layerName[8]; char layerName[8];
snprintf(layerName, sizeof(layerName), "COLOR_%d", int32_t(ci)); snprintf(layerName, sizeof(layerName), "COLOR_%d", colorChannelIndex);
FBX::Node::WritePropertyNode( FBX::Node::WritePropertyNode(
"Name", (const char*)layerName, outstream, binary, indent "Name", (const char*)layerName, outstream, binary, indent
); );
@ -1245,7 +1247,7 @@ void FBXExporter::WriteObjects ()
for (size_t fi = 0; fi < m->mNumFaces; ++fi) { for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
const aiFace &f = m->mFaces[fi]; const aiFace &f = m->mFaces[fi];
for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
const aiColor4D &c = m->mColors[ci][f.mIndices[pvi]]; const aiColor4D &c = m->mColors[colorChannelIndex][f.mIndices[pvi]];
color_data.push_back(c.r); color_data.push_back(c.r);
color_data.push_back(c.g); color_data.push_back(c.g);
color_data.push_back(c.b); color_data.push_back(c.b);
@ -1352,14 +1354,11 @@ void FBXExporter::WriteObjects ()
le.AddChild("Type", "LayerElementNormal"); le.AddChild("Type", "LayerElementNormal");
le.AddChild("TypedIndex", int32_t(0)); le.AddChild("TypedIndex", int32_t(0));
layer.AddChild(le); layer.AddChild(le);
// TODO only 1 color channel currently
for (size_t ci = 0; ci < m->GetNumColorChannels(); ++ci) { le = FBX::Node("LayerElement");
le = FBX::Node("LayerElement"); le.AddChild("Type", "LayerElementColor");
le.AddChild("Type", "LayerElementColor"); le.AddChild("TypedIndex", int32_t(0));
le.AddChild("TypedIndex", int32_t(ci)); layer.AddChild(le);
layer.AddChild(le);
}
le = FBX::Node("LayerElement"); le = FBX::Node("LayerElement");
le.AddChild("Type", "LayerElementMaterial"); le.AddChild("Type", "LayerElementMaterial");
le.AddChild("TypedIndex", int32_t(0)); le.AddChild("TypedIndex", int32_t(0));
@ -2487,57 +2486,6 @@ const std::map<std::string,std::pair<std::string,char>> transform_types = {
{"GeometricScalingInverse", {"GeometricScalingInverse", 'i'}} {"GeometricScalingInverse", {"GeometricScalingInverse", 'i'}}
}; };
//add metadata to fbx property
void add_meta(FBX::Node& fbx_node, const aiNode* node){
if(node->mMetaData == nullptr) return;
aiMetadata* meta = node->mMetaData;
for (unsigned int i = 0; i < meta->mNumProperties; ++i) {
aiString key = meta->mKeys[i];
aiMetadataEntry* entry = &meta->mValues[i];
switch (entry->mType) {
case AI_BOOL:{
bool val = *static_cast<bool *>(entry->mData);
fbx_node.AddP70bool(key.C_Str(), val);
break;
}
case AI_INT32:{
int32_t val = *static_cast<int32_t *>(entry->mData);
fbx_node.AddP70int(key.C_Str(), val);
break;
}
case AI_UINT64:{
//use string to add uint64
uint64_t val = *static_cast<uint64_t *>(entry->mData);
fbx_node.AddP70string(key.C_Str(), std::to_string(val).c_str());
break;
}
case AI_FLOAT:{
float val = *static_cast<float *>(entry->mData);
fbx_node.AddP70double(key.C_Str(), val);
break;
}
case AI_DOUBLE:{
double val = *static_cast<double *>(entry->mData);
fbx_node.AddP70double(key.C_Str(), val);
break;
}
case AI_AISTRING:{
aiString val = *static_cast<aiString *>(entry->mData);
fbx_node.AddP70string(key.C_Str(), val.C_Str());
break;
}
case AI_AIMETADATA: {
//ignore
break;
}
default:
break;
}
}
}
// write a single model node to the stream // write a single model node to the stream
void FBXExporter::WriteModelNode( void FBXExporter::WriteModelNode(
StreamWriterLE& outstream, StreamWriterLE& outstream,
@ -2605,7 +2553,6 @@ void FBXExporter::WriteModelNode(
} }
} }
} }
add_meta(p, node);
m.AddChild(p); m.AddChild(p);
// not sure what these are for, // not sure what these are for,

View File

@ -156,9 +156,6 @@ struct ImportSettings {
/** Set to true to perform a conversion from cm to meter after the import /** Set to true to perform a conversion from cm to meter after the import
*/ */
bool convertToMeters; bool convertToMeters;
// Set to true to ignore the axis configuration in the file
bool ignoreUpDirection = false;
}; };
} // namespace FBX } // namespace FBX

View File

@ -117,7 +117,6 @@ void FBXImporter::SetupProperties(const Importer *pImp) {
mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false); mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true); mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
mSettings.ignoreUpDirection = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION, false);
mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false); mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false);
} }

View File

@ -78,15 +78,7 @@ static constexpr aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursive parsing of LWS files // Recursive parsing of LWS files
namespace { void LWS::Element::Parse(const char *&buffer, const char *end) {
constexpr int MAX_DEPTH = 1000; // Define the maximum depth allowed
}
void LWS::Element::Parse(const char *&buffer, const char *end, int depth) {
if (depth > MAX_DEPTH) {
throw std::runtime_error("Maximum recursion depth exceeded in LWS::Element::Parse");
}
for (; SkipSpacesAndLineEnd(&buffer, end); SkipLine(&buffer, end)) { for (; SkipSpacesAndLineEnd(&buffer, end); SkipLine(&buffer, end)) {
// begin of a new element with children // begin of a new element with children
@ -129,7 +121,7 @@ void LWS::Element::Parse(const char *&buffer, const char *end, int depth) {
// parse more elements recursively // parse more elements recursively
if (sub) { if (sub) {
children.back().Parse(buffer, end, depth + 1); children.back().Parse(buffer, end);
} }
} }
} }

View File

@ -76,7 +76,7 @@ public:
std::list<Element> children; std::list<Element> children;
//! Recursive parsing function //! Recursive parsing function
void Parse(const char *&buffer, const char *end, int depth = 0); void Parse(const char *&buffer, const char *end);
}; };
#define AI_LWS_MASK (0xffffffff >> 4u) #define AI_LWS_MASK (0xffffffff >> 4u)

View File

@ -724,7 +724,6 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
std::vector<unsigned char> mBuffer2(fileSize); std::vector<unsigned char> mBuffer2(fileSize);
file->Read(&mBuffer2[0], 1, fileSize); file->Read(&mBuffer2[0], 1, fileSize);
mBuffer = &mBuffer2[0]; mBuffer = &mBuffer2[0];
const unsigned char* bufferEnd = mBuffer + fileSize;
pcHeader = (BE_NCONST MD3::Header *)mBuffer; pcHeader = (BE_NCONST MD3::Header *)mBuffer;
@ -750,15 +749,9 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Navigate to the list of surfaces // Navigate to the list of surfaces
BE_NCONST MD3::Surface *pcSurfaces = (BE_NCONST MD3::Surface *)(mBuffer + pcHeader->OFS_SURFACES); BE_NCONST MD3::Surface *pcSurfaces = (BE_NCONST MD3::Surface *)(mBuffer + pcHeader->OFS_SURFACES);
if ((const unsigned char*)pcSurfaces + sizeof(MD3::Surface) * pcHeader->NUM_SURFACES > bufferEnd) {
throw DeadlyImportError("MD3 surface headers are outside the file");
}
// Navigate to the list of tags // Navigate to the list of tags
BE_NCONST MD3::Tag *pcTags = (BE_NCONST MD3::Tag *)(mBuffer + pcHeader->OFS_TAGS); BE_NCONST MD3::Tag *pcTags = (BE_NCONST MD3::Tag *)(mBuffer + pcHeader->OFS_TAGS);
if ((const unsigned char*)pcTags + sizeof(MD3::Tag) * pcHeader->NUM_TAGS > bufferEnd) {
throw DeadlyImportError("MD3 tags are outside the file");
}
// Allocate output storage // Allocate output storage
pScene->mNumMeshes = pcHeader->NUM_SURFACES; pScene->mNumMeshes = pcHeader->NUM_SURFACES;
@ -1033,10 +1026,6 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
for (unsigned int i = 0; i < pcHeader->NUM_TAGS; ++i, ++pcTags) { for (unsigned int i = 0; i < pcHeader->NUM_TAGS; ++i, ++pcTags) {
aiNode *nd = pScene->mRootNode->mChildren[i] = new aiNode(); aiNode *nd = pScene->mRootNode->mChildren[i] = new aiNode();
if ((const unsigned char*)pcTags + sizeof(MD3::Tag) > bufferEnd) {
throw DeadlyImportError("MD3 tag is outside the file");
}
nd->mName.Set((const char *)pcTags->NAME); nd->mName.Set((const char *)pcTags->NAME);
nd->mParent = pScene->mRootNode; nd->mParent = pScene->mRootNode;

View File

@ -63,8 +63,7 @@ struct HL1ImportSettings {
read_bone_controllers(false), read_bone_controllers(false),
read_hitboxes(false), read_hitboxes(false),
read_textures(false), read_textures(false),
read_misc_global_info(false), read_misc_global_info(false) {
transform_coord_system(true) {
} }
bool read_animations; bool read_animations;
@ -77,7 +76,6 @@ struct HL1ImportSettings {
bool read_hitboxes; bool read_hitboxes;
bool read_textures; bool read_textures;
bool read_misc_global_info; bool read_misc_global_info;
bool transform_coord_system;
}; };
} // namespace HalfLife } // namespace HalfLife

View File

@ -99,7 +99,7 @@ MDLImporter::MDLImporter() :
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static constexpr uint32_t tokens[] = { static const uint32_t tokens[] = {
AI_MDL_MAGIC_NUMBER_LE_HL2a, AI_MDL_MAGIC_NUMBER_LE_HL2a,
AI_MDL_MAGIC_NUMBER_LE_HL2b, AI_MDL_MAGIC_NUMBER_LE_HL2b,
AI_MDL_MAGIC_NUMBER_LE_GS7, AI_MDL_MAGIC_NUMBER_LE_GS7,
@ -138,7 +138,6 @@ void MDLImporter::SetupProperties(const Importer *pImp) {
mHL1ImportSettings.read_bone_controllers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_BONE_CONTROLLERS, true); mHL1ImportSettings.read_bone_controllers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_BONE_CONTROLLERS, true);
mHL1ImportSettings.read_hitboxes = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_HITBOXES, true); mHL1ImportSettings.read_hitboxes = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_HITBOXES, true);
mHL1ImportSettings.read_misc_global_info = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_MISC_GLOBAL_INFO, true); mHL1ImportSettings.read_misc_global_info = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_MISC_GLOBAL_INFO, true);
mHL1ImportSettings.transform_coord_system = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_TRANSFORM_COORD_SYSTEM);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -147,20 +146,6 @@ const aiImporterDesc *MDLImporter::GetInfo() const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------
static void transformCoordinateSystem(const aiScene *pScene) {
if (pScene == nullptr) {
return;
}
pScene->mRootNode->mTransformation = aiMatrix4x4(
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
-1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f
);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void MDLImporter::InternReadFile(const std::string &pFile, void MDLImporter::InternReadFile(const std::string &pFile,
@ -261,16 +246,18 @@ void MDLImporter::InternReadFile(const std::string &pFile,
". Magic word (", ai_str_toprintable((const char *)&iMagicWord, sizeof(iMagicWord)), ") is not known"); ". Magic word (", ai_str_toprintable((const char *)&iMagicWord, sizeof(iMagicWord)), ") is not known");
} }
if (is_half_life && mHL1ImportSettings.transform_coord_system) { if (is_half_life){
// Now rotate the whole scene 90 degrees around the z and x axes to convert to internal coordinate system // Now rotate the whole scene 90 degrees around the z and x axes to convert to internal coordinate system
transformCoordinateSystem(pScene);
} else {
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4( pScene->mRootNode->mTransformation = aiMatrix4x4(
1.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f,
0.f, -1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f); 0.f, 0.f, 0.f, 1.f);
}
else {
// 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, 0.f, 1.f);
} }
DeleteBufferAndCleanup(); DeleteBufferAndCleanup();

View File

@ -730,12 +730,10 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
// if an ASCII effect description (HLSL?) is contained in the file, // if an ASCII effect description (HLSL?) is contained in the file,
// we can simply ignore it ... // we can simply ignore it ...
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) { if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) {
VALIDATE_FILE_SIZE(szCurrent + sizeof(int32_t));
int32_t iMe = 0; int32_t iMe = 0;
::memcpy(&iMe, szCurrent, sizeof(int32_t)); ::memcpy(&iMe, szCurrent, sizeof(int32_t));
AI_SWAP4(iMe); AI_SWAP4(iMe);
szCurrent += sizeof(char) * iMe + sizeof(int32_t); szCurrent += sizeof(char) * iMe + sizeof(int32_t);
VALIDATE_FILE_SIZE(szCurrent);
} }
*szCurrentOut = szCurrent; *szCurrentOut = szCurrent;
} }

View File

@ -81,27 +81,6 @@ namespace {
return props[idx]; return props[idx];
} }
// ------------------------------------------------------------------------------------------------
static bool isBigEndian(const char *szMe) {
ai_assert(nullptr != szMe);
// binary_little_endian
// binary_big_endian
bool isBigEndian{ false };
#if (defined AI_BUILD_BIG_ENDIAN)
if ('l' == *szMe || 'L' == *szMe) {
isBigEndian = true;
}
#else
if ('b' == *szMe || 'B' == *szMe) {
isBigEndian = true;
}
#endif // ! AI_BUILD_BIG_ENDIAN
return isBigEndian;
}
} // namespace } // namespace
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -113,11 +92,6 @@ PLYImporter::PLYImporter() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
PLYImporter::~PLYImporter() {
delete mGeneratedMesh;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@ -130,6 +104,26 @@ const aiImporterDesc *PLYImporter::GetInfo() const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------
static bool isBigEndian(const char *szMe) {
ai_assert(nullptr != szMe);
// binary_little_endian
// binary_big_endian
bool isBigEndian(false);
#if (defined AI_BUILD_BIG_ENDIAN)
if ('l' == *szMe || 'L' == *szMe) {
isBigEndian = true;
}
#else
if ('b' == *szMe || 'B' == *szMe) {
isBigEndian = true;
}
#endif // ! AI_BUILD_BIG_ENDIAN
return isBigEndian;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
@ -140,7 +134,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
// Get the file-size // Get the file-size
const size_t fileSize = fileStream->FileSize(); const size_t fileSize(fileStream->FileSize());
if (0 == fileSize) { if (0 == fileSize) {
throw DeadlyImportError("File ", pFile, " is empty."); throw DeadlyImportError("File ", pFile, " is empty.");
} }
@ -186,7 +180,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
} else if (!::strncmp(szMe, "binary_", 7)) { } else if (!::strncmp(szMe, "binary_", 7)) {
szMe += 7; szMe += 7;
const bool bIsBE = isBigEndian(szMe); const bool bIsBE(isBigEndian(szMe));
// skip the line, parse the rest of the header and build the DOM // skip the line, parse the rest of the header and build the DOM
if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) { if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) {
@ -247,9 +241,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// fill the mesh list // fill the mesh list
pScene->mNumMeshes = 1; pScene->mNumMeshes = 1;
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
pScene->mMeshes[0] = mGeneratedMesh; pScene->mMeshes[0] = mGeneratedMesh;
// Move the mesh ownership into the scene instance
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
// generate a simple node structure // generate a simple node structure
@ -262,22 +254,20 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
} }
static constexpr ai_uint NotSet = 0xFFFFFFFF;
void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementInstance *instElement, unsigned int pos) { void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementInstance *instElement, unsigned int pos) {
ai_assert(nullptr != pcElement); ai_assert(nullptr != pcElement);
ai_assert(nullptr != instElement); ai_assert(nullptr != instElement);
ai_uint aiPositions[3] = { NotSet, NotSet, NotSet }; ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char }; PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
ai_uint aiNormal[3] = { NotSet, NotSet, NotSet }; ai_uint aiNormal[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiNormalTypes[3] = { EDT_Char, EDT_Char, EDT_Char }; PLY::EDataType aiNormalTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
unsigned int aiColors[4] = { NotSet, NotSet, NotSet, NotSet }; unsigned int aiColors[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiColorsTypes[4] = { EDT_Char, EDT_Char, EDT_Char, EDT_Char }; PLY::EDataType aiColorsTypes[4] = { EDT_Char, EDT_Char, EDT_Char, EDT_Char };
unsigned int aiTexcoord[2] = { NotSet, NotSet }; unsigned int aiTexcoord[2] = { 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char }; PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char };
// now check whether which normal components are available // now check whether which normal components are available
@ -347,17 +337,17 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
if (0 != cnt) { if (0 != cnt) {
// Position // Position
aiVector3D vOut; aiVector3D vOut;
if (NotSet != aiPositions[0]) { if (0xFFFFFFFF != aiPositions[0]) {
vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>( vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]); GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]);
} }
if (NotSet != aiPositions[1]) { if (0xFFFFFFFF != aiPositions[1]) {
vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>( vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]); GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]);
} }
if (NotSet != aiPositions[2]) { if (0xFFFFFFFF != aiPositions[2]) {
vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>( vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]); GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]);
} }
@ -365,19 +355,19 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
// Normals // Normals
aiVector3D nOut; aiVector3D nOut;
bool haveNormal = false; bool haveNormal = false;
if (NotSet != aiNormal[0]) { if (0xFFFFFFFF != aiNormal[0]) {
nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>( nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]); GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]);
haveNormal = true; haveNormal = true;
} }
if (NotSet != aiNormal[1]) { if (0xFFFFFFFF != aiNormal[1]) {
nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>( nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]); GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]);
haveNormal = true; haveNormal = true;
} }
if (NotSet != aiNormal[2]) { if (0xFFFFFFFF != aiNormal[2]) {
nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>( nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]); GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]);
haveNormal = true; haveNormal = true;
@ -386,7 +376,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
// Colors // Colors
aiColor4D cOut; aiColor4D cOut;
bool haveColor = false; bool haveColor = false;
if (NotSet != aiColors[0]) { if (0xFFFFFFFF != aiColors[0]) {
cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[0]) aiColors[0])
.avList.front(), .avList.front(),
@ -394,7 +384,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
haveColor = true; haveColor = true;
} }
if (NotSet != aiColors[1]) { if (0xFFFFFFFF != aiColors[1]) {
cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[1]) aiColors[1])
.avList.front(), .avList.front(),
@ -402,7 +392,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
haveColor = true; haveColor = true;
} }
if (NotSet != aiColors[2]) { if (0xFFFFFFFF != aiColors[2]) {
cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[2]) aiColors[2])
.avList.front(), .avList.front(),
@ -411,7 +401,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
} }
// assume 1.0 for the alpha channel if it is not set // assume 1.0 for the alpha channel if it is not set
if (NotSet == aiColors[3]) { if (0xFFFFFFFF == aiColors[3]) {
cOut.a = 1.0; cOut.a = 1.0;
} else { } else {
cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties,
@ -426,13 +416,13 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
aiVector3D tOut; aiVector3D tOut;
tOut.z = 0; tOut.z = 0;
bool haveTextureCoords = false; bool haveTextureCoords = false;
if (NotSet != aiTexcoord[0]) { if (0xFFFFFFFF != aiTexcoord[0]) {
tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>( tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]); GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]);
haveTextureCoords = true; haveTextureCoords = true;
} }
if (NotSet != aiTexcoord[1]) { if (0xFFFFFFFF != aiTexcoord[1]) {
tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>( tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]); GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]);
haveTextureCoords = true; haveTextureCoords = true;
@ -448,9 +438,6 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
mGeneratedMesh->mNumVertices = pcElement->NumOccur; mGeneratedMesh->mNumVertices = pcElement->NumOccur;
mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices]; mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices];
} }
if (pos >= mGeneratedMesh->mNumVertices) {
throw DeadlyImportError("Invalid .ply file: Too many vertices");
}
mGeneratedMesh->mVertices[pos] = vOut; mGeneratedMesh->mVertices[pos] = vOut;
@ -517,12 +504,16 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
bool bOne = false; bool bOne = false;
// index of the vertex index list // index of the vertex index list
unsigned int iProperty = NotSet; unsigned int iProperty = 0xFFFFFFFF;
PLY::EDataType eType = EDT_Char; PLY::EDataType eType = EDT_Char;
bool bIsTriStrip = false; bool bIsTriStrip = false;
// index of the material index property
// unsigned int iMaterialIndex = 0xFFFFFFFF;
// PLY::EDataType eType2 = EDT_Char;
// texture coordinates // texture coordinates
unsigned int iTextureCoord = NotSet; unsigned int iTextureCoord = 0xFFFFFFFF;
PLY::EDataType eType3 = EDT_Char; PLY::EDataType eType3 = EDT_Char;
// face = unique number of vertex indices // face = unique number of vertex indices
@ -581,7 +572,7 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
if (!bIsTriStrip) { if (!bIsTriStrip) {
// parse the list of vertex indices // parse the list of vertex indices
if (NotSet != iProperty) { if (0xFFFFFFFF != iProperty) {
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size(); const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size();
mGeneratedMesh->mFaces[pos].mNumIndices = iNum; mGeneratedMesh->mFaces[pos].mNumIndices = iNum;
mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum]; mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
@ -594,7 +585,15 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
} }
} }
if (NotSet != iTextureCoord) { // parse the material index
// cannot be handled without processing the whole file first
/*if (0xFFFFFFFF != iMaterialIndex)
{
mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo<unsigned int>(
GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
}*/
if (0xFFFFFFFF != iTextureCoord) {
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size(); const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
// should be 6 coords // should be 6 coords
@ -680,29 +679,41 @@ void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance> &avL
aiColor4D *clrOut) { aiColor4D *clrOut) {
ai_assert(nullptr != clrOut); ai_assert(nullptr != clrOut);
if (NotSet == aiPositions[0]) { if (0xFFFFFFFF == aiPositions[0])
clrOut->r = 0.0f; clrOut->r = 0.0f;
} else { else {
clrOut->r = NormalizeColorValue(GetProperty(avList, aiPositions[0]).avList.front(), aiTypes[0]); clrOut->r = NormalizeColorValue(GetProperty(avList,
aiPositions[0])
.avList.front(),
aiTypes[0]);
} }
if (NotSet == aiPositions[1]) { if (0xFFFFFFFF == aiPositions[1])
clrOut->g = 0.0f; clrOut->g = 0.0f;
} else { else {
clrOut->g = NormalizeColorValue(GetProperty(avList, aiPositions[1]).avList.front(), aiTypes[1]); clrOut->g = NormalizeColorValue(GetProperty(avList,
aiPositions[1])
.avList.front(),
aiTypes[1]);
} }
if (NotSet == aiPositions[2]) if (0xFFFFFFFF == aiPositions[2])
clrOut->b = 0.0f; clrOut->b = 0.0f;
else { else {
clrOut->b = NormalizeColorValue(GetProperty(avList, aiPositions[2]).avList.front(), aiTypes[2]); clrOut->b = NormalizeColorValue(GetProperty(avList,
aiPositions[2])
.avList.front(),
aiTypes[2]);
} }
// assume 1.0 for the alpha channel ifit is not set // assume 1.0 for the alpha channel ifit is not set
if (NotSet == aiPositions[3]) if (0xFFFFFFFF == aiPositions[3])
clrOut->a = 1.0f; clrOut->a = 1.0f;
else { else {
clrOut->a = NormalizeColorValue(GetProperty(avList, aiPositions[3]).avList.front(), aiTypes[3]); clrOut->a = NormalizeColorValue(GetProperty(avList,
aiPositions[3])
.avList.front(),
aiTypes[3]);
} }
} }

View File

@ -62,10 +62,10 @@ using namespace PLY;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Importer class to load the stanford PLY file format /** Importer class to load the stanford PLY file format
*/ */
class PLYImporter final : public BaseImporter { class PLYImporter : public BaseImporter {
public: public:
PLYImporter(); PLYImporter();
~PLYImporter() override; ~PLYImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
@ -120,9 +120,13 @@ protected:
PLY::PropertyInstance::ValueUnion val, PLY::PropertyInstance::ValueUnion val,
PLY::EDataType eType); PLY::EDataType eType);
private: /** Buffer to hold the loaded file */
unsigned char *mBuffer; unsigned char *mBuffer;
/** Document object model representation extracted from the file */
PLY::DOM *pcDOM; PLY::DOM *pcDOM;
/** Mesh generated by loader */
aiMesh *mGeneratedMesh; aiMesh *mGeneratedMesh;
}; };

View File

@ -48,29 +48,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ByteSwapper.h> #include <assimp/ByteSwapper.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <unordered_set>
#include <utility> #include <utility>
namespace Assimp { namespace Assimp {
std::string to_string(EElementSemantic e) {
switch (e) {
case EEST_Vertex:
return std::string{ "vertex" };
case EEST_TriStrip:
return std::string{ "tristrips" };
case EEST_Edge:
return std::string{ "edge" };
case EEST_Material:
return std::string{ "material" };
case EEST_TextureFile:
return std::string{ "TextureFile" };
default:
return std::string{ "invalid" };
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) { PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) {
ai_assert(!buffer.empty()); ai_assert(!buffer.empty());
@ -300,8 +281,6 @@ bool PLY::Element::ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<
// if the exact semantic can't be determined, just store // if the exact semantic can't be determined, just store
// the original string identifier // the original string identifier
pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0]));
auto pos = pOut->szName.find_last_of(' ');
pOut->szName.erase(pos, pOut->szName.size());
} }
if (!PLY::DOM::SkipSpaces(buffer)) if (!PLY::DOM::SkipSpaces(buffer))
@ -434,7 +413,6 @@ bool PLY::DOM::SkipComments(std::vector<char> buffer) {
bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) { bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) {
ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() begin"); ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() begin");
std::unordered_set<std::string> definedAlElements;
// parse all elements // parse all elements
while (!buffer.empty()) { while (!buffer.empty()) {
// skip all comments // skip all comments
@ -443,13 +421,6 @@ bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char>
PLY::Element out; PLY::Element out;
if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) { if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) {
// add the element to the list of elements // add the element to the list of elements
const auto propertyName = (out.szName.empty()) ? to_string(out.eSemantic) : out.szName;
auto alreadyDefined = definedAlElements.find(propertyName);
if (alreadyDefined != definedAlElements.end()) {
throw DeadlyImportError("Property '" + propertyName + "' in header already defined ");
}
definedAlElements.insert(propertyName);
alElements.push_back(out); alElements.push_back(out);
} else if (TokenMatch(buffer, "end_header", 10)) { } else if (TokenMatch(buffer, "end_header", 10)) {
// we have reached the end of the header // we have reached the end of the header

View File

@ -400,12 +400,8 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) {
} }
} }
// nothing to do
if (pcNode->mNumChildren == 0)
return;
// now allocate the output array // now allocate the output array
pcNode->mChildren = new aiNode *[pcNode->mNumChildren]; pcNode->mChildren = new aiNode*[pcNode->mNumChildren];
// and fill all subnodes // and fill all subnodes
unsigned int qq( 0 ); unsigned int qq( 0 );

View File

@ -121,4 +121,3 @@ void USDImporter::InternReadFile(
} // namespace Assimp } // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_USD_IMPORTER #endif // !! ASSIMP_BUILD_NO_USD_IMPORTER

View File

@ -72,7 +72,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../../../contrib/tinyusdz/assimp_tinyusdz_logging.inc" #include "../../../contrib/tinyusdz/assimp_tinyusdz_logging.inc"
namespace { namespace {
static constexpr char TAG[] = "tinyusdz loader"; static constexpr char Tag[] = "tinyusdz loader";
} }
namespace Assimp { namespace Assimp {

View File

@ -1036,10 +1036,10 @@ size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remap
outData = new T[usedCount]; outData = new T[usedCount];
if (remappingIndices != nullptr) { if (remappingIndices != nullptr) {
const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride); const unsigned int maxIndex = static_cast<unsigned int>(maxSize / stride - 1);
for (size_t i = 0; i < usedCount; ++i) { for (size_t i = 0; i < usedCount; ++i) {
size_t srcIdx = (*remappingIndices)[i]; size_t srcIdx = (*remappingIndices)[i];
if (srcIdx >= maxIndexCount) { if (srcIdx > maxIndex) {
throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name)); throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
} }
memcpy(outData + i, data + srcIdx * stride, elemSize); memcpy(outData + i, data + srcIdx * stride, elemSize);

View File

@ -940,7 +940,7 @@ namespace glTF2 {
if (outfile->Write(bodyBuffer->GetPointer(), 1, bodyBuffer->byteLength) != bodyBuffer->byteLength) { if (outfile->Write(bodyBuffer->GetPointer(), 1, bodyBuffer->byteLength) != bodyBuffer->byteLength) {
throw DeadlyExportError("Failed to write body data!"); throw DeadlyExportError("Failed to write body data!");
} }
if (curPaddingLength && outfile->Write(&padding, 1, curPaddingLength) != curPaddingLength) { if (curPaddingLength && outfile->Write(&padding, 1, paddingLength) != paddingLength) {
throw DeadlyExportError("Failed to write body data padding!"); throw DeadlyExportError("Failed to write body data padding!");
} }
} }

View File

@ -1053,7 +1053,7 @@ ENDIF() # IF (ASSIMP_BUILD_USD_IMPORTER)
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(pugixml) hunter_add_package(pugixml)
find_package(pugixml CONFIG REQUIRED) find_package(pugixml CONFIG REQUIRED)
ELSEIF(NOT TARGET pugixml::pugixml) ELSE()
SET( Pugixml_SRCS SET( Pugixml_SRCS
../contrib/pugixml/src/pugiconfig.hpp ../contrib/pugixml/src/pugiconfig.hpp
../contrib/pugixml/src/pugixml.hpp ../contrib/pugixml/src/pugixml.hpp
@ -1334,7 +1334,7 @@ ADD_LIBRARY(assimp::assimp ALIAS assimp)
IF (BUILD_SHARED_LIBS) IF (BUILD_SHARED_LIBS)
TARGET_COMPILE_DEFINITIONS(assimp PRIVATE ASSIMP_BUILD_DLL_EXPORT) TARGET_COMPILE_DEFINITIONS(assimp PRIVATE ASSIMP_BUILD_DLL_EXPORT)
ELSE () ELSE ()
TARGET_COMPILE_DEFINITIONS(assimp PRIVATE OPENDDL_STATIC_LIBARY P2T_STATIC_EXPORTS) TARGET_COMPILE_DEFINITIONS(assimp PRIVATE OPENDDL_STATIC_LIBARY)
ENDIF () ENDIF ()
TARGET_USE_COMMON_OUTPUT_DIRECTORY(assimp) TARGET_USE_COMMON_OUTPUT_DIRECTORY(assimp)
@ -1396,7 +1396,6 @@ IF (ASSIMP_WARNINGS_AS_ERRORS)
-Wno-unused-template -Wno-unused-template
-Wno-undefined-func-template -Wno-undefined-func-template
-Wno-declaration-after-statement -Wno-declaration-after-statement
-Wno-deprecated-declarations
) )
ELSE() ELSE()
TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX) TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX)
@ -1418,7 +1417,9 @@ TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
TARGET_LINK_LIBRARIES(assimp TARGET_LINK_LIBRARIES(assimp
PUBLIC PUBLIC
#polyclipping::polyclipping
openddlparser::openddl_parser openddlparser::openddl_parser
#poly2tri::poly2tri
minizip::minizip minizip::minizip
ZLIB::zlib ZLIB::zlib
RapidJSON::rapidjson RapidJSON::rapidjson
@ -1438,9 +1439,6 @@ ELSE()
if (ASSIMP_BUILD_DRACO) if (ASSIMP_BUILD_DRACO)
target_link_libraries(assimp ${draco_LIBRARIES}) target_link_libraries(assimp ${draco_LIBRARIES})
endif() endif()
if(TARGET pugixml::pugixml)
target_link_libraries(assimp pugixml::pugixml)
endif()
ENDIF() ENDIF()
if(ASSIMP_ANDROID_JNIIOSYSTEM) if(ASSIMP_ANDROID_JNIIOSYSTEM)
@ -1577,7 +1575,7 @@ if(MSVC AND ASSIMP_INSTALL_PDB)
COMPILE_PDB_NAME_DEBUG assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX} COMPILE_PDB_NAME_DEBUG assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}
) )
IF(is_multi_config) IF(GENERATOR_IS_MULTI_CONFIG)
install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
DESTINATION ${ASSIMP_LIB_INSTALL_DIR} DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
CONFIGURATIONS Debug CONFIGURATIONS Debug

View File

@ -359,25 +359,20 @@ void CallbackToLogRedirector(const char *msg, char *dt) {
s->write(msg); s->write(msg);
} }
static LogStream *DefaultStream = nullptr;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, const char *file) { ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, const char *file) {
aiLogStream sout; aiLogStream sout;
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
if (DefaultStream == nullptr) { LogStream *stream = LogStream::createDefaultStream(pStream, file);
DefaultStream = LogStream::createDefaultStream(pStream, file); if (!stream) {
}
if (!DefaultStream) {
sout.callback = nullptr; sout.callback = nullptr;
sout.user = nullptr; sout.user = nullptr;
} else { } else {
sout.callback = &CallbackToLogRedirector; sout.callback = &CallbackToLogRedirector;
sout.user = (char *)DefaultStream; sout.user = (char *)stream;
} }
gPredefinedStreams.push_back(DefaultStream); gPredefinedStreams.push_back(stream);
ASSIMP_END_EXCEPTION_REGION(aiLogStream); ASSIMP_END_EXCEPTION_REGION(aiLogStream);
return sout; return sout;
} }
@ -517,11 +512,6 @@ void aiGetMemoryRequirements(const C_STRUCT aiScene *pIn,
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------
ASSIMP_API const C_STRUCT aiTexture *aiGetEmbeddedTexture(const C_STRUCT aiScene *pIn, const char *filename) {
return pIn->GetEmbeddedTexture(filename);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiPropertyStore *aiCreatePropertyStore(void) { ASSIMP_API aiPropertyStore *aiCreatePropertyStore(void) {
return reinterpret_cast<aiPropertyStore *>(new PropertyMap()); return reinterpret_cast<aiPropertyStore *>(new PropertyMap());
@ -1278,6 +1268,7 @@ ASSIMP_API void aiQuaternionInterpolate(
aiQuaternion::Interpolate(*dst, *start, *end, factor); aiQuaternion::Interpolate(*dst, *start, *end, factor);
} }
// stb_image is a lightweight image loader. It is shared by: // stb_image is a lightweight image loader. It is shared by:
// - M3D import // - M3D import
// - PBRT export // - PBRT export
@ -1288,21 +1279,21 @@ ASSIMP_API void aiQuaternionInterpolate(
#define ASSIMP_HAS_M3D ((!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER) #define ASSIMP_HAS_M3D ((!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER)
#ifndef STB_USE_HUNTER #ifndef STB_USE_HUNTER
#if ASSIMP_HAS_PBRT_EXPORT # if ASSIMP_HAS_PBRT_EXPORT
#define ASSIMP_NEEDS_STB_IMAGE 1 # define ASSIMP_NEEDS_STB_IMAGE 1
#elif ASSIMP_HAS_M3D # elif ASSIMP_HAS_M3D
#define ASSIMP_NEEDS_STB_IMAGE 1 # define ASSIMP_NEEDS_STB_IMAGE 1
#define STBI_ONLY_PNG # define STBI_ONLY_PNG
#endif # endif
#endif #endif
// Ensure all symbols are linked correctly // Ensure all symbols are linked correctly
#if ASSIMP_NEEDS_STB_IMAGE #if ASSIMP_NEEDS_STB_IMAGE
// Share stb_image's PNG loader with other importers/exporters instead of bringing our own copy. // Share stb_image's PNG loader with other importers/exporters instead of bringing our own copy.
#define STBI_ONLY_PNG # define STBI_ONLY_PNG
#ifdef ASSIMP_USE_STB_IMAGE_STATIC # ifdef ASSIMP_USE_STB_IMAGE_STATIC
#define STB_IMAGE_STATIC # define STB_IMAGE_STATIC
#endif # endif
#define STB_IMAGE_IMPLEMENTATION # define STB_IMAGE_IMPLEMENTATION
#include "Common/StbCommon.h" # include "Common/StbCommon.h"
#endif #endif

View File

@ -93,10 +93,6 @@ static std::string WideToUtf8(const wchar_t *in) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Tests for the existence of a file at the given path. // Tests for the existence of a file at the given path.
bool DefaultIOSystem::Exists(const char *pFile) const { bool DefaultIOSystem::Exists(const char *pFile) const {
if (pFile == nullptr) {
return false;
}
#ifdef _WIN32 #ifdef _WIN32
struct __stat64 filestat; struct __stat64 filestat;
if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) { if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) {

View File

@ -848,7 +848,11 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
break; break;
} }
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
continue;
#endif // no validation
// If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
if (pimpl->bExtraVerbose) { if (pimpl->bExtraVerbose) {
ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures"); ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures");
@ -860,7 +864,6 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
break; break;
} }
} }
#endif // no validation
#endif // ! DEBUG #endif // ! DEBUG
} }
pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()), pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()),
@ -936,7 +939,6 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
profiler->EndRegion( "postprocess" ); profiler->EndRegion( "postprocess" );
} }
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
// If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
if ( pimpl->bExtraVerbose || requestValidation ) { if ( pimpl->bExtraVerbose || requestValidation ) {
ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" ); ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" );
@ -947,7 +949,6 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" ); ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" );
} }
} }
#endif // no validation
// clear any data allocated by post-process steps // clear any data allocated by post-process steps
pimpl->mPPShared->Clean(); pimpl->mPPShared->Clean();

View File

@ -63,7 +63,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <stdio.h> #include <stdio.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <unordered_set>
namespace Assimp { namespace Assimp {
@ -253,14 +252,6 @@ void SceneCombiner::AttachToGraph(aiScene *master, std::vector<NodeAttachmentInf
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<AttachmentInfo> &srcList, unsigned int flags) { void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<AttachmentInfo> &srcList, unsigned int flags) {
if (nullptr == _dest) { if (nullptr == _dest) {
std::unordered_set<aiScene *> uniqueScenes;
uniqueScenes.insert(master);
for (const auto &item : srcList) {
uniqueScenes.insert(item.scene);
}
for (const auto &item : uniqueScenes) {
delete item;
}
return; return;
} }
@ -268,7 +259,6 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
if (srcList.empty()) { if (srcList.empty()) {
if (*_dest) { if (*_dest) {
SceneCombiner::CopySceneFlat(_dest, master); SceneCombiner::CopySceneFlat(_dest, master);
delete master;
} else } else
*_dest = master; *_dest = master;
return; return;
@ -1067,7 +1057,7 @@ void SceneCombiner::CopyScene(aiScene **_dest, const aiScene *src, bool allocate
dest->mFlags = src->mFlags; dest->mFlags = src->mFlags;
// source private data might be nullptr if the scene is user-allocated (i.e. for use with the export API) // source private data might be nullptr if the scene is user-allocated (i.e. for use with the export API)
if (src->mPrivate != nullptr) { if (dest->mPrivate != nullptr) {
ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0; ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0;
} }
} }

View File

@ -200,10 +200,8 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
localBitangent.NormalizeSafe(); localBitangent.NormalizeSafe();
// reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN. // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z) bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
|| (-0.5f < localTangent.x && localTangent.x < 0.5f && -0.5f < localTangent.y && localTangent.y < 0.5f && -0.5f < localTangent.z && localTangent.z < 0.5f); bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z);
bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z)
|| (-0.5f < localBitangent.x && localBitangent.x < 0.5f && -0.5f < localBitangent.y && localBitangent.y < 0.5f && -0.5f < localBitangent.z && localBitangent.z < 0.5f);
if (invalid_tangent != invalid_bitangent) { if (invalid_tangent != invalid_bitangent) {
if (invalid_tangent) { if (invalid_tangent) {
localTangent = meshNorm[p] ^ localBitangent; localTangent = meshNorm[p] ^ localBitangent;

View File

@ -143,13 +143,9 @@ bool FindDegeneratesProcess::ExecuteOnMesh(aiMesh *mesh) {
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
aiFace &face = mesh->mFaces[a]; aiFace &face = mesh->mFaces[a];
bool first = true; bool first = true;
auto vertex_in_range = [numVertices = mesh->mNumVertices](unsigned int vertex_idx) { return vertex_idx < numVertices; };
// check whether the face contains degenerated entries // check whether the face contains degenerated entries
for (unsigned int i = 0; i < face.mNumIndices; ++i) { for (unsigned int i = 0; i < face.mNumIndices; ++i) {
if (!std::all_of(face.mIndices, face.mIndices + face.mNumIndices, vertex_in_range))
continue;
// Polygons with more than 4 points are allowed to have double points, that is // Polygons with more than 4 points are allowed to have double points, that is
// simulating polygons with holes just with concave polygons. However, // simulating polygons with holes just with concave polygons. However,
// double points may not come directly after another. // double points may not come directly after another.

View File

@ -380,4 +380,3 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int mes
} }
} // namespace Assimp } // namespace Assimp

View File

@ -65,47 +65,37 @@ void SortByPTypeProcess::SetupProperties(const Importer *pImp) {
mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0); mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0);
} }
// ------------------------------------------------------------------------------------------------
static void clearMeshesInNode(aiNode *node) {
delete[] node->mMeshes;
node->mNumMeshes = 0;
node->mMeshes = nullptr;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Update changed meshes in all nodes // Update changed meshes in all nodes
void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) { void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) {
ai_assert(node != nullptr);
if (node->mNumMeshes) { if (node->mNumMeshes) {
unsigned int newSize = 0; unsigned int newSize = 0;
for (unsigned int m = 0; m < node->mNumMeshes; ++m) { for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
unsigned int add = node->mMeshes[m] << 2; unsigned int add = node->mMeshes[m] << 2;
for (unsigned int i = 0; i < 4; ++i) { for (unsigned int i = 0; i < 4; ++i) {
if (UINT_MAX != replaceMeshIndex[add + i]) { if (UINT_MAX != replaceMeshIndex[add + i]) ++newSize;
++newSize;
}
} }
} }
if (newSize == 0) { if (!newSize) {
clearMeshesInNode(node); delete[] node->mMeshes;
return; node->mNumMeshes = 0;
} node->mMeshes = nullptr;
} else {
// Try to reuse the old array if possible // Try to reuse the old array if possible
unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes); unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes);
for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
unsigned int add = node->mMeshes[m] << 2; for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
for (unsigned int i = 0; i < 4; ++i) { unsigned int add = node->mMeshes[m] << 2;
if (UINT_MAX != replaceMeshIndex[add + i]) { for (unsigned int i = 0; i < 4; ++i) {
*newMeshes++ = replaceMeshIndex[add + i]; if (UINT_MAX != replaceMeshIndex[add + i])
*newMeshes++ = replaceMeshIndex[add + i];
} }
} }
if (newSize > node->mNumMeshes)
delete[] node->mMeshes;
node->mMeshes = newMeshes - (node->mNumMeshes = newSize);
} }
if (newSize > node->mNumMeshes) {
clearMeshesInNode(node);
}
node->mMeshes = newMeshes - (node->mNumMeshes = newSize);
} }
// call all subnodes recursively // call all subnodes recursively
@ -177,10 +167,6 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
// with the largest number of primitives // with the largest number of primitives
unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 }; unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 };
aiFace *pFirstFace = mesh->mFaces; aiFace *pFirstFace = mesh->mFaces;
if (pFirstFace == nullptr) {
continue;
}
aiFace *const pLastFace = pFirstFace + mesh->mNumFaces; aiFace *const pLastFace = pFirstFace + mesh->mNumFaces;
unsigned int numPolyVerts = 0; unsigned int numPolyVerts = 0;

View File

@ -192,13 +192,13 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
const aiFace& face = pMesh->mFaces[a]; const aiFace& face = pMesh->mFaces[a];
if( face.mNumIndices != 3) { if( face.mNumIndices != 3) {
bNeed = true; bNeed = true;
} }
} }
if (!bNeed) { if (!bNeed)
return false; return false;
}
} }
else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) { else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
return false; return false;
@ -213,7 +213,8 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
get_normals = false; get_normals = false;
} }
if( face.mNumIndices <= 3) { if( face.mNumIndices <= 3) {
++numOut; numOut++;
} else { } else {
numOut += face.mNumIndices-2; numOut += face.mNumIndices-2;
max_out = std::max(max_out,face.mNumIndices); max_out = std::max(max_out,face.mNumIndices);
@ -221,11 +222,8 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
} }
// Just another check whether aiMesh::mPrimitiveTypes is correct // Just another check whether aiMesh::mPrimitiveTypes is correct
if (numOut == pMesh->mNumFaces) { ai_assert(numOut != pMesh->mNumFaces);
ASSIMP_LOG_ERROR( "Invalidation detected in the number of indices: does not fit to the primitive type." );
return false;
}
aiVector3D *nor_out = nullptr; aiVector3D *nor_out = nullptr;
// if we don't have normals yet, but expect them to be a cheap side // if we don't have normals yet, but expect them to be a cheap side

View File

@ -891,9 +891,6 @@ void ValidateDSProcess::Validate(const aiNode *pNode) {
ReportError("aiNode \"%s\" child %i \"%s\" parent is someone else: \"%s\"", pNode->mName.C_Str(), i, pChild->mName.C_Str(), parentName); ReportError("aiNode \"%s\" child %i \"%s\" parent is someone else: \"%s\"", pNode->mName.C_Str(), i, pChild->mName.C_Str(), parentName);
} }
} }
} else if (pNode->mChildren) {
ReportError("aiNode::mChildren is not nullptr for empty node %s (aiNode::mNumChildren is %i)",
nodeName, pNode->mNumChildren);
} }
} }

View File

@ -1,6 +1,7 @@
Copyright (c) 2009-2018, Poly2Tri Contributors Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
All rights reserved. http://code.google.com/p/poly2tri/
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:

View File

@ -0,0 +1,51 @@
==================
INSTALLATION GUIDE
==================
------------
Dependencies
------------
Core poly2tri lib:
- Standard Template Library (STL)
Testbed:
- gcc
- OpenGL
- GLFW (http://glfw.sf.net)
- Python
Waf (http://code.google.com/p/waf/) is used to compile the testbed.
A waf script (86kb) is included in the repositoty.
----------------------------------------------
Building the Testbed
----------------------------------------------
Posix/MSYS environment:
./waf configure
./waf build
Windows command line:
python waf configure
python waf build
----------------------------------------------
Running the Examples
----------------------------------------------
Load data points from a file:
p2t <filename> <center_x> <center_y> <zoom>
Random distribution of points inside a consrained box:
p2t random <num_points> <box_radius> <zoom>
Examples:
./p2t dude.dat 300 500 2
./p2t nazca_monkey.dat 0 0 9
./p2t random 10 100 5.0
./p2t random 1000 20000 0.025

View File

@ -1,101 +0,0 @@
Since there are no Input validation of the data given for triangulation you need
to think about this. Poly2Tri does not support repeat points within epsilon.
* If you have a cyclic function that generates random points make sure you don't
add the same coordinate twice.
* If you are given input and aren't sure same point exist twice you need to
check for this yourself.
* Only simple polygons are supported. You may add holes or interior Steiner points
* Interior holes must not touch other holes, nor touch the polyline boundary
* Use the library in this order:
1. Initialize CDT with a simple polyline (this defines the constrained edges)
2. Add holes if necessary (also simple polylines)
3. Add Steiner points
4. Triangulate
Make sure you understand the preceding notice before posting an issue. If you have
an issue not covered by the above, include your data-set with the problem.
The only easy day was yesterday; have a nice day. <Mason Green>
TESTBED INSTALLATION GUIDE
==========================
Dependencies
------------
Core poly2tri lib:
* Standard Template Library (STL)
Unit tests:
* Boost (filesystem, test framework)
Testbed:
* OpenGL
* [GLFW](http://glfw.sf.net)
Build the library
-----------------
With the ninja build system installed:
```
mkdir build && cd build
cmake -GNinja ..
cmake --build .
```
Build and run with unit tests
----------------------------
With the ninja build system:
```
mkdir build && cd build
cmake -GNinja -DP2T_BUILD_TESTS=ON ..
cmake --build .
ctest --output-on-failure
```
Build with the testbed
-----------------
```
mkdir build && cd build
cmake -GNinja -DP2T_BUILD_TESTBED=ON ..
cmake --build .
```
Running the Examples
--------------------
Load data points from a file:
```
build/testbed/p2t <filename> <center_x> <center_y> <zoom>
```
Load data points from a file and automatically fit the geometry to the window:
```
build/testbed/p2t <filename>
```
Random distribution of points inside a constrained box:
```
build/testbed/p2t random <num_points> <box_radius> <zoom>
```
Examples:
```
build/testbed/p2t testbed/data/dude.dat 350 500 3
build/testbed/p2t testbed/data/nazca_monkey.dat
build/testbed/p2t random 10 100 5.0
build/testbed/p2t random 1000 20000 0.025
```
References
==========
- Domiter V. and Zalik B. (2008) Sweepline algorithm for constrained Delaunay triangulation
- FlipScan by library author Thomas Åhlén
![FlipScan](doc/FlipScan.png)

View File

@ -1,61 +0,0 @@
/*
* Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if defined(_MSC_VER)
# pragma warning( disable: 4273)
# define P2T_COMPILER_DLLEXPORT __declspec(dllexport)
# define P2T_COMPILER_DLLIMPORT __declspec(dllimport)
#elif defined(__GNUC__)
# define P2T_COMPILER_DLLEXPORT __attribute__ ((visibility ("default")))
# define P2T_COMPILER_DLLIMPORT __attribute__ ((visibility ("default")))
#else
# define P2T_COMPILER_DLLEXPORT
# define P2T_COMPILER_DLLIMPORT
#endif
// We need to enable shard linkage explicitely
#ifdef ASSIMP_BUILD_DLL_EXPORT
# define P2T_SHARED_EXPORTS 1
#endif
#ifndef P2T_DLL_SYMBOL
# if defined(P2T_STATIC_EXPORTS)
# define P2T_DLL_SYMBOL
# elif defined(P2T_SHARED_EXPORTS)
# define P2T_DLL_SYMBOL P2T_COMPILER_DLLEXPORT
# elif defined(BUILD_SHARED_LIBS)
# define P2T_DLL_SYMBOL P2T_COMPILER_DLLIMPORT
# else
# define P2T_DLL_SYMBOL
# endif
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,24 +29,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "shapes.h" #include "shapes.h"
#include <cassert>
#include <iostream> #include <iostream>
namespace p2t { namespace p2t {
Point::Point(double x, double y) : x(x), y(y)
{
}
std::ostream& operator<<(std::ostream& out, const Point& point) {
return out << point.x << "," << point.y;
}
Triangle::Triangle(Point& a, Point& b, Point& c) Triangle::Triangle(Point& a, Point& b, Point& c)
{ {
points_[0] = &a; points_[1] = &b; points_[2] = &c; points_[0] = &a; points_[1] = &b; points_[2] = &c;
neighbors_[0] = nullptr; neighbors_[1] = nullptr; neighbors_[2] = nullptr; neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL;
constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false;
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
interior_ = false; interior_ = false;
@ -86,37 +76,39 @@ void Triangle::MarkNeighbor(Triangle& t)
void Triangle::Clear() void Triangle::Clear()
{ {
Triangle *t; Triangle *t;
for (auto& neighbor : neighbors_) { for( int i=0; i<3; i++ )
t = neighbor; {
if (t != nullptr) { t = neighbors_[i];
t->ClearNeighbor(this); if( t != NULL )
} {
t->ClearNeighbor( this );
}
} }
ClearNeighbors(); ClearNeighbors();
points_[0]=points_[1]=points_[2] = nullptr; points_[0]=points_[1]=points_[2] = NULL;
} }
void Triangle::ClearNeighbor(const Triangle *triangle ) void Triangle::ClearNeighbor(const Triangle *triangle )
{ {
if( neighbors_[0] == triangle ) if( neighbors_[0] == triangle )
{ {
neighbors_[0] = nullptr; neighbors_[0] = NULL;
} }
else if( neighbors_[1] == triangle ) else if( neighbors_[1] == triangle )
{ {
neighbors_[1] = nullptr; neighbors_[1] = NULL;
} }
else else
{ {
neighbors_[2] = nullptr; neighbors_[2] = NULL;
} }
} }
void Triangle::ClearNeighbors() void Triangle::ClearNeighbors()
{ {
neighbors_[0] = nullptr; neighbors_[0] = NULL;
neighbors_[1] = nullptr; neighbors_[1] = NULL;
neighbors_[2] = nullptr; neighbors_[2] = NULL;
} }
void Triangle::ClearDelunayEdges() void Triangle::ClearDelunayEdges()
@ -228,7 +220,7 @@ Point* Triangle::PointCW(const Point& point)
return points_[1]; return points_[1];
} }
assert(0); assert(0);
return nullptr; return NULL;
} }
// The point counter-clockwise to given point // The point counter-clockwise to given point
@ -242,18 +234,7 @@ Point* Triangle::PointCCW(const Point& point)
return points_[0]; return points_[0];
} }
assert(0); assert(0);
return nullptr; return NULL;
}
// The neighbor across to given point
Triangle* Triangle::NeighborAcross(const Point& point)
{
if (&point == points_[0]) {
return neighbors_[0];
} else if (&point == points_[1]) {
return neighbors_[1];
}
return neighbors_[2];
} }
// The neighbor clockwise to given point // The neighbor clockwise to given point
@ -362,50 +343,23 @@ void Triangle::SetDelunayEdgeCW(const Point& p, bool e)
} }
} }
// The neighbor across to given point
Triangle& Triangle::NeighborAcross(const Point& opoint)
{
if (&opoint == points_[0]) {
return *neighbors_[0];
} else if (&opoint == points_[1]) {
return *neighbors_[1];
}
return *neighbors_[2];
}
void Triangle::DebugPrint() void Triangle::DebugPrint()
{ {
std::cout << *points_[0] << " " << *points_[1] << " " << *points_[2] << std::endl; using namespace std;
cout << points_[0]->x << "," << points_[0]->y << " ";
cout << points_[1]->x << "," << points_[1]->y << " ";
cout << points_[2]->x << "," << points_[2]->y << endl;
} }
bool Triangle::CircumcicleContains(const Point& point) const
{
assert(IsCounterClockwise());
const double dx = points_[0]->x - point.x;
const double dy = points_[0]->y - point.y;
const double ex = points_[1]->x - point.x;
const double ey = points_[1]->y - point.y;
const double fx = points_[2]->x - point.x;
const double fy = points_[2]->y - point.y;
const double ap = dx * dx + dy * dy;
const double bp = ex * ex + ey * ey;
const double cp = fx * fx + fy * fy;
return (dx * (fy * bp - cp * ey) - dy * (fx * bp - cp * ex) + ap * (fx * ey - fy * ex)) < 0;
} }
bool Triangle::IsCounterClockwise() const
{
return (points_[1]->x - points_[0]->x) * (points_[2]->y - points_[0]->y) -
(points_[2]->x - points_[0]->x) * (points_[1]->y - points_[0]->y) >
0;
}
bool IsDelaunay(const std::vector<p2t::Triangle*>& triangles)
{
for (const auto triangle : triangles) {
for (const auto other : triangles) {
if (triangle == other) {
continue;
}
for (int i = 0; i < 3; ++i) {
if (triangle->CircumcicleContains(*other->GetPoint(i))) {
return false;
}
}
}
}
return true;
}
} // namespace p2t

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,24 +29,22 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once // Include guard
#ifndef SHAPES_H
#define SHAPES_H
#include "dll_symbol.h" #include <vector>
#include <cmath>
#include <cstddef> #include <cstddef>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <assert.h>
#include <cmath>
#include <string>
#if defined(_WIN32)
# pragma warning( disable: 4251)
#endif
namespace p2t { namespace p2t {
struct Edge; struct Edge;
struct P2T_DLL_SYMBOL Point { struct Point {
double x, y; double x, y;
@ -61,7 +59,7 @@ struct P2T_DLL_SYMBOL Point {
std::vector<Edge*> edge_list; std::vector<Edge*> edge_list;
/// Construct using coordinates. /// Construct using coordinates.
Point(double x, double y); Point(double x, double y) : x(x), y(y) {}
/// Set this point to all zeros. /// Set this point to all zeros.
void set_zero() void set_zero()
@ -123,10 +121,8 @@ struct P2T_DLL_SYMBOL Point {
}; };
P2T_DLL_SYMBOL std::ostream& operator<<(std::ostream&, const Point&);
// Represents a simple polygon's edge // Represents a simple polygon's edge
struct P2T_DLL_SYMBOL Edge { struct Edge {
Point* p, *q; Point* p, *q;
@ -142,7 +138,9 @@ struct P2T_DLL_SYMBOL Edge {
p = &p2; p = &p2;
} else if (p1.x == p2.x) { } else if (p1.x == p2.x) {
// Repeat points // Repeat points
throw std::runtime_error("Edge::Edge: p1 == p2"); // ASSIMP_CHANGE (aramis_acg)
throw std::runtime_error(std::string("repeat points"));
//assert(false);
} }
} }
@ -153,7 +151,7 @@ struct P2T_DLL_SYMBOL Edge {
// Triangle-based data structures are know to have better performance than quad-edge structures // Triangle-based data structures are know to have better performance than quad-edge structures
// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" // See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator"
// "Triangulations in CGAL" // "Triangulations in CGAL"
class P2T_DLL_SYMBOL Triangle { class Triangle {
public: public:
/// Constructor /// Constructor
@ -180,7 +178,6 @@ void MarkConstrainedEdge(Point* p, Point* q);
int Index(const Point* p); int Index(const Point* p);
int EdgeIndex(const Point* p1, const Point* p2); int EdgeIndex(const Point* p1, const Point* p2);
Triangle* NeighborAcross(const Point& point);
Triangle* NeighborCW(const Point& point); Triangle* NeighborCW(const Point& point);
Triangle* NeighborCCW(const Point& point); Triangle* NeighborCCW(const Point& point);
bool GetConstrainedEdgeCCW(const Point& p); bool GetConstrainedEdgeCCW(const Point& p);
@ -208,14 +205,12 @@ void ClearDelunayEdges();
inline bool IsInterior(); inline bool IsInterior();
inline void IsInterior(bool b); inline void IsInterior(bool b);
Triangle& NeighborAcross(const Point& opoint);
void DebugPrint(); void DebugPrint();
bool CircumcicleContains(const Point&) const;
private: private:
bool IsCounterClockwise() const;
/// Triangle points /// Triangle points
Point* points_[3]; Point* points_[3];
/// Neighbor list /// Neighbor list
@ -263,7 +258,7 @@ inline bool operator ==(const Point& a, const Point& b)
inline bool operator !=(const Point& a, const Point& b) inline bool operator !=(const Point& a, const Point& b)
{ {
return !(a.x == b.x) || !(a.y == b.y); return !(a.x == b.x) && !(a.y == b.y);
} }
/// Peform the dot product on two vectors. /// Peform the dot product on two vectors.
@ -327,7 +322,6 @@ inline void Triangle::IsInterior(bool b)
interior_ = b; interior_ = b;
} }
/// Is this set a valid delaunay triangulation?
P2T_DLL_SYMBOL bool IsDelaunay(const std::vector<p2t::Triangle*>&);
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,15 +29,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #ifndef UTILS_H
#define UTILS_H
// Otherwise #defines like M_PI are undeclared under Visual Studio // Otherwise #defines like M_PI are undeclared under Visual Studio
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include "shapes.h"
#include <cmath>
#include <exception> #include <exception>
#include <math.h>
// C99 removes M_PI from math.h // C99 removes M_PI from math.h
#ifndef M_PI #ifndef M_PI
@ -67,11 +66,7 @@ Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc)
double detleft = (pa.x - pc.x) * (pb.y - pc.y); double detleft = (pa.x - pc.x) * (pb.y - pc.y);
double detright = (pa.y - pc.y) * (pb.x - pc.x); double detright = (pa.y - pc.y) * (pb.x - pc.x);
double val = detleft - detright; double val = detleft - detright;
if (val > -EPSILON && val < EPSILON) {
// Using a tolerance here fails on concave-by-subepsilon boundaries
// if (val > -EPSILON && val < EPSILON) {
// Using == on double makes -Wfloat-equal warnings yell at us
if (std::fpclassify(val) == FP_ZERO) {
return COLLINEAR; return COLLINEAR;
} else if (val > 0) { } else if (val > 0) {
return CCW; return CCW;
@ -128,3 +123,5 @@ bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point&
} }
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,7 +29,10 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #ifndef POLY2TRI_H
#define POLY2TRI_H
#include "common/shapes.h" #include "common/shapes.h"
#include "sweep/cdt.h" #include "sweep/cdt.h"
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -30,8 +30,6 @@
*/ */
#include "advancing_front.h" #include "advancing_front.h"
#include <cassert>
namespace p2t { namespace p2t {
AdvancingFront::AdvancingFront(Node& head, Node& tail) AdvancingFront::AdvancingFront(Node& head, Node& tail)
@ -46,21 +44,21 @@ Node* AdvancingFront::LocateNode(double x)
Node* node = search_node_; Node* node = search_node_;
if (x < node->value) { if (x < node->value) {
while ((node = node->prev) != nullptr) { while ((node = node->prev) != NULL) {
if (x >= node->value) { if (x >= node->value) {
search_node_ = node; search_node_ = node;
return node; return node;
} }
} }
} else { } else {
while ((node = node->next) != nullptr) { while ((node = node->next) != NULL) {
if (x < node->value) { if (x < node->value) {
search_node_ = node->prev; search_node_ = node->prev;
return node->prev; return node->prev;
} }
} }
} }
return nullptr; return NULL;
} }
Node* AdvancingFront::FindSearchNode(double x) Node* AdvancingFront::FindSearchNode(double x)
@ -88,13 +86,13 @@ Node* AdvancingFront::LocatePoint(const Point* point)
} }
} }
} else if (px < nx) { } else if (px < nx) {
while ((node = node->prev) != nullptr) { while ((node = node->prev) != NULL) {
if (point == node->point) { if (point == node->point) {
break; break;
} }
} }
} else { } else {
while ((node = node->next) != nullptr) { while ((node = node->next) != NULL) {
if (point == node->point) if (point == node->point)
break; break;
} }
@ -107,4 +105,4 @@ AdvancingFront::~AdvancingFront()
{ {
} }
} // namespace p2t }

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,7 +29,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #ifndef ADVANCED_FRONT_H
#define ADVANCED_FRONT_H
#include "../common/shapes.h" #include "../common/shapes.h"
@ -113,3 +114,5 @@ inline void AdvancingFront::set_search(Node* node)
} }
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2021, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -68,4 +68,4 @@ CDT::~CDT()
delete sweep_; delete sweep_;
} }
} // namespace p2t }

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,14 +29,13 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #ifndef CDT_H
#define CDT_H
#include "advancing_front.h" #include "advancing_front.h"
#include "sweep_context.h" #include "sweep_context.h"
#include "sweep.h" #include "sweep.h"
#include "../common/dll_symbol.h"
/** /**
* *
* @author Mason Green <mason.green@gmail.com> * @author Mason Green <mason.green@gmail.com>
@ -45,7 +44,7 @@
namespace p2t { namespace p2t {
class P2T_DLL_SYMBOL CDT class CDT
{ {
public: public:
@ -102,3 +101,5 @@ public:
}; };
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -28,21 +28,24 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdexcept>
#include "sweep.h" #include "sweep.h"
#include "sweep_context.h" #include "sweep_context.h"
#include "advancing_front.h" #include "advancing_front.h"
#include "../common/utils.h" #include "../common/utils.h"
#include <cassert>
#include <stdexcept>
namespace p2t { namespace p2t {
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning( disable : 4702 )
#endif // _MSC_VER
// Triangulate simple polygon with holes // Triangulate simple polygon with holes
void Sweep::Triangulate(SweepContext& tcx) void Sweep::Triangulate(SweepContext& tcx)
{ {
tcx.InitTriangulation(); tcx.InitTriangulation();
tcx.CreateAdvancingFront(); tcx.CreateAdvancingFront(nodes_);
// Sweep points; build mesh // Sweep points; build mesh
SweepPoints(tcx); SweepPoints(tcx);
// Clean up // Clean up
@ -54,8 +57,8 @@ void Sweep::SweepPoints(SweepContext& tcx)
for (size_t i = 1; i < tcx.point_count(); i++) { for (size_t i = 1; i < tcx.point_count(); i++) {
Point& point = *tcx.GetPoint(i); Point& point = *tcx.GetPoint(i);
Node* node = &PointEvent(tcx, point); Node* node = &PointEvent(tcx, point);
for (auto& j : point.edge_list) { for (unsigned int ii = 0; ii < point.edge_list.size(); ii++) {
EdgeEvent(tcx, j, node); EdgeEvent(tcx, point.edge_list[ii], node);
} }
} }
} }
@ -65,25 +68,17 @@ void Sweep::FinalizationPolygon(SweepContext& tcx)
// Get an Internal triangle to start with // Get an Internal triangle to start with
Triangle* t = tcx.front()->head()->next->triangle; Triangle* t = tcx.front()->head()->next->triangle;
Point* p = tcx.front()->head()->next->point; Point* p = tcx.front()->head()->next->point;
while (t && !t->GetConstrainedEdgeCW(*p)) { while (!t->GetConstrainedEdgeCW(*p)) {
t = t->NeighborCCW(*p); t = t->NeighborCCW(*p);
} }
// Collect interior triangles constrained by edges // Collect interior triangles constrained by edges
if (t) { tcx.MeshClean(*t);
tcx.MeshClean(*t);
}
} }
Node& Sweep::PointEvent(SweepContext& tcx, Point& point) Node& Sweep::PointEvent(SweepContext& tcx, Point& point)
{ {
Node* node_ptr = tcx.LocateNode(point); Node& node = tcx.LocateNode(point);
if (!node_ptr || !node_ptr->point || !node_ptr->next || !node_ptr->next->point)
{
throw std::runtime_error("PointEvent - null node");
}
Node& node = *node_ptr;
Node& new_node = NewFrontTriangle(tcx, point, node); Node& new_node = NewFrontTriangle(tcx, point, node);
// Only need to check +epsilon since point never have smaller // Only need to check +epsilon since point never have smaller
@ -116,9 +111,9 @@ void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node)
void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point)
{ {
if (triangle == nullptr) { if (triangle == nullptr)
throw std::runtime_error("EdgeEvent - null triangle"); return;
}
if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { if (IsEdgeSideOfTriangle(*triangle, ep, eq)) {
return; return;
} }
@ -126,14 +121,17 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
Point* p1 = triangle->PointCCW(point); Point* p1 = triangle->PointCCW(point);
Orientation o1 = Orient2d(eq, *p1, ep); Orientation o1 = Orient2d(eq, *p1, ep);
if (o1 == COLLINEAR) { if (o1 == COLLINEAR) {
if (triangle->Contains(&eq, p1)) {
triangle->MarkConstrainedEdge(&eq, p1);
if( triangle->Contains(&eq, p1)) {
triangle->MarkConstrainedEdge(&eq, p1 );
// We are modifying the constraint maybe it would be better to // We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint // not change the given constraint and just keep a variable for the new constraint
tcx.edge_event.constrained_edge->q = p1; tcx.edge_event.constrained_edge->q = p1;
triangle = triangle->NeighborAcross(point); triangle = &triangle->NeighborAcross(point);
EdgeEvent(tcx, ep, *p1, triangle, *p1); EdgeEvent( tcx, ep, *p1, triangle, *p1 );
} else { } else {
// ASSIMP_CHANGE (aramis_acg)
throw std::runtime_error("EdgeEvent - collinear points not supported"); throw std::runtime_error("EdgeEvent - collinear points not supported");
} }
return; return;
@ -142,14 +140,18 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
Point* p2 = triangle->PointCW(point); Point* p2 = triangle->PointCW(point);
Orientation o2 = Orient2d(eq, *p2, ep); Orientation o2 = Orient2d(eq, *p2, ep);
if (o2 == COLLINEAR) { if (o2 == COLLINEAR) {
if (triangle->Contains(&eq, p2)) {
triangle->MarkConstrainedEdge(&eq, p2);
if( triangle->Contains(&eq, p2)) {
triangle->MarkConstrainedEdge(&eq, p2 );
// We are modifying the constraint maybe it would be better to // We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint // not change the given constraint and just keep a variable for the new constraint
tcx.edge_event.constrained_edge->q = p2; tcx.edge_event.constrained_edge->q = p2;
triangle = triangle->NeighborAcross(point); triangle = &triangle->NeighborAcross(point);
EdgeEvent(tcx, ep, *p2, triangle, *p2); EdgeEvent( tcx, ep, *p2, triangle, *p2 );
} else { } else {
// ASSIMP_CHANGE (aramis_acg)
throw std::runtime_error("EdgeEvent - collinear points not supported"); throw std::runtime_error("EdgeEvent - collinear points not supported");
} }
return; return;
@ -160,13 +162,12 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
// that will cross edge // that will cross edge
if (o1 == CW) { if (o1 == CW) {
triangle = triangle->NeighborCCW(point); triangle = triangle->NeighborCCW(point);
} else { } else{
triangle = triangle->NeighborCW(point); triangle = triangle->NeighborCW(point);
} }
EdgeEvent(tcx, ep, eq, triangle, point); EdgeEvent(tcx, ep, eq, triangle, point);
} else { } else {
// This triangle crosses constraint so lets flippin start! // This triangle crosses constraint so lets flippin start!
assert(triangle);
FlipEdgeEvent(tcx, ep, eq, triangle, point); FlipEdgeEvent(tcx, ep, eq, triangle, point);
} }
} }
@ -227,6 +228,7 @@ void Sweep::Fill(SweepContext& tcx, Node& node)
if (!Legalize(tcx, *triangle)) { if (!Legalize(tcx, *triangle)) {
tcx.MapTriangleToNodes(*triangle); tcx.MapTriangleToNodes(*triangle);
} }
} }
void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
@ -235,7 +237,7 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
// Fill right holes // Fill right holes
Node* node = n.next; Node* node = n.next;
while (node && node->next) { while (node->next) {
// if HoleAngle exceeds 90 degrees then break. // if HoleAngle exceeds 90 degrees then break.
if (LargeHole_DontFill(node)) break; if (LargeHole_DontFill(node)) break;
Fill(tcx, *node); Fill(tcx, *node);
@ -245,7 +247,7 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
// Fill left holes // Fill left holes
node = n.prev; node = n.prev;
while (node && node->prev) { while (node->prev) {
// if HoleAngle exceeds 90 degrees then break. // if HoleAngle exceeds 90 degrees then break.
if (LargeHole_DontFill(node)) break; if (LargeHole_DontFill(node)) break;
Fill(tcx, *node); Fill(tcx, *node);
@ -262,35 +264,6 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
} }
// True if HoleAngle exceeds 90 degrees. // True if HoleAngle exceeds 90 degrees.
// LargeHole_DontFill checks if the advancing front has a large hole.
// A "Large hole" is a triangle formed by a sequence of points in the advancing
// front where three neighbor points form a triangle.
// And angle between left-top, bottom, and right-top points is more than 90 degrees.
// The first part of the algorithm reviews only three neighbor points, e.g. named A, B, C.
// Additional part of this logic reviews a sequence of 5 points -
// additionally reviews one point before and one after the sequence of three (A, B, C),
// e.g. named X and Y.
// In this case, angles are XBC and ABY and this if angles are negative or more
// than 90 degrees LargeHole_DontFill returns true.
// But there is a configuration when ABC has a negative angle but XBC or ABY is less
// than 90 degrees and positive.
// Then function LargeHole_DontFill return false and initiates filling.
// This filling creates a triangle ABC and adds it to the advancing front.
// But in the case when angle ABC is negative this triangle goes inside the advancing front
// and can intersect previously created triangles.
// This triangle leads to making wrong advancing front and problems in triangulation in the future.
// Looks like such a triangle should not be created.
// The simplest way to check and fix it is to check an angle ABC.
// If it is negative LargeHole_DontFill should return true and
// not initiate creating the ABC triangle in the advancing front.
// X______A Y
// \ /
// \ /
// \ B /
// | /
// | /
// |/
// C
bool Sweep::LargeHole_DontFill(const Node* node) const { bool Sweep::LargeHole_DontFill(const Node* node) const {
const Node* nextNode = node->next; const Node* nextNode = node->next;
@ -298,28 +271,20 @@ bool Sweep::LargeHole_DontFill(const Node* node) const {
if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point)) if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point))
return false; return false;
if (AngleIsNegative(node->point, nextNode->point, prevNode->point))
return true;
// Check additional points on front. // Check additional points on front.
const Node* next2Node = nextNode->next; const Node* next2Node = nextNode->next;
// "..Plus.." because only want angles on same side as point being added. // "..Plus.." because only want angles on same side as point being added.
if ((next2Node != nullptr) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point)) if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point))
return false; return false;
const Node* prev2Node = prevNode->prev; const Node* prev2Node = prevNode->prev;
// "..Plus.." because only want angles on same side as point being added. // "..Plus.." because only want angles on same side as point being added.
if ((prev2Node != nullptr) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point)) if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point))
return false; return false;
return true; return true;
} }
bool Sweep::AngleIsNegative(const Point* origin, const Point* pa, const Point* pb) const {
const double angle = Angle(origin, pa, pb);
return angle < 0;
}
bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const { bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const {
const double angle = Angle(origin, pa, pb); const double angle = Angle(origin, pa, pb);
return ((angle > PI_div2) || (angle < -PI_div2)); return ((angle > PI_div2) || (angle < -PI_div2));
@ -341,7 +306,7 @@ double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const
*/ */
const double px = origin->x; const double px = origin->x;
const double py = origin->y; const double py = origin->y;
const double ax = pa->x - px; const double ax = pa->x- px;
const double ay = pa->y - py; const double ay = pa->y - py;
const double bx = pb->x - px; const double bx = pb->x - px;
const double by = pb->y - py; const double by = pb->y - py;
@ -634,7 +599,7 @@ void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {
// Concave // Concave
FillRightConcaveEdgeEvent(tcx, edge, node); FillRightConcaveEdgeEvent(tcx, edge, node);
} else { } else{
// Convex // Convex
FillRightConvexEdgeEvent(tcx, edge, node); FillRightConvexEdgeEvent(tcx, edge, node);
// Retry this one // Retry this one
@ -658,6 +623,7 @@ void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
} }
} }
} }
} }
void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
@ -666,13 +632,13 @@ void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) {
// Concave // Concave
FillRightConcaveEdgeEvent(tcx, edge, *node.next); FillRightConcaveEdgeEvent(tcx, edge, *node.next);
} else { } else{
// Convex // Convex
// Next above or below edge? // Next above or below edge?
if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) {
// Below // Below
FillRightConvexEdgeEvent(tcx, edge, *node.next); FillRightConvexEdgeEvent(tcx, edge, *node.next);
} else { } else{
// Above // Above
} }
} }
@ -711,13 +677,13 @@ void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) {
// Concave // Concave
FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); FillLeftConcaveEdgeEvent(tcx, edge, *node.prev);
} else { } else{
// Convex // Convex
// Next above or below edge? // Next above or below edge?
if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) {
// Below // Below
FillLeftConvexEdgeEvent(tcx, edge, *node.prev); FillLeftConvexEdgeEvent(tcx, edge, *node.prev);
} else { } else{
// Above // Above
} }
} }
@ -733,22 +699,17 @@ void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {
// Next is concave // Next is concave
FillLeftConcaveEdgeEvent(tcx, edge, node); FillLeftConcaveEdgeEvent(tcx, edge, node);
} else { } else{
// Next is convex // Next is convex
} }
} }
} }
} }
void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p) void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p)
{ {
assert(t); Triangle& ot = t->NeighborAcross(p);
Triangle* ot_ptr = t->NeighborAcross(p);
if (ot_ptr == nullptr)
{
throw std::runtime_error("FlipEdgeEvent - null neighbor across");
}
Triangle& ot = *ot_ptr;
Point& op = *ot.OppositePoint(*t, p); Point& op = *ot.OppositePoint(*t, p);
if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) { if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) {
@ -814,26 +775,10 @@ Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
Triangle& t, Point& p) Triangle& t, Point& p)
{ {
Triangle* ot_ptr = t.NeighborAcross(p); Triangle& ot = t.NeighborAcross(p);
if (ot_ptr == nullptr) { Point& op = *ot.OppositePoint(t, p);
throw std::runtime_error("FlipScanEdgeEvent - null neighbor across");
}
Point* op_ptr = ot_ptr->OppositePoint(t, p); if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) {
if (op_ptr == nullptr) {
throw std::runtime_error("FlipScanEdgeEvent - null opposing point");
}
Point* p1 = flip_triangle.PointCCW(eq);
Point* p2 = flip_triangle.PointCW(eq);
if (p1 == nullptr || p2 == nullptr) {
throw std::runtime_error("FlipScanEdgeEvent - null on either of points");
}
Triangle& ot = *ot_ptr;
Point& op = *op_ptr;
if (InScanArea(eq, *p1, *p2, op)) {
// flip with new edge op->eq // flip with new edge op->eq
FlipEdgeEvent(tcx, eq, op, &ot, op); FlipEdgeEvent(tcx, eq, op, &ot, op);
// TODO: Actually I just figured out that it should be possible to // TODO: Actually I just figured out that it should be possible to
@ -843,7 +788,7 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
// also need to set a new flip_triangle first // also need to set a new flip_triangle first
// Turns out at first glance that this is somewhat complicated // Turns out at first glance that this is somewhat complicated
// so it will have to wait. // so it will have to wait.
} else { } else{
Point& newP = NextFlipPoint(ep, eq, ot, op); Point& newP = NextFlipPoint(ep, eq, ot, op);
FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP);
} }
@ -852,9 +797,14 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
Sweep::~Sweep() { Sweep::~Sweep() {
// Clean up memory // Clean up memory
for (auto& node : nodes_) { for(size_t i = 0; i < nodes_.size(); i++) {
delete node; delete nodes_[i];
} }
} }
} // namespace p2t #ifdef _MSC_VER
# pragma warning( pop )
#endif // _MSC_VER
}

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -33,10 +33,11 @@
* Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation', * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
* International Journal of Geographical Information Science * International Journal of Geographical Information Science
* *
* "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com * "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, thahlen@gmail.com
*/ */
#pragma once #ifndef SWEEP_H
#define SWEEP_H
#include <vector> #include <vector>
@ -171,7 +172,6 @@ private:
// Decision-making about when to Fill hole. // Decision-making about when to Fill hole.
// Contributed by ToolmakerSteve2 // Contributed by ToolmakerSteve2
bool LargeHole_DontFill(const Node* node) const; bool LargeHole_DontFill(const Node* node) const;
bool AngleIsNegative(const Point* origin, const Point* pa, const Point* pb) const;
bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const; bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const;
bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const; bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const;
double Angle(const Point* origin, const Point* pa, const Point* pb) const; double Angle(const Point* origin, const Point* pa, const Point* pb) const;
@ -281,3 +281,5 @@ private:
}; };
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -34,13 +34,13 @@
namespace p2t { namespace p2t {
SweepContext::SweepContext(std::vector<Point*> polyline) : points_(std::move(polyline)), SweepContext::SweepContext(const std::vector<Point*>& polyline) : points_(polyline),
front_(nullptr), front_(0),
head_(nullptr), head_(0),
tail_(nullptr), tail_(0),
af_head_(nullptr), af_head_(0),
af_middle_(nullptr), af_middle_(0),
af_tail_(nullptr) af_tail_(0)
{ {
InitEdges(points_); InitEdges(points_);
} }
@ -48,8 +48,8 @@ SweepContext::SweepContext(std::vector<Point*> polyline) : points_(std::move(pol
void SweepContext::AddHole(const std::vector<Point*>& polyline) void SweepContext::AddHole(const std::vector<Point*>& polyline)
{ {
InitEdges(polyline); InitEdges(polyline);
for (auto i : polyline) { for(unsigned int i = 0; i < polyline.size(); i++) {
points_.push_back(i); points_.push_back(polyline[i]);
} }
} }
@ -73,8 +73,8 @@ void SweepContext::InitTriangulation()
double ymax(points_[0]->y), ymin(points_[0]->y); double ymax(points_[0]->y), ymin(points_[0]->y);
// Calculate bounds. // Calculate bounds.
for (auto& point : points_) { for (unsigned int i = 0; i < points_.size(); i++) {
Point& p = *point; Point& p = *points_[i];
if (p.x > xmax) if (p.x > xmax)
xmax = p.x; xmax = p.x;
if (p.x < xmin) if (p.x < xmin)
@ -87,8 +87,8 @@ void SweepContext::InitTriangulation()
double dx = kAlpha * (xmax - xmin); double dx = kAlpha * (xmax - xmin);
double dy = kAlpha * (ymax - ymin); double dy = kAlpha * (ymax - ymin);
head_ = new Point(xmin - dx, ymin - dy); head_ = new Point(xmax + dx, ymin - dy);
tail_ = new Point(xmax + dx, ymin - dy); tail_ = new Point(xmin - dx, ymin - dy);
// Sort points along y-axis // Sort points along y-axis
std::sort(points_.begin(), points_.end(), cmp); std::sort(points_.begin(), points_.end(), cmp);
@ -114,17 +114,18 @@ void SweepContext::AddToMap(Triangle* triangle)
map_.push_back(triangle); map_.push_back(triangle);
} }
Node* SweepContext::LocateNode(const Point& point) Node& SweepContext::LocateNode(const Point& point)
{ {
// TODO implement search tree // TODO implement search tree
return front_->LocateNode(point.x); return *front_->LocateNode(point.x);
} }
void SweepContext::CreateAdvancingFront() void SweepContext::CreateAdvancingFront(const std::vector<Node*>& nodes)
{ {
(void) nodes;
// Initial triangle // Initial triangle
Triangle* triangle = new Triangle(*points_[0], *head_, *tail_); Triangle* triangle = new Triangle(*points_[0], *tail_, *head_);
map_.push_back(triangle); map_.push_back(triangle);
@ -171,7 +172,7 @@ void SweepContext::MeshClean(Triangle& triangle)
Triangle *t = triangles.back(); Triangle *t = triangles.back();
triangles.pop_back(); triangles.pop_back();
if (t != nullptr && !t->IsInterior()) { if (t != NULL && !t->IsInterior()) {
t->IsInterior(true); t->IsInterior(true);
triangles_.push_back(t); triangles_.push_back(t);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
@ -194,13 +195,17 @@ SweepContext::~SweepContext()
delete af_middle_; delete af_middle_;
delete af_tail_; delete af_tail_;
for (auto ptr : map_) { typedef std::list<Triangle*> type_list;
delete ptr;
for(type_list::iterator iter = map_.begin(); iter != map_.end(); ++iter) {
Triangle* ptr = *iter;
delete ptr;
} }
for (auto& i : edge_list) { for(unsigned int i = 0; i < edge_list.size(); i++) {
delete i; delete edge_list[i];
} }
} }
} // namespace p2t }

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri * http://code.google.com/p/poly2tri/
* *
* All rights reserved. * All rights reserved.
* *
@ -29,7 +29,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #ifndef SWEEP_CONTEXT_H
#define SWEEP_CONTEXT_H
#include <list> #include <list>
#include <vector> #include <vector>
@ -51,7 +52,7 @@ class SweepContext {
public: public:
/// Constructor /// Constructor
explicit SweepContext(std::vector<Point*> polyline); SweepContext(const std::vector<Point*>& polyline);
/// Destructor /// Destructor
~SweepContext(); ~SweepContext();
@ -65,11 +66,11 @@ Point* tail() const;
size_t point_count() const; size_t point_count() const;
Node* LocateNode(const Point& point); Node& LocateNode(const Point& point);
void RemoveNode(Node* node); void RemoveNode(Node* node);
void CreateAdvancingFront(); void CreateAdvancingFront(const std::vector<Node*>& nodes);
/// Try to map a node to all sides of this triangle that don't have a neighbor /// Try to map a node to all sides of this triangle that don't have a neighbor
void MapTriangleToNodes(Triangle& t); void MapTriangleToNodes(Triangle& t);
@ -102,16 +103,15 @@ struct Basin {
double width; double width;
bool left_highest; bool left_highest;
Basin() Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false)
: left_node(nullptr), bottom_node(nullptr), right_node(nullptr), width(0.0), left_highest(false)
{ {
} }
void Clear() void Clear()
{ {
left_node = nullptr; left_node = NULL;
bottom_node = nullptr; bottom_node = NULL;
right_node = nullptr; right_node = NULL;
width = 0.0; width = 0.0;
left_highest = false; left_highest = false;
} }
@ -182,3 +182,5 @@ inline Point* SweepContext::tail() const
} }
} }
#endif

View File

@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) {
aiLogStream stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, nullptr); aiLogStream stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL);
aiAttachLogStream(&stream); aiAttachLogStream(&stream);
Importer importer; Importer importer;

View File

@ -57,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma GCC system_header #pragma GCC system_header
#endif #endif
#include <assimp/StringComparison.h>
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/defs.h> #include <assimp/defs.h>

View File

@ -58,7 +58,6 @@ extern "C" {
#endif #endif
struct aiScene; struct aiScene;
struct aiTexture;
struct aiFileIO; struct aiFileIO;
typedef void (*aiLogStreamCallback)(const char * /* message */, char * /* user */); typedef void (*aiLogStreamCallback)(const char * /* message */, char * /* user */);
@ -374,13 +373,6 @@ ASSIMP_API void aiGetMemoryRequirements(
const C_STRUCT aiScene *pIn, const C_STRUCT aiScene *pIn,
C_STRUCT aiMemoryInfo *in); C_STRUCT aiMemoryInfo *in);
// --------------------------------------------------------------------------------
/** Returns an embedded texture, or nullptr.
* @param pIn Input asset.
* @param filename Texture path extracted from aiGetMaterialString.
*/
ASSIMP_API const C_STRUCT aiTexture *aiGetEmbeddedTexture(const C_STRUCT aiScene *pIn, const char *filename);
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
/** Create an empty property store. Property stores are used to collect import /** Create an empty property store. Property stores are used to collect import
* settings. * settings.

View File

@ -676,19 +676,6 @@ enum aiComponent
#define AI_CONFIG_FBX_CONVERT_TO_M \ #define AI_CONFIG_FBX_CONVERT_TO_M \
"AI_CONFIG_FBX_CONVERT_TO_M" "AI_CONFIG_FBX_CONVERT_TO_M"
// ---------------------------------------------------------------------------
/** @brief Set whether the FBX importer shall ignore the provided axis configuration
*
* If this property is set to true, the axis directions provided in the FBX file
* will be ignored and the file will be loaded as is.
*
* Set to true for Assimp 5.3.x and earlier behavior
* Equivalent to AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION
* Property type: Bool. Default value: false.
*/
#define AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION \
"AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Will enable the skeleton struct to store bone data. /** @brief Will enable the skeleton struct to store bone data.
* *
@ -737,12 +724,6 @@ enum aiComponent
*/ */
#define AI_CONFIG_IMPORT_MDL_HL1_READ_ANIMATION_EVENTS "IMPORT_MDL_HL1_READ_ANIMATION_EVENTS" #define AI_CONFIG_IMPORT_MDL_HL1_READ_ANIMATION_EVENTS "IMPORT_MDL_HL1_READ_ANIMATION_EVENTS"
// ---------------------------------------------------------------------------
/** @brief Set whether you want to convert the HS1 coordinate system in a special way.
* The default value is true (S1)
* Property type: bool
*/
#define AI_CONFIG_IMPORT_MDL_HL1_TRANSFORM_COORD_SYSTEM "TRANSFORM COORDSYSTEM FOR HS! MODELS"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Set whether the MDL (HL1) importer will read blend controllers. /** @brief Set whether the MDL (HL1) importer will read blend controllers.
* \note This property requires AI_CONFIG_IMPORT_MDL_HL1_READ_ANIMATIONS to be set to true. * \note This property requires AI_CONFIG_IMPORT_MDL_HL1_READ_ANIMATIONS to be set to true.

View File

@ -49,16 +49,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_DEFINES_H_INC #define AI_DEFINES_H_INC
#ifdef __GNUC__ #ifdef __GNUC__
# pragma GCC system_header #pragma GCC system_header
#endif #endif
#include <assimp/config.h> #include <assimp/config.h>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
/** /* Define ASSIMP_BUILD_NO_XX_IMPORTER to disable a specific
* @brief Define ASSIMP_BUILD_NO_XX_IMPORTER to disable a specific file format loader. * file format loader. The loader is be excluded from the
*
* The loader is be excluded from the
* build in this case. 'XX' stands for the most common file * build in this case. 'XX' stands for the most common file
* extension of the file format. E.g.: * extension of the file format. E.g.:
* ASSIMP_BUILD_NO_X_IMPORTER disables the X loader. * ASSIMP_BUILD_NO_X_IMPORTER disables the X loader.
@ -78,33 +76,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifndef ASSIMP_BUILD_NO_COMPRESSED_X #ifndef ASSIMP_BUILD_NO_COMPRESSED_X
# define ASSIMP_BUILD_NEED_Z_INFLATE #define ASSIMP_BUILD_NEED_Z_INFLATE
#endif #endif
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
# define ASSIMP_BUILD_NEED_Z_INFLATE #define ASSIMP_BUILD_NEED_Z_INFLATE
#endif #endif
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC #ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
# define ASSIMP_BUILD_NEED_Z_INFLATE #define ASSIMP_BUILD_NEED_Z_INFLATE
# define ASSIMP_BUILD_NEED_UNZIP #define ASSIMP_BUILD_NEED_UNZIP
#endif #endif
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
# define ASSIMP_BUILD_NEED_Z_INFLATE #define ASSIMP_BUILD_NEED_Z_INFLATE
# define ASSIMP_BUILD_NEED_UNZIP #define ASSIMP_BUILD_NEED_UNZIP
#endif #endif
/** // We need those constants, workaround for any platforms where nobody defined them yet
* @brief We need those constants, workaround for any platforms where nobody defined them yet.
*/
#if (!defined SIZE_MAX) #if (!defined SIZE_MAX)
# define SIZE_MAX (~((size_t)0)) #define SIZE_MAX (~((size_t)0))
#endif #endif
/*#if (!defined UINT_MAX)
#define UINT_MAX (~((unsigned int)0))
#endif*/
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
/** @brief Define ASSIMP_BUILD_NO_XX_PROCESS to disable a specific /* Define ASSIMP_BUILD_NO_XX_PROCESS to disable a specific
*
* post processing step. This is the current list of process names ('XX'): * post processing step. This is the current list of process names ('XX'):
* CALCTANGENTS * CALCTANGENTS
* JOINVERTICES * JOINVERTICES
@ -135,50 +134,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* OPTIMIZEGRAPH * OPTIMIZEGRAPH
* GENENTITYMESHES * GENENTITYMESHES
* FIXTEXTUREPATHS * FIXTEXTUREPATHS
* GENBOUNDINGBOXES * GENBOUNDINGBOXES */
*/ //////////////////////////////////////////////////////////////////////////
#ifdef _WIN32
#undef ASSIMP_API
//////////////////////////////////////////////////////////////////////////
/* Define 'ASSIMP_BUILD_DLL_EXPORT' to build a DLL of the library */
//////////////////////////////////////////////////////////////////////////
#ifdef ASSIMP_BUILD_DLL_EXPORT
#define ASSIMP_API __declspec(dllexport)
#define ASSIMP_API_WINONLY __declspec(dllexport)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
/** @brief Define 'ASSIMP_BUILD_DLL_EXPORT' to build a DLL of the library /* Define 'ASSIMP_DLL' before including Assimp to link to ASSIMP in
* * an external DLL under Windows. Default is static linkage. */
* Define 'ASSIMP_DLL' before including Assimp to link to ASSIMP in
* an external DLL under Windows. Default is static linkage.
*/
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifdef _WIN32 #elif (defined ASSIMP_DLL)
# undef ASSIMP_API #define ASSIMP_API __declspec(dllimport)
# ifdef ASSIMP_BUILD_DLL_EXPORT #define ASSIMP_API_WINONLY __declspec(dllimport)
# define ASSIMP_API __declspec(dllexport) #else
# define ASSIMP_API_WINONLY __declspec(dllexport) #define ASSIMP_API
# elif (defined ASSIMP_DLL) #define ASSIMP_API_WINONLY
# define ASSIMP_API __declspec(dllimport) #endif
# define ASSIMP_API_WINONLY __declspec(dllimport) #elif defined(SWIG)
# else /* Do nothing, the relevant defines are all in AssimpSwigPort.i */
# define ASSIMP_API #else
# define ASSIMP_API_WINONLY #define ASSIMP_API __attribute__((visibility("default")))
# endif #define ASSIMP_API_WINONLY
#else
# define ASSIMP_API __attribute__((visibility("default")))
# define ASSIMP_API_WINONLY
#endif // _WIN32 #endif // _WIN32
/**
* @brief Helper macros
*
* @def AI_FORCE_INLINE
* @brief Force the compiler to inline a function, if possible
*
* @def AI_WONT_RETURN
* @brief Tells the compiler that a function never returns.
*
* Used in code analysis to skip dead paths (e.g. after an assertion evaluated to false).
*/
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4521 4512 4714 4127 4351 4510) #pragma warning(disable : 4521 4512 4714 4127 4351 4510)
#ifdef ASSIMP_BUILD_DLL_EXPORT #ifdef ASSIMP_BUILD_DLL_EXPORT
#pragma warning(disable : 4251) #pragma warning(disable : 4251)
#endif #endif
/* Force the compiler to inline a function, if possible */
#define AI_FORCE_INLINE inline #define AI_FORCE_INLINE inline
/* Tells the compiler that a function never returns. Used in code analysis
* to skip dead paths (e.g. after an assertion evaluated to false). */
#define AI_WONT_RETURN __declspec(noreturn) #define AI_WONT_RETURN __declspec(noreturn)
#elif defined(SWIG) #elif defined(SWIG)
/* Do nothing, the relevant defines are all in AssimpSwigPort.i */ /* Do nothing, the relevant defines are all in AssimpSwigPort.i */
@ -228,31 +223,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* to typedef all structs/enums. */ * to typedef all structs/enums. */
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#if (defined ASSIMP_DOXYGEN_BUILD) #if (defined ASSIMP_DOXYGEN_BUILD)
# define C_STRUCT #define C_STRUCT
# define C_ENUM #define C_ENUM
#else #else
# define C_STRUCT struct #define C_STRUCT struct
# define C_ENUM enum #define C_ENUM enum
#endif #endif
#endif #endif
#if (defined(__BORLANDC__) || defined(__BCPLUSPLUS__)) #if (defined(__BORLANDC__) || defined(__BCPLUSPLUS__))
# error Currently, Borland is unsupported. Feel free to port Assimp. #error Currently, Borland is unsupported. Feel free to port Assimp.
#endif #endif
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
/** /* Define ASSIMP_BUILD_SINGLETHREADED to compile assimp
* Define ASSIMP_BUILD_SINGLETHREADED to compile assimp * without threading support. The library doesn't utilize
* without threading support. The library doesn't utilize * threads then and is itself not threadsafe. */
* threads then and is itself not threadsafe.
*/
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
# define ASSIMP_BUILD_SINGLETHREADED #define ASSIMP_BUILD_SINGLETHREADED
#endif #endif
#if defined(_DEBUG) || !defined(NDEBUG) #if defined(_DEBUG) || !defined(NDEBUG)
# define ASSIMP_BUILD_DEBUG #define ASSIMP_BUILD_DEBUG
#endif #endif
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -298,74 +291,55 @@ typedef unsigned int ai_uint;
#ifdef __cplusplus #ifdef __cplusplus
constexpr ai_real ai_epsilon = (ai_real) 1e-6; constexpr ai_real ai_epsilon = (ai_real) 1e-6;
#else #else
# define ai_epsilon ((ai_real)1e-6) #define ai_epsilon ((ai_real)1e-6)
#endif #endif
/** /* Support for big-endian builds */
* @brief Support for big-endian builds
*
* This will check which byte ordering is used on the target architecture.
*/
#if defined(__BYTE_ORDER__) #if defined(__BYTE_ORDER__)
# if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
# if !defined(__BIG_ENDIAN__) #if !defined(__BIG_ENDIAN__)
# define __BIG_ENDIAN__ #define __BIG_ENDIAN__
# endif #endif
# else /* little endian */ #else /* little endian */
# if defined(__BIG_ENDIAN__) #if defined(__BIG_ENDIAN__)
# undef __BIG_ENDIAN__ #undef __BIG_ENDIAN__
# endif #endif
# endif #endif
#endif #endif
#if defined(__BIG_ENDIAN__) #if defined(__BIG_ENDIAN__)
# define AI_BUILD_BIG_ENDIAN #define AI_BUILD_BIG_ENDIAN
#endif #endif
/** /**
* @brief To avoid running out of memory * To avoid running out of memory
*
* This can be adjusted for specific use cases * This can be adjusted for specific use cases
* It's NOT a total limit, just a limit for individual allocations * It's NOT a total limit, just a limit for individual allocations
*/ */
#define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type)) #define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type))
#ifndef _MSC_VER #ifndef _MSC_VER
# if __cplusplus >= 201103L // C++11 #if __cplusplus >= 201103L // C++11
# define AI_NO_EXCEPT noexcept #define AI_NO_EXCEPT noexcept
# else
# define AI_NO_EXCEPT
# endif
#else #else
# if (_MSC_VER >= 1915) #define AI_NO_EXCEPT
# define AI_NO_EXCEPT noexcept #endif
# else #else
# define AI_NO_EXCEPT #if (_MSC_VER >= 1915)
# endif #define AI_NO_EXCEPT noexcept
#else
#define AI_NO_EXCEPT
#endif
#endif // _MSC_VER #endif // _MSC_VER
/** /**
* @brief Helper macro to set a pointer to NULL in debug builds * Helper macro to set a pointer to NULL in debug builds
*/ */
#if (defined ASSIMP_BUILD_DEBUG) #if (defined ASSIMP_BUILD_DEBUG)
# define AI_DEBUG_INVALIDATE_PTR(x) x = NULL; #define AI_DEBUG_INVALIDATE_PTR(x) x = NULL;
#else #else
# define AI_DEBUG_INVALIDATE_PTR(x) #define AI_DEBUG_INVALIDATE_PTR(x)
#endif #endif
#define AI_COUNT_OF(X) (sizeof(X) / sizeof((X)[0])) #define AI_COUNT_OF(X) (sizeof(X) / sizeof((X)[0]))
/**
* @brief Will mark functions or classes as deprecated.
*
* Deprecation means that we will remove this function, class or methods in the next m
*/
#if defined(__GNUC__) || defined(__clang__)
# define AI_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
# define AI_DEPRECATED __declspec(deprecated)
#else
# pragma message("WARNING: You need to implement DEPRECATED for this compiler")
# define AI_DEPRECATED
#endif
#endif // !! AI_DEFINES_H_INC #endif // !! AI_DEFINES_H_INC

View File

@ -292,14 +292,6 @@ enum aiTextureType {
aiTextureType_DIFFUSE_ROUGHNESS = 16, aiTextureType_DIFFUSE_ROUGHNESS = 16,
aiTextureType_AMBIENT_OCCLUSION = 17, aiTextureType_AMBIENT_OCCLUSION = 17,
/** Unknown texture
*
* A texture reference that does not match any of the definitions
* above is considered to be 'unknown'. It is still imported,
* but is excluded from any further post-processing.
*/
aiTextureType_UNKNOWN = 18,
/** PBR Material Modifiers /** PBR Material Modifiers
* Some modern renderers have further PBR modifiers that may be overlaid * Some modern renderers have further PBR modifiers that may be overlaid
* on top of the 'base' PBR materials for additional realism. * on top of the 'base' PBR materials for additional realism.
@ -326,20 +318,20 @@ enum aiTextureType {
*/ */
aiTextureType_TRANSMISSION = 21, aiTextureType_TRANSMISSION = 21,
/** /** Unknown texture
* Maya material declarations *
*/ * A texture reference that does not match any of the definitions
aiTextureType_MAYA_BASE = 22, * above is considered to be 'unknown'. It is still imported,
aiTextureType_MAYA_SPECULAR = 23, * but is excluded from any further post-processing.
aiTextureType_MAYA_SPECULAR_COLOR = 24, */
aiTextureType_MAYA_SPECULAR_ROUGHNESS = 25, aiTextureType_UNKNOWN = 18,
#ifndef SWIG #ifndef SWIG
_aiTextureType_Force32Bit = INT_MAX _aiTextureType_Force32Bit = INT_MAX
#endif #endif
}; };
#define AI_TEXTURE_TYPE_MAX aiTextureType_MAYA_SPECULAR_ROUGHNESS #define AI_TEXTURE_TYPE_MAX aiTextureType_TRANSMISSION
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** /**
@ -701,7 +693,7 @@ struct aiMaterialProperty {
* Material data is stored using a key-value structure. A single key-value * Material data is stored using a key-value structure. A single key-value
* pair is called a 'material property'. C++ users should use the provided * pair is called a 'material property'. C++ users should use the provided
* member functions of aiMaterial to process material properties, C users * member functions of aiMaterial to process material properties, C users
* have to stick with the aiGetMaterialXXX family of unbound functions. * have to stick with the aiMaterialGetXXX family of unbound functions.
* The library defines a set of standard keys (AI_MATKEY_XXX). * The library defines a set of standard keys (AI_MATKEY_XXX).
*/ */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,33 +0,0 @@
// Export headers for Swift (iOS)
module libassimp {
header "ColladaMetaData.h"
header "GltfMaterial.h"
header "ObjMaterial.h"
header "anim.h"
header "camera.h"
header "cexport.h"
header "cfileio.h"
header "cimport.h"
header "color4.h"
header "commonMetaData.h"
header "config.h"
header "defs.h"
header "importerdesc.h"
header "light.h"
header "material.h"
header "matrix3x3.h"
header "matrix4x4.h"
header "mesh.h"
header "metadata.h"
header "pbrmaterial.h"
header "postprocess.h"
header "quaternion.h"
header "revision.h"
header "scene.h"
header "texture.h"
header "types.h"
header "vector2.h"
header "vector3.h"
header "version.h"
export *
}

View File

@ -401,9 +401,8 @@ struct ASSIMP_API aiScene {
//! Returns a short filename from a full path //! Returns a short filename from a full path
static const char* GetShortFilename(const char* filename) { static const char* GetShortFilename(const char* filename) {
const char* lastSlash = strrchr(filename, '/'); const char* lastSlash = strrchr(filename, '/');
const char* lastBackSlash = strrchr(filename, '\\'); if (lastSlash == nullptr) {
if (lastSlash < lastBackSlash) { lastSlash = strrchr(filename, '\\');
lastSlash = lastBackSlash;
} }
const char* shortFilename = lastSlash != nullptr ? lastSlash + 1 : filename; const char* shortFilename = lastSlash != nullptr ? lastSlash + 1 : filename;
return shortFilename; return shortFilename;

View File

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- #-*- coding: utf-8 -*-
from ctypes import POINTER, c_void_p, c_uint, c_char, c_float, Structure, c_double, c_ubyte, c_size_t, c_uint32, c_int from ctypes import POINTER, c_void_p, c_uint, c_char, c_float, Structure, c_double, c_ubyte, c_size_t, c_uint32
class Vector2D(Structure): class Vector2D(Structure):
@ -78,7 +78,7 @@ class String(Structure):
# the number of bytes from the beginning of the string to its end. # the number of bytes from the beginning of the string to its end.
("length", c_uint32), ("length", c_uint32),
# String buffer. Size limit is AI_MAXLEN # String buffer. Size limit is MAXLEN
("data", c_char*AI_MAXLEN), ("data", c_char*AI_MAXLEN),
] ]
@ -1010,54 +1010,6 @@ class Animation(Structure):
] ]
class SkeletonBone(Structure):
"""
See 'mesh.h' for details
"""
_fields_ = [
# The parent bone index, is -1 one if this bone represents the root bone.
("mParent", c_int),
# The number of weights
("mNumnWeights", c_uint),
# The mesh index, which will get influenced by the weight
("mMeshId", POINTER(Mesh)),
# The influence weights of this bone, by vertex index.
("mWeights", POINTER(VertexWeight)),
# Matrix that transforms from bone space to mesh space in bind pose.
#
# This matrix describes the position of the mesh
# in the local space of this bone when the skeleton was bound.
# Thus it can be used directly to determine a desired vertex position,
# given the world-space transform of the bone when animated,
# and the position of the vertex in mesh space.
#
# It is sometimes called an inverse-bind matrix,
# or inverse bind pose matrix
("mOffsetMatrix", Matrix4x4),
# Matrix that transforms the locale bone in bind pose.
("mLocalMatrix", Matrix4x4)
]
class Skeleton(Structure):
"""
See 'mesh.h' for details
"""
_fields_ = [
# Name
("mName", String),
# Number of bones
("mNumBones", c_uint),
# Bones
("mBones", POINTER(POINTER(SkeletonBone)))
]
class ExportDataBlob(Structure): class ExportDataBlob(Structure):
""" """
See 'cexport.h' for details. See 'cexport.h' for details.
@ -1179,15 +1131,6 @@ class Scene(Structure):
# can be used to store format-specific metadata as well. # can be used to store format-specific metadata as well.
("mMetadata", POINTER(Metadata)), ("mMetadata", POINTER(Metadata)),
# The name of the scene itself
("mName", String),
# Number of skeletons
("mNumSkeletons", c_uint),
# Skeletons
("mSkeletons", POINTER(POINTER(Skeleton))),
# Internal data, do not touch # Internal data, do not touch
("mPrivate", POINTER(c_char)), ("mPrivate", POINTER(c_char)),
] ]

View File

@ -1,13 +1,7 @@
# assimp for iOS # assimp for iOS
(deployment target 6.0+, 32/64bit) (deployment target 6.0+, 32/64bit)
### Requirements Builds assimp libraries for several iOS CPU architectures at once, and outputs a fat binary from the result.
- cmake
- pkg-config
Note: all these packages can be installed with [brew](https://brew.sh)
Builds assimp libraries for several iOS CPU architectures at once, and outputs a fat binary / XCFramework from the result.
Run the **build.sh** script from the ```./port/iOS/``` directory. See **./build.sh --help** for information about command line options. Run the **build.sh** script from the ```./port/iOS/``` directory. See **./build.sh --help** for information about command line options.
@ -21,11 +15,11 @@ shadeds-Mac:iOS arul$ ./build.sh --help
Example: Example:
```bash ```bash
cd ./port/iOS/ cd ./port/iOS/
./build.sh --stdlib=libc++ --archs="arm64 x86_64" --no-fat --min-version="16.0" ./build.sh --stdlib=libc++ --archs="armv7 arm64 i386"
``` ```
Supported architectures/devices: Supported architectures/devices:
### Simulator [CPU Architectures](https://docs.elementscompiler.com/Platforms/Cocoa/CpuArchitectures/) ### Simulator
- i386 - i386
- x86_64 - x86_64

View File

@ -76,7 +76,7 @@ build_arch()
rm CMakeCache.txt rm CMakeCache.txt
CMAKE_CLI_INPUT="-DCMAKE_C_COMPILER=$CMAKE_C_COMPILER -DCMAKE_CXX_COMPILER=$CMAKE_CXX_COMPILER -DCMAKE_TOOLCHAIN_FILE=./port/iOS/IPHONEOS_$(echo $1 | tr '[:lower:]' '[:upper:]')_TOOLCHAIN.cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS -DASSIMP_BUILD_ZLIB=ON" CMAKE_CLI_INPUT="-DCMAKE_C_COMPILER=$CMAKE_C_COMPILER -DCMAKE_CXX_COMPILER=$CMAKE_CXX_COMPILER -DCMAKE_TOOLCHAIN_FILE=./port/iOS/IPHONEOS_$(echo $1 | tr '[:lower:]' '[:upper:]')_TOOLCHAIN.cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS"
echo "[!] Running CMake with -G 'Unix Makefiles' $CMAKE_CLI_INPUT" echo "[!] Running CMake with -G 'Unix Makefiles' $CMAKE_CLI_INPUT"
@ -102,7 +102,6 @@ CPP_STD_LIB=${CPP_STD_LIB_LIST[0]}
CPP_STD=${CPP_STD_LIST[0]} CPP_STD=${CPP_STD_LIST[0]}
DEPLOY_ARCHS=${BUILD_ARCHS_ALL[*]} DEPLOY_ARCHS=${BUILD_ARCHS_ALL[*]}
DEPLOY_FAT=1 DEPLOY_FAT=1
DEPLOY_XCFramework=1
for i in "$@"; do for i in "$@"; do
case $i in case $i in
@ -118,11 +117,6 @@ for i in "$@"; do
DEPLOY_ARCHS=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` DEPLOY_ARCHS=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
echo "[!] Selecting architectures: $DEPLOY_ARCHS" echo "[!] Selecting architectures: $DEPLOY_ARCHS"
;; ;;
--min-version=*)
MIN_IOS_VERSION=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
IOS_SDK_TARGET=$MIN_IOS_VERSION
echo "[!] Selecting minimum iOS version: $MIN_IOS_VERSION"
;;
--debug) --debug)
BUILD_TYPE=Debug BUILD_TYPE=Debug
echo "[!] Selecting build type: Debug" echo "[!] Selecting build type: Debug"
@ -135,17 +129,11 @@ for i in "$@"; do
DEPLOY_FAT=0 DEPLOY_FAT=0
echo "[!] Fat binary will not be created." echo "[!] Fat binary will not be created."
;; ;;
--no-xcframework)
DEPLOY_XCFramework=0
echo "[!] XCFramework will not be created."
;;
-h|--help) -h|--help)
echo " - don't build fat library (--no-fat)." echo " - don't build fat library (--no-fat)."
echo " - don't build XCFramework (--no-xcframework)."
echo " - Include debug information and symbols, no compiler optimizations (--debug)." echo " - Include debug information and symbols, no compiler optimizations (--debug)."
echo " - generate dynamic libraries rather than static ones (--shared-lib)." echo " - generate dynamic libraries rather than static ones (--shared-lib)."
echo " - supported architectures (--archs): $(echo $(join , ${BUILD_ARCHS_ALL[*]}) | sed 's/,/, /g')" echo " - supported architectures (--archs): $(echo $(join , ${BUILD_ARCHS_ALL[*]}) | sed 's/,/, /g')"
echo " - minimum iOS version (--min-version): 16.0"
echo " - supported C++ STD libs (--stdlib): $(echo $(join , ${CPP_STD_LIB_LIST[*]}) | sed 's/,/, /g')" echo " - supported C++ STD libs (--stdlib): $(echo $(join , ${CPP_STD_LIB_LIST[*]}) | sed 's/,/, /g')"
echo " - supported C++ standards (--std): $(echo $(join , ${CPP_STD_LIST[*]}) | sed 's/,/, /g')" echo " - supported C++ standards (--std): $(echo $(join , ${CPP_STD_LIST[*]}) | sed 's/,/, /g')"
exit exit
@ -208,32 +196,3 @@ if [[ "$DEPLOY_FAT" -eq 1 ]]; then
echo "[!] Done! The fat binaries can be found at $BUILD_DIR" echo "[!] Done! The fat binaries can be found at $BUILD_DIR"
fi fi
make_xcframework()
{
LIB_NAME=$1
FRAMEWORK_PATH=$BUILD_DIR/$LIB_NAME.xcframework
ARGS = ""
for ARCH_TARGET in $DEPLOY_ARCHS; do
if [[ "$BUILD_SHARED_LIBS" =~ "ON" ]]; then
ARGS="$ARGS -library $BUILD_DIR/$ARCH_TARGET/$LIB_NAME.dylib -headers ./include "
else
ARGS="$ARGS -library $BUILD_DIR/$ARCH_TARGET/$LIB_NAME.a -headers ./include "
fi
done
xcodebuild -create-xcframework $ARGS -output $FRAMEWORK_PATH
}
if [[ "$DEPLOY_XCFramework" -eq 1 ]]; then
echo '[+] Creating XCFramework ...'
if [[ "$BUILD_TYPE" =~ "Debug" ]]; then
make_xcframework 'libassimpd'
else
make_xcframework 'libassimp'
fi
echo "[!] Done! The XCFramework can be found at $BUILD_DIR"
fi

View File

@ -100,7 +100,6 @@ SET( COMMON
unit/Common/utBase64.cpp unit/Common/utBase64.cpp
unit/Common/utHash.cpp unit/Common/utHash.cpp
unit/Common/utBaseProcess.cpp unit/Common/utBaseProcess.cpp
unit/Common/utLogger.cpp
) )
SET(Geometry SET(Geometry

File diff suppressed because one or more lines are too long

View File

@ -1,52 +0,0 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#include "UnitTestPCH.h"
#include <assimp/Importer.hpp>
using namespace Assimp;
class utLogger : public ::testing::Test {};
TEST_F(utLogger, aiGetPredefinedLogStream_leak_test) {
aiLogStream stream1 = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, nullptr);
aiLogStream stream2 = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, nullptr);
ASSERT_EQ(stream1.callback, stream2.callback);
}

View File

@ -311,37 +311,6 @@ TEST_F(utFBXImporterExporter, sceneMetadata) {
} }
} }
TEST_F(utFBXImporterExporter, importCustomAxes) {
// see https://github.com/assimp/assimp/issues/5494
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box.FBX", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
// The ASCII box has customised the Up and Forward axes, verify that the RootNode transform has applied it
ASSERT_FALSE(scene->mRootNode->mTransformation.IsIdentity()) << "Did not apply the custom axis transform";
aiVector3D upVec{ 0, 0, 1 }; // Up is +Z
aiVector3D forwardVec{ 0, -1, 0 }; // Forward is -Y
aiVector3D rightVec{ 1, 0, 0 }; // Right is +X
aiMatrix4x4 mat(rightVec.x, rightVec.y, rightVec.z, 0.0f,
upVec.x, upVec.y, upVec.z, 0.0f,
forwardVec.x, forwardVec.y, forwardVec.z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
EXPECT_EQ(mat, scene->mRootNode->mTransformation);
}
TEST_F(utFBXImporterExporter, importIgnoreCustomAxes) {
// see https://github.com/assimp/assimp/issues/5494
Assimp::Importer importer;
importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION, true);
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box.FBX", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
// Verify that the RootNode transform has NOT applied the custom axes
EXPECT_TRUE(scene->mRootNode->mTransformation.IsIdentity());
}
TEST_F(utFBXImporterExporter, importCubesWithOutOfRangeFloat) { TEST_F(utFBXImporterExporter, importCubesWithOutOfRangeFloat) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/cubes_with_outofrange_float.fbx", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/cubes_with_outofrange_float.fbx", aiProcess_ValidateDataStructure);

View File

@ -206,38 +206,3 @@ TEST_F(FindDegeneratesProcessTest, meshRemoval) {
EXPECT_EQ(scene->mRootNode->mNumMeshes, 1u); EXPECT_EQ(scene->mRootNode->mNumMeshes, 1u);
EXPECT_EQ(scene->mRootNode->mMeshes[0], 0u); EXPECT_EQ(scene->mRootNode->mMeshes[0], 0u);
} }
TEST_F(FindDegeneratesProcessTest, invalidVertexIndex) {
mProcess->EnableAreaCheck(true);
mProcess->EnableInstantRemoval(true);
mProcess->ExecuteOnMesh(mMesh);
std::unique_ptr<aiScene> scene(new aiScene);
scene->mNumMeshes = 1;
scene->mMeshes = new aiMesh *[1];
std::unique_ptr<aiMesh> mesh(new aiMesh);
mesh->mNumVertices = 1;
mesh->mVertices = new aiVector3D[1];
mesh->mVertices[0] = aiVector3D{ 0.0f, 0.0f, 0.0f };
mesh->mNumFaces = 1;
mesh->mFaces = new aiFace[1];
mesh->mFaces[0].mNumIndices = 3;
mesh->mFaces[0].mIndices = new unsigned int[3];
mesh->mFaces[0].mIndices[0] = 0;
mesh->mFaces[0].mIndices[1] = 1;
mesh->mFaces[0].mIndices[2] = 99999;
scene->mMeshes[0] = mesh.release();
scene->mRootNode = new aiNode;
scene->mRootNode->mNumMeshes = 1;
scene->mRootNode->mMeshes = new unsigned int[1];
scene->mRootNode->mMeshes[0] = 0;
mProcess->Execute(scene.get());
EXPECT_EQ(scene->mNumMeshes, 1u);
EXPECT_EQ(scene->mRootNode->mNumMeshes, 1u);
EXPECT_EQ(scene->mRootNode->mMeshes[0], 0u);
}

View File

@ -260,10 +260,6 @@ TEST_F(MaterialSystemTest, testMaterialTextureTypeEnum) {
case aiTextureType_METALNESS: case aiTextureType_METALNESS:
case aiTextureType_DIFFUSE_ROUGHNESS: case aiTextureType_DIFFUSE_ROUGHNESS:
case aiTextureType_AMBIENT_OCCLUSION: case aiTextureType_AMBIENT_OCCLUSION:
case aiTextureType_MAYA_BASE:
case aiTextureType_MAYA_SPECULAR:
case aiTextureType_MAYA_SPECULAR_COLOR:
case aiTextureType_MAYA_SPECULAR_ROUGHNESS:
case aiTextureType_SHEEN: case aiTextureType_SHEEN:
case aiTextureType_CLEARCOAT: case aiTextureType_CLEARCOAT:
case aiTextureType_TRANSMISSION: case aiTextureType_TRANSMISSION:

View File

@ -89,7 +89,7 @@ TEST_F(utPLYImportExport, exportTest_Success) {
#endif // ASSIMP_BUILD_NO_EXPORT #endif // ASSIMP_BUILD_NO_EXPORT
// Test issue 1623, crash when loading two PLY files in a row //Test issue 1623, crash when loading two PLY files in a row
TEST_F(utPLYImportExport, importerMultipleTest) { TEST_F(utPLYImportExport, importerMultipleTest) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure);
@ -109,7 +109,7 @@ TEST_F(utPLYImportExport, importPLYwithUV) {
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_NE(nullptr, scene->mMeshes[0]); EXPECT_NE(nullptr, scene->mMeshes[0]);
// This test model is using n-gons, so 6 faces instead of 12 tris //This test model is using n-gons, so 6 faces instead of 12 tris
EXPECT_EQ(6u, scene->mMeshes[0]->mNumFaces); EXPECT_EQ(6u, scene->mMeshes[0]->mNumFaces);
EXPECT_EQ(aiPrimitiveType_POLYGON, scene->mMeshes[0]->mPrimitiveTypes); EXPECT_EQ(aiPrimitiveType_POLYGON, scene->mMeshes[0]->mPrimitiveTypes);
EXPECT_EQ(true, scene->mMeshes[0]->HasTextureCoords(0)); EXPECT_EQ(true, scene->mMeshes[0]->HasTextureCoords(0));
@ -121,7 +121,7 @@ TEST_F(utPLYImportExport, importBinaryPLY) {
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_NE(nullptr, scene->mMeshes[0]); EXPECT_NE(nullptr, scene->mMeshes[0]);
// This test model is double sided, so 12 faces instead of 6 //This test model is double sided, so 12 faces instead of 6
EXPECT_EQ(12u, scene->mMeshes[0]->mNumFaces); EXPECT_EQ(12u, scene->mMeshes[0]->mNumFaces);
} }
@ -160,7 +160,7 @@ TEST_F(utPLYImportExport, vertexColorTest) {
TEST_F(utPLYImportExport, pointcloudTest) { TEST_F(utPLYImportExport, pointcloudTest) {
Assimp::Importer importer; Assimp::Importer importer;
// Could not use aiProcess_ValidateDataStructure since it's missing faces. //Could not use aiProcess_ValidateDataStructure since it's missing faces.
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
@ -192,7 +192,7 @@ static const char *test_file =
TEST_F(utPLYImportExport, parseErrorTest) { TEST_F(utPLYImportExport, parseErrorTest) {
Assimp::Importer importer; Assimp::Importer importer;
// Could not use aiProcess_ValidateDataStructure since it's missing faces. //Could not use aiProcess_ValidateDataStructure since it's missing faces.
const aiScene *scene = importer.ReadFileFromMemory(test_file, strlen(test_file), 0); const aiScene *scene = importer.ReadFileFromMemory(test_file, strlen(test_file), 0);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
} }
@ -203,61 +203,3 @@ TEST_F(utPLYImportExport, parseInvalid) {
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/invalid/crash-30d6d0f7c529b3b66b4131700b7a4580cd7082df.ply", 0); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/invalid/crash-30d6d0f7c529b3b66b4131700b7a4580cd7082df.ply", 0);
EXPECT_EQ(nullptr, scene); EXPECT_EQ(nullptr, scene);
} }
TEST_F(utPLYImportExport, payload_JVN42386607) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/payload_JVN42386607", 0);
EXPECT_EQ(nullptr, scene);
}
// Tests Issue #5729. Test, if properties defined multiple times. Unclear what to do, better to abort than to crash entirely
TEST_F(utPLYImportExport, parseInvalidDoubleProperty) {
const char data[] = "ply\n"
"format ascii 1.0\n"
"element vertex 4\n"
"property float x\n"
"property float y\n"
"property float z\n"
"element vertex 8\n"
"property float x\n"
"property float y\n"
"property float z\n"
"end_header\n"
"0.0 0.0 0.0 0.0 0.0 0.0\n"
"0.0 0.0 1.0 0.0 0.0 1.0\n"
"0.0 1.0 0.0 0.0 1.0 0.0\n"
"0.0 0.0 1.0\n"
"0.0 1.0 0.0 0.0 0.0 1.0\n"
"0.0 1.0 1.0 0.0 1.0 1.0\n";
Assimp::Importer importer;
const aiScene *scene = importer.ReadFileFromMemory(data, sizeof(data), 0);
EXPECT_EQ(nullptr, scene);
}
// Tests Issue #5729. Test, if properties defined multiple times. Unclear what to do, better to abort than to crash entirely
TEST_F(utPLYImportExport, parseInvalidDoubleCustomProperty) {
const char data[] = "ply\n"
"format ascii 1.0\n"
"element vertex 4\n"
"property float x\n"
"property float y\n"
"property float z\n"
"element name 8\n"
"property float x\n"
"element name 5\n"
"property float x\n"
"end_header\n"
"0.0 0.0 0.0 100.0 10.0\n"
"0.0 0.0 1.0 200.0 20.0\n"
"0.0 1.0 0.0 300.0 30.0\n"
"0.0 1.0 1.0 400.0 40.0\n"
"0.0 0.0 0.0 500.0 50.0\n"
"0.0 0.0 1.0 600.0 60.0\n"
"0.0 1.0 0.0 700.0 70.0\n"
"0.0 1.0 1.0 800.0 80.0\n";
Assimp::Importer importer;
const aiScene *scene = importer.ReadFileFromMemory(data, sizeof(data), 0);
EXPECT_EQ(nullptr, scene);
}

View File

@ -61,7 +61,7 @@ TEST_F( utVersion, aiGetVersionMinorTest ) {
} }
TEST_F( utVersion, aiGetVersionPatchTest ) { TEST_F( utVersion, aiGetVersionPatchTest ) {
EXPECT_EQ(aiGetVersionPatch(), 3U ); EXPECT_EQ(aiGetVersionPatch(), 1U );
} }
TEST_F( utVersion, aiGetCompileFlagsTest ) { TEST_F( utVersion, aiGetCompileFlagsTest ) {