Compare commits

..

81 Commits

Author SHA1 Message Date
Kim Kulling
19f2a624a9 Merge pull request #4451 from Promit/promit/gltf-attrib-bug-fix
GLTF2 attribute name/parse bug fix
2022-03-17 11:35:44 +01:00
Promit Roy
765b38cf04 Update glTF2Asset.inl
Fixing mistakes in attribute names for GLTF. This causes attribute index to not be parsed out correctly (e.g. JOINTS_1) and fails the scene load.
2022-03-16 16:49:45 -04:00
Kim Kulling
a916a0eda5 Merge pull request #4448 from assimp/kimkulling/MDL-fix_stackoverflow-issue4447
Fix stack-overflow in MDLLoader
2022-03-16 14:14:46 +01:00
Kim Kulling
c2b05acaa6 Fix stack-overflow in MDLLoader
- Use correct len to copy filename.
- Closes https://github.com/assimp/assimp/issues/4447
2022-03-16 13:59:21 +01:00
Kim Kulling
a828114a1d Merge pull request #4446 from assimp/kimkulling/mdlimporter_fix_nullptr_dereferencing
Fix nullptr dereferencing
2022-03-16 10:23:29 +01:00
Kim Kulling
552f3a308d Fix nullptr dereferencing
- Check if we have any texture coordinates before calculating them
- closes https://github.com/assimp/assimp/issues/4445
2022-03-16 10:08:20 +01:00
Kim Kulling
784d9615f5 Merge pull request #4444 from EYHN/windows-crt
Add USE_STATIC_CRT option
2022-03-15 21:55:21 +01:00
Kim Kulling
6484dd6825 Merge branch 'master' into windows-crt 2022-03-15 21:29:21 +01:00
Kim Kulling
bcee205542 Merge pull request #4437 from jaefunk/issue_4349
add ifndef guard for resolve to fails to compile
2022-03-15 14:28:43 +01:00
Kim Kulling
0904490150 Merge branch 'master' into issue_4349 2022-03-15 14:11:57 +01:00
Kim Kulling
7919461951 Merge pull request #4441 from assimp/kimkulling/fix_doxygen_version
Update version in doxy-config
2022-03-15 14:11:38 +01:00
Kim Kulling
e4fb0e0960 Merge branch 'master' into kimkulling/fix_doxygen_version 2022-03-15 13:33:54 +01:00
Kim Kulling
d87111983a Merge pull request #4431 from TerenceRussell/master
Added missing ObjMaterial.h to CMakeLists
2022-03-15 13:33:13 +01:00
Kim Kulling
b1dc8cfe56 Merge branch 'master' into master 2022-03-15 11:58:45 +01:00
Kim Kulling
7296ffc3f5 Merge pull request #4426 from sacereda/info-material-properties
Add properties information on assimp info command line
2022-03-15 11:57:58 +01:00
Kim Kulling
b567497a17 Merge branch 'master' into info-material-properties 2022-03-15 10:57:14 +01:00
Kim Kulling
e1dae1402e Merge pull request #4425 from sacereda/metallic-roughness-split
glTF2: Metallic roughness split
2022-03-15 10:56:43 +01:00
Kim Kulling
68f3386c7b Merge branch 'master' into metallic-roughness-split 2022-03-15 08:38:38 +01:00
Kim Kulling
9e0357a8b6 Merge pull request #4423 from youkeyao/parse_obj_anisotropy
Fix getting anisotropy in obj
2022-03-15 08:38:13 +01:00
Kim Kulling
72888c49f6 Merge branch 'master' into parse_obj_anisotropy 2022-03-15 08:13:35 +01:00
eyhn
cd7df53a72 Add USE_STATIC_CRT option 2022-03-15 14:50:01 +08:00
jaefunk
4457d9300a Merge branch 'master' into issue_4349 2022-03-14 15:41:20 +09:00
Kim Kulling
0ef830d2b1 Update version in doxy-config 2022-03-12 16:57:27 +01:00
jaefunk
e02d51ec24 add ifndef guard for resolve to fails to compile 2022-03-11 10:51:13 +09:00
Kim Kulling
a305d14b8f Merge pull request #4421 from RichardTea/update_ai_texture_type_max
Update AI_TEXTURE_TYPE_MAX
2022-03-10 13:54:55 +01:00
Kim Kulling
5e69517742 Merge branch 'master' into update_ai_texture_type_max 2022-03-10 11:37:46 +01:00
Kim Kulling
1b3ae63527 Merge pull request #4434 from karjonas/always_true
Fix 'i >= 0' always true bug
2022-03-10 11:37:03 +01:00
Kim Kulling
47f004517f Add missing cast. 2022-03-10 10:33:29 +01:00
Jonas Karlsson
c14eccefaf Fix 'i >= 0' always true bug
If 'disk_filename' does not contain a dot (.) then 'i' would overflow.
Making 'i' an int makes sure the for loop works as intended.
2022-03-09 23:05:47 +01:00
Terence Russell
efe92e9ec1 Merge branch 'assimp:master' into master 2022-03-09 10:15:41 -07:00
Kim Kulling
1bf5dd2731 Merge pull request #4432 from assimp/kimkulling/init_fbx_texture_members_issue4429
Fix missing members and do some small refactorings.
2022-03-09 11:35:01 +01:00
kimkulling
26598dc6bd Forget to save file. 2022-03-09 11:00:05 +01:00
kimkulling
76e10b96fc Fix missing members and do some small refactorings. 2022-03-09 10:51:37 +01:00
Terence Russell
b35879989c Added missing ObjMaterial.h to CMakeLists 2022-03-08 20:00:22 -07:00
Kim Kulling
40d896ccc1 Merge pull request #4403 from JaroslavPribyl/fix/obj_with_bspline_crash
Fix parsing OBJ with free-form curve/surface body statements
2022-03-07 21:39:38 +01:00
Kim Kulling
ba379c20e1 Merge branch 'master' into fix/obj_with_bspline_crash 2022-03-06 17:39:57 +01:00
Kim Kulling
92b5c284ce Merge pull request #4203 from RichardTea/deprecated_gltfpbr_macros
Reinstate a deprecated gltfpbr macro: AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS
2022-03-06 17:39:35 +01:00
Kim Kulling
9ca9254445 Merge branch 'master' into deprecated_gltfpbr_macros 2022-03-06 11:15:49 +01:00
Kim Kulling
7eb5fd0e4e Merge pull request #4427 from assimp/smartday-master
Smartday master
2022-03-05 23:00:21 +01:00
Kim Kulling
80a8807c47 Fix compiler warnings 2022-03-05 20:37:34 +01:00
Kim Kulling
d4527d4e87 Merge branch 'master' into master 2022-03-05 14:00:32 +01:00
Sergio Acereda
a2543e7151 Add properties information on assimp info command line 2022-03-04 17:09:29 +01:00
Sergio Acereda
a1e03e3481 clang-format 2022-03-04 14:31:06 +01:00
Sergio Acereda
cfe84b9260 Use generic METALNESS and DIFFUSE_ROUGHNESS texture types 2022-03-03 16:18:25 +01:00
Sergio Acereda
52008ec989 Apply clang-format 2022-03-03 15:42:23 +01:00
youkeyao
9b227fc262 Fix getting anisotropy in obj 2022-03-03 01:01:34 +08:00
RichardTea
8a6a1fc2df Update AI_TEXTURE_TYPE_MAX
Must be equal to the largest aiTextureType_XXX enum
2022-03-01 12:12:07 +00:00
RichardTea
d704824be3 Merge branch 'master' into deprecated_gltfpbr_macros 2022-03-01 10:01:43 +00:00
Kim Kulling
bbcefbd034 Merge pull request #4417 from rbsheth/rbsheth_fix_hunter
Update version of Hunter to v0.24.0 that supports VS 2022
2022-02-28 23:48:19 +01:00
Jaroslav Pribyl
62930076af Merge branch 'master' into fix/obj_with_bspline_crash 2022-02-26 04:03:59 +01:00
Rahul Sheth
e368a69824 Merge branch 'master' into rbsheth_fix_hunter 2022-02-25 14:58:07 -06:00
Kim Kulling
3957fbba8b Merge pull request #4416 from SolaToucher/master
Optimize the problem of excessive memory allocation in FBX import
2022-02-25 21:03:47 +01:00
Rahul Sheth
8e59287b94 Update version of Hunter to v0.24.0 that supports VS 2022 2022-02-25 13:52:18 -06:00
sola
c73ff82fc4 FBXConvert::ConvertMeshMultiMaterial: allocate memory using variable count_vertices 2022-02-25 19:58:44 +08:00
Kim Kulling
04858c5d89 Merge pull request #4409 from TerenceRussell/master
Expose the original OBJ "illum" value
2022-02-25 00:06:12 +01:00
Kim Kulling
94178df61b Merge branch 'master' into master 2022-02-24 19:31:31 +01:00
Kim Kulling
1b2f705ee4 Merge pull request #4415 from assimp/kimkulling/fix_negative_offset_in_hast_access-issue4414
Fix possible negative array access
2022-02-24 17:20:03 +01:00
Kim Kulling
0dc24ab3a7 Fix declaration of offset 2022-02-24 17:04:39 +01:00
Kim Kulling
cf96639119 Fix possible negative array access
- Return when the calculated offset gets negative
- closes https://github.com/assimp/assimp/issues/4414
2022-02-24 16:49:35 +01:00
Kim Kulling
72da1e6d7b Merge branch 'master' into master 2022-02-23 21:20:39 +01:00
Kim Kulling
e3001f1eb7 Merge pull request #4408 from assimp/kimkulling/fix_ordering_of_gltf2_issue4407
Fix ordering of member initialization
2022-02-23 21:19:33 +01:00
Kim Kulling
6f31254ae1 Ensure dictionary for LazyDics is created before adding content to it 2022-02-23 20:57:15 +01:00
Terence Russell
3a09d19374 Merge branch 'master' into master 2022-02-22 18:43:11 -07:00
Terence Russell
4ddacdb5df Expose the original OBJ illum model as a material property. 2022-02-22 17:55:41 -07:00
Kim Kulling
466b34cf53 Merge branch 'master' into kimkulling/fix_ordering_of_gltf2_issue4407 2022-02-22 21:09:11 +01:00
Kim Kulling
aa04ee89f1 Fix init order to fix build 2022-02-22 21:07:42 +01:00
Kim Kulling
a6808b868c Small code cleanup 2022-02-22 21:07:23 +01:00
Jaroslav Přibyl
480d6fee2a cleanup 2022-02-22 01:46:47 +01:00
Jaroslav Přibyl
62c9347985 fixed obj parsing with cstype 2022-02-22 01:32:41 +01:00
Kim Kulling
ba785910d1 Merge pull request #4402 from assimp/kimkulling/warn_when_viewer_shall_be_build_on_non_win32
Show warning when assimp_viewer cannot be build on target platform
2022-02-21 15:39:11 +01:00
Kim Kulling
caaeef2b56 Update CMakeLists.txt
- Show a cmake-warning if assimp_view shall be build for linux / mac
2022-02-21 15:17:23 +01:00
Kim Kulling
8b1d94d6b1 Merge branch 'master' into deprecated_gltfpbr_macros 2022-01-23 12:16:49 +01:00
RichardTea
75e7d0f6ef Merge branch 'master' into deprecated_gltfpbr_macros 2021-12-07 09:01:50 +00:00
RichardTea
d18709b899 Small float values should be true 2021-11-23 14:15:32 +00:00
RichardTea
5143044cc8 redefine AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS
This key is deprecated but is used by Qt5 & Qt 6.2.1 QtQuick3D
2021-11-23 13:55:27 +00:00
RichardTea
2fdf52488f float and integer material property bool conversion
All reading float and integer material property values as bool
Zero => False
Non-Zero => True
2021-11-23 13:53:58 +00:00
RichardTea
42766af702 Merge branch 'master' into deprecated_gltfpbr_macros 2021-11-23 12:03:23 +00:00
Kim Kulling
bf1f142a72 Fix warnings 2021-11-20 18:40:38 +01:00
Kim Kulling
6439305379 Remove dead code 2021-08-24 20:53:55 +02:00
Kim Kulling
61ba320a04 Merge branch 'master' into master 2021-08-24 20:53:04 +02:00
bearbit
408b5053a4 update LWO importer(available lwo3) 2021-08-03 20:18:14 +03:00
36 changed files with 1790 additions and 949 deletions

View File

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

View File

@@ -49,8 +49,8 @@ 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)
@@ -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 )
@@ -150,6 +150,27 @@ IF ( WIN32 )
# Multibyte character set is deprecated since at least MSVC2015 (possibly earlier)
ADD_DEFINITIONS( -DUNICODE -D_UNICODE )
ENDIF()
# Link statically against c/c++ lib to avoid missing redistriburable such as
# "VCRUNTIME140.dll not found. Try reinstalling the app.", but give users
# a choice to opt for the shared runtime if they want.
option(USE_STATIC_CRT "Link against the static runtime libraries." OFF)
# The CMAKE_CXX_FLAGS vars can be overriden by some Visual Studio generators, so we use an alternative
# global method here:
if (${USE_STATIC_CRT})
add_compile_options(
$<$<CONFIG:>:/MT>
$<$<CONFIG:Debug>:/MTd>
$<$<CONFIG:Release>:/MT>
)
else()
add_compile_options(
$<$<CONFIG:>:/MD>
$<$<CONFIG:Debug>:/MDd>
$<$<CONFIG:Release>:/MD>
)
endif()
ENDIF()
ENDIF()
@@ -694,11 +715,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

