Merge branch 'master' into deprecated_gltfpbr_macros

pull/4203/head
RichardTea 2022-03-01 10:01:43 +00:00
commit d704824be3
54 changed files with 959 additions and 768 deletions

View File

@ -1,67 +0,0 @@
#---------------------------------------------------------------------------
#Open Asset Import Library (assimp)
#---------------------------------------------------------------------------
# Copyright (c) 2006-2020, assimp team
#
# License see LICENSE file
#
function generate() {
OPTIONS="-DASSIMP_WERROR=ON"
OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=NO"
if [ "$DISABLE_EXPORTERS" = "YES" ] ; then
OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=YES"
else
OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=NO"
fi
if [ "$SHARED_BUILD" = "ON" ] ; then
OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=ON"
else
OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=OFF"
fi
if [ "$ENABLE_COVERALLS" = "ON" ] ; then
OPTIONS="$OPTIONS -DASSIMP_COVERALLS=ON"
else
OPTIONS="$OPTIONS -DASSIMP_COVERALLS=OFF"
fi
if [ "$ASAN" = "ON" ] ; then
OPTIONS="$OPTIONS -DASSIMP_ASAN=ON"
else
OPTIONS="$OPTIONS -DASSIMP_ASAN=OFF"
fi
if [ "$UBSAN" = "ON" ] ; then
OPTIONS="$OPTIONS -DASSIMP_UBSAN=ON"
fi
cmake -G "Unix Makefiles" $OPTIONS
}
# build and run unittests, if not android
if [ $ANDROID ]; then
ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
fi
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ $ANALYZE = "ON" ] ; then
if [ "$CC" = "clang" ]; then
scan-build cmake -G "Unix Makefiles" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_TESTS=OFF
scan-build --status-bugs make -j2
else
cppcheck --version
generate \
&& cppcheck --error-exitcode=1 -j2 -Iinclude -Icode code 2> cppcheck.txt
if [ -s cppcheck.txt ]; then
cat cppcheck.txt
exit 1
fi
fi
else
generate \
&& make -j4 \
&& sudo make install \
&& sudo ldconfig \
&& (cd test/unit; ../../bin/unit)
fi
fi

View File

@ -1,78 +0,0 @@
sudo: required
language: cpp
cache: ccache
before_install:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake cppcheck && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi
- 'if [ "$TRAVIS_OS_NAME" = "osx" ]; then
if brew ls --versions cmake > /dev/null; then
echo cmake already installed.;
else
brew install cmake;
fi;
brew install python3;
brew install homebrew/x11/freeglut;
fi'
- echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
# install latest LCOV (1.9 was failing)
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz && tar xf lcov_1.11.orig.tar.gz && sudo make -C lcov-1.11/ install && gem install coveralls-lcov && lcov --version && g++ --version ; fi
os:
- linux
compiler:
- gcc
- clang
env:
global:
- secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
- PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
git:
depth: 1
matrix:
include:
- os: linux
compiler: clang
env: ASAN=ON
- os: linux
compiler: clang
env: UBSAN=ON
- os: linux
compiler: clang
env: SHARED_BUILD=ON
- os: linux
compiler: gcc
env: ANALYZE=ON
- os: linux
compiler: gcc
env: ENABLE_COVERALLS=ON
- os: linux
compiler: gcc
env: SHARED_BUILD=ON
install:
- if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
before_script:
cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES
script:
- export COVERALLS_SERVICE_NAME=travis-ci
- export COVERALLS_REPO_TOKEN=abc12345
- . ./.travis.sh
after_success:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info && lcov --list coverage.info && coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info ; fi
addons:
coverity_scan:
project:
name: "assimp/assimp"
notification_email: kim.kulling@googlemail.com
build_command_prepend: "cmake ./"
build_command: "make -j4"
branch_pattern: coverity_scan

View File

@ -10,16 +10,15 @@
:: Also see: https://github.com/assimp/assimp/pull/2646
SET SOURCE_DIR=.
SET GENERATOR=Visual Studio 16 2019
:: For generators see "cmake --help"
SET GENERATOR=Visual Studio 15 2017
SET BINARIES_DIR="./BINARIES/Win32"
cmake CMakeLists.txt -G "%GENERATOR%" -S %SOURCE_DIR% -B %BINARIES_DIR%
SET BINARIES_DIR="./build/Win32"
cmake . -G "%GENERATOR%" -A Win32 -S %SOURCE_DIR% -B %BINARIES_DIR%
cmake --build %BINARIES_DIR% --config debug
cmake --build %BINARIES_DIR% --config release
SET BINARIES_DIR="./BINARIES/x64"
cmake CMakeLists.txt -G "%GENERATOR% Win64" -S %SOURCE_DIR% -B %BINARIES_DIR%
SET BINARIES_DIR="./build/x64"
cmake . -G "%GENERATOR%" -A x64 -S %SOURCE_DIR% -B %BINARIES_DIR%
cmake --build %BINARIES_DIR% --config debug
cmake --build %BINARIES_DIR% --config release

View File

@ -49,14 +49,14 @@ option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
IF(ASSIMP_HUNTER_ENABLED)
include("cmake-modules/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.311.tar.gz"
SHA1 "1a82b9b73055879181cb1466b2ab5d48ee8ae410"
URL "https://github.com/cpp-pm/hunter/archive/v0.24.0.tar.gz"
SHA1 "a3d7f4372b1dcd52faa6ff4a3bd5358e1d0e5efd"
)
add_definitions(-DASSIMP_USE_HUNTER)
ENDIF()
PROJECT(Assimp VERSION 5.1.6)
PROJECT(Assimp VERSION 5.2.0)
# All supported options ###############################################
@ -134,12 +134,12 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH
OFF
)
IF ( WIN32 )
IF (WIN32)
# Use subset of Windows.h
ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
IF(MSVC)
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW
OPTION (ASSIMP_BUILD_ASSIMP_VIEW
"If the Assimp view tool is built. (requires DirectX)"
OFF )
@ -243,6 +243,13 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
IF( UNIX )
# Use GNUInstallDirs for Unix predefined directories
INCLUDE(GNUInstallDirs)
# Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
IF( ${OPERATING_SYSTEM} MATCHES "Android")
ELSE()
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
ENDIF()
ENDIF()
ENDIF()
# Grouped compiler settings ########################################
@ -341,9 +348,24 @@ INCLUDE (FindPkgMacros)
INCLUDE (PrecompiledHeader)
# Set Assimp project output directory variables.
SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for runtime output files")
SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for library output files")
SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE STRING "Path for archive output files")
# Will respect top-level CMAKE_*_OUTPUT_DIRECTORY variables if any are set.
IF(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for runtime output files")
ELSE()
SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} CACHE STRING "Path for runtime output files")
ENDIF()
IF(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for library output files")
ELSE()
SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} CACHE STRING "Path for runtime output files")
ENDIF()
IF(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE STRING "Path for library output files")
ELSE()
SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} CACHE STRING "Path for runtime output files")
ENDIF()
# Macro used to set the output directories of a target to the
# respective Assimp output directories.
@ -672,11 +694,13 @@ ENDIF()
ADD_SUBDIRECTORY( code/ )
IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
# The viewer for windows only
IF ( WIN32 )
IF (WIN32)
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" OFF )
IF ( ASSIMP_BUILD_ASSIMP_VIEW )
ADD_SUBDIRECTORY( tools/assimp_view/ )
ENDIF ()
ELSE()
MESSAGE("Building Assimp Viewer only supported on Windows.")
ENDIF ()
# The command line tool
ADD_SUBDIRECTORY( tools/assimp_cmd/ )

View File

