Merge branch 'master' into kimkulling/create_skeleton_data_issue_4015

kimkulling/create_skeleton_data_issue_4015
Kim Kulling 2022-03-08 19:10:53 +01:00
commit 7aa87a9765
31 changed files with 402 additions and 317 deletions

View File

@ -13,8 +13,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
#name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++, ubuntu-gcc-hunter, macos-clang-hunter, windows-msvc-hunter] name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++, ubuntu-gcc-hunter, macos-clang-hunter, windows-msvc-hunter]
name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++, ubuntu-gcc-hunter, macos-clang-hunter]
# For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux. # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
include: include:
- name: windows-latest-cl.exe - name: windows-latest-cl.exe
@ -39,9 +38,9 @@ jobs:
- name: macos-clang-hunter - name: macos-clang-hunter
os: macos-latest os: macos-latest
toolchain: ninja-clang-cxx17-fpic toolchain: ninja-clang-cxx17-fpic
#- name: windows-msvc-hunter - name: windows-msvc-hunter
# os: windows-latest os: windows-latest
# toolchain: ninja-vs-win64-cxx17 toolchain: ninja-vs-win64-cxx17
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2

View File

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

View File

@ -49,8 +49,8 @@ option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
include("cmake-modules/HunterGate.cmake") include("cmake-modules/HunterGate.cmake")
HunterGate( HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.311.tar.gz" URL "https://github.com/cpp-pm/hunter/archive/v0.24.0.tar.gz"
SHA1 "1a82b9b73055879181cb1466b2ab5d48ee8ae410" SHA1 "a3d7f4372b1dcd52faa6ff4a3bd5358e1d0e5efd"
) )
add_definitions(-DASSIMP_USE_HUNTER) add_definitions(-DASSIMP_USE_HUNTER)
@ -134,12 +134,12 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH
OFF OFF
) )
IF ( WIN32 ) IF (WIN32)
# Use subset of Windows.h # Use subset of Windows.h
ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN ) ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
IF(MSVC) IF(MSVC)
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW OPTION (ASSIMP_BUILD_ASSIMP_VIEW
"If the Assimp view tool is built. (requires DirectX)" "If the Assimp view tool is built. (requires DirectX)"
OFF ) OFF )
@ -243,6 +243,13 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
IF( UNIX ) IF( UNIX )
# Use GNUInstallDirs for Unix predefined directories # Use GNUInstallDirs for Unix predefined directories
INCLUDE(GNUInstallDirs) 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() ENDIF()
# Grouped compiler settings ######################################## # Grouped compiler settings ########################################
@ -687,11 +694,13 @@ ENDIF()
ADD_SUBDIRECTORY( code/ ) ADD_SUBDIRECTORY( code/ )
IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
# The viewer for windows only # The viewer for windows only
IF ( WIN32 ) IF (WIN32)
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" OFF ) OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" OFF )
IF ( ASSIMP_BUILD_ASSIMP_VIEW ) IF ( ASSIMP_BUILD_ASSIMP_VIEW )
ADD_SUBDIRECTORY( tools/assimp_view/ ) ADD_SUBDIRECTORY( tools/assimp_view/ )
ENDIF () ENDIF ()
ELSE()
MESSAGE("Building Assimp Viewer only supported on Windows.")
ENDIF () ENDIF ()
# The command line tool # The command line tool
ADD_SUBDIRECTORY( tools/assimp_cmd/ ) ADD_SUBDIRECTORY( tools/assimp_cmd/ )

View File

@ -357,9 +357,9 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
out->mAngleInnerCone = AI_DEG_TO_RAD(srcLight->mFalloffAngle); out->mAngleInnerCone = AI_DEG_TO_RAD(srcLight->mFalloffAngle);
// ... some extension magic. // ... 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. // ... 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 .... // 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 // epsilon chosen to be 0.1
float f = 1.0f; float f = 1.0f;
@ -1065,7 +1065,7 @@ void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, floa
return; return;
} }
for (unsigned int i = 0; i < values.size(); i++) { 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); values[i].mKeys.push_back(k);
return; return;
} else if (time > values[i].mTime && time < values[i + 1].mTime) { } 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 TransformInheritance_MAX // end-of-enum sentinel
}; };
} // namespace FBX } // namespace FBX
} // namespace Assimp } // namespace Assimp
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER #endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // AI_FBXCOMMON_H_INC #endif // AI_FBXCOMMON_H_INC