@@ -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;

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,
@@ -68,23 +67,13 @@ namespace FBX {
using namespace Util;
// ------------------------------------------------------------------------------------------------
LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
: doc(doc)
, element(element)
, id(id)
, flags() {
LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) :
doc(doc), element(element), id(id), flags() {
// empty
}
// ------------------------------------------------------------------------------------------------
LazyObject::~LazyObject()
{
// empty
}
// ------------------------------------------------------------------------------------------------
const Object* LazyObject::Get(bool dieOnError)
{
const Object* LazyObject::Get(bool dieOnError) {
if(IsBeingConstructed() || FailedToConstruct()) {
return nullptr;
}
@@ -234,17 +223,8 @@ const Object* LazyObject::Get(bool dieOnError)
}
// ------------------------------------------------------------------------------------------------
Object::Object(uint64_t id, const Element& element, const std::string& name)
: element(element)
, name(name)
, id(id)
{
// empty
}
// ------------------------------------------------------------------------------------------------
Object::~Object()
{
Object::Object(uint64_t id, const Element& element, const std::string& name) :
element(element), name(name), id(id) {
// empty
}
@@ -255,16 +235,8 @@ FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<cons
}
// ------------------------------------------------------------------------------------------------
FileGlobalSettings::~FileGlobalSettings()
{
// empty
}
// ------------------------------------------------------------------------------------------------
Document::Document(const Parser& parser, const ImportSettings& settings)
: settings(settings)
, parser(parser)
{
Document::Document(const Parser& parser, const ImportSettings& settings) :
settings(settings), parser(parser) {
ASSIMP_LOG_DEBUG("Creating FBX Document");
// Cannot use array default initialization syntax because vc8 fails on it
@@ -285,8 +257,7 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
}
// ------------------------------------------------------------------------------------------------
Document::~Document()
{
Document::~Document() {
for(ObjectMap::value_type& v : objects) {
delete v.second;
}
@@ -348,8 +319,7 @@ void Document::ReadHeader() {
}
// ------------------------------------------------------------------------------------------------
void Document::ReadGlobalSettings()
{
void Document::ReadGlobalSettings() {
const Scope& sc = parser.GetRootScope();
const Element* const ehead = sc["GlobalSettings"];
if ( nullptr == ehead || !ehead->Compound() ) {
@@ -370,8 +340,7 @@ void Document::ReadGlobalSettings()
}
// ------------------------------------------------------------------------------------------------
void Document::ReadObjects()
{
void Document::ReadObjects() {
// read ID objects from "Objects" section
const Scope& sc = parser.GetRootScope();
const Element* const eobjects = sc["Objects"];
@@ -418,8 +387,7 @@ void Document::ReadObjects()
}
// ------------------------------------------------------------------------------------------------
void Document::ReadPropertyTemplates()
{
void Document::ReadPropertyTemplates() {
const Scope& sc = parser.GetRootScope();
// read property templates from "Definitions" section
const Element* const edefs = sc["Definitions"];
@@ -476,8 +444,7 @@ void Document::ReadPropertyTemplates()
}
// ------------------------------------------------------------------------------------------------
void Document::ReadConnections()
{
void Document::ReadConnections() {
const Scope& sc = parser.GetRootScope();
// read property templates from "Definitions" section
const Element* const econns = sc["Connections"];
@@ -524,8 +491,7 @@ void Document::ReadConnections()
}
// ------------------------------------------------------------------------------------------------
const std::vector<const AnimationStack*>& Document::AnimationStacks() const
{
const std::vector<const AnimationStack*>& Document::AnimationStacks() const {
if (!animationStacksResolved.empty() || animationStacks.empty()) {
return animationStacksResolved;
}
@@ -545,17 +511,15 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
}
// ------------------------------------------------------------------------------------------------
LazyObject* Document::GetObject(uint64_t id) const
{
LazyObject* Document::GetObject(uint64_t id) const {
ObjectMap::const_iterator it = objects.find(id);
return it == objects.end() ? nullptr : (*it).second;
}
#define MAX_CLASSNAMES 6
constexpr size_t MAX_CLASSNAMES = 6;
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const
{
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const {
std::vector<const Connection*> temp;
const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
@@ -573,11 +537,9 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, co
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
const ConnectionMap& conns,
const char* const* classnames,
size_t count) const
{
const ConnectionMap& conns,
const char* const* classnames,
size_t count) const {
ai_assert(classnames);
ai_assert( count != 0 );
ai_assert( count <= MAX_CLASSNAMES);
@@ -622,95 +584,72 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
}
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
{
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const {
return GetConnectionsSequenced(source, ConnectionsBySource());
}
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t src, const char* classname) const
{
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t src, const char* classname) const {
const char* arr[] = {classname};
return GetConnectionsBySourceSequenced(src, arr,1);
}
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
const char* const* classnames, size_t count) const
{
const char* const* classnames, size_t count) const {
return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
}
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
const char* classname) const
{
const char* classname) const {
const char* arr[] = {classname};
return GetConnectionsByDestinationSequenced(dest, arr,1);
}
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
{
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const {
return GetConnectionsSequenced(dest, ConnectionsByDestination());
}
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
const char* const* classnames, size_t count) const
{
const char* const* classnames, size_t count) const {
return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
}
// ------------------------------------------------------------------------------------------------
Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop,
const Document& doc)
: insertionOrder(insertionOrder)
, prop(prop)
, src(src)
, dest(dest)
, doc(doc)
{
const Document& doc) :
insertionOrder(insertionOrder), prop(prop), src(src), dest(dest), doc(doc) {
ai_assert(doc.Objects().find(src) != doc.Objects().end());
// dest may be 0 (root node)
ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end());
}
// ------------------------------------------------------------------------------------------------
Connection::~Connection()
{
// empty
}
// ------------------------------------------------------------------------------------------------
LazyObject& Connection::LazySourceObject() const
{
LazyObject& Connection::LazySourceObject() const {
LazyObject* const lazy = doc.GetObject(src);
ai_assert(lazy);
return *lazy;
}
// ------------------------------------------------------------------------------------------------
LazyObject& Connection::LazyDestinationObject() const
{
LazyObject& Connection::LazyDestinationObject() const {
LazyObject* const lazy = doc.GetObject(dest);
ai_assert(lazy);
return *lazy;
}
// ------------------------------------------------------------------------------------------------
const Object* Connection::SourceObject() const
{
const Object* Connection::SourceObject() const {
LazyObject* const lazy = doc.GetObject(src);
ai_assert(lazy);
return lazy->Get();
}
// ------------------------------------------------------------------------------------------------
const Object* Connection::DestinationObject() const
{
const Object* Connection::DestinationObject() const {
LazyObject* const lazy = doc.GetObject(dest);
ai_assert(lazy);
return lazy->Get();
@@ -719,4 +658,4 @@ const Object* Connection::DestinationObject() const
} // !FBX
} // !Assimp
#endif
#endif // ASSIMP_BUILD_NO_FBX_IMPORTER

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,
@@ -89,7 +88,7 @@ class LazyObject {
public:
LazyObject(uint64_t id, const Element& element, const Document& doc);
~LazyObject();
~LazyObject() = default;
const Object* Get(bool dieOnError = false);
@@ -139,7 +138,7 @@ class Object {
public:
Object(uint64_t id, const Element& element, const std::string& name);
virtual ~Object();
virtual ~Object() = default;
const Element& SourceElement() const {
return element;
@@ -267,8 +266,7 @@ public:
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Light();
enum Type
{
enum Type {
Type_Point,
Type_Directional,
Type_Spot,
@@ -278,8 +276,7 @@ public:
Type_MAX // end-of-enum sentinel
};
enum Decay
{
enum Decay {
Decay_None,
Decay_Linear,
Decay_Quadratic,
@@ -347,7 +344,7 @@ public:
Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Model();
virtual ~Model() = default;
fbx_simple_property(QuaternionInterpolate, int, 0)
@@ -578,31 +575,27 @@ public:
BlendMode_BlendModeCount
};
const Texture* getTexture(int index=0) const
{
const Texture* getTexture(int index=0) const {
return textures[index];
}
int textureCount() const {
return static_cast<int>(textures.size());
}
BlendMode GetBlendMode() const
{
BlendMode GetBlendMode() const {
return blendMode;
}
float Alpha()
{
float Alpha() {
return alpha;
}
private:
std::vector<const Texture*> textures;
BlendMode blendMode;
float alpha;
};
typedef std::fbx_unordered_map<std::string, const Texture*> TextureMap;
typedef std::fbx_unordered_map<std::string, const LayeredTexture*> LayeredTextureMap;
using TextureMap = std::fbx_unordered_map<std::string, const Texture*>;
using LayeredTextureMap = std::fbx_unordered_map<std::string, const LayeredTexture*>;
/** DOM class for generic FBX videos */
class Video : public Object {
@@ -690,8 +683,8 @@ private:
LayeredTextureMap layeredTextures;
};
typedef std::vector<int64_t> KeyTimeList;
typedef std::vector<float> KeyValueList;
using KeyTimeList = std::vector<int64_t>;
using KeyValueList = std::vector<float>;
/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */
class AnimationCurve : public Object {
@@ -727,7 +720,7 @@ private:
};
// property-name -> animation curve
typedef std::map<std::string, const AnimationCurve*> AnimationCurveMap;
using AnimationCurveMap = std::map<std::string, const AnimationCurve*>;
/** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
class AnimationCurveNode : public Object {
@@ -777,7 +770,7 @@ private:
const Document& doc;
};
typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
using AnimationCurveNodeList = std::vector<const AnimationCurveNode*>;
/** Represents a FBX animation layer (i.e. a list of node animations) */
class AnimationLayer : public Object {
@@ -800,7 +793,7 @@ private:
const Document& doc;
};
typedef std::vector<const AnimationLayer*> AnimationLayerList;
using AnimationLayerList = std::vector<const AnimationLayer*>;
/** Represents a FBX animation stack (i.e. a list of animation layers) */
class AnimationStack : public Object {
@@ -843,8 +836,8 @@ private:
std::shared_ptr<const PropertyTable> props;
};
typedef std::vector<float> WeightArray;
typedef std::vector<unsigned int> WeightIndexArray;
using WeightArray = std::vector<float>;
using WeightIndexArray = std::vector<unsigned int>;
/** DOM class for BlendShapeChannel deformers */
@@ -956,7 +949,7 @@ class Connection {
public:
Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc);
~Connection();
~Connection() = default;
// note: a connection ensures that the source and dest objects exist, but
// not that they have DOM representations, so the return value of one of
@@ -1011,10 +1004,9 @@ public:
// during their entire lifetime (Document). FBX files have
// up to many thousands of objects (most of which we never use),
// so the memory overhead for them should be kept at a minimum.
typedef std::fbx_unordered_map<uint64_t, LazyObject*> ObjectMap;
typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
typedef std::fbx_unordered_multimap<uint64_t, const Connection*> ConnectionMap;
using ObjectMap = std::fbx_unordered_map<uint64_t, LazyObject*> ;
using PropertyTemplateMap = std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > ;
using ConnectionMap = std::fbx_unordered_multimap<uint64_t, const Connection*>;
/** DOM class for global document settings, a single instance per document can
* be accessed via Document.Globals(). */
@@ -1022,7 +1014,7 @@ class FileGlobalSettings {
public:
FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props);
~FileGlobalSettings();
~FileGlobalSettings() = default;
const PropertyTable& Props() const {
ai_assert(props.get());

View File

@@ -140,11 +140,32 @@ Material::~Material() {
// empty
}
aiVector2D uvTrans;
aiVector2D uvScaling;
ai_real uvRotation;
std::string type;
std::string relativeFileName;
std::string fileName;
std::string alphaSource;
std::shared_ptr<const PropertyTable> props;
unsigned int crop[4]{};
const Video* media;
// ------------------------------------------------------------------------------------------------
Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
Object(id,element,name),
uvTrans(0.0f, 0.0f),
uvScaling(1.0f,1.0f),
media(0) {
uvRotation(0.0f),
type(),
relativeFileName(),
fileName(),
alphaSource(),
props(),
media(nullptr) {
const Scope& sc = GetRequiredScope(element);
const Element* const Type = sc["Type"];

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,10 +75,6 @@ Model::Model(uint64_t id, const Element &element, const Document &doc, const std
ResolveLinks(element, doc);
}
// ------------------------------------------------------------------------------------------------
Model::~Model() {
}
// ------------------------------------------------------------------------------------------------
void Model::ResolveLinks(const Element&, const Document &doc) {
const char *const arr[] = { "Geometry", "Material", "NodeAttribute" };

View File

@@ -64,6 +64,7 @@ namespace LWO {
#define AI_LWO_FOURCC_LWOB AI_IFF_FOURCC('L', 'W', 'O', 'B')
#define AI_LWO_FOURCC_LWO2 AI_IFF_FOURCC('L', 'W', 'O', '2')
#define AI_LWO_FOURCC_LWO3 AI_IFF_FOURCC('L', 'W', 'O', '3')
#define AI_LWO_FOURCC_LXOB AI_IFF_FOURCC('L', 'X', 'O', 'B')
// chunks specific to the LWOB format
@@ -248,6 +249,57 @@ namespace LWO {
#define AI_LWO_SPOT AI_IFF_FOURCC('S', 'P', 'O', 'T')
#define AI_LWO_PICK AI_IFF_FOURCC('P', 'I', 'C', 'K')
// Surface Part
#define AI_LWO_NODS AI_IFF_FOURCC('N', 'O', 'D', 'S')
#define AI_LWO_NNDS AI_IFF_FOURCC('N', 'N', 'D', 'S')
#define AI_LWO_NTAG AI_IFF_FOURCC('N', 'T', 'A', 'G')
#define AI_LWO_NRNM AI_IFF_FOURCC('N', 'R', 'N', 'M')
#define AI_LWO_NRME AI_IFF_FOURCC('N', 'R', 'M', 'E')
#define AI_LWO_NDTA AI_IFF_FOURCC('N', 'D', 'T', 'A')
#define AI_LWO_ATTR AI_IFF_FOURCC('A', 'T', 'T', 'R')
#define AI_LWO_VERS AI_IFF_FOURCC('V', 'E', 'R', 'S')
#define AI_LWO_ENUM AI_IFF_FOURCC('E', 'N', 'U', 'M')
#define AI_LWO_ENTR AI_IFF_FOURCC('E', 'N', 'T', 'R')
#define AI_LWO_NAME AI_IFF_FOURCC('N', 'A', 'M', 'E')
#define AI_LWO_FLAG AI_IFF_FOURCC('F', 'L', 'A', 'G')
#define AI_LWO_TAG AI_IFF_FOURCC('T', 'A', 'G', ' ')
#define AI_LWO_VALU AI_IFF_FOURCC('V', 'A', 'L', 'U')
#define AI_LWO_IBGC AI_IFF_FOURCC('I', 'B', 'G', 'C')
#define AI_LWO_IOPC AI_IFF_FOURCC('I', 'O', 'P', 'C')
#define AI_LWO_IIMG AI_IFF_FOURCC('I', 'I', 'M', 'G')
#define AI_LWO_TXTR AI_IFF_FOURCC('T', 'X', 'T', 'R')
#define AI_LWO_IFAL AI_IFF_FOURCC('I', 'F', 'A', 'L')
#define AI_LWO_ISCL AI_IFF_FOURCC('I', 'S', 'C', 'L')
#define AI_LWO_IPOS AI_IFF_FOURCC('I', 'P', 'O', 'S')
#define AI_LWO_IROT AI_IFF_FOURCC('I', 'R', 'O', 'T')
#define AI_LWO_IBMP AI_IFF_FOURCC('I', 'B', 'M', 'P')
#define AI_LWO_IUTD AI_IFF_FOURCC('I', 'U', 'T', 'D')
#define AI_LWO_IVTD AI_IFF_FOURCC('I', 'V', 'T', 'D')
#define AI_LWO_IPIX AI_IFF_FOURCC('I', 'P', 'I', 'X')
#define AI_LWO_IMIP AI_IFF_FOURCC('I', 'M', 'I', 'P')
#define AI_LWO_IMOD AI_IFF_FOURCC('I', 'M', 'O', 'D')
#define AI_LWO_AMOD AI_IFF_FOURCC('A', 'M', 'O', 'D')
#define AI_LWO_IINV AI_IFF_FOURCC('I', 'I', 'N', 'V')
#define AI_LWO_INCR AI_IFF_FOURCC('I', 'N', 'C', 'R')
#define AI_LWO_IAXS AI_IFF_FOURCC('I', 'A', 'X', 'S')
#define AI_LWO_IFOT AI_IFF_FOURCC('I', 'F', 'O', 'T')
#define AI_LWO_ITIM AI_IFF_FOURCC('I', 'T', 'I', 'M')
#define AI_LWO_IWRL AI_IFF_FOURCC('I', 'W', 'R', 'L')
#define AI_LWO_IUTI AI_IFF_FOURCC('I', 'U', 'T', 'I')
#define AI_LWO_IINX AI_IFF_FOURCC('I', 'I', 'N', 'X')
#define AI_LWO_IINY AI_IFF_FOURCC('I', 'I', 'N', 'Y')
#define AI_LWO_IINZ AI_IFF_FOURCC('I', 'I', 'N', 'Z')
#define AI_LWO_IREF AI_IFF_FOURCC('I', 'R', 'E', 'F')
#define AI_LWO_IMST AI_IFF_FOURCC('I', 'M', 'S', 'T')
#define AI_LWO_VPVL AI_IFF_FOURCC('V', 'P', 'V', 'L')
#define AI_LWO_VPRM AI_IFF_FOURCC('V', 'P', 'R', 'M')
#define AI_LWO_IMAP AI_IFF_FOURCC('I', 'M', 'A', 'P')
#define AI_LWO_IUVI AI_IFF_FOURCC('I', 'U', 'V', 'I')
#define AI_LWO_IUTL AI_IFF_FOURCC('I', 'U', 'T', 'L')
#define AI_LWO_IVTL AI_IFF_FOURCC('I', 'V', 'T', 'L')
// MODO extension - per-vertex normal vectors
#define AI_LWO_MODO_NORM AI_IFF_FOURCC('N', 'O', 'R', 'M')
@@ -555,6 +607,31 @@ struct Surface {
float mAdditiveTransparency;
};
// ---------------------------------------------------------------------------
/** \brief Data structure for a LWO node
*/
struct Node {
// Name of node
std::string mName;
// RefName of node
std::string mRefName;
// Ref FileName
std::string fileName;
};
struct NodeAttribute {
//! Color of the surface
aiColor3D mColor;
//! true for two-sided materials
bool bDoubleSided;
//! Various material parameters
float mDiffuseValue, mSpecularValue, mTransparency, mGlossiness, mLuminosity, mColorHighlights;
};
// ---------------------------------------------------------------------------
#define AI_LWO_VALIDATE_CHUNK_LENGTH(length, name, size) \
if (length < size) { \

View File

@@ -83,6 +83,7 @@ static const aiImporterDesc desc = {
LWOImporter::LWOImporter() :
mIsLWO2(),
mIsLXOB(),
mIsLWO3(),
mLayers(),
mCurLayer(),
mTags(),
@@ -182,16 +183,19 @@ void LWOImporter::InternReadFile(const std::string &pFile,
mCurLayer->mIndex = (uint16_t) -1;
// old lightwave file format (prior to v6)
mIsLWO2 = false;
mIsLWO3 = false;
mIsLXOB = false;
if (AI_LWO_FOURCC_LWOB == fileType) {
ASSIMP_LOG_INFO("LWO file format: LWOB (<= LightWave 5.5)");
mIsLWO2 = false;
mIsLXOB = false;
LoadLWOBFile();
} else if (AI_LWO_FOURCC_LWO2 == fileType) {
// New lightwave format
mIsLXOB = false;
ASSIMP_LOG_INFO("LWO file format: LWO2 (>= LightWave 6)");
} else if ( AI_LWO_FOURCC_LWO3 == fileType ) {
ASSIMP_LOG_INFO("LWO file format: LWO3 (>= LightWave 2018)");
} else if (AI_LWO_FOURCC_LXOB == fileType) {
// MODO file format
mIsLXOB = true;
@@ -207,8 +211,13 @@ void LWOImporter::InternReadFile(const std::string &pFile,
throw DeadlyImportError("Unknown LWO sub format: ", szBuff);
}
if (AI_LWO_FOURCC_LWOB != fileType) {
mIsLWO2 = true;
if (AI_LWO_FOURCC_LWOB != fileType) { //
if( AI_LWO_FOURCC_LWO3 == fileType ) {
mIsLWO3 = true;
} else {
mIsLWO2 = true;
}
LoadLWO2File();
// The newer lightwave format allows the user to configure the
@@ -442,6 +451,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
// The RemoveRedundantMaterials step will clean this up later
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials = (unsigned int)mSurfaces->size()];
for (unsigned int mat = 0; mat < pScene->mNumMaterials; ++mat) {
aiMaterial *pcMat = new aiMaterial();
pScene->mMaterials[mat] = pcMat;
@@ -687,7 +697,7 @@ void LWOImporter::ResolveClips() {
// ------------------------------------------------------------------------------------------------
void LWOImporter::AdjustTexturePath(std::string &out) {
// --- this function is used for both LWO2 and LWOB
if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) {
if (!mIsLWO2 && !mIsLWO3 && ::strstr(out.c_str(), "(sequence)")) {
// remove the (sequence) and append 000
ASSIMP_LOG_INFO("LWOB: Sequence of animated texture found. It will be ignored");
@@ -730,7 +740,7 @@ void LWOImporter::LoadLWOPoints(unsigned int length) {
throw DeadlyImportError("LWO2: Points chunk length is not multiple of vertexLen (12)");
}
unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
if (mIsLWO2) {
if (mIsLWO2 || mIsLWO3) {
mCurLayer->mTempPoints.reserve(regularSize + (regularSize >> 2u));
mCurLayer->mTempPoints.resize(regularSize);
@@ -1155,6 +1165,76 @@ void LWOImporter::LoadLWO2Clip(unsigned int length) {
}
}
void LWOImporter::LoadLWO3Clip(unsigned int length) {
AI_LWO_VALIDATE_CHUNK_LENGTH(length, CLIP, 12);
mClips.push_back(LWO::Clip());
LWO::Clip &clip = mClips.back();
// first - get the index of the clip
clip.idx = GetU4();
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
switch (head.type) {
case AI_LWO_STIL:
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, STIL, 1);
// "Normal" texture
GetS0(clip.path, head.length);
clip.type = Clip::STILL;
break;
case AI_LWO_ISEQ:
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, ISEQ, 16);
// Image sequence. We'll later take the first.
{
uint8_t digits = GetU1();
mFileBuffer++;
int16_t offset = GetU2();
mFileBuffer += 4;
int16_t start = GetU2();
mFileBuffer += 4;
std::string s;
std::ostringstream ss;
GetS0(s, head.length);
head.length -= (uint16_t)s.length() + 1;
ss << s;
ss << std::setw(digits) << offset + start;
GetS0(s, head.length);
ss << s;
clip.path = ss.str();
clip.type = Clip::SEQ;
}
break;
case AI_LWO_STCC:
ASSIMP_LOG_WARN("LWO3: Color shifted images are not supported");
break;
case AI_LWO_ANIM:
ASSIMP_LOG_WARN("LWO3: Animated textures are not supported");
break;
case AI_LWO_XREF:
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, XREF, 4);
// Just a cross-reference to another CLIp
clip.type = Clip::REF;
clip.clipRef = GetU4();
break;
case AI_LWO_NEGA:
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, NEGA, 2);
clip.negate = (0 != GetU2());
break;
default:
ASSIMP_LOG_WARN("LWO3: Encountered unknown CLIP sub-chunk");
}
}
// ------------------------------------------------------------------------------------------------
// Load envelope description
void LWOImporter::LoadLWO2Envelope(unsigned int length) {
@@ -1265,6 +1345,104 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) {
}
}
void LWOImporter::LoadLWO3Envelope(unsigned int length) {
LE_NCONST uint8_t *const end = mFileBuffer + length;
AI_LWO_VALIDATE_CHUNK_LENGTH(length, ENVL, 4);
mEnvelopes.push_back(LWO::Envelope());
LWO::Envelope &envelope = mEnvelopes.back();
// Get the index of the envelope
envelope.index = ReadVSizedIntLWO2(mFileBuffer);
// ... and read all blocks
while (true) {
if (mFileBuffer + 8 >= end) break;
LE_NCONST IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO3: Invalid envelope chunk length");
uint8_t *const next = mFileBuffer + head.length;
switch (head.type) {
// Type & representation of the envelope
case AI_LWO_TYPE:
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, TYPE, 4);
mFileBuffer++; // skip user format
// Determine type of envelope
envelope.type = (LWO::EnvelopeType)*mFileBuffer;
++mFileBuffer;
break;
// precondition
case AI_LWO_PRE:
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, PRE, 4);
envelope.pre = (LWO::PrePostBehaviour)GetU2();
break;
// postcondition
case AI_LWO_POST:
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, POST, 4);
envelope.post = (LWO::PrePostBehaviour)GetU2();
break;
// keyframe
case AI_LWO_KEY: {
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, KEY, 10);
envelope.keys.push_back(LWO::Key());
LWO::Key &key = envelope.keys.back();
key.time = GetF4();
key.value = GetF4();
break;
}
// interval interpolation
case AI_LWO_SPAN: {
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SPAN, 6);
if (envelope.keys.size() < 2)
ASSIMP_LOG_WARN("LWO3: Unexpected SPAN chunk");
else {
LWO::Key &key = envelope.keys.back();
switch (GetU4()) {
case AI_LWO_STEP:
key.inter = LWO::IT_STEP;
break;
case AI_LWO_LINE:
key.inter = LWO::IT_LINE;
break;
case AI_LWO_TCB:
key.inter = LWO::IT_TCB;
break;
case AI_LWO_HERM:
key.inter = LWO::IT_HERM;
break;
case AI_LWO_BEZI:
key.inter = LWO::IT_BEZI;
break;
case AI_LWO_BEZ2:
key.inter = LWO::IT_BEZ2;
break;
default:
ASSIMP_LOG_WARN("LWO3: Unknown interval interpolation mode");
};
// todo ... read params
}
break;
}
default:
ASSIMP_LOG_WARN("LWO3: Encountered unknown ENVL subchunk");
break;
}
// regardless how much we did actually read, go to the next chunk
mFileBuffer = next;
}
}
// ------------------------------------------------------------------------------------------------
// Load file - master function
void LWOImporter::LoadLWO2File() {
@@ -1272,16 +1450,25 @@ void LWOImporter::LoadLWO2File() {
LE_NCONST uint8_t *const end = mFileBuffer + fileSize;
unsigned int iUnnamed = 0;
while (true) {
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end) break;
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
int bufOffset = 0;
if( head.type == AI_IFF_FOURCC_FORM ) { // not chunk, it's a form
mFileBuffer -= 8;
head = IFF::LoadForm(mFileBuffer);
bufOffset = 4;
}
if (mFileBuffer + head.length > end) {
throw DeadlyImportError("LWO2: Chunk length points behind the file");
break;
}
uint8_t *const next = mFileBuffer + head.length;
mFileBuffer += bufOffset;
if (!head.length) {
mFileBuffer = next;
continue;
@@ -1337,7 +1524,6 @@ void LWOImporter::LoadLWO2File() {
break;
}
// vertex list
case AI_LWO_PNTS: {
if (skip)
@@ -1399,19 +1585,29 @@ void LWOImporter::LoadLWO2File() {
// surface chunk
case AI_LWO_SURF: {
LoadLWO2Surface(head.length);
if( mIsLWO3 )
LoadLWO3Surface(head.length);
else
LoadLWO2Surface(head.length);
break;
}
// clip chunk
case AI_LWO_CLIP: {
LoadLWO2Clip(head.length);
if( mIsLWO3 )
LoadLWO3Clip(head.length);
else
LoadLWO2Clip(head.length);
break;
}
// envelope chunk
case AI_LWO_ENVL: {
LoadLWO2Envelope(head.length);
if( mIsLWO3 )
LoadLWO3Envelope(head.length);
else
LoadLWO2Envelope(head.length);
break;
}
}

View File

@@ -116,6 +116,8 @@ private:
*/
inline void GetS0(std::string &out, unsigned int max);
inline float GetF4();
inline float GetF8();
inline uint64_t GetU8();
inline uint32_t GetU4();
inline uint16_t GetU2();
inline uint8_t GetU1();
@@ -131,6 +133,7 @@ private:
* @param size Maximum size to be read, in bytes.
*/
void LoadLWO2Surface(unsigned int size);
void LoadLWO3Surface(unsigned int size);
// -------------------------------------------------------------------
/** Loads a texture block from a LWO2 file.
@@ -197,12 +200,23 @@ private:
* @param length Size of the chunk
*/
void LoadLWO2Clip(unsigned int length);
void LoadLWO3Clip(unsigned int length);
// -------------------------------------------------------------------
/** Load an envelope from an EVL chunk
* @param length Size of the chunk
*/
void LoadLWO2Envelope(unsigned int length);
void LoadLWO3Envelope(unsigned int length);
// -------------------------------------------------------------------
/** Load an nodal blocks from surface form
* @param length Size of the chunk
*/
void LoadNodalBlocks(unsigned int length);
void LoadNodes(unsigned int length);
void LoadNodeTag(unsigned int length);
void LoadNodeData(unsigned int length);
// -------------------------------------------------------------------
/** Count vertices and faces in a LWOB/LWO2 file
@@ -347,6 +361,8 @@ protected:
/** true if the file is a LXOB file*/
bool mIsLXOB;
bool mIsLWO3;
/** Temporary list of layers from the file */
LayerList *mLayers;
@@ -400,6 +416,22 @@ inline float LWOImporter::GetF4() {
return f;
}
inline float LWOImporter::GetF8() {
double f;
::memcpy(&f, mFileBuffer, 8);
mFileBuffer += 8;
AI_LSWAP8(f);
return (float)f;
}
inline uint64_t LWOImporter::GetU8() {
uint64_t f;
::memcpy(&f, mFileBuffer, 8);
mFileBuffer += 8;
AI_LSWAP8(f);
return f;
}
// ------------------------------------------------------------------------------------------------
inline uint32_t LWOImporter::GetU4() {
uint32_t f;

View File

@@ -159,7 +159,7 @@ bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTex
// The older LWOB format does not use indirect references to clips.
// The file name of a texture is directly specified in the tex chunk.
if (mIsLWO2) {
if (mIsLWO2 || mIsLWO3) {
// find the corresponding clip (take the last one if multiple
// share the same index)
ClipList::iterator end = mClips.end(), candidate = end;
@@ -270,7 +270,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat) {
aiShadingMode m;
if (surf.mSpecularValue && surf.mGlossiness) {
float fGloss;
if (mIsLWO2) {
if (mIsLWO2 || mIsLWO3) {
fGloss = std::pow(surf.mGlossiness * ai_real(10.0) + ai_real(2.0), ai_real(2.0));
} else {
if (16.0 >= surf.mGlossiness)
@@ -688,6 +688,252 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader * /*head*/,
surf.mShaders.push_back(shader);
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadNodalBlocks(unsigned int size) {
LE_NCONST uint8_t *const end = mFileBuffer + size;
while (true) {
if (mFileBuffer + 8 >= end)
break;
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
int bufOffset = 0;
if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
mFileBuffer -= 8;
head = IFF::LoadForm(mFileBuffer);
bufOffset = 4;
}
if (mFileBuffer + head.length > end) {
throw DeadlyImportError("LWO3: cannot read length; LoadNodalBlocks");
}
int node_idx = 0;
uint8_t *const next = mFileBuffer + head.length;
mFileBuffer += bufOffset;
switch (head.type) {
case AI_LWO_NNDS:
node_idx++;
LoadNodes(head.length);
break;
}
mFileBuffer = next;
}
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadNodes(unsigned int size) {
LE_NCONST uint8_t *const end = mFileBuffer + size;
while (true) {
if (mFileBuffer + 8 >= end)
break;
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
int bufOffset = 0;
if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
mFileBuffer -= 8;
head = IFF::LoadForm(mFileBuffer);
bufOffset = 4;
}
if (mFileBuffer + head.length > end) {
throw DeadlyImportError("LWO3: cannot read length; LoadNodes");
}
uint8_t *const next = mFileBuffer + head.length;
mFileBuffer += bufOffset;
switch (head.type) {
case AI_LWO_NTAG:
LoadNodeTag(head.length);
break;
}
mFileBuffer = next;
}
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadNodeTag(unsigned int size) {
LE_NCONST uint8_t *const end = mFileBuffer + size;
while (true) {
if (mFileBuffer + 8 >= end)
break;
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
int bufOffset = 0;
if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
mFileBuffer -= 8;
head = IFF::LoadForm(mFileBuffer);
bufOffset = 4;
}
if (mFileBuffer + head.length > end) {
throw DeadlyImportError("LWO3: cannot read length; LoadNodeTag");
}
uint8_t *const next = mFileBuffer + head.length;
mFileBuffer += bufOffset;
switch (head.type) {
case AI_LWO_NDTA:
LoadNodeData(head.length);
break;
}
mFileBuffer = next;
}
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadNodeData(unsigned int size) {
LE_NCONST uint8_t *const end = mFileBuffer + size;
LWO::Surface &surf = mSurfaces->back();
while (true) {
if (mFileBuffer + 8 >= end)
break;
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
int bufOffset = 0;
if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
mFileBuffer -= 8;
head = IFF::LoadForm(mFileBuffer);
bufOffset = 4;
}
if (mFileBuffer + head.length > end) {
throw DeadlyImportError("LWO3: INVALID LENGTH; LoadNodeData");
}
uint8_t *const next = mFileBuffer + head.length;
mFileBuffer += bufOffset;
switch (head.type) {
case AI_LWO_VERS:
case AI_LWO_ENUM:
case AI_LWO_IBGC:
case AI_LWO_IOPC:
case AI_LWO_IIMG:
case AI_LWO_TXTR:
case AI_LWO_IFAL:
case AI_LWO_ISCL:
case AI_LWO_IPOS:
case AI_LWO_IROT:
case AI_LWO_IBMP:
case AI_LWO_IUTD:
case AI_LWO_IVTD:
case AI_LWO_IPIX:
case AI_LWO_IMIP:
case AI_LWO_IMOD:
case AI_LWO_AMOD:
case AI_LWO_IINV:
case AI_LWO_INCR:
case AI_LWO_IAXS:
case AI_LWO_IFOT:
case AI_LWO_ITIM:
case AI_LWO_IWRL:
case AI_LWO_IUTI:
case AI_LWO_IUVI:
case AI_LWO_IINX:
case AI_LWO_IINY:
case AI_LWO_IINZ:
case AI_LWO_IREF:
case AI_LWO_IMST:
case AI_LWO_IMAP:
case AI_LWO_IUTL:
case AI_LWO_IVTL:
case AI_LWO_VPVL:
case AI_LWO_VPRM:
mFileBuffer = next;
break;
case AI_LWO_ENTR:
std::string attrName;
while (true) {
if (mFileBuffer + 8 >= next)
break;
IFF::ChunkHeader head1 = IFF::LoadChunk(mFileBuffer);
int bufOffset1 = 0;
if (head1.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
mFileBuffer -= 8;
head1 = IFF::LoadForm(mFileBuffer);
bufOffset1 = 4;
}
if (mFileBuffer + head1.length > end) {
throw DeadlyImportError("LWO3: cannot read length;");
}
uint8_t *const next1 = mFileBuffer + head1.length;
mFileBuffer += bufOffset1;
switch (head1.type) {
case AI_LWO_FLAG:
case AI_LWO_TAG:
mFileBuffer = next1;
break;
case AI_LWO_NAME:
GetS0(attrName, head1.length);
break;
case AI_LWO_VALU:
mFileBuffer += 8;
std::string valueType;
GetS0(valueType, 8);
if (valueType == "int") {
static_cast<void>(GetU4());
} else if (valueType == "double") {
static_cast<void>(GetU8());
} else if (valueType == "vparam") {
mFileBuffer += 24;
float value = GetF8();
if (attrName == "Diffuse") {
surf.mDiffuseValue = value;
} else if (attrName == "Specular") {
surf.mSpecularValue = value;
} else if (attrName == "Transparency") {
surf.mTransparency = value;
} else if (attrName == "Glossiness") {
surf.mGlossiness = value;
} else if (attrName == "Luminosity") {
surf.mLuminosity = value;
} else if (attrName == "Color Highlight") {
surf.mColorHighlights = value;
} else if (attrName == "Refraction Index") {
surf.mIOR = value;
} else if (attrName == "Bump Height") {
surf.mBumpIntensity = value;
}
} else if (valueType == "vparam3") {
mFileBuffer += 24;
float value1, value2, value3;
value1 = GetF8();
value2 = GetF8();
value3 = GetF8();
if (attrName == "Color") {
surf.mColor.r = value1;
surf.mColor.g = value2;
surf.mColor.b = value3;
}
}
mFileBuffer = next1;
break;
}
}
break;
}
}
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2Surface(unsigned int size) {
LE_NCONST uint8_t *const end = mFileBuffer + size;
@@ -841,4 +1087,69 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) {
}
}
void LWOImporter::LoadLWO3Surface(unsigned int size) {
mFileBuffer += 8;
LE_NCONST uint8_t *const end = mFileBuffer + size - 12;
mSurfaces->push_back(LWO::Surface());
LWO::Surface &surf = mSurfaces->back();
GetS0(surf.mName, size);
// check whether this surface was derived from any other surface
std::string derived;
GetS0(derived, (unsigned int)(end - mFileBuffer));
if (derived.length()) {
// yes, find this surface
for (SurfaceList::iterator it = mSurfaces->begin(), itEnd = mSurfaces->end() - 1; it != itEnd; ++it) {
if ((*it).mName == derived) {
// we have it ...
surf = *it;
derived.clear();
break;
}
}
if (derived.size()) {
ASSIMP_LOG_WARN("LWO3: Unable to find source surface: ", derived);
}
}
while (true) {
if (mFileBuffer + 8 >= end)
break;
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
int bufOffset = 0;
if( head.type == AI_IFF_FOURCC_FORM ) { // not chunk, it's a form
mFileBuffer -= 8;
head = IFF::LoadForm(mFileBuffer);
bufOffset = 4;
}
if (mFileBuffer + head.length > end) {
throw DeadlyImportError("LWO3: cannot read length; LoadLWO3Surface");
}
uint8_t *const next = mFileBuffer + head.length;
mFileBuffer += bufOffset;
switch (head.type) {
case AI_LWO_NODS:
LoadNodalBlocks(head.length);
break;
// polygon sidedness
case AI_LWO_SIDE: {
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SIDE, 2);
surf.bDoubleSided = (3 == GetU2());
break;
}
// maximum smoothing angle
case AI_LWO_SMAN: {
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SMAN, 4);
surf.mMaximumSmoothAngle = std::fabs(GetF4());
break;
}
}
mFileBuffer = next;
}
}
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER

View File

@@ -857,6 +857,9 @@ void MDLImporter::CalculateUVCoordinates_MDL5() {
const float fHeight = (float)iHeight;
aiMesh *pcMesh = this->pScene->mMeshes[0];
for (unsigned int i = 0; i < pcMesh->mNumVertices; ++i) {
if (!pcMesh->HasTextureCoords(0)) {
continue;
}
pcMesh->mTextureCoords[0][i].x /= fWidth;
pcMesh->mTextureCoords[0][i].y /= fHeight;
pcMesh->mTextureCoords[0][i].y = 1.0f - pcMesh->mTextureCoords[0][i].y; // DX to OGL

View File

@@ -493,7 +493,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
size_t iLen2 = iLen + 1;
iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
memcpy(szFile.data, (const char *)szCurrent, iLen2);
szFile.length = (ai_uint32)iLen;
szFile.length = static_cast<ai_uint32>(iLen2);
szCurrent += iLen2;

View File

@@ -605,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);

View File

@@ -238,6 +238,7 @@ void ObjFileMtlImporter::load() {
case 'a': // Anisotropy
{
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->anisotropy);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;

View File

@@ -117,6 +117,7 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
unsigned int processed = 0;
size_t lastFilePos(0);
bool insideCstype = false;
std::vector<char> buffer;
while (streamBuffer.getNextDataLine(buffer, '\\')) {
m_DataIt = buffer.begin();
@@ -131,6 +132,18 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
m_progress->UpdateFileRead(processed, progressTotal);
}
// handle cstype section end (http://paulbourke.net/dataformats/obj/)
if (insideCstype) {
switch (*m_DataIt) {
case 'e': {
std::string name;
getNameNoSpace(m_DataIt, m_DataItEnd, name);
insideCstype = name != "end";
} break;
}
goto pf_skip_line;
}
// parse line
switch (*m_DataIt) {
case 'v': // Parse a vertex texture coordinate
@@ -219,6 +232,14 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
getObjectName();
} break;
case 'c': // handle cstype section start
{
std::string name;
getNameNoSpace(m_DataIt, m_DataItEnd, name);
insideCstype = name == "cstype";
goto pf_skip_line;
} break;
default: {
pf_skip_line:
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);

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
@@ -1156,10 +1158,12 @@ public:
Ref<Scene> scene;
public:
Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) :
mIOSystem(io),
mSchemaDocumentProvider(schemaDocumentProvider),
Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) :
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

@@ -179,11 +179,11 @@ inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::Accessor
v = &(p.attributes.texcoord);
} else if ((pos = Compare(attr, "COLOR"))) {
v = &(p.attributes.color);
} else if ((pos = Compare(attr, "JOINT"))) {
} else if ((pos = Compare(attr, "JOINTS"))) {
v = &(p.attributes.joint);
} else if ((pos = Compare(attr, "JOINTMATRIX"))) {
v = &(p.attributes.jointmatrix);
} else if ((pos = Compare(attr, "WEIGHT"))) {
} else if ((pos = Compare(attr, "WEIGHTS"))) {
v = &(p.attributes.weight);
} else
return false;

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;
}
aiString tex;
// Read texcoord (UV map index)
mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
// Read texcoord (UV map index)
mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
std::string path = tex.C_Str();
if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
std::string path = tex.C_Str();
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 (path.size() > 0) {
std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
if (it != mTexturesByPath.end()) {
texture = mAsset->textures.Get(it->second);
}
bool useBasisUniversal = false;
if (!texture) {
std::string texId = mAsset->FindUniqueID("", "texture");
texture = mAsset->textures.Create(texId);
mTexturesByPath[path] = texture.GetIndex();
bool useBasisUniversal = false;
if (!texture) {
std::string texId = mAsset->FindUniqueID("", "texture");
texture = mAsset->textures.Create(texId);
mTexturesByPath[path] = texture.GetIndex();
std::string imgId = mAsset->FindUniqueID("", "image");
texture->source = mAsset->images.Create(imgId);
std::string imgId = mAsset->FindUniqueID("", "image");
texture->source = mAsset->images.Create(imgId);
const aiTexture *curTex = mScene->GetEmbeddedTexture(path.c_str());
if (curTex != nullptr) { // embedded
texture->source->name = curTex->mFilename.C_Str();
const aiTexture *curTex = mScene->GetEmbeddedTexture(path.c_str());
if (curTex != nullptr) { // embedded
texture->source->name = curTex->mFilename.C_Str();
//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;
}
// 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

@@ -42,23 +42,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF2_IMPORTER)
#include "AssetLib/glTF2/glTF2Importer.h"
#include "PostProcessing/MakeVerboseFormat.h"
#include "AssetLib/glTF2/glTF2Asset.h"
#include "PostProcessing/MakeVerboseFormat.h"
#if !defined(ASSIMP_BUILD_NO_EXPORT)
#include "AssetLib/glTF2/glTF2AssetWriter.h"
#endif
#include <assimp/CreateAnimMesh.h>
#include <assimp/DefaultIOSystem.h>
#include <assimp/StringComparison.h>
#include <assimp/StringUtils.h>
#include <assimp/ai_assert.h>
#include <assimp/commonMetaData.h>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp>
#include <assimp/commonMetaData.h>
#include <assimp/DefaultIOSystem.h>
#include <memory>
#include <unordered_map>
@@ -111,7 +111,7 @@ const aiImporterDesc *glTF2Importer::GetInfo() const {
return &desc;
}
bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig ) const {
bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(filename);
if (!checkSig && (extension != "gltf") && (extension != "glb")) {
return false;
@@ -127,16 +127,16 @@ bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, b
static inline aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) {
switch (gltfWrapMode) {
case SamplerWrap::Mirrored_Repeat:
return aiTextureMapMode_Mirror;
case SamplerWrap::Mirrored_Repeat:
return aiTextureMapMode_Mirror;
case SamplerWrap::Clamp_To_Edge:
return aiTextureMapMode_Clamp;
case SamplerWrap::Clamp_To_Edge:
return aiTextureMapMode_Clamp;
case SamplerWrap::UNSET:
case SamplerWrap::Repeat:
default:
return aiTextureMapMode_Wrap;
case SamplerWrap::UNSET:
case SamplerWrap::Repeat:
default:
return aiTextureMapMode_Wrap;
}
}
@@ -185,8 +185,9 @@ static void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
// coordinate of the actual meshes during import.
const ai_real rcos(cos(-transform.mRotation));
const ai_real rsin(sin(-transform.mRotation));
transform.mTranslation.x = (static_cast<ai_real>( 0.5 ) * transform.mScaling.x) * (-rcos + rsin + 1) + prop.TextureTransformExt_t.offset[0];
transform.mTranslation.y = ((static_cast<ai_real>( 0.5 ) * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y - prop.TextureTransformExt_t.offset[1];;
transform.mTranslation.x = (static_cast<ai_real>(0.5) * transform.mScaling.x) * (-rcos + rsin + 1) + prop.TextureTransformExt_t.offset[0];
transform.mTranslation.y = ((static_cast<ai_real>(0.5) * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y - prop.TextureTransformExt_t.offset[1];
;
mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot);
}
@@ -259,7 +260,10 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_BASE_COLOR);
// Keep AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE for backwards compatibility
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, aiTextureType_METALNESS);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, aiTextureType_DIFFUSE_ROUGHNESS);
aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR);
aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR);
@@ -305,7 +309,6 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
aimat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL);
// KHR_materials_sheen
if (mat.materialSheen.isPresent) {
MaterialSheen &sheen = mat.materialSheen.value;
@@ -378,7 +381,7 @@ void glTF2Importer::ImportMaterials(Asset &r) {
}
}
static inline void SetFaceAndAdvance1(aiFace*& face, unsigned int numVertices, unsigned int a) {
static inline void SetFaceAndAdvance1(aiFace *&face, unsigned int numVertices, unsigned int a) {
if (a >= numVertices) {
return;
}
@@ -388,7 +391,7 @@ static inline void SetFaceAndAdvance1(aiFace*& face, unsigned int numVertices, u
++face;
}
static inline void SetFaceAndAdvance2(aiFace*& face, unsigned int numVertices,
static inline void SetFaceAndAdvance2(aiFace *&face, unsigned int numVertices,
unsigned int a, unsigned int b) {
if ((a >= numVertices) || (b >= numVertices)) {
return;
@@ -400,7 +403,7 @@ static inline void SetFaceAndAdvance2(aiFace*& face, unsigned int numVertices,
++face;
}
static inline void SetFaceAndAdvance3(aiFace*& face, unsigned int numVertices, unsigned int a,
static inline void SetFaceAndAdvance3(aiFace *&face, unsigned int numVertices, unsigned int a,
unsigned int b, unsigned int c) {
if ((a >= numVertices) || (b >= numVertices) || (c >= numVertices)) {
return;
@@ -427,17 +430,16 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign
}
#endif // ASSIMP_BUILD_DEBUG
template<typename T>
aiColor4D* GetVertexColorsForType(Ref<Accessor> input) {
template <typename T>
aiColor4D *GetVertexColorsForType(Ref<Accessor> input) {
constexpr float max = std::numeric_limits<T>::max();
aiColor4t<T>* colors;
aiColor4t<T> *colors;
input->ExtractData(colors);
auto output = new aiColor4D[input->count];
for (size_t i = 0; i < input->count; i++) {
output[i] = aiColor4D(
colors[i].r / max, colors[i].g / max,
colors[i].b / max, colors[i].a / max
);
colors[i].r / max, colors[i].g / max,
colors[i].b / max, colors[i].a / max);
}
delete[] colors;
return output;
@@ -471,21 +473,21 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
}
switch (prim.mode) {
case PrimitiveMode_POINTS:
aim->mPrimitiveTypes |= aiPrimitiveType_POINT;
break;
case PrimitiveMode_POINTS:
aim->mPrimitiveTypes |= aiPrimitiveType_POINT;
break;
case PrimitiveMode_LINES:
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP:
aim->mPrimitiveTypes |= aiPrimitiveType_LINE;
break;
case PrimitiveMode_LINES:
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP:
aim->mPrimitiveTypes |= aiPrimitiveType_LINE;
break;
case PrimitiveMode_TRIANGLES:
case PrimitiveMode_TRIANGLE_STRIP:
case PrimitiveMode_TRIANGLE_FAN:
aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
break;
case PrimitiveMode_TRIANGLES:
case PrimitiveMode_TRIANGLE_STRIP:
case PrimitiveMode_TRIANGLE_FAN:
aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
break;
}
Mesh::Primitive::Attributes &attr = prim.attributes;
@@ -528,7 +530,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) {
if (attr.color[c]->count != aim->mNumVertices) {
DefaultLogger::get()->warn("Color stream size in mesh \"", mesh.name,
"\" does not match the vertex count");
"\" does not match the vertex count");
continue;
}
@@ -551,7 +553,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
if (attr.texcoord[tc]->count != aim->mNumVertices) {
DefaultLogger::get()->warn("Texcoord stream size in mesh \"", mesh.name,
"\" does not match the vertex count");
"\" does not match the vertex count");
continue;
}
@@ -644,77 +646,77 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
}
switch (prim.mode) {
case PrimitiveMode_POINTS: {
nFaces = count;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; ++i) {
SetFaceAndAdvance1(facePtr, aim->mNumVertices, data.GetUInt(i));
}
break;
case PrimitiveMode_POINTS: {
nFaces = count;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; ++i) {
SetFaceAndAdvance1(facePtr, aim->mNumVertices, data.GetUInt(i));
}
break;
}
case PrimitiveMode_LINES: {
nFaces = count / 2;
if (nFaces * 2 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
count = nFaces * 2;
}
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1));
}
break;
case PrimitiveMode_LINES: {
nFaces = count / 2;
if (nFaces * 2 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
count = nFaces * 2;
}
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
facePtr = faces = new aiFace[nFaces];
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1));
for (unsigned int i = 2; i < count; ++i) {
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i - 1), data.GetUInt(i));
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(static_cast<int>(count) - 1), faces[0].mIndices[0]);
}
break;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1));
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
if (nFaces * 3 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
count = nFaces * 3;
}
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
facePtr = faces = new aiFace[nFaces];
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1));
for (unsigned int i = 2; i < count; ++i) {
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i - 1), data.GetUInt(i));
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(static_cast<int>(count) - 1), faces[0].mIndices[0]);
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
if (nFaces * 3 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
count = nFaces * 3;
}
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < nFaces; ++i) {
//The ordering is to ensure that the triangles are all drawn with the same orientation
if ((i + 1) % 2 == 0) {
//For even n, vertices n + 1, n, and n + 2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2));
} else {
//For odd n, vertices n, n+1, and n+2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < nFaces; ++i) {
//The ordering is to ensure that the triangles are all drawn with the same orientation
if ((i + 1) % 2 == 0) {
//For even n, vertices n + 1, n, and n + 2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2));
} else {
//For odd n, vertices n, n+1, and n+2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
}
break;
break;
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 1; i < nFaces; ++i) {
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 1; i < nFaces; ++i) {
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
break;
break;
}
} else { // no indices provided so directly generate from counts
@@ -722,77 +724,77 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
unsigned int count = aim->mNumVertices;
switch (prim.mode) {
case PrimitiveMode_POINTS: {
nFaces = count;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; ++i) {
SetFaceAndAdvance1(facePtr, aim->mNumVertices, i);
}
break;
case PrimitiveMode_POINTS: {
nFaces = count;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; ++i) {
SetFaceAndAdvance1(facePtr, aim->mNumVertices, i);
}
break;
}
case PrimitiveMode_LINES: {
nFaces = count / 2;
if (nFaces * 2 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
count = (unsigned int)nFaces * 2;
}
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFaceAndAdvance2(facePtr, aim->mNumVertices, i, i + 1);
}
break;
case PrimitiveMode_LINES: {
nFaces = count / 2;
if (nFaces * 2 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
count = (unsigned int)nFaces * 2;
}
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
facePtr = faces = new aiFace[nFaces];
SetFaceAndAdvance2(facePtr, aim->mNumVertices, 0, 1);
for (unsigned int i = 2; i < count; ++i) {
SetFaceAndAdvance2(facePtr, aim->mNumVertices, i - 1, i);
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFaceAndAdvance2(facePtr, aim->mNumVertices, count - 1, 0);
}
break;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFaceAndAdvance2(facePtr, aim->mNumVertices, i, i + 1);
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
if (nFaces * 3 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
count = (unsigned int)nFaces * 3;
}
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
facePtr = faces = new aiFace[nFaces];
SetFaceAndAdvance2(facePtr, aim->mNumVertices, 0, 1);
for (unsigned int i = 2; i < count; ++i) {
SetFaceAndAdvance2(facePtr, aim->mNumVertices, i - 1, i);
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFaceAndAdvance2(facePtr, aim->mNumVertices, count - 1, 0);
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
if (nFaces * 3 != count) {
ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
count = (unsigned int)nFaces * 3;
}
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2);
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < nFaces; ++i) {
//The ordering is to ensure that the triangles are all drawn with the same orientation
if ((i + 1) % 2 == 0) {
//For even n, vertices n + 1, n, and n + 2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, i + 1, i, i + 2);
} else {
//For odd n, vertices n, n+1, and n+2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2);
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < nFaces; ++i) {
//The ordering is to ensure that the triangles are all drawn with the same orientation
if ((i + 1) % 2 == 0) {
//For even n, vertices n + 1, n, and n + 2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, i + 1, i, i + 2);
} else {
//For odd n, vertices n, n+1, and n+2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2);
}
}
break;
break;
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, 1, 2);
for (unsigned int i = 1; i < nFaces; ++i) {
SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, i + 1, i + 2);
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, 1, 2);
for (unsigned int i = 1; i < nFaces; ++i) {
SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, i + 1, i + 2);
}
break;
break;
}
}
@@ -876,15 +878,15 @@ void glTF2Importer::ImportLights(glTF2::Asset &r) {
aiLight *ail = mScene->mLights[i] = new aiLight();
switch (light.type) {
case Light::Directional:
ail->mType = aiLightSource_DIRECTIONAL;
break;
case Light::Point:
ail->mType = aiLightSource_POINT;
break;
case Light::Spot:
ail->mType = aiLightSource_SPOT;
break;
case Light::Directional:
ail->mType = aiLightSource_DIRECTIONAL;
break;
case Light::Point:
ail->mType = aiLightSource_POINT;
break;
case Light::Spot:
ail->mType = aiLightSource_SPOT;
break;
}
if (ail->mType != aiLightSource_POINT) {
@@ -926,7 +928,7 @@ static void GetNodeTransform(aiMatrix4x4 &matrix, const glTF2::Node &node) {
if (node.matrix.isPresent) {
CopyValue(node.matrix.value, matrix);
return;
}
}
if (node.translation.isPresent) {
aiVector3D trans;
@@ -1021,7 +1023,7 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) {
metadata->Add(extension.name, extension.mBoolValue.value);
} else if (extension.mValues.isPresent) {
aiMetadata val;
for (auto const & subExtension : extension.mValues.value) {
for (auto const &subExtension : extension.mValues.value) {
ParseExtensions(&val, subExtension);
}
metadata->Add(extension.name, val);
@@ -1030,7 +1032,7 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) {
void ParseExtras(aiMetadata *metadata, const CustomExtension &extension) {
if (extension.mValues.isPresent) {
for (auto const & subExtension : extension.mValues.value) {
for (auto const &subExtension : extension.mValues.value) {
ParseExtensions(metadata, subExtension);
}
}
@@ -1068,11 +1070,10 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
if (!node.meshes.empty()) {
// GLTF files contain at most 1 mesh per node.
if (node.meshes.size() > 1)
{
if (node.meshes.size() > 1) {
throw DeadlyImportError("GLTF: Invalid input, found ", node.meshes.size(),
" meshes in ", getContextForErrorMessages(node.id, node.name),
", but only 1 mesh per node allowed.");
" meshes in ", getContextForErrorMessages(node.id, node.name),
", but only 1 mesh per node allowed.");
}
int mesh_idx = node.meshes[0].GetIndex();
int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx];
@@ -1083,7 +1084,7 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
if (node.skin) {
for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) {
aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo];
unsigned int numBones =static_cast<unsigned int>(node.skin->jointNames.size());
unsigned int numBones = static_cast<unsigned int>(node.skin->jointNames.size());
std::vector<std::vector<aiVertexWeight>> weighting(numBones);
BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting);
@@ -1222,7 +1223,7 @@ struct AnimationSamplers {
Animation::Sampler *weight;
};
aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &samplers) {
aiNodeAnim *CreateNodeAnim(glTF2::Asset &, Node &node, AnimationSamplers &samplers) {
aiNodeAnim *anim = new aiNodeAnim();
try {
@@ -1313,7 +1314,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
}
}
aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset&, Node &node, AnimationSamplers &samplers) {
aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset &, Node &node, AnimationSamplers &samplers) {
auto *anim = new aiMeshMorphAnim();
try {
@@ -1366,7 +1367,7 @@ std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation &an
continue;
}
auto& animsampler = anim.samplers[channel.sampler];
auto &animsampler = anim.samplers[channel.sampler];
if (!animsampler.input) {
ASSIMP_LOG_WARN("Animation ", anim.name, ": Missing sampler input. Skipping.");
@@ -1555,9 +1556,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
if (ext) {
if (strcmp(ext, "jpeg") == 0) {
ext = "jpg";
} else if(strcmp(ext, "ktx2") == 0) { //basisu: ktx remains
} else if (strcmp(ext, "ktx2") == 0) { //basisu: ktx remains
ext = "kx2";
} else if(strcmp(ext, "basis") == 0) { //basisu
} else if (strcmp(ext, "basis") == 0) { //basisu
ext = "bu";
}
@@ -1570,7 +1571,7 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
}
}
void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) {
void glTF2Importer::ImportCommonMetadata(glTF2::Asset &a) {
ASSIMP_LOG_DEBUG("Importing metadata");
ai_assert(mScene->mMetaData == nullptr);
const bool hasVersion = !a.asset.version.empty();
@@ -1604,7 +1605,7 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO
this->mScene = pScene;
// read the asset file
glTF2::Asset asset(pIOHandler, static_cast<rapidjson::IRemoteSchemaDocumentProvider*>(mSchemaDocumentProvider));
glTF2::Asset asset(pIOHandler, static_cast<rapidjson::IRemoteSchemaDocumentProvider *>(mSchemaDocumentProvider));
asset.Load(pFile, GetExtension(pFile) == "glb");
if (asset.scene) {
pScene->mName = asset.scene->name;
@@ -1631,7 +1632,7 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO
}
void glTF2Importer::SetupProperties(const Importer *pImp) {
mSchemaDocumentProvider = static_cast<rapidjson::IRemoteSchemaDocumentProvider*>(pImp->GetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER));
mSchemaDocumentProvider = static_cast<rapidjson::IRemoteSchemaDocumentProvider *>(pImp->GetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER));
}
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER

View File

@@ -78,6 +78,7 @@ SET( PUBLIC_HEADERS
${HEADER_PATH}/matrix4x4.h
${HEADER_PATH}/matrix4x4.inl
${HEADER_PATH}/mesh.h
${HEADER_PATH}/ObjMaterial.h
${HEADER_PATH}/pbrmaterial.h
${HEADER_PATH}/GltfMaterial.h
${HEADER_PATH}/postprocess.h

View File

@@ -35,6 +35,17 @@ struct SubChunkHeader
uint16_t length;
};
/////////////////////////////////////////////////////////////////////////////////
//! Describes an IFF form header
/////////////////////////////////////////////////////////////////////////////////
struct FormHeader
{
//! Length of the chunk data, in bytes
uint32_t length;
//! Type of the chunk header - FourCC
uint32_t type;
};
#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \
((uint8_t)b << 16u) | ((uint8_t)c << 8u) | ((uint8_t)d)))
@@ -77,6 +88,24 @@ inline SubChunkHeader LoadSubChunk(uint8_t*& outFile)
return head;
}
/////////////////////////////////////////////////////////////////////////////////
//! Load a chunk header
//! @param outFile Pointer to the file data - points to the chunk data afterwards
//! @return Copy of the chunk header
/////////////////////////////////////////////////////////////////////////////////
inline ChunkHeader LoadForm(uint8_t*& outFile)
{
ChunkHeader head;
outFile += 4;
::memcpy(&head.length, outFile, 4);
outFile += 4;
::memcpy(&head.type, outFile, 4);
AI_LSWAP4(head.length);
AI_LSWAP4(head.type);
return head;
}
/////////////////////////////////////////////////////////////////////////////////
//! Read the file header and return the type of the file and its size
//! @param outFile Pointer to the file data. The buffer must at

View File

@@ -122,15 +122,15 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) {
voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) {
ZipFile *io_stream = (ZipFile *)stream;
voidpf ret = NULL;
size_t i;
int i;
char *disk_filename = (char*)malloc(io_stream->m_Filename.length() + 1);
strncpy(disk_filename, io_stream->m_Filename.c_str(), io_stream->m_Filename.length() + 1);
for (i = io_stream->m_Filename.length() - 1; i >= 0; i -= 1)
for (i = (int)io_stream->m_Filename.length() - 1; i >= 0; i -= 1)
{
if (disk_filename[i] != '.')
continue;
snprintf(&disk_filename[i], io_stream->m_Filename.length() - i, ".z%02u", number_disk + 1);
snprintf(&disk_filename[i], io_stream->m_Filename.length() - size_t(i), ".z%02u", number_disk + 1);
break;
}

View File

@@ -90,12 +90,14 @@ void ArmaturePopulate::Execute(aiScene *out) {
ai_assert(armature);
#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
// set up bone armature id
bone->mArmature = armature;
// set this bone node to be referenced properly
ai_assert(bone_node);
bone->mNode = bone_node;
#endif
}
}

View File

@@ -32,13 +32,13 @@ PROJECT_NAME = Assimp
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = "v5.0.1. (December 2020)"
PROJECT_NUMBER = "v5.2.2 (January 2022)"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer
# a quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF =
PROJECT_BRIEF = The Asset-Importer-Lib API documentation.
# With the PROJECT_LOGO tag one can specify an logo or icon that is
# included in the documentation. The maximum height of the logo should not

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,7 +75,8 @@ 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

@@ -53,6 +53,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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

View File

@@ -331,7 +331,7 @@ enum aiTextureType {
#endif
};
#define AI_TEXTURE_TYPE_MAX aiTextureType_UNKNOWN
#define AI_TEXTURE_TYPE_MAX aiTextureType_TRANSMISSION
// -------------------------------------------------------------------------------
// Get a string for a given aiTextureType

View File

@@ -130,7 +130,54 @@ AI_FORCE_INLINE aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
}
// ---------------------------------------------------------------------------
AI_FORCE_INLINE aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
// Specialisation for a single bool.
// Casts floating point and integer to bool
template <>
AI_FORCE_INLINE
aiReturn
aiMaterial::Get(const char *pKey, unsigned int type,
unsigned int idx, bool &pOut) const {
const aiMaterialProperty *prop;
const aiReturn ret = ::aiGetMaterialProperty(this, pKey, type, idx,
(const aiMaterialProperty **)&prop);
if (AI_SUCCESS == ret) {
switch (prop->mType) {
// Type cannot be converted
default: return AI_FAILURE;
case aiPTI_Buffer: {
// Native bool value storage
if (prop->mDataLength < sizeof(bool)) {
return AI_FAILURE;
}
::memcpy(&pOut, prop->mData, sizeof(bool));
} break;
case aiPTI_Float:
case aiPTI_Double: {
// Read as float and cast to bool
float value = 0.0f;
if (AI_SUCCESS == ::aiGetMaterialFloat(this, pKey, type, idx, &value)) {
pOut = static_cast<bool>(value);
return AI_SUCCESS;
}
return AI_FAILURE;
}
case aiPTI_Integer: {
// Cast to bool
const int value = static_cast<int>(*prop->mData);
pOut = static_cast<bool>(value);
return AI_SUCCESS;
}
}
}
return ret;
}
// ---------------------------------------------------------------------------
AI_FORCE_INLINE
aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
unsigned int idx,ai_real* pOut,
unsigned int* pMax) const {
return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);

View File

@@ -61,7 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR AI_MATKEY_METALLIC_FACTOR
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR AI_MATKEY_ROUGHNESS_FACTOR
//#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS AI_MATKEY_GLOSSINESS_FACTOR
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR AI_MATKEY_GLOSSINESS_FACTOR
// Use AI_MATKEY_SHADING_MODEL == aiShadingMode_Unlit instead

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

@@ -125,13 +125,154 @@ TEST_F(MaterialSystemTest, testStringProperty) {
}
// ------------------------------------------------------------------------------------------------
TEST_F(MaterialSystemTest, testMaterialNameAccess) {
aiMaterial *mat = new aiMaterial();
EXPECT_NE(nullptr, mat);
aiString name = mat->GetName();
TEST_F(MaterialSystemTest, testDefaultMaterialName) {
aiString name = pcMat->GetName();
const int retValue(strncmp(name.C_Str(), AI_DEFAULT_MATERIAL_NAME, name.length));
EXPECT_EQ(0, retValue);
delete mat;
}
// ------------------------------------------------------------------------------------------------
TEST_F(MaterialSystemTest, testBoolProperty) {
const bool valTrue = true;
const bool valFalse = false;
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&valTrue, 1, "bool_true"));
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&valFalse, 1, "bool_false"));
bool read = false;
EXPECT_EQ(AI_SUCCESS, pcMat->Get("bool_true", 0, 0, read));
EXPECT_TRUE(read) << "read true bool";
EXPECT_EQ(AI_SUCCESS, pcMat->Get("bool_false", 0, 0, read));
EXPECT_FALSE(read) << "read false bool";
}
// ------------------------------------------------------------------------------------------------
TEST_F(MaterialSystemTest, testCastIntProperty) {
int value = 10;
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "integer"));
value = 0;
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero"));
value = -1;
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "negative"));
// To float
float valFloat = 0.0f;
EXPECT_EQ(AI_SUCCESS, pcMat->Get("integer", 0, 0, valFloat));
EXPECT_EQ(10.0f, valFloat);
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valFloat));
EXPECT_EQ(0.0f, valFloat);
EXPECT_EQ(AI_SUCCESS, pcMat->Get("negative", 0, 0, valFloat));
EXPECT_EQ(-1.0f, valFloat);
// To bool
bool valBool = false;
EXPECT_EQ(AI_SUCCESS, pcMat->Get("integer", 0, 0, valBool));
EXPECT_EQ(true, valBool);
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool));
EXPECT_EQ(false, valBool);
EXPECT_EQ(AI_SUCCESS, pcMat->Get("negative", 0, 0, valBool));
EXPECT_EQ(true, valBool);
}
// ------------------------------------------------------------------------------------------------
TEST_F(MaterialSystemTest, testCastFloatProperty) {
float value = 150392.63f;
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "float"));
value = 0;
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero"));
// To int
int valInt = 0.0f;
EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valInt));
EXPECT_EQ(150392, valInt);
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valInt));
EXPECT_EQ(0, valInt);
// To bool
bool valBool = false;
EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valBool));
EXPECT_EQ(true, valBool);
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool));
EXPECT_EQ(false, valBool);
}
// ------------------------------------------------------------------------------------------------
TEST_F(MaterialSystemTest, testCastSmallFloatProperty) {
float value = 0.0078125f;
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "float"));
value = 0;
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero"));
// To int
int valInt = 0.0f;
EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valInt));
EXPECT_EQ(0, valInt);
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valInt));
EXPECT_EQ(0, valInt);
// To bool
bool valBool = false;
EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valBool));
EXPECT_EQ(true, valBool);
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool));
EXPECT_EQ(false, valBool);
}
// ------------------------------------------------------------------------------------------------
#if defined(_MSC_VER)
// Refuse to compile on Windows if any enum values are not explicitly handled in the switch
// TODO: Move this into assimp/Compiler as a macro and add clang/gcc versions so other code can use it
__pragma(warning(push));
__pragma(warning(error : 4061)); // enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label
__pragma(warning(error : 4062)); // enumerator 'identifier' in switch of enum 'enumeration' is not handled
#endif
TEST_F(MaterialSystemTest, testMaterialTextureTypeEnum) {
// Verify that AI_TEXTURE_TYPE_MAX equals the largest 'real' value in the enum
int32_t maxTextureType = 0;
static constexpr int32_t bigNumber = 255;
EXPECT_GT(bigNumber, AI_TEXTURE_TYPE_MAX) << "AI_TEXTURE_TYPE_MAX too large for valid enum test, increase bigNumber";
// Loop until a value larger than any enum
for (int32_t i = 0; i < bigNumber; ++i) {
aiTextureType texType = static_cast<aiTextureType>(i);
switch (texType) {
default: break;
#ifndef SWIG
case _aiTextureType_Force32Bit: break;
#endif
// All the real values
case aiTextureType_NONE:
case aiTextureType_DIFFUSE:
case aiTextureType_SPECULAR:
case aiTextureType_AMBIENT:
case aiTextureType_EMISSIVE:
case aiTextureType_HEIGHT:
case aiTextureType_NORMALS:
case aiTextureType_SHININESS:
case aiTextureType_OPACITY:
case aiTextureType_DISPLACEMENT:
case aiTextureType_LIGHTMAP:
case aiTextureType_REFLECTION:
case aiTextureType_BASE_COLOR:
case aiTextureType_NORMAL_CAMERA:
case aiTextureType_EMISSION_COLOR:
case aiTextureType_METALNESS:
case aiTextureType_DIFFUSE_ROUGHNESS:
case aiTextureType_AMBIENT_OCCLUSION:
case aiTextureType_SHEEN:
case aiTextureType_CLEARCOAT:
case aiTextureType_TRANSMISSION:
case aiTextureType_UNKNOWN:
if (i > maxTextureType)
maxTextureType = i;
break;
}
}
EXPECT_EQ(maxTextureType, AI_TEXTURE_TYPE_MAX) << "AI_TEXTURE_TYPE_MAX macro must be equal to the largest valid aiTextureType_XXX";
}
#if defined(_MSC_VER)
__pragma (warning(pop))
#endif