@ -112,6 +112,7 @@ using namespace Assimp::ASE;
// ------------------------------------------------------------------------------------------------
Parser::Parser(const char *szFile, unsigned int fileFormatDefault) {
ai_assert(nullptr != szFile);
filePtr = szFile;
iFileFormat = fileFormatDefault;
@ -486,7 +487,7 @@ void Parser::ParseLV1MaterialListBlock() {
ParseLV4MeshLong(iIndex);
if (iIndex >= iMaterialCount) {
LogError("Out of range: material index is too large");
LogWarning("Out of range: material index is too large");
iIndex = iMaterialCount - 1;
return;
}
@ -905,7 +906,6 @@ void Parser::ParseLV2LightSettingsBlock(ASE::Light &light) {
}
AI_ASE_HANDLE_SECTION("2", "LIGHT_SETTINGS");
}
return;
}
// ------------------------------------------------------------------------------------------------
@ -1782,7 +1782,9 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) {
// *MESH_MTLID is optional, too
while (true) {
if ('*' == *filePtr) break;
if ('*' == *filePtr) {
break;
}
if (IsLineEnd(*filePtr)) {
return;
}
@ -1831,8 +1833,9 @@ void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) {
void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) {
ai_assert(nullptr != apOut);
for (unsigned int i = 0; i < 3; ++i)
for (unsigned int i = 0; i < 3; ++i) {
ParseLV4MeshFloat(apOut[i]);
}
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloat(ai_real &fOut) {

View File

@ -182,6 +182,8 @@ inline size_t Write<aiVertexWeight>(IOStream *stream, const aiVertexWeight &v) {
return t + Write<float>(stream, v.mWeight);
}
constexpr size_t MatrixSize = 64;
// -----------------------------------------------------------------------------------
// Serialize a mat4x4
template <>
@ -192,7 +194,7 @@ inline size_t Write<aiMatrix4x4>(IOStream *stream, const aiMatrix4x4 &m) {
}
}
return 64;
return MatrixSize;
}
// -----------------------------------------------------------------------------------

View File

@ -66,11 +66,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// zlib is needed for compressed blend files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
#include "Common/Compression.h"
/* #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
# else
# include "../contrib/zlib/zlib.h"
# endif
# endif*/
#endif
namespace Assimp {
@ -141,7 +142,7 @@ void BlenderImporter::SetupProperties(const Importer * /*pImp*/) {
void BlenderImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
std::vector<Bytef> uncompressed;
std::vector<char> uncompressed;
#endif
FileDatabase file;
@ -159,7 +160,6 @@ void BlenderImporter::InternReadFile(const std::string &pFile,
#ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND
ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?");
#else
if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either");
}
@ -173,42 +173,12 @@ void BlenderImporter::InternReadFile(const std::string &pFile,
stream->Seek(0L, aiOrigin_SET);
std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
// build a zlib stream
z_stream zstream;
zstream.opaque = Z_NULL;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.data_type = Z_BINARY;
// http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
inflateInit2(&zstream, 16 + MAX_WBITS);
zstream.next_in = reinterpret_cast<Bytef *>(reader->GetPtr());
zstream.avail_in = (uInt)reader->GetRemainingSize();
size_t total = 0l;
// TODO: be smarter about this, decompress directly into heap buffer
// and decompress the data .... do 1k chunks in the hope that we won't kill the stack
#define MYBLOCK 1024
Bytef block[MYBLOCK];
int ret;
do {
zstream.avail_out = MYBLOCK;
zstream.next_out = block;
ret = inflate(&zstream, Z_NO_FLUSH);
if (ret != Z_STREAM_END && ret != Z_OK) {
ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .BLEND file");
}
const size_t have = MYBLOCK - zstream.avail_out;
total += have;
uncompressed.resize(total);
memcpy(uncompressed.data() + total - have, block, have);
} while (ret != Z_STREAM_END);
// terminate zlib
inflateEnd(&zstream);
size_t total = 0;
Compression compression;
if (compression.open(Compression::Format::Binary, Compression::FlushMode::NoFlush, 16 + Compression::MaxWBits)) {
total = compression.decompress((unsigned char *)reader->GetPtr(), reader->GetRemainingSize(), uncompressed);
compression.close();
}
// replace the input stream with a memory stream
stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));

View File

@ -357,9 +357,9 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
out->mAngleInnerCone = AI_DEG_TO_RAD(srcLight->mFalloffAngle);
// ... some extension magic.
if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET * (1 - 1e-6f)) {
if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET * (1 - ai_epsilon)) {
// ... some deprecation magic.
if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET * (1 - 1e-6f)) {
if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET * (1 - ai_epsilon)) {
// Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
// epsilon chosen to be 0.1
float f = 1.0f;
@ -1065,7 +1065,7 @@ void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, floa
return;
}
for (unsigned int i = 0; i < values.size(); i++) {
if (std::abs(time - values[i].mTime) < 1e-6f) {
if (std::abs(time - values[i].mTime) < ai_epsilon) {
values[i].mKeys.push_back(k);
return;
} else if (time > values[i].mTime && time < values[i + 1].mTime) {

View File

@ -80,8 +80,10 @@ enum TransformInheritance {
TransformInheritance_MAX // end-of-enum sentinel
};
} // namespace FBX
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // AI_FBXCOMMON_H_INC

View File

@ -653,7 +653,7 @@ bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
const PropertyTable &props = model.Props();
bool ok;
const float zero_epsilon = 1e-6f;
const float zero_epsilon = ai_epsilon;
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
const TransformationComp comp = static_cast<TransformationComp>(i);
@ -1267,7 +1267,7 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
const std::vector<aiVector3D> &normals = mesh.GetNormals();
if (normals.size()) {
ai_assert(normals.size() == vertices.size());
out_mesh->mNormals = new aiVector3D[vertices.size()];
out_mesh->mNormals = new aiVector3D[count_vertices];
}
// allocate tangents, binormals.
@ -1295,8 +1295,8 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
ai_assert(tangents.size() == vertices.size());
ai_assert(binormals->size() == vertices.size());
out_mesh->mTangents = new aiVector3D[vertices.size()];
out_mesh->mBitangents = new aiVector3D[vertices.size()];
out_mesh->mTangents = new aiVector3D[count_vertices];
out_mesh->mBitangents = new aiVector3D[count_vertices];
}
}
@ -1308,7 +1308,7 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
break;
}
out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()];
out_mesh->mTextureCoords[i] = new aiVector3D[count_vertices];
out_mesh->mNumUVComponents[i] = 2;
}
@ -1320,7 +1320,7 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
break;
}
out_mesh->mColors[i] = new aiColor4D[vertices.size()];
out_mesh->mColors[i] = new aiColor4D[count_vertices];
}
unsigned int cursor = 0, in_cursor = 0;
@ -3187,7 +3187,8 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
}
bool ok = false;
const float zero_epsilon = 1e-6f;
const float zero_epsilon = ai_epsilon;
const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
if (ok && preRotation.SquareLength() > zero_epsilon) {

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -46,11 +45,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
#else
# include "../contrib/zlib/zlib.h"
#endif
//#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
#include "Common/Compression.h"
//# include <zlib.h>
//#else
//# include "../contrib/zlib/zlib.h"
//#endif
#include "FBXTokenizer.h"
#include "FBXParser.h"
@ -115,9 +115,7 @@ namespace Assimp {
namespace FBX {
// ------------------------------------------------------------------------------------------------
Element::Element(const Token& key_token, Parser& parser)
: key_token(key_token)
{
Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) {
TokenPtr n = nullptr;
do {
n = parser.AdvanceToNextToken();
@ -210,8 +208,7 @@ Scope::Scope(Parser& parser,bool topLevel)
}
// ------------------------------------------------------------------------------------------------
Scope::~Scope()
{
Scope::~Scope() {
for(ElementMap::value_type& v : elements) {
delete v.second;
}
@ -527,9 +524,7 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
// ------------------------------------------------------------------------------------------------
// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
std::vector<char>& buff,
const Element& /*el*/)
{
std::vector<char>& buff, const Element& /*el*/) {
BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
AI_SWAP4(encmode);
data += 4;
@ -571,31 +566,11 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
else if(encmode == 1) {
// zlib/deflate, next comes ZIP head (0x78 0x01)
// see http://www.ietf.org/rfc/rfc1950.txt
z_stream zstream;
zstream.opaque = Z_NULL;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.data_type = Z_BINARY;
// http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
if(Z_OK != inflateInit(&zstream)) {
ParseError("failure initializing zlib");
Compression compress;
if (compress.open(Compression::Format::Binary, Compression::FlushMode::Finish, 0)) {
compress.decompress(data, comp_len, buff);
compress.close();
}
zstream.next_in = reinterpret_cast<Bytef*>( const_cast<char*>(data) );
zstream.avail_in = comp_len;
zstream.avail_out = static_cast<uInt>(buff.size());
zstream.next_out = reinterpret_cast<Bytef*>(&*buff.begin());
const int ret = inflate(&zstream, Z_FINISH);
if (ret != Z_STREAM_END && ret != Z_OK) {
ParseError("failure decompressing compressed data section");
}
// terminate zlib
inflateEnd(&zstream);
}
#ifdef ASSIMP_BUILD_DEBUG
else {
@ -701,7 +676,6 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
}
}
// ------------------------------------------------------------------------------------------------
// read an array of color4 tuples
void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
@ -786,8 +760,7 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
// ------------------------------------------------------------------------------------------------
// read an array of float2 tuples
void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
{
void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el) {
out.resize( 0 );
const TokenList& tok = el.Tokens();
if(tok.empty()) {
@ -831,8 +804,7 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
out.push_back(aiVector2D(static_cast<float>(d[0]),
static_cast<float>(d[1])));
}
}
else if (type == 'f') {
} else if (type == 'f') {
const float* f = reinterpret_cast<const float*>(&buff[0]);
for (unsigned int i = 0; i < count2; ++i, f += 2) {
out.push_back(aiVector2D(f[0],f[1]));
@ -865,8 +837,7 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
// ------------------------------------------------------------------------------------------------
// read an array of ints
void ParseVectorDataArray(std::vector<int>& out, const Element& el)
{
void ParseVectorDataArray(std::vector<int>& out, const Element& el) {
out.resize( 0 );
const TokenList& tok = el.Tokens();
if(tok.empty()) {

View File

@ -275,7 +275,9 @@ void HMPImporter::InternReadFile_HMP7() {
// now load all vertices from the file
aiVector3D *pcVertOut = pcMesh->mVertices;
ai_assert(pcVertOut != nullptr);
aiVector3D *pcNorOut = pcMesh->mNormals;
ai_assert(pcNorOut != nullptr);
const HMP::Vertex_HMP7 *src = (const HMP::Vertex_HMP7 *)szCurrent;
for (unsigned int y = 0; y < height; ++y) {
for (unsigned int x = 0; x < width; ++x) {
@ -327,29 +329,31 @@ void HMPImporter::CreateMaterial(const unsigned char *szCurrent,
// now read the first skin and skip all others
ReadFirstSkin(pcHeader->numskins, szCurrent, &szCurrent);
} else {
// generate a default material
const int iMode = (int)aiShadingMode_Gouraud;
aiMaterial *pcHelper = new aiMaterial();
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
aiColor3D clr;
clr.b = clr.g = clr.r = 0.6f;
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
aiString szName;
szName.Set(AI_DEFAULT_MATERIAL_NAME);
pcHelper->AddProperty(&szName, AI_MATKEY_NAME);
// add the material to the scene
pScene->mNumMaterials = 1;
pScene->mMaterials = new aiMaterial *[1];
pScene->mMaterials[0] = pcHelper;
*szCurrentOut = szCurrent;
return;
}
// generate a default material
const int iMode = (int)aiShadingMode_Gouraud;
aiMaterial *pcHelper = new aiMaterial();
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
aiColor3D clr;
clr.b = clr.g = clr.r = 0.6f;
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
aiString szName;
szName.Set(AI_DEFAULT_MATERIAL_NAME);
pcHelper->AddProperty(&szName, AI_MATKEY_NAME);
// add the material to the scene
pScene->mNumMaterials = 1;
pScene->mMaterials = new aiMaterial *[1];
pScene->mMaterials[0] = pcHelper;
*szCurrentOut = szCurrent;
}
@ -373,27 +377,36 @@ void HMPImporter::CreateOutputFaceList(unsigned int width, unsigned int height)
aiVector3D *pcUVOut(pcUVs);
// Build the terrain square
const unsigned int upperBound = pcMesh->mNumVertices;
unsigned int iCurrent = 0;
for (unsigned int y = 0; y < height - 1; ++y) {
const size_t offset0 = y * width;
const size_t offset1 = (y + 1) * width;
for (unsigned int x = 0; x < width - 1; ++x, ++pcFaceOut) {
pcFaceOut->mNumIndices = 4;
pcFaceOut->mIndices = new unsigned int[4];
if ((offset0 + x + 1) >= upperBound){
continue;
}
if ((offset1 + x + 1) >= upperBound){
continue;
}
*pcVertOut++ = pcMesh->mVertices[y * width + x];
*pcVertOut++ = pcMesh->mVertices[(y + 1) * width + x];
*pcVertOut++ = pcMesh->mVertices[(y + 1) * width + x + 1];
*pcVertOut++ = pcMesh->mVertices[y * width + x + 1];
*pcVertOut++ = pcMesh->mVertices[offset0 + x];
*pcVertOut++ = pcMesh->mVertices[offset1 + x];
*pcVertOut++ = pcMesh->mVertices[offset1 + x + 1];
*pcVertOut++ = pcMesh->mVertices[offset0 + x + 1];
*pcNorOut++ = pcMesh->mNormals[y * width + x];
*pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x];
*pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x + 1];
*pcNorOut++ = pcMesh->mNormals[y * width + x + 1];
*pcNorOut++ = pcMesh->mNormals[offset0 + x];
*pcNorOut++ = pcMesh->mNormals[offset1 + x];
*pcNorOut++ = pcMesh->mNormals[offset1 + x + 1];
*pcNorOut++ = pcMesh->mNormals[offset0 + x + 1];
if (pcMesh->mTextureCoords[0]) {
*pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x + 1];
*pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x + 1];
*pcUVOut++ = pcMesh->mTextureCoords[0][offset0 + x];
*pcUVOut++ = pcMesh->mTextureCoords[0][offset1 + x];
*pcUVOut++ = pcMesh->mTextureCoords[0][offset1 + x + 1];
*pcUVOut++ = pcMesh->mTextureCoords[0][offset0 + x + 1];
}
for (unsigned int i = 0; i < 4; ++i)

View File

@ -66,12 +66,12 @@ bool IntersectSegmentPlane(const IfcVector3 &p, const IfcVector3 &n, const IfcVe
// if segment ends on plane, do not report a hit. We stay on that side until a following segment starting at this
// point leaves the plane through the other side
if (std::abs(dotOne + dotTwo) < 1e-6)
if (std::abs(dotOne + dotTwo) < ai_epsilon)
return false;
// if segment starts on the plane, report a hit only if the end lies on the *other* side
if (std::abs(dotTwo) < 1e-6) {
if ((assumeStartOnWhiteSide && dotOne + dotTwo < 1e-6) || (!assumeStartOnWhiteSide && dotOne + dotTwo > -1e-6)) {
if (std::abs(dotTwo) < ai_epsilon) {
if ((assumeStartOnWhiteSide && dotOne + dotTwo < ai_epsilon) || (!assumeStartOnWhiteSide && dotOne + dotTwo > -ai_epsilon)) {
out = e0;
return true;
} else {
@ -81,7 +81,7 @@ bool IntersectSegmentPlane(const IfcVector3 &p, const IfcVector3 &n, const IfcVe
// ignore if segment is parallel to plane and far away from it on either side
// Warning: if there's a few thousand of such segments which slowly accumulate beyond the epsilon, no hit would be registered
if (std::abs(dotOne) < 1e-6)
if (std::abs(dotOne) < ai_epsilon)
return false;
// t must be in [0..1] if the intersection point is within the given segment
@ -163,7 +163,7 @@ void ProcessBooleanHalfSpaceDifference(const Schema_2x3::IfcHalfSpaceSolid *hs,
for (iit = begin; iit != end; vidx += *iit++) {
unsigned int newcount = 0;
bool isAtWhiteSide = (in[vidx] - p) * n > -1e-6;
bool isAtWhiteSide = (in[vidx] - p) * n > -ai_epsilon;
for (unsigned int i = 0; i < *iit; ++i) {
const IfcVector3 &e0 = in[vidx + i], e1 = in[vidx + (i + 1) % *iit];
@ -259,7 +259,7 @@ bool IntersectsBoundaryProfile(const IfcVector3 &e0, const IfcVector3 &e1, const
// segment-segment intersection
// solve b0 + b*s = e0 + e*t for (s,t)
const IfcFloat det = (-b.x * e.y + e.x * b.y);
if (std::abs(det) < 1e-6) {
if (std::abs(det) < ai_epsilon) {
// no solutions (parallel lines)
continue;
}
@ -316,7 +316,7 @@ bool IntersectsBoundaryProfile(const IfcVector3 &e0, const IfcVector3 &e1, const
// for a valid intersection, s and t should be in range [0,1]. Including a bit of epsilon on s, potential double
// hits on two consecutive boundary segments are filtered
if (s >= -1e-6 * b_sqlen_inv && s <= 1.0 + 1e-6 * b_sqlen_inv && t >= 0.0 && (t <= 1.0 || halfOpen)) {
if (s >= -ai_epsilon * b_sqlen_inv && s <= 1.0 + ai_epsilon * b_sqlen_inv && t >= 0.0 && (t <= 1.0 || halfOpen)) {
// only insert the point into the list if it is sufficiently far away from the previous intersection point.
// This way, we avoid duplicate detection if the intersection is directly on the vertex between two segments.
if (!intersect_results.empty() && intersect_results.back().first == i - 1) {
@ -431,14 +431,14 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
// if the poly is parallel to the plane, put it completely on the black or white side
if (std::abs(polyNormal * n) > 0.9999) {
bool isOnWhiteSide = (srcVertices[0] - p) * n > -1e-6;
bool isOnWhiteSide = (srcVertices[0] - p) * n > -ai_epsilon;
std::vector<IfcVector3> &targetSide = isOnWhiteSide ? whiteside : blackside;
targetSide.insert(targetSide.end(), srcVertices, srcVertices + srcVtxCount);
} else {
// otherwise start building one polygon for each side. Whenever the current line segment intersects the plane
// we put a point there as an end of the current segment. Then we switch to the other side, put a point there, too,
// as a beginning of the current segment, and simply continue accumulating vertices.
bool isCurrentlyOnWhiteSide = ((srcVertices[0]) - p) * n > -1e-6;
bool isCurrentlyOnWhiteSide = ((srcVertices[0]) - p) * n > -ai_epsilon;
for (size_t a = 0; a < srcVtxCount; ++a) {
IfcVector3 e0 = srcVertices[a];
IfcVector3 e1 = srcVertices[(a + 1) % srcVtxCount];

View File

@ -380,21 +380,19 @@ void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh&
bool take_any = false;
for (unsigned int j = 0; j < 2; ++j, take_any = true) {
if ((last_dir == 0 || take_any) && std::abs(d.x) > 1e-6) {
if ((last_dir == 0 || take_any) && std::abs(d.x) > ai_epsilon) {
q.y = startvec.y;
q.z = startvec.z;
q.x = -(d.y * q.y + d.z * q.z) / d.x;
last_dir = 0;
break;
}
else if ((last_dir == 1 || take_any) && std::abs(d.y) > 1e-6) {
} else if ((last_dir == 1 || take_any) && std::abs(d.y) > ai_epsilon) {
q.x = startvec.x;
q.z = startvec.z;
q.y = -(d.x * q.x + d.z * q.z) / d.y;
last_dir = 1;
break;
}
else if ((last_dir == 2 && std::abs(d.z) > 1e-6) || take_any) {
} else if ((last_dir == 2 && std::abs(d.z) > ai_epsilon) || take_any) {
q.y = startvec.y;
q.x = startvec.x;
q.z = -(d.y * q.y + d.x * q.x) / d.z;
@ -529,7 +527,7 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
return m;
}
const auto closeDistance = 1e-6;
const auto closeDistance = ai_epsilon;
bool areClose(Schema_2x3::IfcCartesianPoint pt1,Schema_2x3::IfcCartesianPoint pt2) {
if(pt1.Coordinates.size() != pt2.Coordinates.size())
@ -561,7 +559,7 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
// Outline: 'curve' is now a list of vertex points forming the underlying profile, extrude along the given axis,
// forming new triangles.
const bool has_area = solid.SweptArea->ProfileType == "AREA" && curve.mVerts.size() > 2;
if( solid.Depth < 1e-6 ) {
if (solid.Depth < ai_epsilon) {
if( has_area ) {
result.Append(curve);
}

View File

@ -1133,7 +1133,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
}
for(size_t i = 0; i < out_contour.size(); ++i) {
ai_assert((out_contour[i]-out_contour2[i]).SquareLength() < 1e-6);
ai_assert((out_contour[i] - out_contour2[i]).SquareLength() < ai_epsilon);
}
#endif
@ -1435,7 +1435,7 @@ std::vector<IfcVector2> GetContourInPlane2D(std::shared_ptr<TempMesh> mesh,IfcMa
const auto outernor = ((mesh->mVerts[2] - mesh->mVerts[0]) ^ (mesh->mVerts[1] - mesh->mVerts[0])).Normalize();
const IfcFloat dot = planeNor * outernor;
if(std::fabs(dot) < 1.f - 1e-6f) {
if (std::fabs(dot) < 1.f - ai_epsilon) {
std::stringstream msg;
msg << "Skipping: Unaligned opening (" << planeNor.x << ", " << planeNor.y << ", " << planeNor.z << ")";
msg << " . ( " << outernor.x << ", " << outernor.y << ", " << outernor.z << ") = " << dot;
@ -1476,7 +1476,7 @@ std::vector<IfcVector2> GetContourInPlane2D(std::shared_ptr<TempMesh> mesh,IfcMa
return contour;
}
const float close { 1e-6f };
const float close{ ai_epsilon };
static bool isClose(IfcVector2 first,IfcVector2 second) {
auto diff = (second - first);

View File

@ -228,25 +228,24 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
// ------------------------------------------------------------------------------------------------
// Compute the normal of the last polygon in the given mesh
IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const
{
IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const {
return ComputePolygonNormal(&mVerts[mVerts.size() - mVertcnt.back()], mVertcnt.back(), normalize);
}
struct CompareVector
{
bool operator () (const IfcVector3& a, const IfcVector3& b) const
{
struct CompareVector {
bool operator () (const IfcVector3& a, const IfcVector3& b) const {
IfcVector3 d = a - b;
IfcFloat eps = 1e-6;
IfcFloat eps = ai_epsilon;
return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps);
}
};
struct FindVector
{
struct FindVector {
IfcVector3 v;
FindVector(const IfcVector3& p) : v(p) { }
bool operator () (const IfcVector3& p) { return FuzzyVectorCompare(1e-6)(p, v); }
bool operator()(const IfcVector3 &p) {
return FuzzyVectorCompare(ai_epsilon)(p, v);
}
};
// ------------------------------------------------------------------------------------------------
@ -357,8 +356,7 @@ void TempMesh::FixupFaceOrientation()
// to reverse the neighbour
nb_vidx = (nb_vidx + 1) % nbvc;
size_t oursideidx = (a + 1) % vc;
if( FuzzyVectorCompare(1e-6)(mVerts[vsi + oursideidx], mVerts[nbvsi + nb_vidx]) )
{
if (FuzzyVectorCompare(ai_epsilon)(mVerts[vsi + oursideidx], mVerts[nbvsi + nb_vidx])) {
std::reverse(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc);
std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
for (size_t aa = 0; aa < nbvc - 1; ++aa) {
@ -564,7 +562,7 @@ void ConvertDirection(IfcVector3& out, const Schema_2x3::IfcDirection& in)
out[static_cast<unsigned int>(i)] = in.DirectionRatios[i];
}
const IfcFloat len = out.Length();
if (len<1e-6) {
if (len < ai_epsilon) {
IFCImporter::LogWarn("direction vector magnitude too small, normalization would result in a division by zero");
return;
}

View File

@ -83,9 +83,13 @@ AnimResolver::AnimResolver(std::list<Envelope> &_envelopes, double tick) :
(*it).old_first = 0;
(*it).old_last = (*it).keys.size() - 1;
if ((*it).keys.empty()) continue;
if ((*it).keys.empty()) {
continue;
}
if ((int)(*it).type < 1 || (int)(*it).type>EnvelopeType_Unknown) {
continue;
}
switch ((*it).type) {
// translation
case LWO::EnvelopeType_Position_X:
trans_x = &*it;

View File

@ -195,6 +195,9 @@ struct Material {
//! PBR Anisotropy
ai_real anisotropy;
//! bump map multipler (normal map scalar)(-bm)
ai_real bump_multiplier;
//! Constructor
Material() :
diffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
@ -208,7 +211,8 @@ struct Material {
sheen(ai_real(1.0), ai_real(1.0), ai_real(1.0)),
clearcoat_thickness(ai_real(0.0)),
clearcoat_roughness(ai_real(0.0)),
anisotropy(ai_real(0.0)) {
anisotropy(ai_real(0.0)),
bump_multiplier(ai_real(1.0)) {
std::fill_n(clamp, static_cast<unsigned int>(TextureTypeCount), false);
}

View File

@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp>
#include <assimp/ObjMaterial.h>
#include <memory>
static const aiImporterDesc desc = {
@ -604,6 +605,9 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
mat->AddProperty<int>(&sm, 1, AI_MATKEY_SHADING_MODEL);
// Preserve the original illum value
mat->AddProperty<int>(&pCurrentMaterial->illumination_model, 1, AI_MATKEY_OBJ_ILLUM);
// Adding material colors
mat->AddProperty(&pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT);
mat->AddProperty(&pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
@ -657,6 +661,9 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
if (0 != pCurrentMaterial->textureBump.length) {
mat->AddProperty(&pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_HEIGHT(0));
if (pCurrentMaterial->bump_multiplier != 1.0) {
mat->AddProperty(&pCurrentMaterial->bump_multiplier, 1, AI_MATKEY_OBJ_BUMPMULT_HEIGHT(0));
}
if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType]) {
addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
}
@ -665,6 +672,9 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
if (0 != pCurrentMaterial->textureNormal.length) {
mat->AddProperty(&pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_NORMALS(0));
if (pCurrentMaterial->bump_multiplier != 1.0) {
mat->AddProperty(&pCurrentMaterial->bump_multiplier, 1, AI_MATKEY_OBJ_BUMPMULT_NORMALS(0));
}
if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType]) {
addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
}

View File

@ -472,7 +472,11 @@ void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString
}
skipToken = 2;
} else if (!ASSIMP_strincmp(pPtr, BlendUOption.c_str(), static_cast<unsigned int>(BlendUOption.size())) || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), static_cast<unsigned int>(BlendVOption.size())) || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), static_cast<unsigned int>(BoostOption.size())) || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), static_cast<unsigned int>(ResolutionOption.size())) || !ASSIMP_strincmp(pPtr, BumpOption.c_str(), static_cast<unsigned int>(BumpOption.size())) || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), static_cast<unsigned int>(ChannelOption.size()))) {
} else if (!ASSIMP_strincmp(pPtr, BumpOption.c_str(), static_cast<unsigned int>(BumpOption.size()))) {
DataArrayIt it = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
getFloat(it, m_DataItEnd, m_pModel->m_pCurrentMaterial->bump_multiplier);
skipToken = 2;
} else if (!ASSIMP_strincmp(pPtr, BlendUOption.c_str(), static_cast<unsigned int>(BlendUOption.size())) || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), static_cast<unsigned int>(BlendVOption.size())) || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), static_cast<unsigned int>(BoostOption.size())) || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), static_cast<unsigned int>(ResolutionOption.size())) || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), static_cast<unsigned int>(ChannelOption.size()))) {
skipToken = 2;
} else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), static_cast<unsigned int>(ModifyMapOption.size()))) {
skipToken = 3;

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -60,25 +58,11 @@ using namespace Assimp::Formatter;
#ifndef ASSIMP_BUILD_NO_COMPRESSED_X
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
#include <zlib.h>
#else
#include "../contrib/zlib/zlib.h"
#endif
#include "Common/Compression.h"
// Magic identifier for MSZIP compressed data
#define MSZIP_MAGIC 0x4B43
#define MSZIP_BLOCK 32786
// ------------------------------------------------------------------------------------------------
// Dummy memory wrappers for use with zlib
static void *dummy_alloc(void * /*opaque*/, unsigned int items, unsigned int size) {
return ::operator new(items *size);
}
static void dummy_free(void * /*opaque*/, void *address) {
return ::operator delete(address);
}
constexpr unsigned int MSZIP_MAGIC = 0x4B43;
constexpr size_t MSZIP_BLOCK = 32786l;
#endif // !! ASSIMP_BUILD_NO_COMPRESSED_X
@ -133,13 +117,13 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
mIsBinaryFormat = true;
compressed = true;
} else
ThrowException("Unsupported xfile format '", mP[8], mP[9], mP[10], mP[11], "'");
ThrowException("Unsupported x-file format '", mP[8], mP[9], mP[10], mP[11], "'");
// float size
mBinaryFloatSize = (unsigned int)(mP[12] - 48) * 1000 + (unsigned int)(mP[13] - 48) * 100 + (unsigned int)(mP[14] - 48) * 10 + (unsigned int)(mP[15] - 48);
if (mBinaryFloatSize != 32 && mBinaryFloatSize != 64)
ThrowException("Unknown float size ", mBinaryFloatSize, " specified in xfile header.");
ThrowException("Unknown float size ", mBinaryFloatSize, " specified in x-file header.");
// The x format specifies size in bits, but we work in bytes
mBinaryFloatSize /= 8;
@ -171,16 +155,6 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
* ///////////////////////////////////////////////////////////////////////
*/
// build a zlib stream
z_stream stream;
stream.opaque = nullptr;
stream.zalloc = &dummy_alloc;
stream.zfree = &dummy_free;
stream.data_type = (mIsBinaryFormat ? Z_BINARY : Z_ASCII);
// initialize the inflation algorithm
::inflateInit2(&stream, -MAX_WBITS);
// skip unknown data (checksum, flags?)
mP += 6;
@ -207,43 +181,29 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
// and advance to the next offset
P1 += ofs;
est_out += MSZIP_BLOCK; // one decompressed block is 32786 in size
est_out += MSZIP_BLOCK; // one decompressed block is 327861 in size
}
// Allocate storage and terminating zero and do the actual uncompressing
Compression compression;
uncompressed.resize(est_out + 1);
char *out = &uncompressed.front();
while (mP + 3 < mEnd) {
uint16_t ofs = *((uint16_t *)mP);
AI_SWAP2(ofs);
mP += 4;
if (compression.open(mIsBinaryFormat ? Compression::Format::Binary : Compression::Format::ASCII,
Compression::FlushMode::SyncFlush, -Compression::MaxWBits)) {
while (mP + 3 < mEnd) {
uint16_t ofs = *((uint16_t *)mP);
AI_SWAP2(ofs);
mP += 4;
if (mP + ofs > mEnd + 2) {
throw DeadlyImportError("X: Unexpected EOF in compressed chunk");
if (mP + ofs > mEnd + 2) {
throw DeadlyImportError("X: Unexpected EOF in compressed chunk");
}
out += compression.decompressBlock(mP, ofs, out, MSZIP_BLOCK);
mP += ofs;
}
// push data to the stream
stream.next_in = (Bytef *)mP;
stream.avail_in = ofs;
stream.next_out = (Bytef *)out;
stream.avail_out = MSZIP_BLOCK;
// and decompress the data ....
int ret = ::inflate(&stream, Z_SYNC_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END)
throw DeadlyImportError("X: Failed to decompress MSZIP-compressed data");
::inflateReset(&stream);
::inflateSetDictionary(&stream, (const Bytef *)out, MSZIP_BLOCK - stream.avail_out);
// and advance to the next offset
out += MSZIP_BLOCK - stream.avail_out;
mP += ofs;
compression.close();
}
// terminate zlib
::inflateEnd(&stream);
// ok, update pointers to point to the uncompressed file data
mP = &uncompressed[0];
mEnd = out;
@ -279,15 +239,16 @@ void XFileParser::ParseFile() {
while (running) {
// read name of next object
std::string objectName = GetNextToken();
if (objectName.length() == 0)
if (objectName.length() == 0) {
break;
}
// parse specific object
if (objectName == "template")
if (objectName == "template") {
ParseDataObjectTemplate();
else if (objectName == "Frame")
} else if (objectName == "Frame") {
ParseDataObjectFrame(nullptr);
else if (objectName == "Mesh") {
} else if (objectName == "Mesh") {
// some meshes have no frames at all
Mesh *mesh = new Mesh;
ParseDataObjectMesh(mesh);
@ -326,11 +287,13 @@ void XFileParser::ParseDataObjectTemplate() {
while (running) {
std::string s = GetNextToken();
if (s == "}")
if (s == "}") {
break;
}
if (s.length() == 0)
if (s.length() == 0) {
ThrowException("Unexpected end of file reached while parsing template definition");
}
}
}
@ -500,7 +463,7 @@ void XFileParser::ParseDataObjectSkinWeights(Mesh *pMesh) {
bone.mWeights.reserve(numWeights);
for (unsigned int a = 0; a < numWeights; a++) {
BoneWeight weight;
BoneWeight weight = {};
weight.mVertex = ReadInt();
bone.mWeights.push_back(weight);
}

View File

@ -44,28 +44,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
#include "XGLLoader.h"
#include "Common/Compression.h"
#include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h>
#include <assimp/MemoryIOWrapper.h>
#include <assimp/StreamReader.h>
#include <assimp/importerdesc.h>
#include <assimp/mesh.h>
#include <assimp/scene.h>
#include <cctype>
#include <memory>
//#include <cctype>
//#include <memory>
using namespace Assimp;
// zlib is needed for compressed XGL files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
# else
# include <contrib/zlib/zlib.h>
# endif
#endif
namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
template <>
@ -73,6 +65,7 @@ const char *LogFunctions<XGLImporter>::Prefix() {
static auto prefix = "XGL: ";
return prefix;
}
} // namespace Assimp
static const aiImporterDesc desc = {
@ -118,8 +111,8 @@ const aiImporterDesc *XGLImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
std::vector<Bytef> uncompressed;
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
std::vector<char> uncompressed;
#endif
m_scene = pScene;
@ -137,48 +130,16 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
#else
std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
// build a zlib stream
z_stream zstream;
zstream.opaque = Z_NULL;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.data_type = Z_BINARY;
// raw decompression without a zlib or gzip header
inflateInit2(&zstream, -MAX_WBITS);
// skip two extra bytes, zgl files do carry a crc16 upfront (I think)
raw_reader->IncPtr(2);
zstream.next_in = reinterpret_cast<Bytef *>(raw_reader->GetPtr());
zstream.avail_in = (uInt) raw_reader->GetRemainingSize();
size_t total = 0l;
// TODO: be smarter about this, decompress directly into heap buffer
// and decompress the data .... do 1k chunks in the hope that we won't kill the stack
#define MYBLOCK 1024
Bytef block[MYBLOCK];
int ret;
do {
zstream.avail_out = MYBLOCK;
zstream.next_out = block;
ret = inflate(&zstream, Z_NO_FLUSH);
if (ret != Z_STREAM_END && ret != Z_OK) {
ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .XGL file");
}
const size_t have = MYBLOCK - zstream.avail_out;
total += have;
uncompressed.resize(total);
memcpy(uncompressed.data() + total - have, block, have);
} while (ret != Z_STREAM_END);
// terminate zlib
inflateEnd(&zstream);
Compression compression;
size_t total = 0l;
if (compression.open(Compression::Format::Binary, Compression::FlushMode::NoFlush, -Compression::MaxWBits)) {
// skip two extra bytes, zgl files do carry a crc16 upfront (I think)
raw_reader->IncPtr(2);
total = compression.decompress((unsigned char *)raw_reader->GetPtr(), raw_reader->GetRemainingSize(), uncompressed);
compression.close();
}
// replace the input stream with a memory stream
stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));
stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(uncompressed.data()), total));
#endif
}
@ -239,7 +200,7 @@ void XGLImporter::ReadWorld(XmlNode &node, TempScope &scope) {
if (!nd) {
ThrowException("failure reading <world>");
}
if (!nd->mName.length) {
if (nd->mName.length == 0) {
nd->mName.Set("WORLD");
}
@ -291,7 +252,8 @@ aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope) {
const std::string &s = ai_stdStrToLower(child.name());
if (s == "mesh") {
const size_t prev = scope.meshes_linear.size();
if (ReadMesh(child, scope)) {
bool empty;
if (ReadMesh(child, scope, empty)) {
const size_t newc = scope.meshes_linear.size();
for (size_t i = 0; i < newc - prev; ++i) {
meshes.push_back(static_cast<unsigned int>(i + prev));
@ -475,12 +437,12 @@ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
}
// ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) {
TempMesh t;
std::map<unsigned int, TempMaterialMesh> bymat;
const unsigned int mesh_id = ReadIDAttr(node);
bool empty_mesh = true;
for (XmlNode &child : node.children()) {
const std::string &s = ai_stdStrToLower(child.name());
@ -539,6 +501,9 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
mid = ResolveMaterialRef(sub_child, scope);
}
}
if (has[0] || has[1] || has[2]) {
empty_mesh = false;
}
if (mid == ~0u) {
ThrowException("missing material index");
@ -590,6 +555,11 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
scope.meshes.insert(std::pair<unsigned int, aiMesh *>(mesh_id, m));
}
}
if (empty_mesh) {
LogWarn("Mesh is empty, skipping.");
empty = empty_mesh;
return false;
}
// no id == not a reference, insert this mesh right *here*
return mesh_id == ~0u;
@ -759,7 +729,7 @@ aiVector2D XGLImporter::ReadVec2(XmlNode &node) {
std::string val;
XmlParser::getValueAsString(node, val);
const char *s = val.c_str();
ai_real v[2];
ai_real v[2] = {};
for (int i = 0; i < 2; ++i) {
if (!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse vec2");
@ -814,4 +784,4 @@ aiColor3D XGLImporter::ReadCol3(XmlNode &node) {
return aiColor3D(v.x, v.y, v.z);
}
#endif
#endif // ASSIMP_BUILD_NO_XGL_IMPORTER

View File

@ -186,7 +186,7 @@ private:
void ReadLighting(XmlNode &node, TempScope &scope);
aiLight *ReadDirectionalLight(XmlNode &node);
aiNode *ReadObject(XmlNode &node, TempScope &scope);
bool ReadMesh(XmlNode &node, TempScope &scope);
bool ReadMesh(XmlNode &node, TempScope &scope, bool &empty);
void ReadMaterial(XmlNode &node, TempScope &scope);
aiVector2D ReadVec2(XmlNode &node);
aiVector3D ReadVec3(XmlNode &node);

View File

@ -260,20 +260,9 @@ public:
VEC4,
MAT2,
MAT3,
MAT4 };
private:
static const size_t NUM_VALUES = static_cast<size_t>(MAT4) + 1;
struct Info {
const char *name;
unsigned int numComponents;
MAT4
};
template <int N>
struct data { static const Info infos[NUM_VALUES]; };
public:
inline static Value FromString(const char *str) {
for (size_t i = 0; i < NUM_VALUES; ++i) {
if (strcmp(data<0>::infos[i].name, str) == 0) {
@ -290,40 +279,31 @@ public:
inline static unsigned int GetNumComponents(Value type) {
return data<0>::infos[static_cast<size_t>(type)].numComponents;
}
private:
static const size_t NUM_VALUES = static_cast<size_t>(MAT4) + 1;
struct Info {
const char *name;
unsigned int numComponents;
};
template <int N>
struct data {
static const Info infos[NUM_VALUES];
};
};
// must match the order of the AttribTypeTraits::Value enum!
template <int N>
const AttribType::Info
AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
{ "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 }
};
/*
//! A reference to one top-level object, which is valid
//! until the Asset instance is destroyed
template<class T>
class Ref
{
std::vector<T*>* vector;
unsigned int index;
public:
Ref() : vector(0), index(0) {}
Ref(std::vector<T*>& vec, unsigned int idx) : vector(&vec), index(idx) {}
inline unsigned int GetIndex() const
{ return index; }
operator bool() const
{ return vector != 0; }
T* operator->()
{ return (*vector)[index]; }
T& operator*()
{ return *((*vector)[index]); }
};*/
const AttribType::Info AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
{ "SCALAR", 1 },
{ "VEC2", 2 },
{ "VEC3", 3 },
{ "VEC4", 4 },
{ "MAT2", 4 },
{ "MAT3", 9 },
{ "MAT4", 16 }
};
//! Base class for all glTF top-level objects
struct Object {
@ -333,6 +313,7 @@ struct Object {
//! Objects marked as special are not exported (used to emulate the binary body buffer)
virtual bool IsSpecial() const { return false; }
Object() = default;
virtual ~Object() {}
//! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
@ -401,21 +382,19 @@ struct Accessor : public Object {
return Indexer(*this);
}
Accessor() {}
Accessor() = default;
void Read(Value &obj, Asset &r);
};
//! A buffer points to binary geometry, animation, or skins.
struct Buffer : public Object {
/********************* Types *********************/
public:
enum Type {
Type_arraybuffer,
Type_text
};
/// \struct SEncodedRegion
/// Descriptor of encoded region in "bufferView".
/// @brief Descriptor of encoded region in "bufferView".
struct SEncodedRegion {
const size_t Offset; ///< Offset from begin of "bufferView" to encoded region, in bytes.
const size_t EncodedData_Length; ///< Size of encoded region, in bytes.
@ -423,8 +402,7 @@ public:
const size_t DecodedData_Length; ///< Size of decoded region, in bytes.
const std::string ID; ///< ID of the region.
/// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
/// Constructor.
/// @brief Constructor.
/// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
/// \param [in] pEncodedData_Length - size of encoded region, in bytes.
/// \param [in] pDecodedData - pointer to decoded data array.
@ -433,16 +411,13 @@ public:
SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) :
Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) {}
/// \fn ~SEncodedRegion()
/// Destructor.
~SEncodedRegion() { delete[] DecodedData; }
};
/******************* Variables *******************/
//std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required)
size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
//std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
Type type;
@ -486,7 +461,6 @@ public:
bool LoadFromStream(IOStream &stream, size_t length = 0, size_t baseOffset = 0);
/// \fn void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
/// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
/// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
/// \param [in] pEncodedData_Length - size of encoded region, in bytes.
@ -495,12 +469,10 @@ public:
/// \param [in] pID - ID of the region.
void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID);
/// \fn void EncodedRegion_SetCurrent(const std::string& pID)
/// Select current encoded region by ID. \sa EncodedRegion_Current.
/// \param [in] pID - ID of the region.
void EncodedRegion_SetCurrent(const std::string &pID);
/// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
/// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
/// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
/// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
@ -558,37 +530,29 @@ struct Camera : public Object {
} ortographic;
};
Camera() {}
Camera() = default;
void Read(Value &obj, Asset &r);
};
//! Image data used to create a texture.
struct Image : public Object {
std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
Ref<BufferView> bufferView;
std::string mimeType;
int width, height;
private:
std::unique_ptr<uint8_t[]> mData;
size_t mDataLength;
public:
Image();
void Read(Value &obj, Asset &r);
inline bool HasData() const { return mDataLength > 0; }
inline size_t GetDataLength() const { return mDataLength; }
inline const uint8_t *GetData() const { return mData.get(); }
inline uint8_t *StealData();
inline void SetData(uint8_t *data, size_t length, Asset &r);
private:
std::unique_ptr<uint8_t[]> mData;
size_t mDataLength;
};
//! Holds a material property that can be a texture or a color
@ -671,6 +635,7 @@ struct Mesh : public Object {
};
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
/// \struct SCompression_Open3DGC
/// Compression of mesh data using Open3DGC algorithm.
struct SCompression_Open3DGC : public SExtension {
@ -703,7 +668,6 @@ struct Mesh : public Object {
Mesh() {}
/// \fn ~Mesh()
/// Destructor.
~Mesh() {
for (std::list<SExtension *>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) {
@ -711,15 +675,13 @@ struct Mesh : public Object {
};
}
/// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
/// Get mesh data from JSON-object and place them to root asset.
/// @brief Get mesh data from JSON-object and place them to root asset.
/// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
/// \param [out] pAsset_Root - reference to root asset where data will be stored.
void Read(Value &pJSON_Object, Asset &pAsset_Root);
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
/// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root)
/// Decode part of "buffer" which encoded with Open3DGC algorithm.
/// @brief Decode part of "buffer" which encoded with Open3DGC algorithm.
/// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region.
/// \param [out] pAsset_Root - reference to root assed where data will be stored.
void Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DGC, Asset &pAsset_Root);
@ -759,7 +721,7 @@ struct Sampler : public Object {
SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required)
SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required)
Sampler() {}
Sampler() = default;
void Read(Value &obj, Asset &r);
void SetDefaults();
};
@ -767,12 +729,12 @@ struct Sampler : public Object {
struct Scene : public Object {
std::vector<Ref<Node>> nodes;
Scene() {}
Scene() = default;
void Read(Value &obj, Asset &r);
};
struct Shader : public Object {
Shader() {}
Shader() = default;
void Read(Value &obj, Asset &r);
};
@ -782,7 +744,7 @@ struct Skin : public Object {
std::vector<Ref<Node>> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin.
std::string name; //!< The user-defined name of this object.
Skin() {}
Skin() = default;
void Read(Value &obj, Asset &r);
};
@ -796,7 +758,7 @@ struct Technique : public Object {
struct Functions {
};
Technique() {}
Technique() = default;
void Read(Value &obj, Asset &r);
};
@ -805,13 +767,7 @@ struct Texture : public Object {
Ref<Sampler> sampler; //!< The ID of the sampler used by this texture. (required)
Ref<Image> source; //!< The ID of the image used by this texture. (required)
//TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
//TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
//TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D)
//TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE)
Texture() {}
Texture() = default;
void Read(Value &obj, Asset &r);
};
@ -826,7 +782,6 @@ struct Light : public Object {
};
Type type;
vec4 color;
float distance;
float constantAttenuation;
@ -835,9 +790,8 @@ struct Light : public Object {
float falloffAngle;
float falloffExponent;
Light() {}
Light() = default;
void Read(Value &obj, Asset &r);
void SetDefaults();
};
@ -865,15 +819,11 @@ struct Animation : public Object {
Ref<Accessor> translation; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
};
// AnimChannel Channels[3]; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
// AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
// AnimSampler Samplers[3]; //!< The parameterized inputs representing the key-frame data.
std::vector<AnimChannel> Channels; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
std::vector<AnimSampler> Samplers; //!< The parameterized inputs representing the key-frame data.
Animation() {}
Animation() = default;
void Read(Value &obj, Asset &r);
};
@ -963,13 +913,11 @@ struct AssetMetadata {
//! Root object for a glTF asset
class Asset {
typedef std::gltf_unordered_map<std::string, int> IdMap;
using IdMap = std::gltf_unordered_map<std::string, int>;
template <class T>
friend class LazyDict;
friend struct Buffer; // To access OpenFile
friend class AssetWriter;
private:
@ -1010,12 +958,9 @@ public:
LazyDict<Material> materials;
LazyDict<Mesh> meshes;
LazyDict<Node> nodes;
//LazyDict<Program> programs;
LazyDict<Sampler> samplers;
LazyDict<Scene> scenes;
//LazyDict<Shader> shaders;
LazyDict<Skin> skins;
//LazyDict<Technique> techniques;
LazyDict<Texture> textures;
LazyDict<Light> lights; // KHR_materials_common ext
@ -1024,16 +969,20 @@ public:
public:
Asset(IOSystem *io = 0) :
mIOSystem(io), asset(), accessors(*this, "accessors"), animations(*this, "animations"), buffers(*this, "buffers"), bufferViews(*this, "bufferViews"), cameras(*this, "cameras"), images(*this, "images"), materials(*this, "materials"), meshes(*this, "meshes"), nodes(*this, "nodes")
//, programs (*this, "programs")
,
mIOSystem(io),
asset(),
accessors(*this, "accessors"),
animations(*this, "animations"),
buffers(*this, "buffers"),
bufferViews(*this, "bufferViews"),
cameras(*this, "cameras"),
images(*this, "images"),
materials(*this, "materials"),
meshes(*this, "meshes"),
nodes(*this, "nodes"),
samplers(*this, "samplers"),
scenes(*this, "scenes")
//, shaders (*this, "shaders")
,
skins(*this, "skins")
//, techniques (*this, "techniques")
,
scenes(*this, "scenes"),
skins(*this, "skins"),
textures(*this, "textures"),
lights(*this, "lights", "KHR_materials_common") {
memset(&extensionsUsed, 0, sizeof(extensionsUsed));

View File

@ -237,8 +237,6 @@ bool ParseDataURI(const char *const_uri, size_t uriLen, DataURI &out);
#define CHECK_EXT(EXT) \
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
//! Helper struct to represent values that might not be present
template <class T>
struct Nullable {

View File

@ -106,7 +106,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# define gltf_unordered_map tr1::unordered_map
# define gltf_unordered_set tr1::unordered_set
# else
# define gltf_unordered_map unordered_map
# define gltf_unordered_map unordered_map
# define gltf_unordered_set unordered_set
# endif
#endif
@ -1087,29 +1087,11 @@ class Asset {
template <class T>
friend class LazyDict;
friend struct Buffer; // To access OpenFile
friend class AssetWriter;
private:
IOSystem *mIOSystem;
rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider;
std::string mCurrentAssetDir;
size_t mSceneLength;
size_t mBodyOffset, mBodyLength;
std::vector<LazyDictBase *> mDicts;
IdMap mUsedIds;
Ref<Buffer> mBodyBuffer;
Asset(Asset &);
Asset &operator=(const Asset &);
public:
//! Keeps info about the enabled extensions
struct Extensions {
@ -1125,16 +1107,36 @@ public:
bool KHR_draco_mesh_compression;
bool FB_ngon_encoding;
bool KHR_texture_basisu;
Extensions() :
KHR_materials_pbrSpecularGlossiness(false),
KHR_materials_unlit(false),
KHR_lights_punctual(false),
KHR_texture_transform(false),
KHR_materials_sheen(false),
KHR_materials_clearcoat(false),
KHR_materials_transmission(false),
KHR_materials_volume(false),
KHR_materials_ior(false),
KHR_draco_mesh_compression(false),
FB_ngon_encoding(false),
KHR_texture_basisu(false) {
// empty
}
} extensionsUsed;
//! Keeps info about the required extensions
struct RequiredExtensions {
bool KHR_draco_mesh_compression;
bool KHR_texture_basisu;
RequiredExtensions() : KHR_draco_mesh_compression(false), KHR_texture_basisu(false) {
// empty
}
} extensionsRequired;
AssetMetadata asset;
Value *extras = nullptr;
Value *extras;
// Dictionaries for each type of object
@ -1157,9 +1159,11 @@ public:
public:
Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) :
mIOSystem(io),
mSchemaDocumentProvider(schemaDocumentProvider),
mDicts(),
extensionsUsed(),
extensionsRequired(),
asset(),
extras(nullptr),
accessors(*this, "accessors"),
animations(*this, "animations"),
buffers(*this, "buffers"),
@ -1173,9 +1177,10 @@ public:
samplers(*this, "samplers"),
scenes(*this, "scenes"),
skins(*this, "skins"),
textures(*this, "textures") {
memset(&extensionsUsed, 0, sizeof(extensionsUsed));
memset(&extensionsRequired, 0, sizeof(extensionsRequired));
textures(*this, "textures") ,
mIOSystem(io),
mSchemaDocumentProvider(schemaDocumentProvider) {
// empty
}
//! Main function
@ -1192,18 +1197,31 @@ public:
Ref<Buffer> GetBodyBuffer() { return mBodyBuffer; }
Asset(Asset &) = delete;
Asset &operator=(const Asset &) = delete;
private:
void ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData);
//! Obtain a JSON document from the stream.
// \param second argument is a buffer used by the document. It must be kept
// alive while the document is in use.
/// Obtain a JSON document from the stream.
/// \param second argument is a buffer used by the document. It must be kept
/// alive while the document is in use.
Document ReadDocument(IOStream& stream, bool isBinary, std::vector<char>& sceneData);
void ReadExtensionsUsed(Document &doc);
void ReadExtensionsRequired(Document &doc);
IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
private:
IOSystem *mIOSystem;
rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider;
std::string mCurrentAssetDir;
size_t mSceneLength;
size_t mBodyOffset;
size_t mBodyLength;
IdMap mUsedIds;
Ref<Buffer> mBodyBuffer;
};
inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {

View File

@ -515,72 +515,74 @@ void glTF2Exporter::GetMatTexProp(const aiMaterial &mat, float &prop, const char
}
void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) {
if (mat.GetTextureCount(tt) > 0) {
aiString tex;
if (mat.GetTextureCount(tt) == 0) {
return;
}
// Read texcoord (UV map index)
mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
aiString tex;
if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
std::string path = tex.C_Str();
// Read texcoord (UV map index)
mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
if (path.size() > 0) {
std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
if (it != mTexturesByPath.end()) {
texture = mAsset->textures.Get(it->second);
}
if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
std::string path = tex.C_Str();
bool useBasisUniversal = false;
if (!texture) {
std::string texId = mAsset->FindUniqueID("", "texture");
texture = mAsset->textures.Create(texId);
mTexturesByPath[path] = texture.GetIndex();
if (path.size() > 0) {
std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
if (it != mTexturesByPath.end()) {
texture = mAsset->textures.Get(it->second);
}
std::string imgId = mAsset->FindUniqueID("", "image");
texture->source = mAsset->images.Create(imgId);
bool useBasisUniversal = false;
if (!texture) {
std::string texId = mAsset->FindUniqueID("", "texture");
texture = mAsset->textures.Create(texId);
mTexturesByPath[path] = texture.GetIndex();
const aiTexture *curTex = mScene->GetEmbeddedTexture(path.c_str());
if (curTex != nullptr) { // embedded
texture->source->name = curTex->mFilename.C_Str();
std::string imgId = mAsset->FindUniqueID("", "image");
texture->source = mAsset->images.Create(imgId);
//basisu: embedded ktx2, bu
if (curTex->achFormatHint[0]) {
std::string mimeType = "image/";
if (memcmp(curTex->achFormatHint, "jpg", 3) == 0)
mimeType += "jpeg";
else if (memcmp(curTex->achFormatHint, "ktx", 3) == 0) {
useBasisUniversal = true;
mimeType += "ktx";
} else if (memcmp(curTex->achFormatHint, "kx2", 3) == 0) {
useBasisUniversal = true;
mimeType += "ktx2";
} else if (memcmp(curTex->achFormatHint, "bu", 2) == 0) {
useBasisUniversal = true;
mimeType += "basis";
} else
mimeType += curTex->achFormatHint;
texture->source->mimeType = mimeType;
}
const aiTexture *curTex = mScene->GetEmbeddedTexture(path.c_str());
if (curTex != nullptr) { // embedded
texture->source->name = curTex->mFilename.C_Str();
// The asset has its own buffer, see Image::SetData
//basisu: "image/ktx2", "image/basis" as is
texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset);
} else {
texture->source->uri = path;
if (texture->source->uri.find(".ktx") != std::string::npos ||
texture->source->uri.find(".basis") != std::string::npos) {
//basisu: embedded ktx2, bu
if (curTex->achFormatHint[0]) {
std::string mimeType = "image/";
if (memcmp(curTex->achFormatHint, "jpg", 3) == 0)
mimeType += "jpeg";
else if (memcmp(curTex->achFormatHint, "ktx", 3) == 0) {
useBasisUniversal = true;
}
mimeType += "ktx";
} else if (memcmp(curTex->achFormatHint, "kx2", 3) == 0) {
useBasisUniversal = true;
mimeType += "ktx2";
} else if (memcmp(curTex->achFormatHint, "bu", 2) == 0) {
useBasisUniversal = true;
mimeType += "basis";
} else
mimeType += curTex->achFormatHint;
texture->source->mimeType = mimeType;
}
//basisu
if (useBasisUniversal) {
mAsset->extensionsUsed.KHR_texture_basisu = true;
mAsset->extensionsRequired.KHR_texture_basisu = true;
// The asset has its own buffer, see Image::SetData
//basisu: "image/ktx2", "image/basis" as is
texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset);
} else {
texture->source->uri = path;
if (texture->source->uri.find(".ktx") != std::string::npos ||
texture->source->uri.find(".basis") != std::string::npos) {
useBasisUniversal = true;
}
GetTexSampler(mat, texture, tt, slot);
}
//basisu
if (useBasisUniversal) {
mAsset->extensionsUsed.KHR_texture_basisu = true;
mAsset->extensionsRequired.KHR_texture_basisu = true;
}
GetTexSampler(mat, texture, tt, slot);
}
}
}
@ -588,12 +590,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsi
void glTF2Exporter::GetMatTex(const aiMaterial &mat, TextureInfo &prop, aiTextureType tt, unsigned int slot = 0) {
Ref<Texture> &texture = prop.texture;
GetMatTex(mat, texture, prop.texCoord, tt, slot);
//if (texture) {
// GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
//}
}
void glTF2Exporter::GetMatTex(const aiMaterial &mat, NormalTextureInfo &prop, aiTextureType tt, unsigned int slot = 0) {
@ -681,12 +678,14 @@ bool glTF2Exporter::GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlo
bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen) {
// Return true if got any valid Sheen properties or textures
if (GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_SHEEN_COLOR_FACTOR) != aiReturn_SUCCESS)
if (GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_SHEEN_COLOR_FACTOR) != aiReturn_SUCCESS) {
return false;
}
// Default Sheen color factor {0,0,0} disables Sheen, so do not export
if (sheen.sheenColorFactor == defaultSheenFactor)
if (sheen.sheenColorFactor == defaultSheenFactor) {
return false;
}
mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor);
@ -781,9 +780,7 @@ void glTF2Exporter::ExportMaterials() {
aiColor4D specularColor;
ai_real shininess;
if (
mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
if (mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
// convert specular color to luminance
float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f;
//normalize shininess (assuming max is 1000) with an inverse exponentional curve
@ -916,7 +913,8 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin> &skinRef) {
return parentNodeRef;
}
void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buffer> &bufferRef, Ref<Skin> &skinRef, std::vector<aiMatrix4x4> &inverseBindMatricesData) {
void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buffer> &bufferRef, Ref<Skin> &skinRef,
std::vector<aiMatrix4x4> &inverseBindMatricesData) {
if (aimesh->mNumBones < 1) {
return;
}
@ -986,7 +984,8 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buf
} // End: for-loop mNumMeshes
Mesh::Primitive &p = meshRef->primitives.back();
Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices,
vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
if (vertexJointAccessor) {
size_t offset = vertexJointAccessor->bufferView->byteOffset;
size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
@ -1069,8 +1068,11 @@ void glTF2Exporter::ExportMeshes() {
p.ngonEncoded = (aim->mPrimitiveTypes & aiPrimitiveType_NGONEncodingFlag) != 0;
/******************* Vertices ********************/
Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (v) p.attributes.position.push_back(v);
Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3,
AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (v) {
p.attributes.position.push_back(v);
}
/******************** Normals ********************/
// Normalize all normals as the validator can emit a warning otherwise
@ -1080,13 +1082,17 @@ void glTF2Exporter::ExportMeshes() {
}
}
Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (n) p.attributes.normal.push_back(n);
Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3,
AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (n) {
p.attributes.normal.push_back(n);
}
/************** Texture coordinates **************/
for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (!aim->HasTextureCoords(i))
if (!aim->HasTextureCoords(i)) {
continue;
}
// Flip UV y coords
if (aim->mNumUVComponents[i] > 1) {
@ -1098,16 +1104,21 @@ void glTF2Exporter::ExportMeshes() {
if (aim->mNumUVComponents[i] > 0) {
AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3;
Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (tc) p.attributes.texcoord.push_back(tc);
Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i],
AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (tc) {
p.attributes.texcoord.push_back(tc);
}
}
}
/*************** Vertex colors ****************/
for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) {
Ref<Accessor> c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (c)
Ref<Accessor> c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel],
AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (c) {
p.attributes.color.push_back(c);
}
}
/*************** Vertices indices ****************/
@ -1121,7 +1132,8 @@ void glTF2Exporter::ExportMeshes() {
}
}
p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER);
p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR,
ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER);
}
switch (aim->mPrimitiveTypes) {
@ -1136,6 +1148,7 @@ void glTF2Exporter::ExportMeshes() {
break;
default: // aiPrimitiveType_TRIANGLE
p.mode = PrimitiveMode_TRIANGLES;
break;
}
/*************** Skins ****************/
@ -1155,8 +1168,9 @@ void glTF2Exporter::ExportMeshes() {
p.targets.resize(aim->mNumAnimMeshes);
for (unsigned int am = 0; am < aim->mNumAnimMeshes; ++am) {
aiAnimMesh *pAnimMesh = aim->mAnimMeshes[am];
if (bExportTargetNames)
m->targetNames.push_back(pAnimMesh->mName.data);
if (bExportTargetNames) {
m->targetNames.emplace_back(pAnimMesh->mName.data);
}
// position
if (pAnimMesh->HasPositions()) {
// NOTE: in gltf it is the diff stored
@ -1319,12 +1333,12 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode *n) {
}
for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i]));
node->meshes.emplace_back(mAsset->meshes.Get(n->mMeshes[i]));
}
for (unsigned int i = 0; i < n->mNumChildren; ++i) {
unsigned int idx = ExportNode(n->mChildren[i], node);
node->children.push_back(mAsset->nodes.Get(idx));
node->children.emplace_back(mAsset->nodes.Get(idx));
}
return node.GetIndex();
@ -1366,12 +1380,12 @@ unsigned int glTF2Exporter::ExportNode(const aiNode *n, Ref<Node> &parent) {
}
for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i]));
node->meshes.emplace_back(mAsset->meshes.Get(n->mMeshes[i]));
}
for (unsigned int i = 0; i < n->mNumChildren; ++i) {
unsigned int idx = ExportNode(n->mChildren[i], node);
node->children.push_back(mAsset->nodes.Get(idx));
node->children.emplace_back(mAsset->nodes.Get(idx));
}
return node.GetIndex();
@ -1386,7 +1400,7 @@ void glTF2Exporter::ExportScene() {
// root node will be the first one exported (idx 0)
if (mAsset->nodes.Size() > 0) {
scene->nodes.push_back(mAsset->nodes.Get(0u));
scene->nodes.emplace_back(mAsset->nodes.Get(0u));
}
// set as the default scene
@ -1521,12 +1535,6 @@ void glTF2Exporter::ExportAnimations() {
AddSampler(animRef, animNode, scaleSampler, AnimationPath_SCALE);
}
}
// Assimp documentation states this is not used (not implemented)
// for (unsigned int channelIndex = 0; channelIndex < anim->mNumMeshChannels; ++channelIndex) {
// const aiMeshAnim* meshChannel = anim->mMeshChannels[channelIndex];
// }
} // End: for-loop mNumAnimations
}

View File

@ -166,6 +166,8 @@ SET( Logging_SRCS
SOURCE_GROUP(Logging FILES ${Logging_SRCS})
SET( Common_SRCS
Common/Compression.cpp
Common/Compression.h
Common/BaseImporter.cpp
Common/BaseProcess.cpp
Common/BaseProcess.h
@ -1315,11 +1317,10 @@ ENDIF ()
INSTALL( TARGETS assimp
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
COMPONENT ${LIBASSIMP_COMPONENT}
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP-DEV_COMPONENT}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
)
INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2021, assimp team
Copyright (c) 2006-2022, assimp team
All rights reserved.
@ -57,7 +57,7 @@ static const uint8_t tableDecodeBase64[128] = {
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0
};
static const char* tableEncodeBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
static const char *tableEncodeBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
static inline char EncodeChar(uint8_t b) {
return tableEncodeBase64[size_t(b)];
@ -104,17 +104,16 @@ void Encode(const uint8_t *in, size_t inLength, std::string &out) {
}
}
void Encode(const std::vector<uint8_t>& in, std::string &out) {
Encode (in.data (), in.size (), out);
void Encode(const std::vector<uint8_t> &in, std::string &out) {
Encode(in.data(), in.size(), out);
}
std::string Encode (const std::vector<uint8_t>& in) {
std::string Encode(const std::vector<uint8_t> &in) {
std::string encoded;
Encode (in, encoded);
Encode(in, encoded);
return encoded;
}
size_t Decode(const char *in, size_t inLength, uint8_t *&out) {
if (inLength % 4 != 0) {
throw DeadlyImportError("Invalid base64 encoded data: \"", std::string(in, std::min(size_t(32), inLength)), "\", length:", inLength);
@ -159,23 +158,22 @@ size_t Decode(const char *in, size_t inLength, uint8_t *&out) {
return outLength;
}
size_t Decode(const std::string& in, std::vector<uint8_t>& out) {
uint8_t* outPtr = nullptr;
size_t decodedSize = Decode (in.data (), in.size (), outPtr);
size_t Decode(const std::string &in, std::vector<uint8_t> &out) {
uint8_t *outPtr = nullptr;
size_t decodedSize = Decode(in.data(), in.size(), outPtr);
if (outPtr == nullptr) {
return 0;
}
out.assign (outPtr, outPtr + decodedSize);
out.assign(outPtr, outPtr + decodedSize);
delete[] outPtr;
return decodedSize;
}
std::vector<uint8_t> Decode (const std::string& in) {
std::vector<uint8_t> Decode(const std::string &in) {
std::vector<uint8_t> result;
Decode (in, result);
Decode(in, result);
return result;
}
}
}
} // namespace Base64
} // namespace Assimp

View File

@ -0,0 +1,214 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2022, 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 "Compression.h"
#include <assimp/ai_assert.h>
#include <assimp/Exceptional.h>
namespace Assimp {
struct Compression::impl {
bool mOpen;
z_stream mZSstream;
FlushMode mFlushMode;
impl() :
mOpen(false),
mZSstream(),
mFlushMode(Compression::FlushMode::NoFlush) {
// empty
}
};
Compression::Compression() :
mImpl(new impl) {
// empty
}
Compression::~Compression() {
ai_assert(mImpl != nullptr);
delete mImpl;
}
bool Compression::open(Format format, FlushMode flush, int windowBits) {
ai_assert(mImpl != nullptr);
if (mImpl->mOpen) {
return false;
}
// build a zlib stream
mImpl->mZSstream.opaque = Z_NULL;
mImpl->mZSstream.zalloc = Z_NULL;
mImpl->mZSstream.zfree = Z_NULL;
mImpl->mFlushMode = flush;
if (format == Format::Binary) {
mImpl->mZSstream.data_type = Z_BINARY;
} else {
mImpl->mZSstream.data_type = Z_ASCII;
}
// raw decompression without a zlib or gzip header
if (windowBits == 0) {
inflateInit(&mImpl->mZSstream);
} else {
inflateInit2(&mImpl->mZSstream, windowBits);
}
mImpl->mOpen = true;
return mImpl->mOpen;
}
static int getFlushMode(Compression::FlushMode flush) {
int z_flush = 0;
switch (flush) {
case Compression::FlushMode::NoFlush:
z_flush = Z_NO_FLUSH;
break;
case Compression::FlushMode::Block:
z_flush = Z_BLOCK;
break;
case Compression::FlushMode::Tree:
z_flush = Z_TREES;
break;
case Compression::FlushMode::SyncFlush:
z_flush = Z_SYNC_FLUSH;
break;
case Compression::FlushMode::Finish:
z_flush = Z_FINISH;
break;
default:
ai_assert(false);
break;
}
return z_flush;
}
constexpr size_t MYBLOCK = 32786;
size_t Compression::decompress(const void *data, size_t in, std::vector<char> &uncompressed) {
ai_assert(mImpl != nullptr);
if (data == nullptr || in == 0) {
return 0l;
}
mImpl->mZSstream.next_in = (Bytef*)(data);
mImpl->mZSstream.avail_in = (uInt)in;
int ret = 0;
size_t total = 0l;
const int flushMode = getFlushMode(mImpl->mFlushMode);
if (flushMode == Z_FINISH) {
mImpl->mZSstream.avail_out = static_cast<uInt>(uncompressed.size());
mImpl->mZSstream.next_out = reinterpret_cast<Bytef *>(&*uncompressed.begin());
ret = inflate(&mImpl->mZSstream, Z_FINISH);
if (ret != Z_STREAM_END && ret != Z_OK) {
throw DeadlyImportError("Compression", "Failure decompressing this file using gzip.");
}
total = mImpl->mZSstream.avail_out;
} else {
do {
Bytef block[MYBLOCK] = {};
mImpl->mZSstream.avail_out = MYBLOCK;
mImpl->mZSstream.next_out = block;
ret = inflate(&mImpl->mZSstream, flushMode);
if (ret != Z_STREAM_END && ret != Z_OK) {
throw DeadlyImportError("Compression", "Failure decompressing this file using gzip.");
}
const size_t have = MYBLOCK - mImpl->mZSstream.avail_out;
total += have;
uncompressed.resize(total);
::memcpy(uncompressed.data() + total - have, block, have);
} while (ret != Z_STREAM_END);
}
return total;
}
size_t Compression::decompressBlock(const void *data, size_t in, char *out, size_t availableOut) {
ai_assert(mImpl != nullptr);
if (data == nullptr || in == 0 || out == nullptr || availableOut == 0) {
return 0l;
}
// push data to the stream
mImpl->mZSstream.next_in = (Bytef *)data;
mImpl->mZSstream.avail_in = (uInt)in;
mImpl->mZSstream.next_out = (Bytef *)out;
mImpl->mZSstream.avail_out = (uInt)availableOut;
// and decompress the data ....
int ret = ::inflate(&mImpl->mZSstream, Z_SYNC_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END) {
throw DeadlyImportError("X: Failed to decompress MSZIP-compressed data");
}
::inflateReset(&mImpl->mZSstream);
::inflateSetDictionary(&mImpl->mZSstream, (const Bytef *)out, (uInt)availableOut - mImpl->mZSstream.avail_out);
return availableOut - (size_t)mImpl->mZSstream.avail_out;
}
bool Compression::isOpen() const {
ai_assert(mImpl != nullptr);
return mImpl->mOpen;
}
bool Compression::close() {
ai_assert(mImpl != nullptr);
if (!mImpl->mOpen) {
return false;
}
inflateEnd(&mImpl->mZSstream);
mImpl->mOpen = false;
return true;
}
} // namespace Assimp

View File

@ -0,0 +1,121 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2022, 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.
----------------------------------------------------------------------
*/
#pragma once
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
#include <zlib.h>
#else
#include "../contrib/zlib/zlib.h"
#endif
#include <vector>
#include <cstddef> // size_t
namespace Assimp {
/// @brief This class provides the decompression of zlib-compressed data.
class Compression {
public:
static const int MaxWBits = MAX_WBITS;
/// @brief Describes the format data type
enum class Format {
InvalidFormat = -1, ///< Invalid enum type.
Binary = 0, ///< Binary format.
ASCII, ///< ASCII format.
NumFormats ///< The number of supported formats.
};
/// @brief The supported flush mode, used for blocked access.
enum class FlushMode {
InvalidFormat = -1, ///< Invalid enum type.
NoFlush = 0, ///< No flush, will be done on inflate end.
Block, ///< Assists in combination of compress.
Tree, ///< Assists in combination of compress and returns if stream is finish.
SyncFlush, ///< Synced flush mode.
Finish, ///< Finish mode, all in once, no block access.
NumModes ///< The number of supported modes.
};
/// @brief The class constructor.
Compression();
/// @brief The class destructor.
~Compression();
/// @brief Will open the access to the compression.
/// @param[in] format The format type
/// @param[in] flush The flush mode.
/// @param[in] windowBits The windows history working size, shall be between 8 and 15.
/// @return true if close was successful, false if not.
bool open(Format format, FlushMode flush, int windowBits);
/// @brief Will return the open state.
/// @return true if the access is opened, false if not.
bool isOpen() const;
/// @brief Will close the decompress access.
/// @return true if close was successful, false if not.
bool close();
/// @brief Will decompress the data buffer in one step.
/// @param[in] data The data to decompress
/// @param[in] in The size of the data.
/// @param[out uncompressed A std::vector containing the decompressed data.
size_t decompress(const void *data, size_t in, std::vector<char> &uncompressed);
/// @brief Will decompress the data buffer block-wise.
/// @param[in] data The compressed data
/// @param[in] in The size of the data buffer
/// @param[out] out The output buffer
/// @param[out] availableOut The upper limit of the output buffer.
/// @return The size of the decompressed data buffer.
size_t decompressBlock(const void *data, size_t in, char *out, size_t availableOut);
private:
struct impl;
impl *mImpl;
};
} // namespace Assimp

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2019, assimp team
Copyright (c) 2006-2022, assimp team
All rights reserved.

View File

@ -5,7 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -53,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
static const char *LEGAL_INFORMATION =
"Open Asset Import Library (Assimp).\n"
"A free C/C++ library to import various 3D file formats into applications\n\n"
"(c) 2006-2021, Assimp team\n"
"(c) 2006-2022, Assimp team\n"
"License under the terms and conditions of the 3-clause BSD license\n"
"https://www.assimp.org\n";

View File

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

View File

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

View File

@ -191,9 +191,9 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
tangent.y = (w.y * sy - v.y * ty) * dirCorrection;
tangent.z = (w.z * sy - v.z * ty) * dirCorrection;
bitangent.x = (w.x * sx - v.x * tx) * dirCorrection;
bitangent.y = (w.y * sx - v.y * tx) * dirCorrection;
bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
bitangent.x = (- w.x * sx + v.x * tx) * dirCorrection;
bitangent.y = (- w.y * sx + v.y * tx) * dirCorrection;
bitangent.z = (- w.z * sx + v.z * tx) * dirCorrection;
// store for every vertex of that face
for (unsigned int b = 0; b < face.mNumIndices; ++b) {
@ -201,7 +201,7 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
// project tangent and bitangent into the plane formed by the vertex' normal
aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]) - localTangent * (bitangent * localTangent);
localTangent.NormalizeSafe();
localBitangent.NormalizeSafe();

View File

@ -221,7 +221,7 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
if ( mConfigCheckAreaOfTriangle ) {
if ( face.mNumIndices == 3 ) {
ai_real area = calculateAreaOfTriangle( face, mesh );
if ( area < 1e-6 ) {
if (area < ai_epsilon) {
if ( mConfigRemoveDegenerates ) {
remove_me[ a ] = true;
++deg;

View File

@ -50,6 +50,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace Base64 {
/// @brief Will encode the given
/// @param in
/// @param inLength
/// @param out
void Encode(const uint8_t *in, size_t inLength, std::string &out);
void Encode(const std::vector<uint8_t>& in, std::string &out);
std::string Encode(const std::vector<uint8_t>& in);

View File

@ -211,7 +211,7 @@ template <typename T> struct ByteSwap::_swapper<T,8> {
// --------------------------------------------------------------------------------------
#if (defined AI_BUILD_BIG_ENDIAN)
# define AI_LE(t) (t)
# define AI_BE(t) ByteSwap::Swapped(t)
# define AI_BE(t) Assimp::ByteSwap::Swapped(t)
# define AI_LSWAP2(p)
# define AI_LSWAP4(p)
# define AI_LSWAP8(p)
@ -219,16 +219,16 @@ template <typename T> struct ByteSwap::_swapper<T,8> {
# define AI_LSWAP4P(p)
# define AI_LSWAP8P(p)
# define LE_NCONST const
# define AI_SWAP2(p) ByteSwap::Swap2(&(p))
# define AI_SWAP4(p) ByteSwap::Swap4(&(p))
# define AI_SWAP8(p) ByteSwap::Swap8(&(p))
# define AI_SWAP2P(p) ByteSwap::Swap2((p))
# define AI_SWAP4P(p) ByteSwap::Swap4((p))
# define AI_SWAP8P(p) ByteSwap::Swap8((p))
# define AI_SWAP2(p) Assimp::ByteSwap::Swap2(&(p))
# define AI_SWAP4(p) Assimp::ByteSwap::Swap4(&(p))
# define AI_SWAP8(p) Assimp::ByteSwap::Swap8(&(p))
# define AI_SWAP2P(p) Assimp::ByteSwap::Swap2((p))
# define AI_SWAP4P(p) Assimp::ByteSwap::Swap4((p))
# define AI_SWAP8P(p) Assimp::ByteSwap::Swap8((p))
# define BE_NCONST
#else
# define AI_BE(t) (t)
# define AI_LE(t) ByteSwap::Swapped(t)
# define AI_LE(t) Assimp::ByteSwap::Swapped(t)
# define AI_SWAP2(p)
# define AI_SWAP4(p)
# define AI_SWAP8(p)
@ -236,12 +236,12 @@ template <typename T> struct ByteSwap::_swapper<T,8> {
# define AI_SWAP4P(p)
# define AI_SWAP8P(p)
# define BE_NCONST const
# define AI_LSWAP2(p) ByteSwap::Swap2(&(p))
# define AI_LSWAP4(p) ByteSwap::Swap4(&(p))
# define AI_LSWAP8(p) ByteSwap::Swap8(&(p))
# define AI_LSWAP2P(p) ByteSwap::Swap2((p))
# define AI_LSWAP4P(p) ByteSwap::Swap4((p))
# define AI_LSWAP8P(p) ByteSwap::Swap8((p))
# define AI_LSWAP2(p) Assimp::ByteSwap::Swap2(&(p))
# define AI_LSWAP4(p) Assimp::ByteSwap::Swap4(&(p))
# define AI_LSWAP8(p) Assimp::ByteSwap::Swap8(&(p))
# define AI_LSWAP2P(p) Assimp::ByteSwap::Swap2((p))
# define AI_LSWAP4P(p) Assimp::ByteSwap::Swap4((p))
# define AI_LSWAP8P(p) Assimp::ByteSwap::Swap8((p))
# define LE_NCONST
#endif

View File

@ -98,10 +98,6 @@ public:
DeadlyErrorBase(Assimp::Formatter::format(), std::forward<T>(args)...) {
// empty
}
#if defined(_MSC_VER) && defined(__clang__)
DeadlyImportError(DeadlyImportError& other) = delete;
#endif
};
// ---------------------------------------------------------------------------
@ -114,10 +110,6 @@ public:
template<typename... T>
explicit DeadlyExportError(T&&... args) :
DeadlyErrorBase(Assimp::Formatter::format(), std::forward<T>(args)...) {}
#if defined(_MSC_VER) && defined(__clang__)
DeadlyExportError(DeadlyExportError& other) = delete;
#endif
};
#ifdef _MSC_VER

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -76,6 +75,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
inline uint32_t SuperFastHash (const char * data, uint32_t len = 0, uint32_t hash = 0) {
uint32_t tmp;
int rem;
size_t offset;
if (!data) return 0;
if (!len)len = (uint32_t)::strlen(data);
@ -96,7 +96,11 @@ int rem;
switch (rem) {
case 3: hash += get16bits (data);
hash ^= hash << 16;
hash ^= data[sizeof (uint16_t)] << 18;
offset = static_cast<size_t>(sizeof(uint16_t));
if (offset < 0) {
return 0;
}
hash ^= data[offset] << 18;
hash += hash >> 11;
break;
case 2: hash += get16bits (data);

View File

@ -0,0 +1,84 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2022, 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.
---------------------------------------------------------------------------
*/
/** @file OBJMATERIAL.h
* @brief Obj-specific material macros
*
*/
#ifndef AI_OBJMATERIAL_H_INC
#define AI_OBJMATERIAL_H_INC
#ifdef __GNUC__
# pragma GCC system_header
#endif
#include <assimp/material.h>
// ---------------------------------------------------------------------------
// the original illum property
#define AI_MATKEY_OBJ_ILLUM "$mat.illum", 0, 0
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Pure key names for all obj texture-related properties
//! @cond MATS_DOC_FULL
// support for bump -bm
#define _AI_MATKEY_OBJ_BUMPMULT_BASE "$tex.bumpmult"
//! @endcond
// ---------------------------------------------------------------------------
#define AI_MATKEY_OBJ_BUMPMULT(type, N) _AI_MATKEY_OBJ_BUMPMULT_BASE, type, N
//! @cond MATS_DOC_FULL
#define AI_MATKEY_OBJ_BUMPMULT_NORMALS(N) \
AI_MATKEY_OBJ_BUMPMULT(aiTextureType_NORMALS, N)
#define AI_MATKEY_OBJ_BUMPMULT_HEIGHT(N) \
AI_MATKEY_OBJ_BUMPMULT(aiTextureType_HEIGHT, N)
//! @endcond
#endif

View File

@ -119,29 +119,41 @@ public:
* work for const references, so many function prototypes will
* include const basic_formatter<T>& s but might still want to
* modify the formatted string without the need for a full copy.*/
template <typename TToken>
const basic_formatter& operator << (const TToken& s) const {
template <typename TToken, typename std::enable_if<!std::is_base_of<std::exception, TToken>::value>::type * = nullptr>
const basic_formatter &operator<<(const TToken &s) const {
underlying << s;
return *this;
}
template <typename TToken>
basic_formatter& operator << (const TToken& s) {
template <typename TToken, typename std::enable_if<std::is_base_of<std::exception, TToken>::value>::type * = nullptr>
const basic_formatter &operator<<(const TToken &s) const {
underlying << s.what();
return *this;
}
template <typename TToken, typename std::enable_if<!std::is_base_of<std::exception, TToken>::value>::type * = nullptr>
basic_formatter &operator<<(const TToken &s) {
underlying << s;
return *this;
}
template <typename TToken, typename std::enable_if<std::is_base_of<std::exception, TToken>::value>::type * = nullptr>
basic_formatter &operator<<(const TToken &s) {
underlying << s.what();
return *this;
}
// comma operator overloaded as well, choose your preferred way.
template <typename TToken>
const basic_formatter& operator, (const TToken& s) const {
underlying << s;
*this << s;
return *this;
}
template <typename TToken>
basic_formatter& operator, (const TToken& s) {
underlying << s;
*this << s;
return *this;
}
@ -149,7 +161,7 @@ public:
// See https://sourceforge.net/projects/assimp/forums/forum/817654/topic/4372824
template <typename TToken>
basic_formatter& operator, (TToken& s) {
underlying << s;
*this << s;
return *this;
}

View File

@ -279,11 +279,11 @@ typedef unsigned int ai_uint;
#define AI_MATH_HALF_PI_F (AI_MATH_PI_F * 0.5f)
/* Tiny macro to convert from radians to degrees and back */
#define AI_DEG_TO_RAD(x) ((x) * (ai_real)0.0174532925)
#define AI_RAD_TO_DEG(x) ((x) * (ai_real)57.2957795)
#define AI_DEG_TO_RAD(x) ((x) * (ai_real) 0.0174532925)
#define AI_RAD_TO_DEG(x) ((x) * (ai_real) 57.2957795)
/* Numerical limits */
static const ai_real ai_epsilon = (ai_real)0.00001;
static const ai_real ai_epsilon = (ai_real) 1e-6;
/* Support for big-endian builds */
#if defined(__BYTE_ORDER__)

View File

@ -95,7 +95,7 @@ public:
bool operator== (const aiMatrix3x3t<TReal>& m) const;
bool operator!= (const aiMatrix3x3t<TReal>& m) const;
bool Equal(const aiMatrix3x3t<TReal>& m, TReal epsilon = 1e-6) const;
bool Equal(const aiMatrix3x3t<TReal> &m, TReal epsilon = ai_epsilon) const;
template <typename TOther>
operator aiMatrix3x3t<TOther> () const;

View File

@ -110,7 +110,7 @@ public:
bool operator== (const aiMatrix4x4t& m) const;
bool operator!= (const aiMatrix4x4t& m) const;
bool Equal(const aiMatrix4x4t& m, TReal epsilon = 1e-6) const;
bool Equal(const aiMatrix4x4t &m, TReal epsilon = ai_epsilon) const;
// matrix multiplication.
aiMatrix4x4t& operator *= (const aiMatrix4x4t& m);

View File

@ -92,7 +92,7 @@ public:
// transform vector by matrix
aiQuaterniont& operator *= (const aiMatrix4x4t<TReal>& mat);
bool Equal(const aiQuaterniont& o, TReal epsilon = 1e-6) const;
bool Equal(const aiQuaterniont &o, TReal epsilon = ai_epsilon) const;
public:

View File

@ -85,7 +85,7 @@ public:
bool operator== (const aiVector2t& other) const;
bool operator!= (const aiVector2t& other) const;
bool Equal(const aiVector2t& other, TReal epsilon = 1e-6) const;
bool Equal(const aiVector2t &other, TReal epsilon = ai_epsilon) const;
aiVector2t& operator= (TReal f);
const aiVector2t SymMul(const aiVector2t& o);

View File

@ -114,7 +114,7 @@ public:
bool operator < (const aiVector3t& other) const;
/// @brief
bool Equal(const aiVector3t& other, TReal epsilon = 1e-6) const;
bool Equal(const aiVector3t &other, TReal epsilon = ai_epsilon) const;
template <typename TOther>
operator aiVector3t<TOther> () const;

View File

@ -60,7 +60,7 @@ protected:
};
TEST_F(utMesh, emptyMeshHasNoContentTest) {
EXPECT_EQ(0, mesh->mName.length);
EXPECT_EQ(0u, mesh->mName.length);
EXPECT_FALSE(mesh->HasPositions());
EXPECT_FALSE(mesh->HasFaces());
EXPECT_FALSE(mesh->HasNormals());
@ -69,8 +69,8 @@ TEST_F(utMesh, emptyMeshHasNoContentTest) {
EXPECT_FALSE(mesh->HasVertexColors(AI_MAX_NUMBER_OF_COLOR_SETS));
EXPECT_FALSE(mesh->HasTextureCoords(0));
EXPECT_FALSE(mesh->HasTextureCoords(AI_MAX_NUMBER_OF_TEXTURECOORDS));
EXPECT_EQ(0, mesh->GetNumUVChannels());
EXPECT_EQ(0, mesh->GetNumColorChannels());
EXPECT_EQ(0u, mesh->GetNumUVChannels());
EXPECT_EQ(0u, mesh->GetNumColorChannels());
EXPECT_FALSE(mesh->HasBones());
EXPECT_FALSE(mesh->HasTextureCoordsName(0));
EXPECT_FALSE(mesh->HasTextureCoordsName(AI_MAX_NUMBER_OF_TEXTURECOORDS));
@ -80,8 +80,8 @@ TEST_F(utMesh, setTextureCoordsName) {
EXPECT_FALSE(mesh->HasTextureCoordsName(0));
const aiString texcoords_name("texcoord_name");
mesh->SetTextureCoordsName(0, texcoords_name);
EXPECT_TRUE(mesh->HasTextureCoordsName(0));
EXPECT_FALSE(mesh->HasTextureCoordsName(1));
EXPECT_TRUE(mesh->HasTextureCoordsName(0u));
EXPECT_FALSE(mesh->HasTextureCoordsName(1u));
ASSERT_NE(nullptr, mesh->mTextureCoordsNames);
ASSERT_NE(nullptr, mesh->mTextureCoordsNames[0]);
EXPECT_STREQ(texcoords_name.C_Str(), mesh->mTextureCoordsNames[0]->C_Str());
@ -94,3 +94,4 @@ TEST_F(utMesh, setTextureCoordsName) {
EXPECT_EQ(nullptr, mesh->mTextureCoordsNames[0]);
EXPECT_EQ(nullptr, mesh->GetTextureCoordsName(0));
}

View File

@ -124,9 +124,9 @@ TEST_F(utColladaExport, testExportLight) {
ASSERT_NE(pTest, nullptr);
ASSERT_TRUE(pTest->HasLights());
const unsigned int origNumLights(pTest->mNumLights);
const unsigned int origNumLights = pTest->mNumLights;
// There are FIVE!!! LIGHTS!!!
EXPECT_EQ(5, origNumLights) << "lights.dae should contain five lights";
EXPECT_EQ(5u, origNumLights) << "lights.dae should contain five lights";
std::vector<aiLight> origLights(5);
for (size_t i = 0; i < origNumLights; i++) {

View File

@ -53,7 +53,7 @@ using namespace Assimp;
class utFBXImporterExporter : public AbstractImportExportBase {
public:
virtual bool importerTest() {
bool importerTest() override {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/spider.fbx", aiProcess_ValidateDataStructure);
return nullptr != scene;

View File

@ -48,12 +48,12 @@ TEST_F( utVersion, aiGetLegalStringTest ) {
EXPECT_NE( lv, nullptr );
std::string text( lv );
size_t pos = text.find(std::string("2021"));
size_t pos = text.find(std::string("2022"));
EXPECT_NE(pos, std::string::npos);
}
TEST_F( utVersion, aiGetVersionMinorTest ) {
EXPECT_EQ(aiGetVersionMinor(), 1U);
EXPECT_EQ(aiGetVersionMinor(), 2U);
}
TEST_F( utVersion, aiGetVersionMajorTest ) {
@ -61,7 +61,7 @@ TEST_F( utVersion, aiGetVersionMajorTest ) {
}
TEST_F( utVersion, aiGetVersionPatchTest ) {
EXPECT_EQ(aiGetVersionPatch(), 6U );
EXPECT_EQ(aiGetVersionPatch(), 0U );
}
TEST_F( utVersion, aiGetCompileFlagsTest ) {

View File

@ -573,7 +573,7 @@ TEST_F(utglTF2ImportExport, export_normalized_normals) {
scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxBadNormals-glTF-Binary/BoxBadNormals_out.glb", aiProcess_ValidateDataStructure);
for ( auto i = 0u; i < scene->mMeshes[0]->mNumVertices; ++i ) {
const auto length = scene->mMeshes[0]->mNormals[i].Length();
EXPECT_TRUE(abs(length) < 1e-6 || abs(length - 1) < 1e-6);
EXPECT_TRUE(abs(length) < 1e-6 || abs(length - 1) < ai_epsilon);
}
}