View File

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

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 // 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 // point leaves the plane through the other side
if (std::abs(dotOne + dotTwo) < 1e-6) if (std::abs(dotOne + dotTwo) < ai_epsilon)
return false; return false;
// if segment starts on the plane, report a hit only if the end lies on the *other* side // 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 (std::abs(dotTwo) < ai_epsilon) {
if ((assumeStartOnWhiteSide && dotOne + dotTwo < 1e-6) || (!assumeStartOnWhiteSide && dotOne + dotTwo > -1e-6)) { if ((assumeStartOnWhiteSide && dotOne + dotTwo < ai_epsilon) || (!assumeStartOnWhiteSide && dotOne + dotTwo > -ai_epsilon)) {
out = e0; out = e0;
return true; return true;
} else { } 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 // 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 // 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; return false;
// t must be in [0..1] if the intersection point is within the given segment // 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++) { for (iit = begin; iit != end; vidx += *iit++) {
unsigned int newcount = 0; 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) { for (unsigned int i = 0; i < *iit; ++i) {
const IfcVector3 &e0 = in[vidx + i], e1 = in[vidx + (i + 1) % *iit]; 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 // segment-segment intersection
// solve b0 + b*s = e0 + e*t for (s,t) // solve b0 + b*s = e0 + e*t for (s,t)
const IfcFloat det = (-b.x * e.y + e.x * b.y); 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) // no solutions (parallel lines)
continue; 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 // 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 // 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. // 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. // 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) { 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 the poly is parallel to the plane, put it completely on the black or white side
if (std::abs(polyNormal * n) > 0.9999) { 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; std::vector<IfcVector3> &targetSide = isOnWhiteSide ? whiteside : blackside;
targetSide.insert(targetSide.end(), srcVertices, srcVertices + srcVtxCount); targetSide.insert(targetSide.end(), srcVertices, srcVertices + srcVtxCount);
} else { } else {
// otherwise start building one polygon for each side. Whenever the current line segment intersects the plane // 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, // 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. // 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) { for (size_t a = 0; a < srcVtxCount; ++a) {
IfcVector3 e0 = srcVertices[a]; IfcVector3 e0 = srcVertices[a];
IfcVector3 e1 = srcVertices[(a + 1) % srcVtxCount]; IfcVector3 e1 = srcVertices[(a + 1) % srcVtxCount];

View File

@ -380,21 +380,19 @@ void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh&
bool take_any = false; bool take_any = false;
for (unsigned int j = 0; j < 2; ++j, take_any = true) { 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.y = startvec.y;
q.z = startvec.z; q.z = startvec.z;
q.x = -(d.y * q.y + d.z * q.z) / d.x; q.x = -(d.y * q.y + d.z * q.z) / d.x;
last_dir = 0; last_dir = 0;
break; break;
} } else if ((last_dir == 1 || take_any) && std::abs(d.y) > ai_epsilon) {
else if ((last_dir == 1 || take_any) && std::abs(d.y) > 1e-6) {
q.x = startvec.x; q.x = startvec.x;
q.z = startvec.z; q.z = startvec.z;
q.y = -(d.x * q.x + d.z * q.z) / d.y; q.y = -(d.x * q.x + d.z * q.z) / d.y;
last_dir = 1; last_dir = 1;
break; break;
} } else if ((last_dir == 2 && std::abs(d.z) > ai_epsilon) || take_any) {
else if ((last_dir == 2 && std::abs(d.z) > 1e-6) || take_any) {
q.y = startvec.y; q.y = startvec.y;
q.x = startvec.x; q.x = startvec.x;
q.z = -(d.y * q.y + d.x * q.x) / d.z; 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; return m;
} }
const auto closeDistance = 1e-6; const auto closeDistance = ai_epsilon;
bool areClose(Schema_2x3::IfcCartesianPoint pt1,Schema_2x3::IfcCartesianPoint pt2) { bool areClose(Schema_2x3::IfcCartesianPoint pt1,Schema_2x3::IfcCartesianPoint pt2) {
if(pt1.Coordinates.size() != pt2.Coordinates.size()) 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, // Outline: 'curve' is now a list of vertex points forming the underlying profile, extrude along the given axis,
// forming new triangles. // forming new triangles.
const bool has_area = solid.SweptArea->ProfileType == "AREA" && curve.mVerts.size() > 2; 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 ) { if( has_area ) {
result.Append(curve); 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) { 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 #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 auto outernor = ((mesh->mVerts[2] - mesh->mVerts[0]) ^ (mesh->mVerts[1] - mesh->mVerts[0])).Normalize();
const IfcFloat dot = planeNor * outernor; const IfcFloat dot = planeNor * outernor;
if(std::fabs(dot) < 1.f - 1e-6f) { if (std::fabs(dot) < 1.f - ai_epsilon) {
std::stringstream msg; std::stringstream msg;
msg << "Skipping: Unaligned opening (" << planeNor.x << ", " << planeNor.y << ", " << planeNor.z << ")"; msg << "Skipping: Unaligned opening (" << planeNor.x << ", " << planeNor.y << ", " << planeNor.z << ")";
msg << " . ( " << outernor.x << ", " << outernor.y << ", " << outernor.z << ") = " << dot; msg << " . ( " << outernor.x << ", " << outernor.y << ", " << outernor.z << ") = " << dot;
@ -1476,7 +1476,7 @@ std::vector<IfcVector2> GetContourInPlane2D(std::shared_ptr<TempMesh> mesh,IfcMa
return contour; return contour;
} }
const float close { 1e-6f }; const float close{ ai_epsilon };
static bool isClose(IfcVector2 first,IfcVector2 second) { static bool isClose(IfcVector2 first,IfcVector2 second) {
auto diff = (second - first); 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 // 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); return ComputePolygonNormal(&mVerts[mVerts.size() - mVertcnt.back()], mVertcnt.back(), normalize);
} }
struct CompareVector struct CompareVector {
{ bool operator () (const IfcVector3& a, const IfcVector3& b) const {
bool operator () (const IfcVector3& a, const IfcVector3& b) const
{
IfcVector3 d = a - b; 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); 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; IfcVector3 v;
FindVector(const IfcVector3& p) : v(p) { } 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 // to reverse the neighbour
nb_vidx = (nb_vidx + 1) % nbvc; nb_vidx = (nb_vidx + 1) % nbvc;
size_t oursideidx = (a + 1) % vc; 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(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc);
std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc); std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
for (size_t aa = 0; aa < nbvc - 1; ++aa) { 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]; out[static_cast<unsigned int>(i)] = in.DirectionRatios[i];
} }
const IfcFloat len = out.Length(); 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"); IFCImporter::LogWarn("direction vector magnitude too small, normalization would result in a division by zero");
return; return;
} }

View File

@ -195,6 +195,9 @@ struct Material {
//! PBR Anisotropy //! PBR Anisotropy
ai_real anisotropy; ai_real anisotropy;
//! bump map multipler (normal map scalar)(-bm)
ai_real bump_multiplier;
//! Constructor //! Constructor
Material() : Material() :
diffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)), 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)), sheen(ai_real(1.0), ai_real(1.0), ai_real(1.0)),
clearcoat_thickness(ai_real(0.0)), clearcoat_thickness(ai_real(0.0)),
clearcoat_roughness(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); 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/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <assimp/ObjMaterial.h>
#include <memory> #include <memory>
static const aiImporterDesc desc = { 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); 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 // Adding material colors
mat->AddProperty(&pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT); mat->AddProperty(&pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT);
mat->AddProperty(&pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); 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) { if (0 != pCurrentMaterial->textureBump.length) {
mat->AddProperty(&pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0)); mat->AddProperty(&pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_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]) { if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType]) {
addTextureMappingModeProperty(mat, aiTextureType_HEIGHT); addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
} }
@ -665,6 +672,9 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
if (0 != pCurrentMaterial->textureNormal.length) { if (0 != pCurrentMaterial->textureNormal.length) {
mat->AddProperty(&pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0)); mat->AddProperty(&pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
mat->AddProperty(&uvwIndex, 1, AI_MATKEY_UVWSRC_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]) { if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType]) {
addTextureMappingModeProperty(mat, aiTextureType_NORMALS); addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
} }