View File

@@ -50,12 +50,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <string>
const char* AICMD_MSG_INFO_HELP_E =
"assimp info <file> [-r] [-v]\n"
"\tPrint basic structure of a 3D model\n"
"\t-r,--raw: No postprocessing, do a raw import\n"
"\t-v,--verbose: Print verbose info such as node transform data\n"
"\t-s, --silent: Print only minimal info\n";
const char *AICMD_MSG_INFO_HELP_E =
"assimp info <file> [-r] [-v]\n"
"\tPrint basic structure of a 3D model\n"
"\t-r,--raw: No postprocessing, do a raw import\n"
"\t-v,--verbose: Print verbose info such as node transform data\n"
"\t-s, --silent: Print only minimal info\n";
const char *TREE_BRANCH_ASCII = "|-";
const char *TREE_BRANCH_UTF8 = "\xe2\x94\x9c\xe2\x95\xb4";
@@ -73,411 +73,433 @@ const char *TREE_STOP = TREE_STOP_UTF8;
const char *TREE_CONTINUE = TREE_CONTINUE_UTF8;
// -----------------------------------------------------------------------------------
unsigned int CountNodes(const aiNode* root)
{
unsigned int i = 0;
for (unsigned int a = 0; a < root->mNumChildren; ++a ) {
i += CountNodes(root->mChildren[a]);
}
return 1+i;
unsigned int CountNodes(const aiNode *root) {
unsigned int i = 0;
for (unsigned int a = 0; a < root->mNumChildren; ++a) {
i += CountNodes(root->mChildren[a]);
}
return 1 + i;
}
// -----------------------------------------------------------------------------------
unsigned int GetMaxDepth(const aiNode* root)
{
unsigned int cnt = 0;
for (unsigned int i = 0; i < root->mNumChildren; ++i ) {
cnt = std::max(cnt,GetMaxDepth(root->mChildren[i]));
}
return cnt+1;
unsigned int GetMaxDepth(const aiNode *root) {
unsigned int cnt = 0;
for (unsigned int i = 0; i < root->mNumChildren; ++i) {
cnt = std::max(cnt, GetMaxDepth(root->mChildren[i]));
}
return cnt + 1;
}
// -----------------------------------------------------------------------------------
unsigned int CountVertices(const aiScene* scene)
{
unsigned int cnt = 0;
for(unsigned int i = 0; i < scene->mNumMeshes; ++i) {
cnt += scene->mMeshes[i]->mNumVertices;
}
return cnt;
unsigned int CountVertices(const aiScene *scene) {
unsigned int cnt = 0;
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
cnt += scene->mMeshes[i]->mNumVertices;
}
return cnt;
}
// -----------------------------------------------------------------------------------
unsigned int CountFaces(const aiScene* scene)
{
unsigned int cnt = 0;
for(unsigned int i = 0; i < scene->mNumMeshes; ++i) {
cnt += scene->mMeshes[i]->mNumFaces;
}
return cnt;
unsigned int CountFaces(const aiScene *scene) {
unsigned int cnt = 0;
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
cnt += scene->mMeshes[i]->mNumFaces;
}
return cnt;
}
// -----------------------------------------------------------------------------------
unsigned int CountBones(const aiScene* scene)
{
unsigned int cnt = 0;
for(unsigned int i = 0; i < scene->mNumMeshes; ++i) {
cnt += scene->mMeshes[i]->mNumBones;
}
return cnt;
unsigned int CountBones(const aiScene *scene) {
unsigned int cnt = 0;
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
cnt += scene->mMeshes[i]->mNumBones;
}
return cnt;
}
// -----------------------------------------------------------------------------------
unsigned int CountAnimChannels(const aiScene* scene)
{
unsigned int cnt = 0;
for(unsigned int i = 0; i < scene->mNumAnimations; ++i) {
cnt += scene->mAnimations[i]->mNumChannels;
}
return cnt;
unsigned int CountAnimChannels(const aiScene *scene) {
unsigned int cnt = 0;
for (unsigned int i = 0; i < scene->mNumAnimations; ++i) {
cnt += scene->mAnimations[i]->mNumChannels;
}
return cnt;
}
// -----------------------------------------------------------------------------------
unsigned int GetAvgFacePerMesh(const aiScene* scene) {
return (scene->mNumMeshes != 0) ? static_cast<unsigned int>(CountFaces(scene)/scene->mNumMeshes) : 0;
unsigned int GetAvgFacePerMesh(const aiScene *scene) {
return (scene->mNumMeshes != 0) ? static_cast<unsigned int>(CountFaces(scene) / scene->mNumMeshes) : 0;
}
// -----------------------------------------------------------------------------------
unsigned int GetAvgVertsPerMesh(const aiScene* scene) {
return (scene->mNumMeshes != 0) ? static_cast<unsigned int>(CountVertices(scene)/scene->mNumMeshes) : 0;
unsigned int GetAvgVertsPerMesh(const aiScene *scene) {
return (scene->mNumMeshes != 0) ? static_cast<unsigned int>(CountVertices(scene) / scene->mNumMeshes) : 0;
}
// -----------------------------------------------------------------------------------
void FindSpecialPoints(const aiScene* scene,const aiNode* root,aiVector3D special_points[3],const aiMatrix4x4& mat=aiMatrix4x4())
{
// XXX that could be greatly simplified by using code from code/ProcessHelper.h
// XXX I just don't want to include it here.
const aiMatrix4x4 trafo = root->mTransformation*mat;
for(unsigned int i = 0; i < root->mNumMeshes; ++i) {
const aiMesh* mesh = scene->mMeshes[root->mMeshes[i]];
void FindSpecialPoints(const aiScene *scene, const aiNode *root, aiVector3D special_points[3], const aiMatrix4x4 &mat = aiMatrix4x4()) {
// XXX that could be greatly simplified by using code from code/ProcessHelper.h
// XXX I just don't want to include it here.
const aiMatrix4x4 trafo = root->mTransformation * mat;
for (unsigned int i = 0; i < root->mNumMeshes; ++i) {
const aiMesh *mesh = scene->mMeshes[root->mMeshes[i]];
for(unsigned int a = 0; a < mesh->mNumVertices; ++a) {
aiVector3D v = trafo*mesh->mVertices[a];
for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
aiVector3D v = trafo * mesh->mVertices[a];
special_points[0].x = std::min(special_points[0].x,v.x);
special_points[0].y = std::min(special_points[0].y,v.y);
special_points[0].z = std::min(special_points[0].z,v.z);
special_points[0].x = std::min(special_points[0].x, v.x);
special_points[0].y = std::min(special_points[0].y, v.y);
special_points[0].z = std::min(special_points[0].z, v.z);
special_points[1].x = std::max(special_points[1].x,v.x);
special_points[1].y = std::max(special_points[1].y,v.y);
special_points[1].z = std::max(special_points[1].z,v.z);
}
}
special_points[1].x = std::max(special_points[1].x, v.x);
special_points[1].y = std::max(special_points[1].y, v.y);
special_points[1].z = std::max(special_points[1].z, v.z);
}
}
for(unsigned int i = 0; i < root->mNumChildren; ++i) {
FindSpecialPoints(scene,root->mChildren[i],special_points,trafo);
}
for (unsigned int i = 0; i < root->mNumChildren; ++i) {
FindSpecialPoints(scene, root->mChildren[i], special_points, trafo);
}
}
// -----------------------------------------------------------------------------------
void FindSpecialPoints(const aiScene* scene,aiVector3D special_points[3])
{
special_points[0] = aiVector3D(1e10,1e10,1e10);
special_points[1] = aiVector3D(-1e10,-1e10,-1e10);
void FindSpecialPoints(const aiScene *scene, aiVector3D special_points[3]) {
special_points[0] = aiVector3D(1e10, 1e10, 1e10);
special_points[1] = aiVector3D(-1e10, -1e10, -1e10);
FindSpecialPoints(scene,scene->mRootNode,special_points);
special_points[2] = (special_points[0]+special_points[1])*(ai_real)0.5;
FindSpecialPoints(scene, scene->mRootNode, special_points);
special_points[2] = (special_points[0] + special_points[1]) * (ai_real)0.5;
}
// -----------------------------------------------------------------------------------
std::string FindPTypes(const aiScene* scene)
{
bool haveit[4] = {0};
for(unsigned int i = 0; i < scene->mNumMeshes; ++i) {
const unsigned int pt = scene->mMeshes[i]->mPrimitiveTypes;
if (pt & aiPrimitiveType_POINT) {
haveit[0]=true;
}
if (pt & aiPrimitiveType_LINE) {
haveit[1]=true;
}
if (pt & aiPrimitiveType_TRIANGLE) {
haveit[2]=true;
}
if (pt & aiPrimitiveType_POLYGON) {
haveit[3]=true;
}
}
return (haveit[0]?std::string("points"):"")+(haveit[1]?"lines":"")+
(haveit[2]?"triangles":"")+(haveit[3]?"n-polygons":"");
std::string FindPTypes(const aiScene *scene) {
bool haveit[4] = { 0 };
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
const unsigned int pt = scene->mMeshes[i]->mPrimitiveTypes;
if (pt & aiPrimitiveType_POINT) {
haveit[0] = true;
}
if (pt & aiPrimitiveType_LINE) {
haveit[1] = true;
}
if (pt & aiPrimitiveType_TRIANGLE) {
haveit[2] = true;
}
if (pt & aiPrimitiveType_POLYGON) {
haveit[3] = true;
}
}
return (haveit[0] ? std::string("points") : "") + (haveit[1] ? "lines" : "") +
(haveit[2] ? "triangles" : "") + (haveit[3] ? "n-polygons" : "");
}
// -----------------------------------------------------------------------------------
// Prettily print the node graph to stdout
void PrintHierarchy(
const aiNode* node,
const std::string &indent,
bool verbose,
bool last = false,
bool first = true
){
// tree visualization
std::string branchchar;
if (first) { branchchar = ""; }
else if (last) { branchchar = TREE_STOP; } // "'-"
else { branchchar = TREE_BRANCH; } // "|-"
const aiNode *node,
const std::string &indent,
bool verbose,
bool last = false,
bool first = true) {
// tree visualization
std::string branchchar;
if (first) {
branchchar = "";
} else if (last) {
branchchar = TREE_STOP;
} // "'-"
else {
branchchar = TREE_BRANCH;
} // "|-"
// print the indent and the branch character and the name
std::cout << indent << branchchar << node->mName.C_Str();
// print the indent and the branch character and the name
std::cout << indent << branchchar << node->mName.C_Str();
// if there are meshes attached, indicate this
if (node->mNumMeshes) {
std::cout << " (mesh ";
bool sep = false;
for (size_t i=0; i < node->mNumMeshes; ++i) {
unsigned int mesh_index = node->mMeshes[i];
if (sep) { std::cout << ", "; }
std::cout << mesh_index;
sep = true;
}
std::cout << ")";
}
// if there are meshes attached, indicate this
if (node->mNumMeshes) {
std::cout << " (mesh ";
bool sep = false;
for (size_t i = 0; i < node->mNumMeshes; ++i) {
unsigned int mesh_index = node->mMeshes[i];
if (sep) {
std::cout << ", ";
}
std::cout << mesh_index;
sep = true;
}
std::cout << ")";
}
// finish the line
std::cout << std::endl;
// finish the line
std::cout << std::endl;
// in verbose mode, print the transform data as well
if (verbose) {
// indent to use
std::string indentadd;
if (last) { indentadd += " "; }
else { indentadd += TREE_CONTINUE; } // "| "..
if (node->mNumChildren == 0) { indentadd += " "; }
else { indentadd += TREE_CONTINUE; } // .."| "
aiVector3D s, r, t;
node->mTransformation.Decompose(s, r, t);
if (s.x != 1.0 || s.y != 1.0 || s.z != 1.0) {
std::cout << indent << indentadd;
printf(" S:[%f %f %f]\n", s.x, s.y, s.z);
}
if (r.x || r.y || r.z) {
std::cout << indent << indentadd;
printf(" R:[%f %f %f]\n", r.x, r.y, r.z);
}
if (t.x || t.y || t.z) {
std::cout << indent << indentadd;
printf(" T:[%f %f %f]\n", t.x, t.y, t.z);
}
}
// in verbose mode, print the transform data as well
if (verbose) {
// indent to use
std::string indentadd;
if (last) {
indentadd += " ";
} else {
indentadd += TREE_CONTINUE;
} // "| "..
if (node->mNumChildren == 0) {
indentadd += " ";
} else {
indentadd += TREE_CONTINUE;
} // .."| "
aiVector3D s, r, t;
node->mTransformation.Decompose(s, r, t);
if (s.x != 1.0 || s.y != 1.0 || s.z != 1.0) {
std::cout << indent << indentadd;
printf(" S:[%f %f %f]\n", s.x, s.y, s.z);
}
if (r.x || r.y || r.z) {
std::cout << indent << indentadd;
printf(" R:[%f %f %f]\n", r.x, r.y, r.z);
}
if (t.x || t.y || t.z) {
std::cout << indent << indentadd;
printf(" T:[%f %f %f]\n", t.x, t.y, t.z);
}
}
// and recurse
std::string nextIndent;
if (first) { nextIndent = indent; }
else if (last) { nextIndent = indent + " "; }
else { nextIndent = indent + TREE_CONTINUE; } // "| "
for (size_t i = 0; i < node->mNumChildren; ++i) {
bool lastone = (i == node->mNumChildren - 1);
PrintHierarchy(
node->mChildren[i],
nextIndent,
verbose,
lastone,
false
);
}
// and recurse
std::string nextIndent;
if (first) {
nextIndent = indent;
} else if (last) {
nextIndent = indent + " ";
} else {
nextIndent = indent + TREE_CONTINUE;
} // "| "
for (size_t i = 0; i < node->mNumChildren; ++i) {
bool lastone = (i == node->mNumChildren - 1);
PrintHierarchy(
node->mChildren[i],
nextIndent,
verbose,
lastone,
false);
}
}
// -----------------------------------------------------------------------------------
// Implementation of the assimp info utility to print basic file info
int Assimp_Info (const char* const* params, unsigned int num) {
// --help
if (!strcmp( params[0],"-h")||!strcmp( params[0],"--help")||!strcmp( params[0],"-?") ) {
printf("%s",AICMD_MSG_INFO_HELP_E);
return AssimpCmdError::Success;
}
int Assimp_Info(const char *const *params, unsigned int num) {
// --help
if (!strcmp(params[0], "-h") || !strcmp(params[0], "--help") || !strcmp(params[0], "-?")) {
printf("%s", AICMD_MSG_INFO_HELP_E);
return AssimpCmdError::Success;
}
// asssimp info <file> [-r]
if (num < 1) {
printf("assimp info: Invalid number of arguments. "
"See \'assimp info --help\'\n");
return AssimpCmdError::InvalidNumberOfArguments;
}
// asssimp info <file> [-r]
if (num < 1) {
printf("assimp info: Invalid number of arguments. "
"See \'assimp info --help\'\n");
return AssimpCmdError::InvalidNumberOfArguments;
}
const std::string in = std::string(params[0]);
const std::string in = std::string(params[0]);
// get -r and -v arguments
bool raw = false;
bool verbose = false;
bool silent = false;
for(unsigned int i = 1; i < num; ++i) {
if (!strcmp(params[i],"--raw")||!strcmp(params[i],"-r")) {
raw = true;
}
if (!strcmp(params[i],"--verbose")||!strcmp(params[i],"-v")) {
verbose = true;
}
if (!strcmp(params[i], "--silent") || !strcmp(params[i], "-s")) {
silent = true;
}
}
// get -r and -v arguments
bool raw = false;
bool verbose = false;
bool silent = false;
for (unsigned int i = 1; i < num; ++i) {
if (!strcmp(params[i], "--raw") || !strcmp(params[i], "-r")) {
raw = true;
}
if (!strcmp(params[i], "--verbose") || !strcmp(params[i], "-v")) {
verbose = true;
}
if (!strcmp(params[i], "--silent") || !strcmp(params[i], "-s")) {
silent = true;
}
}
// Verbose and silent at the same time are not allowed
if ( verbose && silent ) {
printf("assimp info: Invalid arguments, verbose and silent at the same time are forbidden. ");
return AssimpCmdInfoError::InvalidCombinaisonOfArguments;
}
// Verbose and silent at the same time are not allowed
if (verbose && silent) {
printf("assimp info: Invalid arguments, verbose and silent at the same time are forbidden. ");
return AssimpCmdInfoError::InvalidCombinaisonOfArguments;
}
// Parse post-processing flags unless -r was specified
ImportData import;
if (!raw) {
// get import flags
ProcessStandardArguments(import, params + 1, num - 1);
// Parse post-processing flags unless -r was specified
ImportData import;
if (!raw) {
// get import flags
ProcessStandardArguments(import, params + 1, num - 1);
//No custom post process flags defined, we set all the post process flags active
if(import.ppFlags == 0)
import.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality;
}
//No custom post process flags defined, we set all the post process flags active
if (import.ppFlags == 0)
import.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality;
}
// import the main model
const aiScene* scene = ImportModel(import,in);
if (!scene) {
printf("assimp info: Unable to load input file %s\n",
in.c_str());
return AssimpCmdError::FailedToLoadInputFile;
}
// import the main model
const aiScene *scene = ImportModel(import, in);
if (!scene) {
printf("assimp info: Unable to load input file %s\n",
in.c_str());
return AssimpCmdError::FailedToLoadInputFile;
}
aiMemoryInfo mem;
globalImporter->GetMemoryRequirements(mem);
aiMemoryInfo mem;
globalImporter->GetMemoryRequirements(mem);
static const char *format_string =
"Memory consumption: %i B\n"
"Nodes: %i\n"
"Maximum depth %i\n"
"Meshes: %i\n"
"Animations: %i\n"
"Textures (embed.): %i\n"
"Materials: %i\n"
"Cameras: %i\n"
"Lights: %i\n"
"Vertices: %i\n"
"Faces: %i\n"
"Bones: %i\n"
"Animation Channels: %i\n"
"Primitive Types: %s\n"
"Average faces/mesh %i\n"
"Average verts/mesh %i\n"
"Minimum point (%f %f %f)\n"
"Maximum point (%f %f %f)\n"
"Center point (%f %f %f)\n"
static const char* format_string =
"Memory consumption: %i B\n"
"Nodes: %i\n"
"Maximum depth %i\n"
"Meshes: %i\n"
"Animations: %i\n"
"Textures (embed.): %i\n"
"Materials: %i\n"
"Cameras: %i\n"
"Lights: %i\n"
"Vertices: %i\n"
"Faces: %i\n"
"Bones: %i\n"
"Animation Channels: %i\n"
"Primitive Types: %s\n"
"Average faces/mesh %i\n"
"Average verts/mesh %i\n"
"Minimum point (%f %f %f)\n"
"Maximum point (%f %f %f)\n"
"Center point (%f %f %f)\n"
;
;
aiVector3D special_points[3];
FindSpecialPoints(scene, special_points);
printf(format_string,
mem.total,
CountNodes(scene->mRootNode),
GetMaxDepth(scene->mRootNode),
scene->mNumMeshes,
scene->mNumAnimations,
scene->mNumTextures,
scene->mNumMaterials,
scene->mNumCameras,
scene->mNumLights,
CountVertices(scene),
CountFaces(scene),
CountBones(scene),
CountAnimChannels(scene),
FindPTypes(scene).c_str(),
GetAvgFacePerMesh(scene),
GetAvgVertsPerMesh(scene),
special_points[0][0], special_points[0][1], special_points[0][2],
special_points[1][0], special_points[1][1], special_points[1][2],
special_points[2][0], special_points[2][1], special_points[2][2]);
aiVector3D special_points[3];
FindSpecialPoints(scene,special_points);
printf(format_string,
mem.total,
CountNodes(scene->mRootNode),
GetMaxDepth(scene->mRootNode),
scene->mNumMeshes,
scene->mNumAnimations,
scene->mNumTextures,
scene->mNumMaterials,
scene->mNumCameras,
scene->mNumLights,
CountVertices(scene),
CountFaces(scene),
CountBones(scene),
CountAnimChannels(scene),
FindPTypes(scene).c_str(),
GetAvgFacePerMesh(scene),
GetAvgVertsPerMesh(scene),
special_points[0][0],special_points[0][1],special_points[0][2],
special_points[1][0],special_points[1][1],special_points[1][2],
special_points[2][0],special_points[2][1],special_points[2][2]
)
;
if (silent) {
printf("\n");
return AssimpCmdError::Success;
}
if (silent)
{
printf("\n");
return AssimpCmdError::Success;
}
// meshes
if (scene->mNumMeshes) {
printf("\nMeshes: (name) [vertices / bones / faces | primitive_types]\n");
}
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
const aiMesh *mesh = scene->mMeshes[i];
printf(" %d (%s)", i, mesh->mName.C_Str());
printf(
": [%d / %d / %d |",
mesh->mNumVertices,
mesh->mNumBones,
mesh->mNumFaces);
const unsigned int ptypes = mesh->mPrimitiveTypes;
if (ptypes & aiPrimitiveType_POINT) {
printf(" point");
}
if (ptypes & aiPrimitiveType_LINE) {
printf(" line");
}
if (ptypes & aiPrimitiveType_TRIANGLE) {
printf(" triangle");
}
if (ptypes & aiPrimitiveType_POLYGON) {
printf(" polygon");
}
printf("]\n");
}
// meshes
if (scene->mNumMeshes) {
printf("\nMeshes: (name) [vertices / bones / faces | primitive_types]\n");
}
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
const aiMesh* mesh = scene->mMeshes[i];
printf(" %d (%s)", i, mesh->mName.C_Str());
printf(
": [%d / %d / %d |",
mesh->mNumVertices,
mesh->mNumBones,
mesh->mNumFaces
);
const unsigned int ptypes = mesh->mPrimitiveTypes;
if (ptypes & aiPrimitiveType_POINT) { printf(" point"); }
if (ptypes & aiPrimitiveType_LINE) { printf(" line"); }
if (ptypes & aiPrimitiveType_TRIANGLE) { printf(" triangle"); }
if (ptypes & aiPrimitiveType_POLYGON) { printf(" polygon"); }
printf("]\n");
}
// materials
if (scene->mNumMaterials)
printf("\nNamed Materials:");
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
const aiMaterial *mat = scene->mMaterials[i];
aiString name = mat->GetName();
printf("\n \'%s\'", name.data);
if (mat->mNumProperties)
printf(" (prop) [index / bytes | texture semantic]");
for (unsigned p = 0; p < mat->mNumProperties; p++) {
const aiMaterialProperty *prop = mat->mProperties[p];
const aiTextureType textype = static_cast<aiTextureType>(prop->mSemantic);
printf("\n %d (%s): [%d / %d | %s]",
p,
prop->mKey.data,
prop->mIndex,
prop->mDataLength,
TextureTypeToString(textype));
}
}
if (scene->mNumMaterials) {
printf("\n");
}
// materials
unsigned int total=0;
for(unsigned int i = 0;i < scene->mNumMaterials; ++i) {
aiString name;
if (AI_SUCCESS==aiGetMaterialString(scene->mMaterials[i],AI_MATKEY_NAME,&name)) {
printf("%s\n \'%s\'",(total++?"":"\nNamed Materials:" ),name.data);
}
}
if(total) {
printf("\n");
}
// textures
unsigned int total = 0;
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
aiString name;
static const aiTextureType types[] = {
aiTextureType_NONE,
aiTextureType_DIFFUSE,
aiTextureType_SPECULAR,
aiTextureType_AMBIENT,
aiTextureType_EMISSIVE,
aiTextureType_HEIGHT,
aiTextureType_NORMALS,
aiTextureType_SHININESS,
aiTextureType_OPACITY,
aiTextureType_DISPLACEMENT,
aiTextureType_LIGHTMAP,
aiTextureType_REFLECTION,
aiTextureType_BASE_COLOR,
aiTextureType_NORMAL_CAMERA,
aiTextureType_EMISSION_COLOR,
aiTextureType_METALNESS,
aiTextureType_DIFFUSE_ROUGHNESS,
aiTextureType_AMBIENT_OCCLUSION,
aiTextureType_UNKNOWN
};
for (unsigned int type = 0; type < sizeof(types) / sizeof(types[0]); ++type) {
for (unsigned int idx = 0; AI_SUCCESS == aiGetMaterialString(scene->mMaterials[i],
AI_MATKEY_TEXTURE(types[type], idx), &name);
++idx) {
printf("%s\n \'%s\'", (total++ ? "" : "\nTexture Refs:"), name.data);
}
}
}
if (total) {
printf("\n");
}
// textures
total=0;
for(unsigned int i = 0;i < scene->mNumMaterials; ++i) {
aiString name;
static const aiTextureType types[] = {
aiTextureType_NONE,
aiTextureType_DIFFUSE,
aiTextureType_SPECULAR,
aiTextureType_AMBIENT,
aiTextureType_EMISSIVE,
aiTextureType_HEIGHT,
aiTextureType_NORMALS,
aiTextureType_SHININESS,
aiTextureType_OPACITY,
aiTextureType_DISPLACEMENT,
aiTextureType_LIGHTMAP,
aiTextureType_REFLECTION,
aiTextureType_BASE_COLOR,
aiTextureType_NORMAL_CAMERA,
aiTextureType_EMISSION_COLOR,
aiTextureType_METALNESS,
aiTextureType_DIFFUSE_ROUGHNESS,
aiTextureType_AMBIENT_OCCLUSION,
aiTextureType_UNKNOWN
};
for(unsigned int type = 0; type < sizeof(types)/sizeof(types[0]); ++type) {
for(unsigned int idx = 0;AI_SUCCESS==aiGetMaterialString(scene->mMaterials[i],
AI_MATKEY_TEXTURE(types[type],idx),&name); ++idx) {
printf("%s\n \'%s\'",(total++?"":"\nTexture Refs:" ),name.data);
}
}
}
if(total) {
printf("\n");
}
// animations
total = 0;
for (unsigned int i = 0; i < scene->mNumAnimations; ++i) {
if (scene->mAnimations[i]->mName.length) {
printf("%s\n \'%s\'", (total++ ? "" : "\nNamed Animations:"), scene->mAnimations[i]->mName.data);
}
}
if (total) {
printf("\n");
}
// animations
total=0;
for(unsigned int i = 0;i < scene->mNumAnimations; ++i) {
if (scene->mAnimations[i]->mName.length) {
printf("%s\n \'%s\'",(total++?"":"\nNamed Animations:" ),scene->mAnimations[i]->mName.data);
}
}
if(total) {
printf("\n");
}
// node hierarchy
printf("\nNode hierarchy:\n");
PrintHierarchy(scene->mRootNode, "", verbose);
// node hierarchy
printf("\nNode hierarchy:\n");
PrintHierarchy(scene->mRootNode,"",verbose);
printf("\n");
return AssimpCmdError::Success;
printf("\n");
return AssimpCmdError::Success;
}