View File

@ -472,7 +472,11 @@ void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString
} }
skipToken = 2; 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; skipToken = 2;
} else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), static_cast<unsigned int>(ModifyMapOption.size()))) { } else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), static_cast<unsigned int>(ModifyMapOption.size()))) {
skipToken = 3; skipToken = 3;

View File

@ -260,20 +260,9 @@ public:
VEC4, VEC4,
MAT2, MAT2,
MAT3, MAT3,
MAT4 }; MAT4
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]; };
public:
inline static Value FromString(const char *str) { inline static Value FromString(const char *str) {
for (size_t i = 0; i < NUM_VALUES; ++i) { for (size_t i = 0; i < NUM_VALUES; ++i) {
if (strcmp(data<0>::infos[i].name, str) == 0) { if (strcmp(data<0>::infos[i].name, str) == 0) {
@ -290,40 +279,31 @@ public:
inline static unsigned int GetNumComponents(Value type) { inline static unsigned int GetNumComponents(Value type) {
return data<0>::infos[static_cast<size_t>(type)].numComponents; 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! // must match the order of the AttribTypeTraits::Value enum!
template <int N> template <int N>
const AttribType::Info const AttribType::Info AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
AttribType::data<N>::infos[AttribType::NUM_VALUES] = { { "SCALAR", 1 },
{ "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 } { "VEC2", 2 },
}; { "VEC3", 3 },
{ "VEC4", 4 },
/* { "MAT2", 4 },
//! A reference to one top-level object, which is valid { "MAT3", 9 },
//! until the Asset instance is destroyed { "MAT4", 16 }
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]); }
};*/
//! Base class for all glTF top-level objects //! Base class for all glTF top-level objects
struct Object { struct Object {
@ -333,6 +313,7 @@ struct Object {
//! Objects marked as special are not exported (used to emulate the binary body buffer) //! Objects marked as special are not exported (used to emulate the binary body buffer)
virtual bool IsSpecial() const { return false; } virtual bool IsSpecial() const { return false; }
Object() = default;
virtual ~Object() {} virtual ~Object() {}
//! Maps special IDs to another ID, where needed. Subclasses may override it (statically) //! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
@ -401,21 +382,19 @@ struct Accessor : public Object {
return Indexer(*this); return Indexer(*this);
} }
Accessor() {} Accessor() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
//! A buffer points to binary geometry, animation, or skins. //! A buffer points to binary geometry, animation, or skins.
struct Buffer : public Object { struct Buffer : public Object {
/********************* Types *********************/ /********************* Types *********************/
public:
enum Type { enum Type {
Type_arraybuffer, Type_arraybuffer,
Type_text Type_text
}; };
/// \struct SEncodedRegion /// @brief Descriptor of encoded region in "bufferView".
/// Descriptor of encoded region in "bufferView".
struct SEncodedRegion { struct SEncodedRegion {
const size_t Offset; ///< Offset from begin of "bufferView" to encoded region, in bytes. 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. 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 size_t DecodedData_Length; ///< Size of decoded region, in bytes.
const std::string ID; ///< ID of the region. 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) /// @brief Constructor.
/// Constructor.
/// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes. /// \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] pEncodedData_Length - size of encoded region, in bytes.
/// \param [in] pDecodedData - pointer to decoded data array. /// \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) : 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) {} Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) {}
/// \fn ~SEncodedRegion()
/// Destructor. /// Destructor.
~SEncodedRegion() { delete[] DecodedData; } ~SEncodedRegion() { delete[] DecodedData; }
}; };
/******************* Variables *******************/ /******************* 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) size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
//std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
Type type; Type type;
@ -486,7 +461,6 @@ public:
bool LoadFromStream(IOStream &stream, size_t length = 0, size_t baseOffset = 0); 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. /// 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] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
/// \param [in] pEncodedData_Length - size of 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. /// \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); 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. /// Select current encoded region by ID. \sa EncodedRegion_Current.
/// \param [in] pID - ID of the region. /// \param [in] pID - ID of the region.
void EncodedRegion_SetCurrent(const std::string &pID); 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. /// 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_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. /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
@ -558,37 +530,29 @@ struct Camera : public Object {
} ortographic; } ortographic;
}; };
Camera() {} Camera() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
//! Image data used to create a texture. //! Image data used to create a texture.
struct Image : public Object { struct Image : public Object {
std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required) std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
Ref<BufferView> bufferView; Ref<BufferView> bufferView;
std::string mimeType; std::string mimeType;
int width, height; int width, height;
private:
std::unique_ptr<uint8_t[]> mData;
size_t mDataLength;
public: public:
Image(); Image();
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
inline bool HasData() const { return mDataLength > 0; } inline bool HasData() const { return mDataLength > 0; }
inline size_t GetDataLength() const { return mDataLength; } inline size_t GetDataLength() const { return mDataLength; }
inline const uint8_t *GetData() const { return mData.get(); } inline const uint8_t *GetData() const { return mData.get(); }
inline uint8_t *StealData(); inline uint8_t *StealData();
inline void SetData(uint8_t *data, size_t length, Asset &r); 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 //! 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 #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
/// \struct SCompression_Open3DGC /// \struct SCompression_Open3DGC
/// Compression of mesh data using Open3DGC algorithm. /// Compression of mesh data using Open3DGC algorithm.
struct SCompression_Open3DGC : public SExtension { struct SCompression_Open3DGC : public SExtension {
@ -703,7 +668,6 @@ struct Mesh : public Object {
Mesh() {} Mesh() {}
/// \fn ~Mesh()
/// Destructor. /// Destructor.
~Mesh() { ~Mesh() {
for (std::list<SExtension *>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) { 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) /// @brief Get mesh data from JSON-object and place them to root asset.
/// 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 [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. /// \param [out] pAsset_Root - reference to root asset where data will be stored.
void Read(Value &pJSON_Object, Asset &pAsset_Root); void Read(Value &pJSON_Object, Asset &pAsset_Root);
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
/// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root) /// @brief Decode part of "buffer" which encoded with Open3DGC algorithm.
/// Decode part of "buffer" which encoded with Open3DGC algorithm.
/// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region. /// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region.
/// \param [out] pAsset_Root - reference to root assed where data will be stored. /// \param [out] pAsset_Root - reference to root assed where data will be stored.
void Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DGC, Asset &pAsset_Root); 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 wrapS; //!< The texture wrapping in the S direction. (required)
SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required) SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required)
Sampler() {} Sampler() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
void SetDefaults(); void SetDefaults();
}; };
@ -767,12 +729,12 @@ struct Sampler : public Object {
struct Scene : public Object { struct Scene : public Object {
std::vector<Ref<Node>> nodes; std::vector<Ref<Node>> nodes;
Scene() {} Scene() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
struct Shader : public Object { struct Shader : public Object {
Shader() {} Shader() = default;
void Read(Value &obj, Asset &r); 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::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. std::string name; //!< The user-defined name of this object.
Skin() {} Skin() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
@ -796,7 +758,7 @@ struct Technique : public Object {
struct Functions { struct Functions {
}; };
Technique() {} Technique() = default;
void Read(Value &obj, Asset &r); 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<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) Ref<Image> source; //!< The ID of the image used by this texture. (required)
//TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA) Texture() = default;
//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() {}
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
@ -826,7 +782,6 @@ struct Light : public Object {
}; };
Type type; Type type;
vec4 color; vec4 color;
float distance; float distance;
float constantAttenuation; float constantAttenuation;
@ -835,9 +790,8 @@ struct Light : public Object {
float falloffAngle; float falloffAngle;
float falloffExponent; float falloffExponent;
Light() {} Light() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
void SetDefaults(); 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. 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. 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. AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
std::vector<AnimSampler> Samplers; //!< The parameterized inputs representing the key-frame data. std::vector<AnimSampler> Samplers; //!< The parameterized inputs representing the key-frame data.
Animation() {} Animation() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
@ -963,13 +913,11 @@ struct AssetMetadata {
//! Root object for a glTF asset //! Root object for a glTF asset
class Asset { class Asset {
typedef std::gltf_unordered_map<std::string, int> IdMap; using IdMap = std::gltf_unordered_map<std::string, int>;
template <class T> template <class T>
friend class LazyDict; friend class LazyDict;
friend struct Buffer; // To access OpenFile friend struct Buffer; // To access OpenFile
friend class AssetWriter; friend class AssetWriter;
private: private:
@ -1010,12 +958,9 @@ public:
LazyDict<Material> materials; LazyDict<Material> materials;
LazyDict<Mesh> meshes; LazyDict<Mesh> meshes;
LazyDict<Node> nodes; LazyDict<Node> nodes;
//LazyDict<Program> programs;
LazyDict<Sampler> samplers; LazyDict<Sampler> samplers;
LazyDict<Scene> scenes; LazyDict<Scene> scenes;
//LazyDict<Shader> shaders;
LazyDict<Skin> skins; LazyDict<Skin> skins;
//LazyDict<Technique> techniques;
LazyDict<Texture> textures; LazyDict<Texture> textures;
LazyDict<Light> lights; // KHR_materials_common ext LazyDict<Light> lights; // KHR_materials_common ext
@ -1024,16 +969,20 @@ public:
public: public:
Asset(IOSystem *io = 0) : 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") mIOSystem(io),
//, programs (*this, "programs") 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"), samplers(*this, "samplers"),
scenes(*this, "scenes") scenes(*this, "scenes"),
//, shaders (*this, "shaders") skins(*this, "skins"),
,
skins(*this, "skins")
//, techniques (*this, "techniques")
,
textures(*this, "textures"), textures(*this, "textures"),
lights(*this, "lights", "KHR_materials_common") { lights(*this, "lights", "KHR_materials_common") {
memset(&extensionsUsed, 0, sizeof(extensionsUsed)); 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) \ #define CHECK_EXT(EXT) \
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
//! Helper struct to represent values that might not be present //! Helper struct to represent values that might not be present
template <class T> template <class T>
struct Nullable { 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_map tr1::unordered_map
# define gltf_unordered_set tr1::unordered_set # define gltf_unordered_set tr1::unordered_set
# else # else
# define gltf_unordered_map unordered_map # define gltf_unordered_map unordered_map
# define gltf_unordered_set unordered_set # define gltf_unordered_set unordered_set
# endif # endif
#endif #endif
@ -1087,29 +1087,11 @@ class Asset {
template <class T> template <class T>
friend class LazyDict; friend class LazyDict;
friend struct Buffer; // To access OpenFile friend struct Buffer; // To access OpenFile
friend class AssetWriter; friend class AssetWriter;
private:
IOSystem *mIOSystem;
rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider;
std::string mCurrentAssetDir;
size_t mSceneLength;
size_t mBodyOffset, mBodyLength;
std::vector<LazyDictBase *> mDicts; std::vector<LazyDictBase *> mDicts;
IdMap mUsedIds;
Ref<Buffer> mBodyBuffer;
Asset(Asset &);
Asset &operator=(const Asset &);
public: public:
//! Keeps info about the enabled extensions //! Keeps info about the enabled extensions
struct Extensions { struct Extensions {
@ -1125,16 +1107,36 @@ public:
bool KHR_draco_mesh_compression; bool KHR_draco_mesh_compression;
bool FB_ngon_encoding; bool FB_ngon_encoding;
bool KHR_texture_basisu; 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; } extensionsUsed;
//! Keeps info about the required extensions //! Keeps info about the required extensions
struct RequiredExtensions { struct RequiredExtensions {
bool KHR_draco_mesh_compression; bool KHR_draco_mesh_compression;
bool KHR_texture_basisu; bool KHR_texture_basisu;
RequiredExtensions() : KHR_draco_mesh_compression(false), KHR_texture_basisu(false) {
// empty
}
} extensionsRequired; } extensionsRequired;
AssetMetadata asset; AssetMetadata asset;
Value *extras = nullptr; Value *extras;
// Dictionaries for each type of object // Dictionaries for each type of object
@ -1157,9 +1159,11 @@ public:
public: public:
Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) : Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) :
mIOSystem(io), mDicts(),
mSchemaDocumentProvider(schemaDocumentProvider), extensionsUsed(),
extensionsRequired(),
asset(), asset(),
extras(nullptr),
accessors(*this, "accessors"), accessors(*this, "accessors"),
animations(*this, "animations"), animations(*this, "animations"),
buffers(*this, "buffers"), buffers(*this, "buffers"),
@ -1173,9 +1177,10 @@ public:
samplers(*this, "samplers"), samplers(*this, "samplers"),
scenes(*this, "scenes"), scenes(*this, "scenes"),
skins(*this, "skins"), skins(*this, "skins"),
textures(*this, "textures") { textures(*this, "textures") ,
memset(&extensionsUsed, 0, sizeof(extensionsUsed)); mIOSystem(io),
memset(&extensionsRequired, 0, sizeof(extensionsRequired)); mSchemaDocumentProvider(schemaDocumentProvider) {
// empty
} }
//! Main function //! Main function
@ -1192,18 +1197,31 @@ public:
Ref<Buffer> GetBodyBuffer() { return mBodyBuffer; } Ref<Buffer> GetBodyBuffer() { return mBodyBuffer; }
Asset(Asset &) = delete;
Asset &operator=(const Asset &) = delete;
private: private:
void ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData); void ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData);
//! Obtain a JSON document from the stream. /// Obtain a JSON document from the stream.
// \param second argument is a buffer used by the document. It must be kept /// \param second argument is a buffer used by the document. It must be kept
// alive while the document is in use. /// alive while the document is in use.
Document ReadDocument(IOStream& stream, bool isBinary, std::vector<char>& sceneData); Document ReadDocument(IOStream& stream, bool isBinary, std::vector<char>& sceneData);
void ReadExtensionsUsed(Document &doc); void ReadExtensionsUsed(Document &doc);
void ReadExtensionsRequired(Document &doc); void ReadExtensionsRequired(Document &doc);
IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false); 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) { 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) { void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) {
if (mat.GetTextureCount(tt) > 0) { if (mat.GetTextureCount(tt) == 0) {
aiString tex; return;
}
// Read texcoord (UV map index) aiString tex;
mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { // Read texcoord (UV map index)
std::string path = tex.C_Str(); mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
if (path.size() > 0) { if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path); std::string path = tex.C_Str();
if (it != mTexturesByPath.end()) {
texture = mAsset->textures.Get(it->second);
}
bool useBasisUniversal = false; if (path.size() > 0) {
if (!texture) { std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
std::string texId = mAsset->FindUniqueID("", "texture"); if (it != mTexturesByPath.end()) {
texture = mAsset->textures.Create(texId); texture = mAsset->textures.Get(it->second);
mTexturesByPath[path] = texture.GetIndex(); }
std::string imgId = mAsset->FindUniqueID("", "image"); bool useBasisUniversal = false;
texture->source = mAsset->images.Create(imgId); 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()); std::string imgId = mAsset->FindUniqueID("", "image");
if (curTex != nullptr) { // embedded texture->source = mAsset->images.Create(imgId);
texture->source->name = curTex->mFilename.C_Str();
//basisu: embedded ktx2, bu const aiTexture *curTex = mScene->GetEmbeddedTexture(path.c_str());
if (curTex->achFormatHint[0]) { if (curTex != nullptr) { // embedded
std::string mimeType = "image/"; texture->source->name = curTex->mFilename.C_Str();
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;
}
// The asset has its own buffer, see Image::SetData //basisu: embedded ktx2, bu
//basisu: "image/ktx2", "image/basis" as is if (curTex->achFormatHint[0]) {
texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset); std::string mimeType = "image/";
} else { if (memcmp(curTex->achFormatHint, "jpg", 3) == 0)
texture->source->uri = path; mimeType += "jpeg";
if (texture->source->uri.find(".ktx") != std::string::npos || else if (memcmp(curTex->achFormatHint, "ktx", 3) == 0) {
texture->source->uri.find(".basis") != std::string::npos) {
useBasisUniversal = true; 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 // The asset has its own buffer, see Image::SetData
if (useBasisUniversal) { //basisu: "image/ktx2", "image/basis" as is
mAsset->extensionsUsed.KHR_texture_basisu = true; texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset);
mAsset->extensionsRequired.KHR_texture_basisu = true; } 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) { void glTF2Exporter::GetMatTex(const aiMaterial &mat, TextureInfo &prop, aiTextureType tt, unsigned int slot = 0) {
Ref<Texture> &texture = prop.texture; Ref<Texture> &texture = prop.texture;
GetMatTex(mat, texture, prop.texCoord, tt, slot); 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) { 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) { bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen) {
// Return true if got any valid Sheen properties or textures // 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; return false;
}
// Default Sheen color factor {0,0,0} disables Sheen, so do not export // Default Sheen color factor {0,0,0} disables Sheen, so do not export
if (sheen.sheenColorFactor == defaultSheenFactor) if (sheen.sheenColorFactor == defaultSheenFactor) {
return false; return false;
}
mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor); mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor);
@ -781,9 +780,7 @@ void glTF2Exporter::ExportMaterials() {
aiColor4D specularColor; aiColor4D specularColor;
ai_real shininess; ai_real shininess;
if ( if (mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
// convert specular color to luminance // convert specular color to luminance
float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f; 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 //normalize shininess (assuming max is 1000) with an inverse exponentional curve
@ -916,7 +913,8 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin> &skinRef) {
return parentNodeRef; 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) { if (aimesh->mNumBones < 1) {
return; return;
} }
@ -986,7 +984,8 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buf
} // End: for-loop mNumMeshes } // End: for-loop mNumMeshes
Mesh::Primitive &p = meshRef->primitives.back(); 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) { if (vertexJointAccessor) {
size_t offset = vertexJointAccessor->bufferView->byteOffset; size_t offset = vertexJointAccessor->bufferView->byteOffset;
size_t bytesLen = vertexJointAccessor->bufferView->byteLength; size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
@ -1069,8 +1068,11 @@ void glTF2Exporter::ExportMeshes() {
p.ngonEncoded = (aim->mPrimitiveTypes & aiPrimitiveType_NGONEncodingFlag) != 0; p.ngonEncoded = (aim->mPrimitiveTypes & aiPrimitiveType_NGONEncodingFlag) != 0;
/******************* Vertices ********************/ /******************* Vertices ********************/
Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3,
if (v) p.attributes.position.push_back(v); AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (v) {
p.attributes.position.push_back(v);
}
/******************** Normals ********************/ /******************** Normals ********************/
// Normalize all normals as the validator can emit a warning otherwise // 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); Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3,
if (n) p.attributes.normal.push_back(n); AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (n) {
p.attributes.normal.push_back(n);
}
/************** Texture coordinates **************/ /************** Texture coordinates **************/
for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (!aim->HasTextureCoords(i)) if (!aim->HasTextureCoords(i)) {
continue; continue;
}
// Flip UV y coords // Flip UV y coords
if (aim->mNumUVComponents[i] > 1) { if (aim->mNumUVComponents[i] > 1) {
@ -1098,16 +1104,21 @@ void glTF2Exporter::ExportMeshes() {
if (aim->mNumUVComponents[i] > 0) { if (aim->mNumUVComponents[i] > 0) {
AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3; 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); Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i],
if (tc) p.attributes.texcoord.push_back(tc); AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (tc) {
p.attributes.texcoord.push_back(tc);
}
} }
} }
/*************** Vertex colors ****************/ /*************** Vertex colors ****************/
for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) { 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); Ref<Accessor> c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel],
if (c) AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (c) {
p.attributes.color.push_back(c); p.attributes.color.push_back(c);
}
} }
/*************** Vertices indices ****************/ /*************** 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) { switch (aim->mPrimitiveTypes) {
@ -1136,6 +1148,7 @@ void glTF2Exporter::ExportMeshes() {
break; break;
default: // aiPrimitiveType_TRIANGLE default: // aiPrimitiveType_TRIANGLE
p.mode = PrimitiveMode_TRIANGLES; p.mode = PrimitiveMode_TRIANGLES;
break;
} }
/*************** Skins ****************/ /*************** Skins ****************/
@ -1155,8 +1168,9 @@ void glTF2Exporter::ExportMeshes() {
p.targets.resize(aim->mNumAnimMeshes); p.targets.resize(aim->mNumAnimMeshes);
for (unsigned int am = 0; am < aim->mNumAnimMeshes; ++am) { for (unsigned int am = 0; am < aim->mNumAnimMeshes; ++am) {
aiAnimMesh *pAnimMesh = aim->mAnimMeshes[am]; aiAnimMesh *pAnimMesh = aim->mAnimMeshes[am];
if (bExportTargetNames) if (bExportTargetNames) {
m->targetNames.push_back(pAnimMesh->mName.data); m->targetNames.emplace_back(pAnimMesh->mName.data);
}
// position // position
if (pAnimMesh->HasPositions()) { if (pAnimMesh->HasPositions()) {
// NOTE: in gltf it is the diff stored // 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) { 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) { for (unsigned int i = 0; i < n->mNumChildren; ++i) {
unsigned int idx = ExportNode(n->mChildren[i], node); 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(); 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) { 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) { for (unsigned int i = 0; i < n->mNumChildren; ++i) {
unsigned int idx = ExportNode(n->mChildren[i], node); 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(); return node.GetIndex();
@ -1386,7 +1400,7 @@ void glTF2Exporter::ExportScene() {
// root node will be the first one exported (idx 0) // root node will be the first one exported (idx 0)
if (mAsset->nodes.Size() > 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 // set as the default scene
@ -1521,12 +1535,6 @@ void glTF2Exporter::ExportAnimations() {
AddSampler(animRef, animNode, scaleSampler, AnimationPath_SCALE); 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 } // End: for-loop mNumAnimations
} }

View File

@ -1317,11 +1317,10 @@ ENDIF ()
INSTALL( TARGETS assimp INSTALL( TARGETS assimp
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP-DEV_COMPONENT}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR} INCLUDES DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
) )
INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev) INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)

View File

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

View File

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

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, 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) { inline uint32_t SuperFastHash (const char * data, uint32_t len = 0, uint32_t hash = 0) {
uint32_t tmp; uint32_t tmp;
int rem; int rem;
size_t offset;
if (!data) return 0; if (!data) return 0;
if (!len)len = (uint32_t)::strlen(data); if (!len)len = (uint32_t)::strlen(data);
@ -96,7 +96,11 @@ int rem;
switch (rem) { switch (rem) {
case 3: hash += get16bits (data); case 3: hash += get16bits (data);
hash ^= hash << 16; 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; hash += hash >> 11;
break; break;
case 2: hash += get16bits (data); 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

@ -279,11 +279,11 @@ typedef unsigned int ai_uint;
#define AI_MATH_HALF_PI_F (AI_MATH_PI_F * 0.5f) #define AI_MATH_HALF_PI_F (AI_MATH_PI_F * 0.5f)
/* Tiny macro to convert from radians to degrees and back */ /* Tiny macro to convert from radians to degrees and back */
#define AI_DEG_TO_RAD(x) ((x) * (ai_real)0.0174532925) #define AI_DEG_TO_RAD(x) ((x) * (ai_real) 0.0174532925)
#define AI_RAD_TO_DEG(x) ((x) * (ai_real)57.2957795) #define AI_RAD_TO_DEG(x) ((x) * (ai_real) 57.2957795)
/* Numerical limits */ /* 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 */ /* Support for big-endian builds */
#if defined(__BYTE_ORDER__) #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 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> template <typename TOther>
operator aiMatrix3x3t<TOther> () const; operator aiMatrix3x3t<TOther> () const;

View File

@ -110,7 +110,7 @@ public:
bool operator== (const aiMatrix4x4t& m) const; bool operator== (const aiMatrix4x4t& m) const;
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. // matrix multiplication.
aiMatrix4x4t& operator *= (const aiMatrix4x4t& m); aiMatrix4x4t& operator *= (const aiMatrix4x4t& m);

View File

@ -92,7 +92,7 @@ public:
// transform vector by matrix // transform vector by matrix
aiQuaterniont& operator *= (const aiMatrix4x4t<TReal>& mat); 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: public:

View File

@ -85,7 +85,7 @@ public:
bool operator== (const aiVector2t& other) const; bool operator== (const aiVector2t& other) const;
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); aiVector2t& operator= (TReal f);
const aiVector2t SymMul(const aiVector2t& o); const aiVector2t SymMul(const aiVector2t& o);

View File

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

View File

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

View File

@ -124,9 +124,9 @@ TEST_F(utColladaExport, testExportLight) {
ASSERT_NE(pTest, nullptr); ASSERT_NE(pTest, nullptr);
ASSERT_TRUE(pTest->HasLights()); ASSERT_TRUE(pTest->HasLights());
const unsigned int origNumLights(pTest->mNumLights); const unsigned int origNumLights = pTest->mNumLights;
// There are FIVE!!! LIGHTS!!! // 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); std::vector<aiLight> origLights(5);
for (size_t i = 0; i < origNumLights; i++) { for (size_t i = 0; i < origNumLights; i++) {

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); 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 ) { for ( auto i = 0u; i < scene->mMeshes[0]->mNumVertices; ++i ) {
const auto length = scene->mMeshes[0]->mNormals[i].Length(); 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);
} }
} }