Merge branch 'master' into x3d_pugi_migration
parent
6db142ee51
commit
3001d88172
|
@ -25,7 +25,7 @@ CMakeSettings.json
|
|||
# Output
|
||||
bin/
|
||||
lib/
|
||||
|
||||
x64/
|
||||
# QtCreator
|
||||
CMakeLists.txt.user
|
||||
|
||||
|
|
|
@ -44,10 +44,10 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.10 )
|
|||
option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
|
||||
|
||||
IF(ASSIMP_HUNTER_ENABLED)
|
||||
include("cmake/HunterGate.cmake")
|
||||
include("cmake-modules/HunterGate.cmake")
|
||||
HunterGate(
|
||||
URL "https://github.com/cpp-pm/hunter/archive/v0.23.293.tar.gz"
|
||||
SHA1 "e8e5470652db77149d9b38656db2a6c0b7642693"
|
||||
URL "https://github.com/cpp-pm/hunter/archive/v0.23.311.tar.gz"
|
||||
SHA1 "1a82b9b73055879181cb1466b2ab5d48ee8ae410"
|
||||
)
|
||||
|
||||
add_definitions(-DASSIMP_USE_HUNTER)
|
||||
|
@ -135,11 +135,11 @@ IF ( WIN32 )
|
|||
# Use subset of Windows.h
|
||||
ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
|
||||
|
||||
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW
|
||||
"If the Assimp view tool is built. (requires DirectX)"
|
||||
OFF )
|
||||
|
||||
IF(MSVC)
|
||||
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW
|
||||
"If the Assimp view tool is built. (requires DirectX)"
|
||||
OFF )
|
||||
|
||||
OPTION( ASSIMP_INSTALL_PDB
|
||||
"Install MSVC debug files."
|
||||
ON )
|
||||
|
@ -268,6 +268,8 @@ ELSEIF(MSVC)
|
|||
ADD_COMPILE_OPTIONS(/wd4351)
|
||||
ENDIF()
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
|
||||
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||
IF(NOT ASSIMP_HUNTER_ENABLED)
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
|
@ -395,14 +397,14 @@ set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
|||
|
||||
IF(ASSIMP_HUNTER_ENABLED)
|
||||
set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
|
||||
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake/assimp-hunter-config.cmake.in")
|
||||
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in")
|
||||
set(NAMESPACE "${PROJECT_NAME}::")
|
||||
set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
|
||||
set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
|
||||
ELSE()
|
||||
set(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
|
||||
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake/assimp-plain-config.cmake.in")
|
||||
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in")
|
||||
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)
|
||||
set(NAMESPACE "${PROJECT_NAME_LOWERCASE}::")
|
||||
set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets")
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
# Find IrrXMl from irrlicht project
|
||||
#
|
||||
# Find LibIrrXML headers and library
|
||||
#
|
||||
# IRRXML_FOUND - IrrXML found
|
||||
# IRRXML_INCLUDE_DIR - Headers location
|
||||
# IRRXML_LIBRARY - IrrXML main library
|
||||
|
||||
find_path(IRRXML_INCLUDE_DIR irrXML.h
|
||||
PATH_SUFFIXES include/irrlicht include/irrxml)
|
||||
find_library(IRRXML_LIBRARY IrrXML)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(IrrXML REQUIRED_VARS IRRXML_INCLUDE_DIR IRRXML_LIBRARY)
|
||||
|
||||
|
||||
mark_as_advanced(IRRXML_INCLUDE_DIR IRRXML_LIBRARY)
|
|
@ -0,0 +1,19 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
find_package(RapidJSON CONFIG REQUIRED)
|
||||
find_package(ZLIB CONFIG REQUIRED)
|
||||
find_package(utf8cpp CONFIG REQUIRED)
|
||||
find_package(minizip CONFIG REQUIRED)
|
||||
find_package(openddlparser CONFIG REQUIRED)
|
||||
find_package(poly2tri CONFIG REQUIRED)
|
||||
find_package(polyclipping CONFIG REQUIRED)
|
||||
find_package(zip CONFIG REQUIRED)
|
||||
find_package(pugixml CONFIG REQUIRED)
|
||||
find_package(stb CONFIG REQUIRED)
|
||||
|
||||
if(@ASSIMP_BUILD_DRACO@)
|
||||
find_package(draco CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
|
@ -1,18 +0,0 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
find_package(RapidJSON CONFIG REQUIRED)
|
||||
find_package(ZLIB CONFIG REQUIRED)
|
||||
find_package(utf8cpp CONFIG REQUIRED)
|
||||
find_package(minizip CONFIG REQUIRED)
|
||||
find_package(openddlparser CONFIG REQUIRED)
|
||||
find_package(poly2tri CONFIG REQUIRED)
|
||||
find_package(polyclipping CONFIG REQUIRED)
|
||||
find_package(zip CONFIG REQUIRED)
|
||||
find_package(pugixml CONFIG REQUIRED)
|
||||
|
||||
if(@ASSIMP_BUILD_DRACO@)
|
||||
find_package(draco CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
|
@ -68,8 +68,8 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
|
|||
unsigned int idx(NotSet);
|
||||
for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
|
||||
std::string s = mScene->mMaterials[i].mName;
|
||||
for (std::string::iterator it = s.begin(); it != s.end(); ++it) {
|
||||
*it = static_cast<char>(::tolower(static_cast<unsigned char>(*it)));
|
||||
for (char & it : s) {
|
||||
it = static_cast<char>(::tolower(static_cast<unsigned char>(it)));
|
||||
}
|
||||
|
||||
if (std::string::npos == s.find("default")) continue;
|
||||
|
@ -79,12 +79,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
|
|||
mScene->mMaterials[i].mDiffuse.r !=
|
||||
mScene->mMaterials[i].mDiffuse.b) continue;
|
||||
|
||||
if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 ||
|
||||
mScene->mMaterials[i].sTexBump.mMapName.length() != 0 ||
|
||||
mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 ||
|
||||
mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 ||
|
||||
mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 ||
|
||||
mScene->mMaterials[i].sTexShininess.mMapName.length() != 0) {
|
||||
if (ContainsTextures(i)) {
|
||||
continue;
|
||||
}
|
||||
idx = i;
|
||||
|
|
|
@ -348,16 +348,16 @@ struct Texture {
|
|||
// empty
|
||||
}
|
||||
|
||||
Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)),
|
||||
Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend),
|
||||
mMapName(std::move(other.mMapName)),
|
||||
mOffsetU(std::move(other.mOffsetU)),
|
||||
mOffsetV(std::move(other.mOffsetV)),
|
||||
mScaleU(std::move(other.mScaleU)),
|
||||
mScaleV(std::move(other.mScaleV)),
|
||||
mRotation(std::move(other.mRotation)),
|
||||
mMapMode(std::move(other.mMapMode)),
|
||||
bPrivate(std::move(other.bPrivate)),
|
||||
iUVSrc(std::move(other.iUVSrc)) {
|
||||
mOffsetU(other.mOffsetU),
|
||||
mOffsetV(other.mOffsetV),
|
||||
mScaleU(other.mScaleU),
|
||||
mScaleV(other.mScaleV),
|
||||
mRotation(other.mRotation),
|
||||
mMapMode(other.mMapMode),
|
||||
bPrivate(other.bPrivate),
|
||||
iUVSrc(other.iUVSrc) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -366,16 +366,16 @@ struct Texture {
|
|||
return *this;
|
||||
}
|
||||
|
||||
mTextureBlend = std::move(other.mTextureBlend);
|
||||
mTextureBlend = other.mTextureBlend;
|
||||
mMapName = std::move(other.mMapName);
|
||||
mOffsetU = std::move(other.mOffsetU);
|
||||
mOffsetV = std::move(other.mOffsetV);
|
||||
mScaleU = std::move(other.mScaleU);
|
||||
mScaleV = std::move(other.mScaleV);
|
||||
mRotation = std::move(other.mRotation);
|
||||
mMapMode = std::move(other.mMapMode);
|
||||
bPrivate = std::move(other.bPrivate);
|
||||
iUVSrc = std::move(other.iUVSrc);
|
||||
mOffsetU = other.mOffsetU;
|
||||
mOffsetV = other.mOffsetV;
|
||||
mScaleU = other.mScaleU;
|
||||
mScaleV = other.mScaleV;
|
||||
mRotation = other.mRotation;
|
||||
mMapMode = other.mMapMode;
|
||||
bPrivate = other.bPrivate;
|
||||
iUVSrc = other.iUVSrc;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -461,13 +461,13 @@ struct Material {
|
|||
|
||||
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
|
||||
Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)),
|
||||
mDiffuse(std::move(other.mDiffuse)),
|
||||
mSpecularExponent(std::move(other.mSpecularExponent)),
|
||||
mShininessStrength(std::move(other.mShininessStrength)),
|
||||
mSpecular(std::move(other.mSpecular)),
|
||||
mAmbient(std::move(other.mAmbient)),
|
||||
mShading(std::move(other.mShading)),
|
||||
mTransparency(std::move(other.mTransparency)),
|
||||
mDiffuse(other.mDiffuse),
|
||||
mSpecularExponent(other.mSpecularExponent),
|
||||
mShininessStrength(other.mShininessStrength),
|
||||
mSpecular(other.mSpecular),
|
||||
mAmbient(other.mAmbient),
|
||||
mShading(other.mShading),
|
||||
mTransparency(other.mTransparency),
|
||||
sTexDiffuse(std::move(other.sTexDiffuse)),
|
||||
sTexOpacity(std::move(other.sTexOpacity)),
|
||||
sTexSpecular(std::move(other.sTexSpecular)),
|
||||
|
@ -475,10 +475,10 @@ struct Material {
|
|||
sTexBump(std::move(other.sTexBump)),
|
||||
sTexEmissive(std::move(other.sTexEmissive)),
|
||||
sTexShininess(std::move(other.sTexShininess)),
|
||||
mBumpHeight(std::move(other.mBumpHeight)),
|
||||
mEmissive(std::move(other.mEmissive)),
|
||||
mBumpHeight(other.mBumpHeight),
|
||||
mEmissive(other.mEmissive),
|
||||
sTexAmbient(std::move(other.sTexAmbient)),
|
||||
mTwoSided(std::move(other.mTwoSided)) {
|
||||
mTwoSided(other.mTwoSided) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -488,13 +488,13 @@ struct Material {
|
|||
}
|
||||
|
||||
mName = std::move(other.mName);
|
||||
mDiffuse = std::move(other.mDiffuse);
|
||||
mSpecularExponent = std::move(other.mSpecularExponent);
|
||||
mShininessStrength = std::move(other.mShininessStrength),
|
||||
mSpecular = std::move(other.mSpecular);
|
||||
mAmbient = std::move(other.mAmbient);
|
||||
mShading = std::move(other.mShading);
|
||||
mTransparency = std::move(other.mTransparency);
|
||||
mDiffuse = other.mDiffuse;
|
||||
mSpecularExponent = other.mSpecularExponent;
|
||||
mShininessStrength = other.mShininessStrength,
|
||||
mSpecular = other.mSpecular;
|
||||
mAmbient = other.mAmbient;
|
||||
mShading = other.mShading;
|
||||
mTransparency = other.mTransparency;
|
||||
sTexDiffuse = std::move(other.sTexDiffuse);
|
||||
sTexOpacity = std::move(other.sTexOpacity);
|
||||
sTexSpecular = std::move(other.sTexSpecular);
|
||||
|
@ -502,10 +502,10 @@ struct Material {
|
|||
sTexBump = std::move(other.sTexBump);
|
||||
sTexEmissive = std::move(other.sTexEmissive);
|
||||
sTexShininess = std::move(other.sTexShininess);
|
||||
mBumpHeight = std::move(other.mBumpHeight);
|
||||
mEmissive = std::move(other.mEmissive);
|
||||
mBumpHeight = other.mBumpHeight;
|
||||
mEmissive = other.mEmissive;
|
||||
sTexAmbient = std::move(other.sTexAmbient);
|
||||
mTwoSided = std::move(other.mTwoSided);
|
||||
mTwoSided = other.mTwoSided;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -208,6 +208,15 @@ protected:
|
|||
*/
|
||||
void ReplaceDefaultMaterial();
|
||||
|
||||
bool ContainsTextures(unsigned int i) const {
|
||||
return !mScene->mMaterials[i].sTexDiffuse.mMapName.empty() ||
|
||||
!mScene->mMaterials[i].sTexBump.mMapName.empty() ||
|
||||
!mScene->mMaterials[i].sTexOpacity.mMapName.empty() ||
|
||||
!mScene->mMaterials[i].sTexEmissive.mMapName.empty() ||
|
||||
!mScene->mMaterials[i].sTexSpecular.mMapName.empty() ||
|
||||
!mScene->mMaterials[i].sTexShininess.mMapName.empty() ;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Convert the whole scene
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2021, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <assimp/vector3.h>
|
||||
#include <assimp/matrix4x4.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
struct aiMaterial;
|
||||
struct aiMesh;
|
||||
|
||||
namespace Assimp {
|
||||
namespace D3MF {
|
||||
|
||||
enum class ResourceType {
|
||||
RT_Object,
|
||||
RT_BaseMaterials,
|
||||
RT_EmbeddedTexture2D,
|
||||
RT_Texture2DGroup,
|
||||
RT_Unknown
|
||||
}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
|
||||
|
||||
class Resource {
|
||||
public:
|
||||
int mId;
|
||||
|
||||
Resource(int id) :
|
||||
mId(id) {
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ~Resource() {
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ResourceType getType() const {
|
||||
return ResourceType::RT_Unknown;
|
||||
}
|
||||
};
|
||||
|
||||
class EmbeddedTexture : public Resource {
|
||||
public:
|
||||
std::string mPath;
|
||||
std::string mContentType;
|
||||
std::string mTilestyleU;
|
||||
std::string mTilestyleV;
|
||||
std::vector<char> mBuffer;
|
||||
|
||||
EmbeddedTexture(int id) :
|
||||
Resource(id),
|
||||
mPath(),
|
||||
mContentType(),
|
||||
mTilestyleU(),
|
||||
mTilestyleV() {
|
||||
// empty
|
||||
}
|
||||
|
||||
~EmbeddedTexture() = default;
|
||||
|
||||
ResourceType getType() const override {
|
||||
return ResourceType::RT_EmbeddedTexture2D;
|
||||
}
|
||||
};
|
||||
|
||||
class Texture2DGroup : public Resource {
|
||||
public:
|
||||
std::vector<aiVector2D> mTex2dCoords;
|
||||
int mTexId;
|
||||
Texture2DGroup(int id) :
|
||||
Resource(id),
|
||||
mTexId(-1) {
|
||||
// empty
|
||||
}
|
||||
|
||||
~Texture2DGroup() = default;
|
||||
|
||||
ResourceType getType() const override {
|
||||
return ResourceType::RT_Texture2DGroup;
|
||||
}
|
||||
};
|
||||
|
||||
class BaseMaterials : public Resource {
|
||||
public:
|
||||
std::vector<unsigned int> mMaterialIndex;
|
||||
|
||||
BaseMaterials(int id) :
|
||||
Resource(id),
|
||||
mMaterialIndex() {
|
||||
// empty
|
||||
}
|
||||
|
||||
~BaseMaterials() = default;
|
||||
|
||||
ResourceType getType() const override {
|
||||
return ResourceType::RT_BaseMaterials;
|
||||
}
|
||||
};
|
||||
|
||||
struct Component {
|
||||
int mObjectId;
|
||||
aiMatrix4x4 mTransformation;
|
||||
};
|
||||
|
||||
class Object : public Resource {
|
||||
public:
|
||||
std::vector<aiMesh *> mMeshes;
|
||||
std::vector<unsigned int> mMeshIndex;
|
||||
std::vector<Component> mComponents;
|
||||
std::string mName;
|
||||
|
||||
Object(int id) :
|
||||
Resource(id),
|
||||
mName(std::string("Object_") + ai_to_string(id)) {
|
||||
// empty
|
||||
}
|
||||
|
||||
~Object() = default;
|
||||
|
||||
ResourceType getType() const override {
|
||||
return ResourceType::RT_Object;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace D3MF
|
||||
} // namespace Assimp
|
|
@ -80,13 +80,21 @@ namespace XmlTag {
|
|||
const char* const item = "item";
|
||||
const char* const objectid = "objectid";
|
||||
const char* const transform = "transform";
|
||||
const char *const path = "path";
|
||||
|
||||
// Material definitions
|
||||
const char* const basematerials = "basematerials";
|
||||
const char* const basematerials_id = "id";
|
||||
const char* const basematerials_base = "base";
|
||||
const char* const basematerials_name = "name";
|
||||
const char* const basematerials_displaycolor = "displaycolor";
|
||||
const char* const texture_2d = "m:texture2d";
|
||||
const char *const texture_group = "m:texture2dgroup";
|
||||
const char *const texture_content_type = "contenttype";
|
||||
const char *const texture_tilestyleu = "tilestyleu";
|
||||
const char *const texture_tilestylev = "tilestylev";
|
||||
const char *const texture_2d_coord = "m:tex2coord";
|
||||
const char *const texture_cuurd_u = "u";
|
||||
const char *const texture_cuurd_v = "v";
|
||||
|
||||
// Meta info tags
|
||||
const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
|
||||
|
@ -103,7 +111,7 @@ namespace XmlTag {
|
|||
const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
|
||||
const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
|
||||
const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
|
||||
}
|
||||
}
|
||||
|
||||
} // Namespace D3MF
|
||||
} // Namespace Assimp
|
||||
|
|
|
@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "D3MFImporter.h"
|
||||
#include "3MFXmlTags.h"
|
||||
#include "D3MFOpcPackage.h"
|
||||
#include "XmlSerializer.h"
|
||||
|
||||
#include <assimp/StringComparison.h>
|
||||
#include <assimp/StringUtils.h>
|
||||
|
@ -61,513 +62,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace Assimp {
|
||||
namespace D3MF {
|
||||
|
||||
enum class ResourceType {
|
||||
RT_Object,
|
||||
RT_BaseMaterials,
|
||||
RT_Unknown
|
||||
}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
|
||||
|
||||
class Resource {
|
||||
public:
|
||||
int mId;
|
||||
|
||||
Resource(int id) :
|
||||
mId(id) {
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ~Resource() {
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ResourceType getType() const {
|
||||
return ResourceType::RT_Unknown;
|
||||
}
|
||||
};
|
||||
|
||||
class BaseMaterials : public Resource {
|
||||
public:
|
||||
std::vector<aiMaterial *> mMaterials;
|
||||
std::vector<unsigned int> mMaterialIndex;
|
||||
|
||||
BaseMaterials(int id) :
|
||||
Resource(id),
|
||||
mMaterials(),
|
||||
mMaterialIndex() {
|
||||
// empty
|
||||
}
|
||||
|
||||
~BaseMaterials() = default;
|
||||
|
||||
ResourceType getType() const override {
|
||||
return ResourceType::RT_BaseMaterials;
|
||||
}
|
||||
};
|
||||
|
||||
struct Component {
|
||||
int mObjectId;
|
||||
aiMatrix4x4 mTransformation;
|
||||
};
|
||||
|
||||
class Object : public Resource {
|
||||
public:
|
||||
std::vector<aiMesh *> mMeshes;
|
||||
std::vector<unsigned int> mMeshIndex;
|
||||
std::vector<Component> mComponents;
|
||||
std::string mName;
|
||||
|
||||
Object(int id) :
|
||||
Resource(id),
|
||||
mName(std::string("Object_") + ai_to_string(id)) {
|
||||
// empty
|
||||
}
|
||||
|
||||
~Object() = default;
|
||||
|
||||
ResourceType getType() const override {
|
||||
return ResourceType::RT_Object;
|
||||
}
|
||||
};
|
||||
|
||||
class XmlSerializer {
|
||||
public:
|
||||
XmlSerializer(XmlParser *xmlParser) :
|
||||
mResourcesDictionnary(),
|
||||
mMaterialCount(0),
|
||||
mMeshCount(0),
|
||||
mXmlParser(xmlParser) {
|
||||
// empty
|
||||
}
|
||||
|
||||
~XmlSerializer() {
|
||||
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) {
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void ImportXml(aiScene *scene) {
|
||||
if (nullptr == scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene->mRootNode = new aiNode(XmlTag::RootTag);
|
||||
|
||||
XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
|
||||
if (node.empty()) {
|
||||
return;
|
||||
}
|
||||
XmlNode resNode = node.child(XmlTag::resources);
|
||||
for (auto ¤tNode : resNode.children()) {
|
||||
const std::string currentNodeName = currentNode.name();
|
||||
if (currentNodeName == XmlTag::object) {
|
||||
ReadObject(currentNode);
|
||||
} else if (currentNodeName == XmlTag::basematerials) {
|
||||
ReadBaseMaterials(currentNode);
|
||||
} else if (currentNodeName == XmlTag::meta) {
|
||||
ReadMetadata(currentNode);
|
||||
}
|
||||
}
|
||||
|
||||
XmlNode buildNode = node.child(XmlTag::build);
|
||||
for (auto ¤tNode : buildNode.children()) {
|
||||
const std::string currentNodeName = currentNode.name();
|
||||
if (currentNodeName == XmlTag::item) {
|
||||
int objectId = -1;
|
||||
std::string transformationMatrixStr;
|
||||
aiMatrix4x4 transformationMatrix;
|
||||
getNodeAttribute(currentNode, D3MF::XmlTag::objectid, objectId);
|
||||
bool hasTransform = getNodeAttribute(currentNode, D3MF::XmlTag::transform, transformationMatrixStr);
|
||||
|
||||
auto it = mResourcesDictionnary.find(objectId);
|
||||
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
|
||||
Object *obj = static_cast<Object *>(it->second);
|
||||
if (hasTransform) {
|
||||
transformationMatrix = parseTransformMatrix(transformationMatrixStr);
|
||||
}
|
||||
|
||||
addObjectToNode(scene->mRootNode, obj, transformationMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// import the metadata
|
||||
if (!mMetaData.empty()) {
|
||||
const size_t numMeta = mMetaData.size();
|
||||
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
|
||||
for (size_t i = 0; i < numMeta; ++i) {
|
||||
aiString val(mMetaData[i].value);
|
||||
scene->mMetaData->Set(static_cast<unsigned int>(i), mMetaData[i].name, val);
|
||||
}
|
||||
}
|
||||
|
||||
// import the meshes
|
||||
scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
|
||||
if (scene->mNumMeshes != 0) {
|
||||
scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
|
||||
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
|
||||
if (it->second->getType() == ResourceType::RT_Object) {
|
||||
Object *obj = static_cast<Object *>(it->second);
|
||||
ai_assert(nullptr != obj);
|
||||
for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
|
||||
scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// import the materials
|
||||
scene->mNumMaterials = mMaterialCount;
|
||||
if (scene->mNumMaterials != 0) {
|
||||
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
|
||||
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
|
||||
if (it->second->getType() == ResourceType::RT_BaseMaterials) {
|
||||
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
|
||||
for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
|
||||
scene->mMaterials[baseMaterials->mMaterialIndex[i]] = baseMaterials->mMaterials[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
|
||||
ai_assert(nullptr != obj);
|
||||
|
||||
aiNode *sceneNode = new aiNode(obj->mName);
|
||||
sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
|
||||
sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
|
||||
std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
|
||||
|
||||
sceneNode->mTransformation = nodeTransform;
|
||||
if (nullptr != parent) {
|
||||
parent->addChildren(1, &sceneNode);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < obj->mComponents.size(); ++i) {
|
||||
Component c = obj->mComponents[i];
|
||||
auto it = mResourcesDictionnary.find(c.mObjectId);
|
||||
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
|
||||
addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
|
||||
pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
|
||||
if (!objectAttribute.empty()) {
|
||||
value = objectAttribute.as_string();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
|
||||
std::string strValue;
|
||||
bool ret = getNodeAttribute(node, attribute, strValue);
|
||||
if (ret) {
|
||||
value = std::atoi(strValue.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
|
||||
// split the string
|
||||
std::vector<float> numbers;
|
||||
std::string currentNumber;
|
||||
for (size_t i = 0; i < matrixStr.size(); ++i) {
|
||||
const char c = matrixStr[i];
|
||||
if (c == ' ') {
|
||||
if (currentNumber.size() > 0) {
|
||||
float f = std::stof(currentNumber);
|
||||
numbers.push_back(f);
|
||||
currentNumber.clear();
|
||||
}
|
||||
} else {
|
||||
currentNumber.push_back(c);
|
||||
}
|
||||
}
|
||||
if (currentNumber.size() > 0) {
|
||||
const float f = std::stof(currentNumber);
|
||||
numbers.push_back(f);
|
||||
}
|
||||
|
||||
aiMatrix4x4 transformMatrix;
|
||||
transformMatrix.a1 = numbers[0];
|
||||
transformMatrix.b1 = numbers[1];
|
||||
transformMatrix.c1 = numbers[2];
|
||||
transformMatrix.d1 = 0;
|
||||
|
||||
transformMatrix.a2 = numbers[3];
|
||||
transformMatrix.b2 = numbers[4];
|
||||
transformMatrix.c2 = numbers[5];
|
||||
transformMatrix.d2 = 0;
|
||||
|
||||
transformMatrix.a3 = numbers[6];
|
||||
transformMatrix.b3 = numbers[7];
|
||||
transformMatrix.c3 = numbers[8];
|
||||
transformMatrix.d3 = 0;
|
||||
|
||||
transformMatrix.a4 = numbers[9];
|
||||
transformMatrix.b4 = numbers[10];
|
||||
transformMatrix.c4 = numbers[11];
|
||||
transformMatrix.d4 = 1;
|
||||
|
||||
return transformMatrix;
|
||||
}
|
||||
|
||||
void ReadObject(XmlNode &node) {
|
||||
int id = -1, pid = -1, pindex = -1;
|
||||
bool hasId = getNodeAttribute(node, XmlTag::id, id);
|
||||
bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
|
||||
bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
|
||||
if (!hasId) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object *obj = new Object(id);
|
||||
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string ¤tName = currentNode.name();
|
||||
if (currentName == D3MF::XmlTag::mesh) {
|
||||
auto mesh = ReadMesh(currentNode);
|
||||
mesh->mName.Set(ai_to_string(id));
|
||||
|
||||
if (hasPid) {
|
||||
auto it = mResourcesDictionnary.find(pid);
|
||||
if (hasPindex && it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_BaseMaterials) {
|
||||
BaseMaterials *materials = static_cast<BaseMaterials *>(it->second);
|
||||
mesh->mMaterialIndex = materials->mMaterialIndex[pindex];
|
||||
}
|
||||
}
|
||||
|
||||
obj->mMeshes.push_back(mesh);
|
||||
obj->mMeshIndex.push_back(mMeshCount);
|
||||
mMeshCount++;
|
||||
} else if (currentName == D3MF::XmlTag::components) {
|
||||
for (XmlNode ¤tSubNode : currentNode.children()) {
|
||||
const std::string subNodeName = currentSubNode.name();
|
||||
if (subNodeName == D3MF::XmlTag::component) {
|
||||
int objectId = -1;
|
||||
std::string componentTransformStr;
|
||||
aiMatrix4x4 componentTransform;
|
||||
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::transform, componentTransformStr)) {
|
||||
componentTransform = parseTransformMatrix(componentTransformStr);
|
||||
}
|
||||
|
||||
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
|
||||
obj->mComponents.push_back({ objectId, componentTransform });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mResourcesDictionnary.insert(std::make_pair(id, obj));
|
||||
}
|
||||
|
||||
aiMesh *ReadMesh(XmlNode &node) {
|
||||
aiMesh *mesh = new aiMesh();
|
||||
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
if (currentName == XmlTag::vertices) {
|
||||
ImportVertices(currentNode, mesh);
|
||||
} else if (currentName == XmlTag::triangles) {
|
||||
ImportTriangles(currentNode, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void ReadMetadata(XmlNode &node) {
|
||||
pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
|
||||
const std::string name = attribute.as_string();
|
||||
const std::string value = node.value();
|
||||
if (name.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MetaEntry entry;
|
||||
entry.name = name;
|
||||
entry.value = value;
|
||||
mMetaData.push_back(entry);
|
||||
}
|
||||
|
||||
void ImportVertices(XmlNode &node, aiMesh *mesh) {
|
||||
std::vector<aiVector3D> vertices;
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
if (currentName == XmlTag::vertex) {
|
||||
vertices.push_back(ReadVertex(currentNode));
|
||||
}
|
||||
}
|
||||
|
||||
mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
|
||||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||
std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
|
||||
}
|
||||
|
||||
aiVector3D ReadVertex(XmlNode &node) {
|
||||
aiVector3D vertex;
|
||||
vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
|
||||
vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
|
||||
vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
|
||||
|
||||
return vertex;
|
||||
}
|
||||
|
||||
void ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||
std::vector<aiFace> faces;
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
if (currentName == XmlTag::triangle) {
|
||||
aiFace face = ReadTriangle(currentNode);
|
||||
faces.push_back(face);
|
||||
|
||||
int pid = 0, p1 = 0;
|
||||
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
|
||||
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
|
||||
|
||||
if (hasPid && hasP1) {
|
||||
auto it = mResourcesDictionnary.find(pid);
|
||||
if (it != mResourcesDictionnary.end()) {
|
||||
if (it->second->getType() == ResourceType::RT_BaseMaterials) {
|
||||
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
|
||||
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
|
||||
}
|
||||
// TODO: manage the separation into several meshes if the triangles of the mesh do not all refer to the same material
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mesh->mNumFaces = static_cast<unsigned int>(faces.size());
|
||||
mesh->mFaces = new aiFace[mesh->mNumFaces];
|
||||
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||
|
||||
std::copy(faces.begin(), faces.end(), mesh->mFaces);
|
||||
}
|
||||
|
||||
aiFace ReadTriangle(XmlNode &node) {
|
||||
aiFace face;
|
||||
|
||||
face.mNumIndices = 3;
|
||||
face.mIndices = new unsigned int[face.mNumIndices];
|
||||
face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
|
||||
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
|
||||
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
void ReadBaseMaterials(XmlNode &node) {
|
||||
int id = -1;
|
||||
if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
|
||||
BaseMaterials *baseMaterials = new BaseMaterials(id);
|
||||
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
if (currentName == XmlTag::basematerials_base) {
|
||||
baseMaterials->mMaterialIndex.push_back(mMaterialCount);
|
||||
baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
|
||||
++mMaterialCount;
|
||||
}
|
||||
}
|
||||
|
||||
mResourcesDictionnary.insert(std::make_pair(id, baseMaterials));
|
||||
}
|
||||
}
|
||||
|
||||
bool parseColor(const char *color, aiColor4D &diffuse) {
|
||||
if (nullptr == color) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
|
||||
const size_t len = strlen(color);
|
||||
if (9 != len && 7 != len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *buf(color);
|
||||
if ('#' != buf[0]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char r[3] = { buf[1], buf[2], '\0' };
|
||||
diffuse.r = static_cast<ai_real>(strtol(r, nullptr, 16)) / ai_real(255.0);
|
||||
|
||||
char g[3] = { buf[3], buf[4], '\0' };
|
||||
diffuse.g = static_cast<ai_real>(strtol(g, nullptr, 16)) / ai_real(255.0);
|
||||
|
||||
char b[3] = { buf[5], buf[6], '\0' };
|
||||
diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
|
||||
|
||||
if (7 == len)
|
||||
return true;
|
||||
|
||||
char a[3] = { buf[7], buf[8], '\0' };
|
||||
diffuse.a = static_cast<ai_real>(strtol(a, nullptr, 16)) / ai_real(255.0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
|
||||
const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
|
||||
aiColor4D diffuse;
|
||||
if (parseColor(color, diffuse)) {
|
||||
mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
}
|
||||
}
|
||||
|
||||
aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId) {
|
||||
aiMaterial *material = new aiMaterial();
|
||||
material->mNumProperties = 0;
|
||||
std::string name;
|
||||
bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
|
||||
|
||||
std::string stdMaterialName;
|
||||
const std::string strId(ai_to_string(basematerialsId));
|
||||
stdMaterialName += "id";
|
||||
stdMaterialName += strId;
|
||||
stdMaterialName += "_";
|
||||
if (hasName) {
|
||||
stdMaterialName += std::string(name);
|
||||
} else {
|
||||
stdMaterialName += "basemat_";
|
||||
stdMaterialName += ai_to_string(mMaterialCount - basematerialsId);
|
||||
}
|
||||
|
||||
aiString assimpMaterialName(stdMaterialName);
|
||||
material->AddProperty(&assimpMaterialName, AI_MATKEY_NAME);
|
||||
|
||||
assignDiffuseColor(node, material);
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
private:
|
||||
struct MetaEntry {
|
||||
std::string name;
|
||||
std::string value;
|
||||
};
|
||||
std::vector<MetaEntry> mMetaData;
|
||||
std::map<unsigned int, Resource *> mResourcesDictionnary;
|
||||
unsigned int mMaterialCount, mMeshCount;
|
||||
XmlParser *mXmlParser;
|
||||
};
|
||||
|
||||
} //namespace D3MF
|
||||
|
||||
using namespace D3MF;
|
||||
|
||||
|
@ -597,7 +94,9 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
|
|||
const std::string extension(GetExtension(filename));
|
||||
if (extension == desc.mFileExtensions) {
|
||||
return true;
|
||||
} else if (!extension.length() || checkSig) {
|
||||
}
|
||||
|
||||
if (!extension.length() || checkSig) {
|
||||
if (nullptr == pIOHandler) {
|
||||
return false;
|
||||
}
|
||||
|
@ -611,7 +110,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
|
|||
return false;
|
||||
}
|
||||
|
||||
void D3MFImporter::SetupProperties(const Importer * /*pImp*/) {
|
||||
void D3MFImporter::SetupProperties(const Importer*) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -626,6 +125,15 @@ void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene,
|
|||
if (xmlParser.parse(opcPackage.RootStream())) {
|
||||
XmlSerializer xmlSerializer(&xmlParser);
|
||||
xmlSerializer.ImportXml(pScene);
|
||||
|
||||
const std::vector<aiTexture*> &tex = opcPackage.GetEmbeddedTextures();
|
||||
if (!tex.empty()) {
|
||||
pScene->mNumTextures = static_cast<unsigned int>(tex.size());
|
||||
pScene->mTextures = new aiTexture *[pScene->mNumTextures];
|
||||
for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {
|
||||
pScene->mTextures[i] = tex[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2021, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
@ -47,17 +46,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/// @brief The 3MF-importer class.
|
||||
///
|
||||
/// Implements the basic topology import and embedded textures.
|
||||
// ---------------------------------------------------------------------------
|
||||
class D3MFImporter : public BaseImporter {
|
||||
public:
|
||||
/// @brief The default class constructor.
|
||||
D3MFImporter();
|
||||
~D3MFImporter();
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
|
||||
void SetupProperties(const Importer *pImp);
|
||||
const aiImporterDesc *GetInfo() const;
|
||||
|
||||
/// @brief The class destructor.
|
||||
~D3MFImporter() override;
|
||||
|
||||
/// @brief Performs the data format detection.
|
||||
/// @param pFile The filename to check.
|
||||
/// @param pIOHandler The used IO-System.
|
||||
/// @param checkSig true for signature checking.
|
||||
/// @return true for can be loaded, false for not.
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
|
||||
|
||||
/// @brief Not used
|
||||
/// @param pImp Not used
|
||||
void SetupProperties(const Importer *pImp) override;
|
||||
|
||||
/// @brief The importer description getter.
|
||||
/// @return The info
|
||||
const aiImporterDesc *GetInfo() const override;
|
||||
|
||||
protected:
|
||||
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
|
||||
/// @brief Internal read function, performs the file parsing.
|
||||
/// @param pFile The filename
|
||||
/// @param pScene The scene to load in.
|
||||
/// @param pIOHandler The io-system
|
||||
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
|
||||
};
|
||||
|
||||
} // Namespace Assimp
|
||||
|
|
|
@ -43,14 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "D3MFOpcPackage.h"
|
||||
#include <assimp/Exceptional.h>
|
||||
|
||||
#include <assimp/XmlParser.h>
|
||||
#include <assimp/ZipArchiveIOSystem.h>
|
||||
#include <assimp/ai_assert.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/IOStream.hpp>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
|
||||
#include <assimp/texture.h>
|
||||
#include "3MFXmlTags.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
@ -64,11 +63,12 @@ namespace Assimp {
|
|||
namespace D3MF {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
|
||||
using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
|
||||
|
||||
class OpcPackageRelationshipReader {
|
||||
public:
|
||||
OpcPackageRelationshipReader(XmlParser &parser) {
|
||||
OpcPackageRelationshipReader(XmlParser &parser) :
|
||||
m_relationShips() {
|
||||
XmlNode root = parser.getRootNode();
|
||||
ParseRootNode(root);
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ public:
|
|||
if (relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -100,7 +101,7 @@ public:
|
|||
}
|
||||
|
||||
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
||||
std::string name = currentNode.name();
|
||||
const std::string name = currentNode.name();
|
||||
if (name == "Relationship") {
|
||||
OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
|
||||
relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string();
|
||||
|
@ -116,11 +117,23 @@ public:
|
|||
std::vector<OpcPackageRelationshipPtr> m_relationShips;
|
||||
};
|
||||
|
||||
static bool IsEmbeddedTexture( const std::string &filename ) {
|
||||
const std::string extension = BaseImporter::GetExtension(filename);
|
||||
if (extension == "jpg" || extension == "png") {
|
||||
std::string::size_type pos = filename.find("thumbnail");
|
||||
if (pos == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
||||
mRootStream(nullptr),
|
||||
mZipArchive() {
|
||||
mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile));
|
||||
mZipArchive = new ZipArchiveIOSystem(pIOHandler, rFile);
|
||||
if (!mZipArchive->isOpen()) {
|
||||
throw DeadlyImportError("Failed to open file ", rFile, ".");
|
||||
}
|
||||
|
@ -141,7 +154,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
|||
}
|
||||
|
||||
std::string rootFile = ReadPackageRootRelationship(fileStream);
|
||||
if (rootFile.size() > 0 && rootFile[0] == '/') {
|
||||
if (!rootFile.empty() && rootFile[0] == '/') {
|
||||
rootFile = rootFile.substr(1);
|
||||
if (rootFile[0] == '/') {
|
||||
// deal with zip-bug
|
||||
|
@ -158,9 +171,12 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
|||
if (nullptr == mRootStream) {
|
||||
throw DeadlyImportError("Cannot open root-file in archive : " + rootFile);
|
||||
}
|
||||
|
||||
} else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
|
||||
ASSIMP_LOG_WARN("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file);
|
||||
} else if (IsEmbeddedTexture(file)) {
|
||||
IOStream *fileStream = mZipArchive->Open(file.c_str());
|
||||
LoadEmbeddedTextures(fileStream, file);
|
||||
mZipArchive->Close(fileStream);
|
||||
} else {
|
||||
ASSIMP_LOG_WARN("Ignored file of unknown type: ", file);
|
||||
}
|
||||
|
@ -169,20 +185,26 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
|||
|
||||
D3MFOpcPackage::~D3MFOpcPackage() {
|
||||
mZipArchive->Close(mRootStream);
|
||||
delete mZipArchive;
|
||||
mZipArchive = nullptr;
|
||||
}
|
||||
|
||||
IOStream *D3MFOpcPackage::RootStream() const {
|
||||
return mRootStream;
|
||||
}
|
||||
|
||||
static const std::string ModelRef = "3D/3dmodel.model";
|
||||
const std::vector<aiTexture *> &D3MFOpcPackage::GetEmbeddedTextures() const {
|
||||
return mEmbeddedTextures;
|
||||
}
|
||||
|
||||
static const char *const ModelRef = "3D/3dmodel.model";
|
||||
|
||||
bool D3MFOpcPackage::validate() {
|
||||
if (nullptr == mRootStream || nullptr == mZipArchive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mZipArchive->Exists(ModelRef.c_str());
|
||||
return mZipArchive->Exists(ModelRef);
|
||||
}
|
||||
|
||||
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
|
||||
|
@ -204,6 +226,31 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
|
|||
return (*itr)->target;
|
||||
}
|
||||
|
||||
void D3MFOpcPackage::LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename) {
|
||||
if (nullptr == fileStream) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t size = fileStream->FileSize();
|
||||
if (0 == size) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char *data = new unsigned char[size];
|
||||
fileStream->Read(data, 1, size);
|
||||
aiTexture *texture = new aiTexture;
|
||||
std::string embName = "*" + filename;
|
||||
texture->mFilename.Set(embName.c_str());
|
||||
texture->mWidth = static_cast<unsigned int>(size);
|
||||
texture->mHeight = 0;
|
||||
texture->achFormatHint[0] = 'p';
|
||||
texture->achFormatHint[1] = 'n';
|
||||
texture->achFormatHint[2] = 'g';
|
||||
texture->achFormatHint[3] = '\0';
|
||||
texture->pcData = (aiTexel*) data;
|
||||
mEmbeddedTextures.emplace_back(texture);
|
||||
}
|
||||
|
||||
} // Namespace D3MF
|
||||
} // Namespace Assimp
|
||||
|
||||
|
|
|
@ -46,8 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <string>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
|
||||
struct aiTexture;
|
||||
|
||||
namespace Assimp {
|
||||
class ZipArchiveIOSystem;
|
||||
|
||||
class ZipArchiveIOSystem;
|
||||
|
||||
namespace D3MF {
|
||||
|
||||
|
@ -63,16 +66,19 @@ public:
|
|||
~D3MFOpcPackage();
|
||||
IOStream* RootStream() const;
|
||||
bool validate();
|
||||
const std::vector<aiTexture*> &GetEmbeddedTextures() const;
|
||||
|
||||
protected:
|
||||
std::string ReadPackageRootRelationship(IOStream* stream);
|
||||
void LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename);
|
||||
|
||||
private:
|
||||
IOStream* mRootStream;
|
||||
std::unique_ptr<ZipArchiveIOSystem> mZipArchive;
|
||||
ZipArchiveIOSystem *mZipArchive;
|
||||
std::vector<aiTexture *> mEmbeddedTextures;
|
||||
};
|
||||
|
||||
} // Namespace D3MF
|
||||
} // Namespace Assimp
|
||||
} // namespace D3MF
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // D3MFOPCPACKAGE_H
|
||||
|
|
|
@ -0,0 +1,594 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2021, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#include "XmlSerializer.h"
|
||||
#include "D3MFOpcPackage.h"
|
||||
#include "3MFXmlTags.h"
|
||||
#include "3MFTypes.h"
|
||||
#include <assimp/scene.h>
|
||||
|
||||
namespace Assimp {
|
||||
namespace D3MF {
|
||||
|
||||
static const int IdNotSet = -1;
|
||||
|
||||
namespace {
|
||||
|
||||
static const size_t ColRGBA_Len = 9;
|
||||
static const size_t ColRGB_Len = 7;
|
||||
|
||||
// format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
|
||||
bool validateColorString(const char *color) {
|
||||
const size_t len = strlen(color);
|
||||
if (ColRGBA_Len != len && ColRGB_Len != len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
aiFace ReadTriangle(XmlNode &node) {
|
||||
aiFace face;
|
||||
|
||||
face.mNumIndices = 3;
|
||||
face.mIndices = new unsigned int[face.mNumIndices];
|
||||
face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
|
||||
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
|
||||
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
aiVector3D ReadVertex(XmlNode &node) {
|
||||
aiVector3D vertex;
|
||||
vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
|
||||
vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
|
||||
vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
|
||||
|
||||
return vertex;
|
||||
}
|
||||
|
||||
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
|
||||
pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
|
||||
if (!objectAttribute.empty()) {
|
||||
value = objectAttribute.as_string();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
|
||||
std::string strValue;
|
||||
const bool ret = getNodeAttribute(node, attribute, strValue);
|
||||
if (ret) {
|
||||
value = std::atoi(strValue.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
|
||||
// split the string
|
||||
std::vector<float> numbers;
|
||||
std::string currentNumber;
|
||||
for (char c : matrixStr) {
|
||||
if (c == ' ') {
|
||||
if (!currentNumber.empty()) {
|
||||
float f = std::stof(currentNumber);
|
||||
numbers.push_back(f);
|
||||
currentNumber.clear();
|
||||
}
|
||||
} else {
|
||||
currentNumber.push_back(c);
|
||||
}
|
||||
}
|
||||
if (!currentNumber.empty()) {
|
||||
const float f = std::stof(currentNumber);
|
||||
numbers.push_back(f);
|
||||
}
|
||||
|
||||
aiMatrix4x4 transformMatrix;
|
||||
transformMatrix.a1 = numbers[0];
|
||||
transformMatrix.b1 = numbers[1];
|
||||
transformMatrix.c1 = numbers[2];
|
||||
transformMatrix.d1 = 0;
|
||||
|
||||
transformMatrix.a2 = numbers[3];
|
||||
transformMatrix.b2 = numbers[4];
|
||||
transformMatrix.c2 = numbers[5];
|
||||
transformMatrix.d2 = 0;
|
||||
|
||||
transformMatrix.a3 = numbers[6];
|
||||
transformMatrix.b3 = numbers[7];
|
||||
transformMatrix.c3 = numbers[8];
|
||||
transformMatrix.d3 = 0;
|
||||
|
||||
transformMatrix.a4 = numbers[9];
|
||||
transformMatrix.b4 = numbers[10];
|
||||
transformMatrix.c4 = numbers[11];
|
||||
transformMatrix.d4 = 1;
|
||||
|
||||
return transformMatrix;
|
||||
}
|
||||
|
||||
bool parseColor(const char *color, aiColor4D &diffuse) {
|
||||
if (nullptr == color) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validateColorString(color)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//const char *buf(color);
|
||||
if ('#' != color[0]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char r[3] = { color[1], color[2], '\0' };
|
||||
diffuse.r = static_cast<ai_real>(strtol(r, nullptr, 16)) / ai_real(255.0);
|
||||
|
||||
char g[3] = { color[3], color[4], '\0' };
|
||||
diffuse.g = static_cast<ai_real>(strtol(g, nullptr, 16)) / ai_real(255.0);
|
||||
|
||||
char b[3] = { color[5], color[6], '\0' };
|
||||
diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
|
||||
const size_t len = strlen(color);
|
||||
if (ColRGB_Len == len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char a[3] = { color[7], color[8], '\0' };
|
||||
diffuse.a = static_cast<ai_real>(strtol(a, nullptr, 16)) / ai_real(255.0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
|
||||
const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
|
||||
aiColor4D diffuse;
|
||||
if (parseColor(color, diffuse)) {
|
||||
mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
XmlSerializer::XmlSerializer(XmlParser *xmlParser) :
|
||||
mResourcesDictionnary(),
|
||||
mMeshCount(0),
|
||||
mXmlParser(xmlParser) {
|
||||
ai_assert(nullptr != xmlParser);
|
||||
}
|
||||
|
||||
XmlSerializer::~XmlSerializer() {
|
||||
for (auto &it : mResourcesDictionnary) {
|
||||
delete it.second;
|
||||
}
|
||||
}
|
||||
|
||||
void XmlSerializer::ImportXml(aiScene *scene) {
|
||||
if (nullptr == scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene->mRootNode = new aiNode(XmlTag::RootTag);
|
||||
XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
|
||||
if (node.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
XmlNode resNode = node.child(XmlTag::resources);
|
||||
for (auto ¤tNode : resNode.children()) {
|
||||
const std::string currentNodeName = currentNode.name();
|
||||
if (currentNodeName == XmlTag::texture_2d) {
|
||||
ReadEmbeddecTexture(currentNode);
|
||||
} else if (currentNodeName == XmlTag::texture_group) {
|
||||
ReadTextureGroup(currentNode);
|
||||
} else if (currentNodeName == XmlTag::object) {
|
||||
ReadObject(currentNode);
|
||||
} else if (currentNodeName == XmlTag::basematerials) {
|
||||
ReadBaseMaterials(currentNode);
|
||||
} else if (currentNodeName == XmlTag::meta) {
|
||||
ReadMetadata(currentNode);
|
||||
}
|
||||
}
|
||||
StoreMaterialsInScene(scene);
|
||||
XmlNode buildNode = node.child(XmlTag::build);
|
||||
if (buildNode.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto ¤tNode : buildNode.children()) {
|
||||
const std::string currentNodeName = currentNode.name();
|
||||
if (currentNodeName == XmlTag::item) {
|
||||
int objectId = IdNotSet;
|
||||
std::string transformationMatrixStr;
|
||||
aiMatrix4x4 transformationMatrix;
|
||||
getNodeAttribute(currentNode, D3MF::XmlTag::objectid, objectId);
|
||||
bool hasTransform = getNodeAttribute(currentNode, D3MF::XmlTag::transform, transformationMatrixStr);
|
||||
|
||||
auto it = mResourcesDictionnary.find(objectId);
|
||||
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
|
||||
Object *obj = static_cast<Object *>(it->second);
|
||||
if (hasTransform) {
|
||||
transformationMatrix = parseTransformMatrix(transformationMatrixStr);
|
||||
}
|
||||
|
||||
addObjectToNode(scene->mRootNode, obj, transformationMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// import the metadata
|
||||
if (!mMetaData.empty()) {
|
||||
const size_t numMeta = mMetaData.size();
|
||||
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
|
||||
for (size_t i = 0; i < numMeta; ++i) {
|
||||
aiString val(mMetaData[i].value);
|
||||
scene->mMetaData->Set(static_cast<unsigned int>(i), mMetaData[i].name, val);
|
||||
}
|
||||
}
|
||||
|
||||
// import the meshes, materials are already stored
|
||||
scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
|
||||
if (scene->mNumMeshes != 0) {
|
||||
scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
|
||||
for (auto &it : mResourcesDictionnary) {
|
||||
if (it.second->getType() == ResourceType::RT_Object) {
|
||||
Object *obj = static_cast<Object *>(it.second);
|
||||
ai_assert(nullptr != obj);
|
||||
for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
|
||||
scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XmlSerializer::addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
|
||||
ai_assert(nullptr != obj);
|
||||
|
||||
aiNode *sceneNode = new aiNode(obj->mName);
|
||||
sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
|
||||
sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
|
||||
std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
|
||||
|
||||
sceneNode->mTransformation = nodeTransform;
|
||||
if (nullptr != parent) {
|
||||
parent->addChildren(1, &sceneNode);
|
||||
}
|
||||
|
||||
for (Assimp::D3MF::Component c : obj->mComponents) {
|
||||
auto it = mResourcesDictionnary.find(c.mObjectId);
|
||||
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
|
||||
addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XmlSerializer::ReadObject(XmlNode &node) {
|
||||
int id = IdNotSet, pid = IdNotSet, pindex = IdNotSet;
|
||||
bool hasId = getNodeAttribute(node, XmlTag::id, id);
|
||||
if (!hasId) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
|
||||
bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
|
||||
|
||||
Object *obj = new Object(id);
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
if (currentName == D3MF::XmlTag::mesh) {
|
||||
auto mesh = ReadMesh(currentNode);
|
||||
mesh->mName.Set(ai_to_string(id));
|
||||
|
||||
if (hasPid) {
|
||||
auto it = mResourcesDictionnary.find(pid);
|
||||
if (hasPindex && it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_BaseMaterials) {
|
||||
BaseMaterials *materials = static_cast<BaseMaterials *>(it->second);
|
||||
mesh->mMaterialIndex = materials->mMaterialIndex[pindex];
|
||||
}
|
||||
}
|
||||
|
||||
obj->mMeshes.push_back(mesh);
|
||||
obj->mMeshIndex.push_back(mMeshCount);
|
||||
mMeshCount++;
|
||||
} else if (currentName == D3MF::XmlTag::components) {
|
||||
for (XmlNode ¤tSubNode : currentNode.children()) {
|
||||
const std::string subNodeName = currentSubNode.name();
|
||||
if (subNodeName == D3MF::XmlTag::component) {
|
||||
int objectId = IdNotSet;
|
||||
std::string componentTransformStr;
|
||||
aiMatrix4x4 componentTransform;
|
||||
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::transform, componentTransformStr)) {
|
||||
componentTransform = parseTransformMatrix(componentTransformStr);
|
||||
}
|
||||
|
||||
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
|
||||
obj->mComponents.push_back({ objectId, componentTransform });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mResourcesDictionnary.insert(std::make_pair(id, obj));
|
||||
}
|
||||
|
||||
aiMesh *XmlSerializer::ReadMesh(XmlNode &node) {
|
||||
if (node.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
aiMesh *mesh = new aiMesh();
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
if (currentName == XmlTag::vertices) {
|
||||
ImportVertices(currentNode, mesh);
|
||||
} else if (currentName == XmlTag::triangles) {
|
||||
ImportTriangles(currentNode, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void XmlSerializer::ReadMetadata(XmlNode &node) {
|
||||
pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
|
||||
const std::string name = attribute.as_string();
|
||||
const std::string value = node.value();
|
||||
if (name.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MetaEntry entry;
|
||||
entry.name = name;
|
||||
entry.value = value;
|
||||
mMetaData.push_back(entry);
|
||||
}
|
||||
|
||||
void XmlSerializer::ImportVertices(XmlNode &node, aiMesh *mesh) {
|
||||
ai_assert(nullptr != mesh);
|
||||
|
||||
std::vector<aiVector3D> vertices;
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
if (currentName == XmlTag::vertex) {
|
||||
vertices.push_back(ReadVertex(currentNode));
|
||||
}
|
||||
}
|
||||
|
||||
mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
|
||||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||
std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
|
||||
}
|
||||
|
||||
void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||
std::vector<aiFace> faces;
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
if (currentName == XmlTag::triangle) {
|
||||
int pid = IdNotSet, p1 = IdNotSet;
|
||||
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
|
||||
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
|
||||
|
||||
if (hasPid && hasP1) {
|
||||
auto it = mResourcesDictionnary.find(pid);
|
||||
if (it != mResourcesDictionnary.end()) {
|
||||
if (it->second->getType() == ResourceType::RT_BaseMaterials) {
|
||||
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
|
||||
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
|
||||
} else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
|
||||
if (mesh->mTextureCoords[0] == nullptr) {
|
||||
Texture2DGroup *group = static_cast<Texture2DGroup *>(it->second);
|
||||
const std::string name = ai_to_string(group->mTexId);
|
||||
for (size_t i = 0; i < mMaterials.size(); ++i) {
|
||||
if (name == mMaterials[i]->GetName().C_Str()) {
|
||||
mesh->mMaterialIndex = static_cast<unsigned int>(i);
|
||||
}
|
||||
}
|
||||
mesh->mTextureCoords[0] = new aiVector3D[group->mTex2dCoords.size()];
|
||||
for (unsigned int i = 0; i < group->mTex2dCoords.size(); ++i) {
|
||||
mesh->mTextureCoords[0][i] = aiVector3D(group->mTex2dCoords[i].x, group->mTex2dCoords[i].y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiFace face = ReadTriangle(currentNode);
|
||||
faces.push_back(face);
|
||||
}
|
||||
}
|
||||
|
||||
mesh->mNumFaces = static_cast<unsigned int>(faces.size());
|
||||
mesh->mFaces = new aiFace[mesh->mNumFaces];
|
||||
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||
|
||||
std::copy(faces.begin(), faces.end(), mesh->mFaces);
|
||||
}
|
||||
|
||||
void XmlSerializer::ReadBaseMaterials(XmlNode &node) {
|
||||
int id = IdNotSet;
|
||||
if (getNodeAttribute(node, D3MF::XmlTag::id, id)) {
|
||||
BaseMaterials *baseMaterials = new BaseMaterials(id);
|
||||
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
if (currentName == XmlTag::basematerials_base) {
|
||||
baseMaterials->mMaterialIndex.push_back(static_cast<unsigned int>(mMaterials.size()));
|
||||
mMaterials.push_back(readMaterialDef(currentNode, id));
|
||||
}
|
||||
}
|
||||
|
||||
mResourcesDictionnary.insert(std::make_pair(id, baseMaterials));
|
||||
}
|
||||
}
|
||||
|
||||
void XmlSerializer::ReadEmbeddecTexture(XmlNode &node) {
|
||||
if (node.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string value;
|
||||
EmbeddedTexture *tex2D = nullptr;
|
||||
if (XmlParser::getStdStrAttribute(node, XmlTag::id, value)) {
|
||||
tex2D = new EmbeddedTexture(atoi(value.c_str()));
|
||||
}
|
||||
if (nullptr == tex2D) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (XmlParser::getStdStrAttribute(node, XmlTag::path, value)) {
|
||||
tex2D->mPath = value;
|
||||
}
|
||||
if (XmlParser::getStdStrAttribute(node, XmlTag::texture_content_type, value)) {
|
||||
tex2D->mContentType = value;
|
||||
}
|
||||
if (XmlParser::getStdStrAttribute(node, XmlTag::texture_tilestyleu, value)) {
|
||||
tex2D->mTilestyleU = value;
|
||||
}
|
||||
if (XmlParser::getStdStrAttribute(node, XmlTag::texture_tilestylev, value)) {
|
||||
tex2D->mTilestyleV = value;
|
||||
}
|
||||
mEmbeddedTextures.emplace_back(tex2D);
|
||||
StoreEmbeddedTexture(tex2D);
|
||||
}
|
||||
|
||||
void XmlSerializer::StoreEmbeddedTexture(EmbeddedTexture *tex) {
|
||||
aiMaterial *mat = new aiMaterial;
|
||||
aiString s;
|
||||
s.Set(ai_to_string(tex->mId).c_str());
|
||||
mat->AddProperty(&s, AI_MATKEY_NAME);
|
||||
const std::string name = "*" + tex->mPath;
|
||||
s.Set(name);
|
||||
mat->AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
|
||||
aiColor3D col;
|
||||
mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_AMBIENT);
|
||||
mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_EMISSIVE);
|
||||
mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_SPECULAR);
|
||||
mMaterials.emplace_back(mat);
|
||||
}
|
||||
|
||||
void XmlSerializer::ReadTextureCoords2D(XmlNode &node, Texture2DGroup *tex2DGroup) {
|
||||
if (node.empty() || nullptr == tex2DGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
int id = IdNotSet;
|
||||
if (XmlParser::getIntAttribute(node, "texid", id)) {
|
||||
tex2DGroup->mTexId = id;
|
||||
}
|
||||
|
||||
double value = 0.0;
|
||||
for (XmlNode currentNode : node.children()) {
|
||||
const std::string currentName = currentNode.name();
|
||||
aiVector2D texCoord;
|
||||
if (currentName == XmlTag::texture_2d_coord) {
|
||||
XmlParser::getDoubleAttribute(currentNode, XmlTag::texture_cuurd_u, value);
|
||||
texCoord.x = (ai_real)value;
|
||||
XmlParser::getDoubleAttribute(currentNode, XmlTag::texture_cuurd_v, value);
|
||||
texCoord.y = (ai_real)value;
|
||||
tex2DGroup->mTex2dCoords.push_back(texCoord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XmlSerializer::ReadTextureGroup(XmlNode &node) {
|
||||
if (node.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int id = IdNotSet;
|
||||
if (!XmlParser::getIntAttribute(node, XmlTag::id, id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Texture2DGroup *group = new Texture2DGroup(id);
|
||||
ReadTextureCoords2D(node, group);
|
||||
mResourcesDictionnary.insert(std::make_pair(id, group));
|
||||
}
|
||||
|
||||
aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basematerialsId) {
|
||||
aiMaterial *material = new aiMaterial();
|
||||
material->mNumProperties = 0;
|
||||
std::string name;
|
||||
bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
|
||||
|
||||
std::string stdMaterialName;
|
||||
const std::string strId(ai_to_string(basematerialsId));
|
||||
stdMaterialName += "id";
|
||||
stdMaterialName += strId;
|
||||
stdMaterialName += "_";
|
||||
if (hasName) {
|
||||
stdMaterialName += std::string(name);
|
||||
} else {
|
||||
stdMaterialName += "basemat_";
|
||||
stdMaterialName += ai_to_string(mMaterials.size());
|
||||
}
|
||||
|
||||
aiString assimpMaterialName(stdMaterialName);
|
||||
material->AddProperty(&assimpMaterialName, AI_MATKEY_NAME);
|
||||
|
||||
assignDiffuseColor(node, material);
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
|
||||
if (nullptr == scene || mMaterials.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
|
||||
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
|
||||
for (size_t i = 0; i < mMaterials.size(); ++i) {
|
||||
scene->mMaterials[i] = mMaterials[i];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace D3MF
|
||||
} // namespace Assimp
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2021, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <assimp/XmlParser.h>
|
||||
#include <assimp/mesh.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
struct aiNode;
|
||||
struct aiMesh;
|
||||
struct aiMaterial;
|
||||
|
||||
namespace Assimp {
|
||||
namespace D3MF {
|
||||
|
||||
class Resource;
|
||||
class D3MFOpcPackage;
|
||||
class Object;
|
||||
class Texture2DGroup;
|
||||
class EmbeddedTexture;
|
||||
|
||||
class XmlSerializer {
|
||||
public:
|
||||
XmlSerializer(XmlParser *xmlParser);
|
||||
~XmlSerializer();
|
||||
void ImportXml(aiScene *scene);
|
||||
|
||||
private:
|
||||
void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform);
|
||||
void ReadObject(XmlNode &node);
|
||||
aiMesh *ReadMesh(XmlNode &node);
|
||||
void ReadMetadata(XmlNode &node);
|
||||
void ImportVertices(XmlNode &node, aiMesh *mesh);
|
||||
void ImportTriangles(XmlNode &node, aiMesh *mesh);
|
||||
void ReadBaseMaterials(XmlNode &node);
|
||||
void ReadEmbeddecTexture(XmlNode &node);
|
||||
void StoreEmbeddedTexture(EmbeddedTexture *tex);
|
||||
void ReadTextureCoords2D(XmlNode &node, Texture2DGroup *tex2DGroup);
|
||||
void ReadTextureGroup(XmlNode &node);
|
||||
aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId);
|
||||
void StoreMaterialsInScene(aiScene *scene);
|
||||
|
||||
private:
|
||||
struct MetaEntry {
|
||||
std::string name;
|
||||
std::string value;
|
||||
};
|
||||
std::vector<MetaEntry> mMetaData;
|
||||
std::vector<EmbeddedTexture *> mEmbeddedTextures;
|
||||
std::vector<aiMaterial *> mMaterials;
|
||||
std::map<unsigned int, Resource *> mResourcesDictionnary;
|
||||
unsigned int mMeshCount;
|
||||
XmlParser *mXmlParser;
|
||||
};
|
||||
|
||||
} // namespace D3MF
|
||||
} // namespace Assimp
|
|
@ -95,8 +95,8 @@ struct Material : public D3DS::Material {
|
|||
Material(Material &&other) AI_NO_EXCEPT
|
||||
: D3DS::Material(std::move(other)),
|
||||
avSubMaterials(std::move(other.avSubMaterials)),
|
||||
pcInstance(std::move(other.pcInstance)),
|
||||
bNeed(std::move(other.bNeed)) {
|
||||
pcInstance(other.pcInstance),
|
||||
bNeed(other.bNeed) {
|
||||
other.pcInstance = nullptr;
|
||||
}
|
||||
|
||||
|
@ -108,8 +108,8 @@ struct Material : public D3DS::Material {
|
|||
//D3DS::Material::operator=(std::move(other));
|
||||
|
||||
avSubMaterials = std::move(other.avSubMaterials);
|
||||
pcInstance = std::move(other.pcInstance);
|
||||
bNeed = std::move(other.bNeed);
|
||||
pcInstance = other.pcInstance;
|
||||
bNeed = other.bNeed;
|
||||
|
||||
other.pcInstance = nullptr;
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ inline size_t Write<aiQuaternion>(IOStream *stream, const aiQuaternion &v) {
|
|||
t += Write<float>(stream, v.z);
|
||||
ai_assert(t == 16);
|
||||
|
||||
return 16;
|
||||
return t;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
|
|
|
@ -41,12 +41,17 @@ public:
|
|||
enum {
|
||||
Flag_DoNotIndent = 0x1,
|
||||
Flag_WriteSpecialFloats = 0x2,
|
||||
Flag_SkipWhitespaces = 0x4
|
||||
};
|
||||
|
||||
JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) :
|
||||
out(out), first(), flags(flags) {
|
||||
out(out), indent (""), newline("\n"), space(" "), buff (), first(false), flags(flags) {
|
||||
// make sure that all formatting happens using the standard, C locale and not the user's current locale
|
||||
buff.imbue(std::locale("C"));
|
||||
if (flags & Flag_SkipWhitespaces) {
|
||||
newline = "";
|
||||
space = "";
|
||||
}
|
||||
}
|
||||
|
||||
~JSONWriter() {
|
||||
|
@ -70,7 +75,7 @@ public:
|
|||
void Key(const std::string &name) {
|
||||
AddIndentation();
|
||||
Delimit();
|
||||
buff << '\"' + name + "\": ";
|
||||
buff << '\"' + name + "\":" << space;
|
||||
}
|
||||
|
||||
template <typename Literal>
|
||||
|
@ -78,12 +83,12 @@ public:
|
|||
AddIndentation();
|
||||
Delimit();
|
||||
|
||||
LiteralToString(buff, name) << '\n';
|
||||
LiteralToString(buff, name) << newline;
|
||||
}
|
||||
|
||||
template <typename Literal>
|
||||
void SimpleValue(const Literal &s) {
|
||||
LiteralToString(buff, s) << '\n';
|
||||
LiteralToString(buff, s) << newline;
|
||||
}
|
||||
|
||||
void SimpleValue(const void *buffer, size_t len) {
|
||||
|
@ -102,7 +107,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
buff << '\"' << cur_out << "\"\n";
|
||||
buff << '\"' << cur_out << "\"" << newline;
|
||||
delete[] cur_out;
|
||||
}
|
||||
|
||||
|
@ -115,7 +120,7 @@ public:
|
|||
}
|
||||
}
|
||||
first = true;
|
||||
buff << "{\n";
|
||||
buff << "{" << newline;
|
||||
PushIndent();
|
||||
}
|
||||
|
||||
|
@ -123,7 +128,7 @@ public:
|
|||
PopIndent();
|
||||
AddIndentation();
|
||||
first = false;
|
||||
buff << "}\n";
|
||||
buff << "}" << newline;
|
||||
}
|
||||
|
||||
void StartArray(bool is_element = false) {
|
||||
|
@ -135,19 +140,19 @@ public:
|
|||
}
|
||||
}
|
||||
first = true;
|
||||
buff << "[\n";
|
||||
buff << "[" << newline;
|
||||
PushIndent();
|
||||
}
|
||||
|
||||
void EndArray() {
|
||||
PopIndent();
|
||||
AddIndentation();
|
||||
buff << "]\n";
|
||||
buff << "]" << newline;
|
||||
first = false;
|
||||
}
|
||||
|
||||
void AddIndentation() {
|
||||
if (!(flags & Flag_DoNotIndent)) {
|
||||
if (!(flags & Flag_DoNotIndent) && !(flags & Flag_SkipWhitespaces)) {
|
||||
buff << indent;
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +161,7 @@ public:
|
|||
if (!first) {
|
||||
buff << ',';
|
||||
} else {
|
||||
buff << ' ';
|
||||
buff << space;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +232,9 @@ private:
|
|||
|
||||
private:
|
||||
Assimp::IOStream &out;
|
||||
std::string indent, newline;
|
||||
std::string indent;
|
||||
std::string newline;
|
||||
std::string space;
|
||||
std::stringstream buff;
|
||||
bool first;
|
||||
|
||||
|
@ -765,7 +772,7 @@ void Write(JSONWriter &out, const aiScene &ai) {
|
|||
out.EndObj();
|
||||
}
|
||||
|
||||
void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *) {
|
||||
void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *pProperties) {
|
||||
std::unique_ptr<Assimp::IOStream> str(io->Open(file, "wt"));
|
||||
if (!str) {
|
||||
throw DeadlyExportError("could not open output file");
|
||||
|
@ -782,7 +789,12 @@ void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *sc
|
|||
splitter.Execute(scenecopy_tmp);
|
||||
|
||||
// XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters
|
||||
JSONWriter s(*str, JSONWriter::Flag_WriteSpecialFloats);
|
||||
|
||||
unsigned int flags = JSONWriter::Flag_WriteSpecialFloats;
|
||||
if (pProperties->GetPropertyBool("JSON_SKIP_WHITESPACES", false)) {
|
||||
flags |= JSONWriter::Flag_SkipWhitespaces;
|
||||
}
|
||||
JSONWriter s(*str, flags);
|
||||
Write(s, *scenecopy_tmp);
|
||||
|
||||
} catch (...) {
|
||||
|
|
|
@ -143,7 +143,7 @@ AI_WONT_RETURN void B3DImporter::Oops() {
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AI_WONT_RETURN void B3DImporter::Fail(string str) {
|
||||
AI_WONT_RETURN void B3DImporter::Fail(const string &str) {
|
||||
#ifdef DEBUG_B3D
|
||||
ASSIMP_LOG_ERROR("Error in B3D file data: ", str);
|
||||
#endif
|
||||
|
|
|
@ -96,7 +96,7 @@ private:
|
|||
};
|
||||
|
||||
AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void Fail(const std::string &str) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
void ReadTEXS();
|
||||
void ReadBRUS();
|
||||
|
|
|
@ -679,7 +679,7 @@ void BlenderImporter::BuildMaterials(ConversionData &conv_data) {
|
|||
|
||||
BuildDefaultMaterial(conv_data);
|
||||
|
||||
for (std::shared_ptr<Material> mat : conv_data.materials_raw) {
|
||||
for (const std::shared_ptr<Material> &mat : conv_data.materials_raw) {
|
||||
|
||||
// reset per material global counters
|
||||
for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) {
|
||||
|
|
|
@ -146,8 +146,14 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
|||
ThrowException("failed to read document " + pFile);
|
||||
}
|
||||
|
||||
// Generate the root-node
|
||||
pScene->mRootNode = new aiNode("<C4DRoot>");
|
||||
|
||||
// convert left-handed to right-handed
|
||||
pScene->mRootNode->mTransformation.a1 = 0.01f;
|
||||
pScene->mRootNode->mTransformation.b2 = 0.01f;
|
||||
pScene->mRootNode->mTransformation.c3 = -0.01f;
|
||||
|
||||
// first convert all materials
|
||||
ReadMaterials(doc->GetFirstMaterial());
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertTexture(std::shared_ptr<Texture> tex, aiMaterial *out, aiTextureType type) {
|
||||
void ConvertTexture(const std::shared_ptr<Texture> &tex, aiMaterial *out, aiTextureType type) {
|
||||
const aiString path(tex->path);
|
||||
out->AddProperty(&path, AI_MATKEY_TEXTURE(type, 0));
|
||||
out->AddProperty(&tex->transform, 1, AI_MATKEY_UVTRANSFORM(type, 0));
|
||||
|
|
|
@ -135,14 +135,15 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
|
|||
|
||||
// XML - too generic, we need to open the file and search for typical keywords
|
||||
if (extension == "xml" || !extension.length() || checkSig) {
|
||||
/* If CanRead() is called in order to check whether we
|
||||
* support a specific file extension in general pIOHandler
|
||||
* might be nullptr and it's our duty to return true here.
|
||||
*/
|
||||
if (!pIOHandler) {
|
||||
// If CanRead() is called in order to check whether we
|
||||
// support a specific file extension in general pIOHandler
|
||||
// might be nullptr and it's our duty to return true here.
|
||||
if (nullptr == pIOHandler) {
|
||||
return true;
|
||||
}
|
||||
static const char *tokens[] = { "<collada" };
|
||||
static const char* tokens[] = {
|
||||
"<collada"
|
||||
};
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
|
||||
}
|
||||
|
||||
|
@ -573,7 +574,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
|
|||
|
||||
// now place all mesh references we gathered in the target node
|
||||
pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
|
||||
if (newMeshRefs.size()) {
|
||||
if (!newMeshRefs.empty()) {
|
||||
struct UIntTypeConverter {
|
||||
unsigned int operator()(const size_t &v) const {
|
||||
return static_cast<unsigned int>(v);
|
||||
|
@ -619,6 +620,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
|
|||
dstMesh->mName = pSrcMesh->mId;
|
||||
}
|
||||
|
||||
if (pSrcMesh->mPositions.empty()) {
|
||||
return dstMesh.release();
|
||||
}
|
||||
|
||||
// count the vertices addressed by its faces
|
||||
const size_t numVertices = std::accumulate(pSrcMesh->mFaceSize.begin() + pStartFace,
|
||||
pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0));
|
||||
|
@ -1682,7 +1687,7 @@ void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/)
|
|||
|
||||
// store the material
|
||||
mMaterialIndexByName[matIt->first] = newMats.size();
|
||||
newMats.push_back(std::pair<Effect *, aiMaterial *>(&effect, mat));
|
||||
newMats.emplace_back(&effect, mat);
|
||||
}
|
||||
// ScenePreprocessor generates a default material automatically if none is there.
|
||||
// All further code here in this loader works well without a valid material so
|
||||
|
|
|
@ -170,10 +170,10 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
ColladaParser::~ColladaParser() {
|
||||
for (auto & it : mNodeLibrary) {
|
||||
for (auto &it : mNodeLibrary) {
|
||||
delete it.second;
|
||||
}
|
||||
for (auto & it : mMeshLibrary) {
|
||||
for (auto &it : mMeshLibrary) {
|
||||
delete it.second;
|
||||
}
|
||||
}
|
||||
|
@ -231,11 +231,7 @@ void ColladaParser::UriDecodePath(aiString &ss) {
|
|||
|
||||
// Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
|
||||
// I need to filter it without destroying linux paths starting with "/somewhere"
|
||||
#if defined(_MSC_VER)
|
||||
if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
|
||||
#else
|
||||
if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
|
||||
#endif
|
||||
--ss.length;
|
||||
::memmove(ss.data, ss.data + 1, ss.length);
|
||||
ss.data[ss.length] = 0;
|
||||
|
@ -396,7 +392,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
|
|||
|
||||
std::string animName;
|
||||
if (!XmlParser::getStdStrAttribute(node, "name", animName)) {
|
||||
if (!XmlParser::getStdStrAttribute( node, "id", animName )) {
|
||||
if (!XmlParser::getStdStrAttribute(node, "id", animName)) {
|
||||
animName = std::string("animation_") + ai_to_string(mAnimationClipLibrary.size());
|
||||
}
|
||||
}
|
||||
|
@ -420,7 +416,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
|
|||
|
||||
void ColladaParser::PostProcessControllers() {
|
||||
std::string meshId;
|
||||
for (auto & it : mControllerLibrary) {
|
||||
for (auto &it : mControllerLibrary) {
|
||||
meshId = it.second.mMeshId;
|
||||
if (meshId.empty()) {
|
||||
continue;
|
||||
|
@ -445,7 +441,7 @@ void ColladaParser::PostProcessRootAnimations() {
|
|||
}
|
||||
|
||||
Animation temp;
|
||||
for (auto & it : mAnimationClipLibrary) {
|
||||
for (auto &it : mAnimationClipLibrary) {
|
||||
std::string clipName = it.first;
|
||||
|
||||
Animation *clip = new Animation();
|
||||
|
@ -453,7 +449,7 @@ void ColladaParser::PostProcessRootAnimations() {
|
|||
|
||||
temp.mSubAnims.push_back(clip);
|
||||
|
||||
for (std::string animationID : it.second) {
|
||||
for (const std::string &animationID : it.second) {
|
||||
AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID);
|
||||
|
||||
if (animation != mAnimationLibrary.end()) {
|
||||
|
@ -552,7 +548,7 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
|
|||
pParent->mSubAnims.push_back(anim);
|
||||
}
|
||||
|
||||
for (const auto & channel : channels) {
|
||||
for (const auto &channel : channels) {
|
||||
anim->mChannels.push_back(channel.second);
|
||||
}
|
||||
|
||||
|
@ -626,8 +622,6 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
|
|||
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
|
||||
XmlNode currentNode;
|
||||
while (xmlIt.getNext(currentNode)) {
|
||||
|
||||
//for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string ¤tName = currentNode.name();
|
||||
if (currentName == "morph") {
|
||||
controller.mType = Morph;
|
||||
|
@ -644,7 +638,7 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
|
|||
} else if (currentName == "skin") {
|
||||
std::string id;
|
||||
if (XmlParser::getStdStrAttribute(currentNode, "source", id)) {
|
||||
controller.mMeshId = id.substr(1, id.size()-1);
|
||||
controller.mMeshId = id.substr(1, id.size() - 1);
|
||||
}
|
||||
} else if (currentName == "bind_shape_matrix") {
|
||||
std::string v;
|
||||
|
@ -698,7 +692,7 @@ void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pCo
|
|||
} else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) {
|
||||
pController.mJointOffsetMatrixSource = attrSource;
|
||||
} else {
|
||||
throw DeadlyImportError("Unknown semantic \"" , attrSemantic , "\" in <joints> data <input> element");
|
||||
throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <joints> data <input> element");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -708,7 +702,7 @@ void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pCo
|
|||
// Reads the joint weights for the given controller
|
||||
void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) {
|
||||
// Read vertex count from attributes and resize the array accordingly
|
||||
int vertexCount=0;
|
||||
int vertexCount = 0;
|
||||
XmlParser::getIntAttribute(node, "count", vertexCount);
|
||||
pController.mWeightCounts.resize(vertexCount);
|
||||
|
||||
|
@ -723,7 +717,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
|
|||
|
||||
// local URLS always start with a '#'. We don't support global URLs
|
||||
if (attrSource[0] != '#') {
|
||||
throw DeadlyImportError( "Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element");
|
||||
throw DeadlyImportError("Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element");
|
||||
}
|
||||
channel.mAccessor = attrSource + 1;
|
||||
|
||||
|
@ -777,7 +771,7 @@ void ColladaParser::ReadImageLibrary(XmlNode &node) {
|
|||
const std::string ¤tName = currentNode.name();
|
||||
if (currentName == "image") {
|
||||
std::string id;
|
||||
if (XmlParser::getStdStrAttribute( currentNode, "id", id )) {
|
||||
if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
|
||||
mImageLibrary[id] = Image();
|
||||
// read on from there
|
||||
ReadImage(currentNode, mImageLibrary[id]);
|
||||
|
@ -920,7 +914,7 @@ void ColladaParser::ReadMaterial(XmlNode &node, Collada::Material &pMaterial) {
|
|||
if (currentName == "instance_effect") {
|
||||
std::string url;
|
||||
readUrlAttribute(currentNode, url);
|
||||
pMaterial.mEffect = url.c_str();
|
||||
pMaterial.mEffect = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1361,8 +1355,8 @@ void ColladaParser::ReadMesh(XmlNode &node, Mesh &pMesh) {
|
|||
} else if (currentName == "vertices") {
|
||||
ReadVertexData(currentNode, pMesh);
|
||||
} else if (currentName == "triangles" || currentName == "lines" || currentName == "linestrips" ||
|
||||
currentName == "polygons" || currentName == "polylist" || currentName == "trifans" ||
|
||||
currentName == "tristrips") {
|
||||
currentName == "polygons" || currentName == "polylist" || currentName == "trifans" ||
|
||||
currentName == "tristrips") {
|
||||
ReadIndexData(currentNode, pMesh);
|
||||
}
|
||||
}
|
||||
|
@ -1439,9 +1433,8 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
|
|||
throw DeadlyImportError("Expected more values while reading float_array contents.");
|
||||
}
|
||||
|
||||
ai_real value;
|
||||
// read a number
|
||||
//SkipSpacesAndLineEnd(&content);
|
||||
ai_real value;
|
||||
content = fast_atoreal_move<ai_real>(content, value);
|
||||
data.mValues.push_back(value);
|
||||
// skip whitespace after it
|
||||
|
@ -1489,11 +1482,10 @@ void ColladaParser::ReadAccessor(XmlNode &node, const std::string &pID) {
|
|||
std::string name;
|
||||
if (XmlParser::hasAttribute(currentNode, "name")) {
|
||||
XmlParser::getStdStrAttribute(currentNode, "name", name);
|
||||
//name = mReader->getAttributeValue(attrName);
|
||||
|
||||
// analyse for common type components and store it's sub-offset in the corresponding field
|
||||
|
||||
/* Cartesian coordinates */
|
||||
// Cartesian coordinates
|
||||
if (name == "X")
|
||||
acc.mSubOffset[0] = acc.mParams.size();
|
||||
else if (name == "Y")
|
||||
|
@ -1674,12 +1666,9 @@ void ColladaParser::ReadInputChannel(XmlNode &node, std::vector<InputChannel> &p
|
|||
|
||||
// read set if texture coordinates
|
||||
if (channel.mType == IT_Texcoord || channel.mType == IT_Color) {
|
||||
int attrSet = -1;
|
||||
if (XmlParser::hasAttribute(node, "set")) {
|
||||
XmlParser::getIntAttribute(node, "set", attrSet);
|
||||
}
|
||||
|
||||
channel.mIndex = attrSet;
|
||||
unsigned int attrSet = 0;
|
||||
if (XmlParser::getUIntAttribute(node, "set", attrSet))
|
||||
channel.mIndex = attrSet;
|
||||
}
|
||||
|
||||
// store, if valid type
|
||||
|
@ -1704,20 +1693,20 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
|
|||
// determine the expected number of indices
|
||||
size_t expectedPointCount = 0;
|
||||
switch (pPrimType) {
|
||||
case Prim_Polylist: {
|
||||
for (size_t i : pVCount)
|
||||
expectedPointCount += i;
|
||||
break;
|
||||
}
|
||||
case Prim_Lines:
|
||||
expectedPointCount = 2 * pNumPrimitives;
|
||||
break;
|
||||
case Prim_Triangles:
|
||||
expectedPointCount = 3 * pNumPrimitives;
|
||||
break;
|
||||
default:
|
||||
// other primitive types don't state the index count upfront... we need to guess
|
||||
break;
|
||||
case Prim_Polylist: {
|
||||
for (size_t i : pVCount)
|
||||
expectedPointCount += i;
|
||||
break;
|
||||
}
|
||||
case Prim_Lines:
|
||||
expectedPointCount = 2 * pNumPrimitives;
|
||||
break;
|
||||
case Prim_Triangles:
|
||||
expectedPointCount = 3 * pNumPrimitives;
|
||||
break;
|
||||
default:
|
||||
// other primitive types don't state the index count upfront... we need to guess
|
||||
break;
|
||||
}
|
||||
|
||||
// and read all indices into a temporary array
|
||||
|
@ -1727,7 +1716,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
|
|||
}
|
||||
|
||||
// It is possible to not contain any indices
|
||||
if (pNumPrimitives > 0) {
|
||||
if (pNumPrimitives > 0) {
|
||||
std::string v;
|
||||
XmlParser::getValueAsString(node, v);
|
||||
const char *content = v.c_str();
|
||||
|
@ -1925,87 +1914,87 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
|
|||
|
||||
// now we reinterpret it according to the type we're reading here
|
||||
switch (pInput.mType) {
|
||||
case IT_Position: // ignore all position streams except 0 - there can be only one position
|
||||
if (pInput.mIndex == 0) {
|
||||
pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
|
||||
}
|
||||
break;
|
||||
case IT_Normal:
|
||||
case IT_Position: // ignore all position streams except 0 - there can be only one position
|
||||
if (pInput.mIndex == 0) {
|
||||
pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
|
||||
}
|
||||
break;
|
||||
case IT_Normal:
|
||||
// pad to current vertex count if necessary
|
||||
if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1)
|
||||
pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0));
|
||||
|
||||
// ignore all normal streams except 0 - there can be only one normal
|
||||
if (pInput.mIndex == 0) {
|
||||
pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
|
||||
}
|
||||
break;
|
||||
case IT_Tangent:
|
||||
// pad to current vertex count if necessary
|
||||
if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1)
|
||||
pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0));
|
||||
|
||||
// ignore all tangent streams except 0 - there can be only one tangent
|
||||
if (pInput.mIndex == 0) {
|
||||
pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
|
||||
}
|
||||
break;
|
||||
case IT_Bitangent:
|
||||
// pad to current vertex count if necessary
|
||||
if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) {
|
||||
pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
|
||||
}
|
||||
|
||||
// ignore all bitangent streams except 0 - there can be only one bitangent
|
||||
if (pInput.mIndex == 0) {
|
||||
pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
|
||||
}
|
||||
break;
|
||||
case IT_Texcoord:
|
||||
// up to 4 texture coord sets are fine, ignore the others
|
||||
if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
||||
// pad to current vertex count if necessary
|
||||
if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1)
|
||||
pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0));
|
||||
if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
|
||||
pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
|
||||
pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
|
||||
|
||||
// ignore all normal streams except 0 - there can be only one normal
|
||||
if (pInput.mIndex == 0) {
|
||||
pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
|
||||
pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
|
||||
pMesh.mNumUVComponents[pInput.mIndex] = 3;
|
||||
}
|
||||
break;
|
||||
case IT_Tangent:
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
|
||||
}
|
||||
break;
|
||||
case IT_Color:
|
||||
// up to 4 color sets are fine, ignore the others
|
||||
if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
|
||||
// pad to current vertex count if necessary
|
||||
if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1)
|
||||
pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0));
|
||||
if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
|
||||
pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
|
||||
pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
|
||||
|
||||
// ignore all tangent streams except 0 - there can be only one tangent
|
||||
if (pInput.mIndex == 0) {
|
||||
pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
|
||||
}
|
||||
break;
|
||||
case IT_Bitangent:
|
||||
// pad to current vertex count if necessary
|
||||
if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) {
|
||||
pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
|
||||
aiColor4D result(0, 0, 0, 1);
|
||||
for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
|
||||
result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
|
||||
}
|
||||
pMesh.mColors[pInput.mIndex].push_back(result);
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
|
||||
}
|
||||
|
||||
// ignore all bitangent streams except 0 - there can be only one bitangent
|
||||
if (pInput.mIndex == 0) {
|
||||
pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
|
||||
}
|
||||
break;
|
||||
case IT_Texcoord:
|
||||
// up to 4 texture coord sets are fine, ignore the others
|
||||
if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
||||
// pad to current vertex count if necessary
|
||||
if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
|
||||
pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
|
||||
pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
|
||||
|
||||
pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
|
||||
if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
|
||||
pMesh.mNumUVComponents[pInput.mIndex] = 3;
|
||||
}
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
|
||||
}
|
||||
break;
|
||||
case IT_Color:
|
||||
// up to 4 color sets are fine, ignore the others
|
||||
if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
|
||||
// pad to current vertex count if necessary
|
||||
if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
|
||||
pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
|
||||
pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
|
||||
|
||||
aiColor4D result(0, 0, 0, 1);
|
||||
for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
|
||||
result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
|
||||
}
|
||||
pMesh.mColors[pInput.mIndex].push_back(result);
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// IT_Invalid and IT_Vertex
|
||||
ai_assert(false && "shouldn't ever get here");
|
||||
break;
|
||||
default:
|
||||
// IT_Invalid and IT_Vertex
|
||||
ai_assert(false && "shouldn't ever get here");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2170,10 +2159,10 @@ void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, Transform
|
|||
|
||||
// read as many parameters and store in the transformation
|
||||
for (unsigned int a = 0; a < sNumParameters[pType]; a++) {
|
||||
// skip whitespace before the number
|
||||
SkipSpacesAndLineEnd(&content);
|
||||
// read a number
|
||||
content = fast_atoreal_move<ai_real>(content, tf.f[a]);
|
||||
// skip whitespace after it
|
||||
SkipSpacesAndLineEnd(&content);
|
||||
}
|
||||
|
||||
// place the transformation at the queue of the node
|
||||
|
@ -2215,8 +2204,8 @@ void ColladaParser::ReadMaterialVertexInputBinding(XmlNode &node, Collada::Seman
|
|||
|
||||
void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive) {
|
||||
// Attempt to load any undefined Collada::Image in ImageLibrary
|
||||
for (ImageLibrary::iterator it = mImageLibrary.begin(); it != mImageLibrary.end(); ++it) {
|
||||
Collada::Image &image = (*it).second;
|
||||
for (auto & it : mImageLibrary) {
|
||||
Collada::Image &image = it.second;
|
||||
|
||||
if (image.mImageData.empty()) {
|
||||
std::unique_ptr<IOStream> image_file(zip_archive.Open(image.mFileName.c_str()));
|
||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2021, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -917,8 +917,10 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root
|
|||
} else if (line) {
|
||||
const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
|
||||
std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
|
||||
} else {
|
||||
} else if (geo) {
|
||||
FBXImporter::LogWarn("ignoring unrecognized geometry: ", geo->Name());
|
||||
} else {
|
||||
FBXImporter::LogWarn("skipping null geometry");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1766,6 +1768,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
|
|||
// XXX handle all kinds of UV transformations
|
||||
uvTrafo.mScaling = tex->UVScaling();
|
||||
uvTrafo.mTranslation = tex->UVTranslation();
|
||||
uvTrafo.mRotation = tex->UVRotation();
|
||||
out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0);
|
||||
|
||||
const PropertyTable &props = tex->Props();
|
||||
|
@ -1885,6 +1888,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
|
|||
// XXX handle all kinds of UV transformations
|
||||
uvTrafo.mScaling = tex->UVScaling();
|
||||
uvTrafo.mTranslation = tex->UVTranslation();
|
||||
uvTrafo.mRotation = tex->UVRotation();
|
||||
out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex);
|
||||
|
||||
const PropertyTable &props = tex->Props();
|
||||
|
@ -2129,7 +2133,7 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
|
|||
if (ok) {
|
||||
out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE);
|
||||
} else {
|
||||
const aiColor3D &emissiveColor = GetColorPropertyFromMaterial(props, "Maya|emissive", ok);
|
||||
const aiColor3D &emissiveColor = GetColorProperty(props, "Maya|emissive", ok);
|
||||
if (ok) {
|
||||
out_mat->AddProperty(&emissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
|
||||
}
|
||||
|
@ -2216,7 +2220,7 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
|
|||
}
|
||||
|
||||
// PBR material information
|
||||
const aiColor3D &baseColor = GetColorPropertyFromMaterial(props, "Maya|base_color", ok);
|
||||
const aiColor3D &baseColor = GetColorProperty(props, "Maya|base_color", ok);
|
||||
if (ok) {
|
||||
out_mat->AddProperty(&baseColor, 1, AI_MATKEY_BASE_COLOR);
|
||||
}
|
||||
|
@ -2324,6 +2328,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
|
|||
// XXX handle all kinds of UV transformations
|
||||
uvTrafo.mScaling = tex->UVScaling();
|
||||
uvTrafo.mTranslation = tex->UVTranslation();
|
||||
uvTrafo.mRotation = tex->UVRotation();
|
||||
out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0);
|
||||
|
||||
int uvIndex = 0;
|
||||
|
@ -2599,7 +2604,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
|
|||
anim->mMorphMeshChannels = new aiMeshMorphAnim *[numMorphMeshChannels];
|
||||
anim->mNumMorphMeshChannels = numMorphMeshChannels;
|
||||
unsigned int i = 0;
|
||||
for (auto morphAnimIt : morphAnimDatas) {
|
||||
for (const auto &morphAnimIt : morphAnimDatas) {
|
||||
morphAnimData *animData = morphAnimIt.second;
|
||||
unsigned int numKeys = static_cast<unsigned int>(animData->size());
|
||||
aiMeshMorphAnim *meshMorphAnim = new aiMeshMorphAnim();
|
||||
|
|
|
@ -57,9 +57,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
@ -248,10 +249,8 @@ Object::~Object()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
|
||||
: props(props)
|
||||
, doc(doc)
|
||||
{
|
||||
FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<const PropertyTable> props) :
|
||||
props(std::move(props)), doc(doc) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
|
|
@ -500,6 +500,10 @@ public:
|
|||
return uvScaling;
|
||||
}
|
||||
|
||||
const ai_real &UVRotation() const {
|
||||
return uvRotation;
|
||||
}
|
||||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
|
@ -517,6 +521,7 @@ public:
|
|||
private:
|
||||
aiVector2D uvTrans;
|
||||
aiVector2D uvScaling;
|
||||
ai_real uvRotation;
|
||||
|
||||
std::string type;
|
||||
std::string relativeFileName;
|
||||
|
|
|
@ -144,9 +144,8 @@ void FBX::Node::AddP70time(
|
|||
// public member functions for writing nodes to stream
|
||||
|
||||
void FBX::Node::Dump(
|
||||
std::shared_ptr<Assimp::IOStream> outfile,
|
||||
bool binary, int indent
|
||||
) {
|
||||
const std::shared_ptr<Assimp::IOStream> &outfile,
|
||||
bool binary, int indent) {
|
||||
if (binary) {
|
||||
Assimp::StreamWriterLE outstream(outfile);
|
||||
DumpBinary(outstream);
|
||||
|
|
|
@ -157,9 +157,8 @@ public: // member functions for writing data to a file or stream
|
|||
|
||||
// write the full node to the given file or stream
|
||||
void Dump(
|
||||
std::shared_ptr<Assimp::IOStream> outfile,
|
||||
bool binary, int indent
|
||||
);
|
||||
const std::shared_ptr<Assimp::IOStream> &outfile,
|
||||
bool binary, int indent);
|
||||
void Dump(Assimp::StreamWriterLE &s, bool binary, int indent);
|
||||
|
||||
// these other functions are for writing data piece by piece.
|
||||
|
|
|
@ -541,10 +541,17 @@ void FBXExporter::WriteReferences ()
|
|||
// (before any actual data is written)
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
size_t count_nodes(const aiNode* n) {
|
||||
size_t count = 1;
|
||||
size_t count_nodes(const aiNode* n, const aiNode* root) {
|
||||
size_t count;
|
||||
if (n == root) {
|
||||
count = n->mNumMeshes; // (not counting root node)
|
||||
} else if (n->mNumMeshes > 1) {
|
||||
count = n->mNumMeshes + 1;
|
||||
} else {
|
||||
count = 1;
|
||||
}
|
||||
for (size_t i = 0; i < n->mNumChildren; ++i) {
|
||||
count += count_nodes(n->mChildren[i]);
|
||||
count += count_nodes(n->mChildren[i], root);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -714,7 +721,7 @@ void FBXExporter::WriteDefinitions ()
|
|||
|
||||
// Model / FbxNode
|
||||
// <~~ node hierarchy
|
||||
count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
|
||||
count = int32_t(count_nodes(mScene->mRootNode, mScene->mRootNode));
|
||||
if (count) {
|
||||
n = FBX::Node("ObjectType", "Model");
|
||||
n.AddChild("Count", count);
|
||||
|
@ -1681,6 +1688,10 @@ void FBXExporter::WriteObjects ()
|
|||
// link the image data to the texture
|
||||
connections.emplace_back("C", "OO", image_uid, texture_uid);
|
||||
|
||||
aiUVTransform trafo;
|
||||
unsigned int max = sizeof(aiUVTransform);
|
||||
aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE, 0), (ai_real *)&trafo, &max);
|
||||
|
||||
// now write the actual texture node
|
||||
FBX::Node tnode("Texture");
|
||||
// TODO: some way to determine texture name?
|
||||
|
@ -1691,6 +1702,9 @@ void FBXExporter::WriteObjects ()
|
|||
tnode.AddChild("Version", int32_t(202));
|
||||
tnode.AddChild("TextureName", texture_name);
|
||||
FBX::Node p("Properties70");
|
||||
p.AddP70vectorA("Translation", trafo.mTranslation[0], trafo.mTranslation[1], 0.0);
|
||||
p.AddP70vectorA("Rotation", 0, 0, trafo.mRotation);
|
||||
p.AddP70vectorA("Scaling", trafo.mScaling[0], trafo.mScaling[1], 0.0);
|
||||
p.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify
|
||||
//p.AddP70string("UVSet", ""); // TODO: how should this work?
|
||||
p.AddP70bool("UseMaterial", 1);
|
||||
|
@ -2196,7 +2210,65 @@ void FBXExporter::WriteObjects ()
|
|||
bpnode.Dump(outstream, binary, indent);
|
||||
}*/
|
||||
|
||||
// TODO: cameras, lights
|
||||
// lights
|
||||
indent = 1;
|
||||
lights_uids.clear();
|
||||
for (size_t li = 0; li < mScene->mNumLights; ++li) {
|
||||
aiLight* l = mScene->mLights[li];
|
||||
|
||||
int64_t uid = generate_uid();
|
||||
const std::string lightNodeAttributeName = l->mName.C_Str() + FBX::SEPARATOR + "NodeAttribute";
|
||||
|
||||
FBX::Node lna("NodeAttribute");
|
||||
lna.AddProperties(uid, lightNodeAttributeName, "Light");
|
||||
FBX::Node lnap("Properties70");
|
||||
|
||||
// Light color.
|
||||
lnap.AddP70colorA("Color", l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b);
|
||||
|
||||
// TODO Assimp light description is quite concise and do not handle light intensity.
|
||||
// Default value to 1000W.
|
||||
lnap.AddP70numberA("Intensity", 1000);
|
||||
|
||||
// FBXLight::EType conversion
|
||||
switch (l->mType) {
|
||||
case aiLightSource_POINT:
|
||||
lnap.AddP70enum("LightType", 0);
|
||||
break;
|
||||
case aiLightSource_DIRECTIONAL:
|
||||
lnap.AddP70enum("LightType", 1);
|
||||
break;
|
||||
case aiLightSource_SPOT:
|
||||
lnap.AddP70enum("LightType", 2);
|
||||
lnap.AddP70numberA("InnerAngle", AI_RAD_TO_DEG(l->mAngleInnerCone));
|
||||
lnap.AddP70numberA("OuterAngle", AI_RAD_TO_DEG(l->mAngleOuterCone));
|
||||
break;
|
||||
// TODO Assimp do not handle 'area' nor 'volume' lights, but FBX does.
|
||||
/*case aiLightSource_AREA:
|
||||
lnap.AddP70enum("LightType", 3);
|
||||
lnap.AddP70enum("AreaLightShape", 0); // 0=Rectangle, 1=Sphere
|
||||
break;
|
||||
case aiLightSource_VOLUME:
|
||||
lnap.AddP70enum("LightType", 4);
|
||||
break;*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Did not understood how to configure the decay so disabling attenuation.
|
||||
lnap.AddP70enum("DecayType", 0);
|
||||
|
||||
// Dump to FBX stream
|
||||
lna.AddChild(lnap);
|
||||
lna.AddChild("TypeFlags", FBX::FBXExportProperty("Light"));
|
||||
lna.AddChild("GeometryVersion", FBX::FBXExportProperty(int32_t(124)));
|
||||
lna.Dump(outstream, binary, indent);
|
||||
|
||||
// Store name and uid (will be used later when parsing scene nodes)
|
||||
lights_uids[l->mName.C_Str()] = uid;
|
||||
}
|
||||
|
||||
// TODO: cameras
|
||||
|
||||
// write nodes (i.e. model hierarchy)
|
||||
// start at root node
|
||||
|
@ -2600,10 +2672,19 @@ void FBXExporter::WriteModelNodes(
|
|||
// and connect them
|
||||
connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
|
||||
} else {
|
||||
// generate a null node so we can add children to it
|
||||
WriteModelNode(
|
||||
outstream, binary, node, node_uid, "Null", transform_chain
|
||||
);
|
||||
const auto& lightIt = lights_uids.find(node->mName.C_Str());
|
||||
if(lightIt != lights_uids.end()) {
|
||||
// Node has a light connected to it.
|
||||
WriteModelNode(
|
||||
outstream, binary, node, node_uid, "Light", transform_chain
|
||||
);
|
||||
connections.emplace_back("C", "OO", lightIt->second, node_uid);
|
||||
} else {
|
||||
// generate a null node so we can add children to it
|
||||
WriteModelNode(
|
||||
outstream, binary, node, node_uid, "Null", transform_chain
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// if more than one child mesh, make nodes for each mesh
|
||||
|
@ -2625,17 +2706,14 @@ void FBXExporter::WriteModelNodes(
|
|||
],
|
||||
new_node_uid
|
||||
);
|
||||
// write model node
|
||||
FBX::Node m("Model");
|
||||
|
||||
aiNode new_node;
|
||||
// take name from mesh name, if it exists
|
||||
std::string name = mScene->mMeshes[node->mMeshes[i]]->mName.C_Str();
|
||||
name += FBX::SEPARATOR + "Model";
|
||||
m.AddProperties(new_node_uid, name, "Mesh");
|
||||
m.AddChild("Version", int32_t(232));
|
||||
FBX::Node p("Properties70");
|
||||
p.AddP70enum("InheritType", 1);
|
||||
m.AddChild(p);
|
||||
m.Dump(outstream, binary, 1);
|
||||
new_node.mName = mScene->mMeshes[node->mMeshes[i]]->mName;
|
||||
// write model node
|
||||
WriteModelNode(
|
||||
outstream, binary, &new_node, new_node_uid, "Mesh", std::vector<std::pair<std::string,aiVector3D>>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2647,16 +2725,14 @@ void FBXExporter::WriteModelNodes(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void FBXExporter::WriteAnimationCurveNode(
|
||||
StreamWriterLE& outstream,
|
||||
int64_t uid,
|
||||
const std::string& name, // "T", "R", or "S"
|
||||
aiVector3D default_value,
|
||||
std::string property_name, // "Lcl Translation" etc
|
||||
int64_t layer_uid,
|
||||
int64_t node_uid
|
||||
) {
|
||||
StreamWriterLE &outstream,
|
||||
int64_t uid,
|
||||
const std::string &name, // "T", "R", or "S"
|
||||
aiVector3D default_value,
|
||||
const std::string &property_name, // "Lcl Translation" etc
|
||||
int64_t layer_uid,
|
||||
int64_t node_uid) {
|
||||
FBX::Node n("AnimationCurveNode");
|
||||
n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", "");
|
||||
FBX::Node p("Properties70");
|
||||
|
@ -2671,7 +2747,6 @@ void FBXExporter::WriteAnimationCurveNode(
|
|||
this->connections.emplace_back("C", "OP", uid, node_uid, property_name);
|
||||
}
|
||||
|
||||
|
||||
void FBXExporter::WriteAnimationCurve(
|
||||
StreamWriterLE& outstream,
|
||||
double default_value,
|
||||
|
|
|
@ -63,10 +63,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
struct aiScene;
|
||||
struct aiNode;
|
||||
//struct aiMaterial;
|
||||
struct aiLight;
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Assimp {
|
||||
class IOSystem;
|
||||
class IOStream;
|
||||
class ExportProperties;
|
||||
|
@ -95,6 +94,7 @@ namespace Assimp
|
|||
std::vector<int64_t> mesh_uids;
|
||||
std::vector<int64_t> material_uids;
|
||||
std::map<const aiNode*,int64_t> node_uids;
|
||||
std::map<std::string,int64_t> lights_uids;
|
||||
|
||||
// this crude unique-ID system is actually fine
|
||||
int64_t last_uid = 999999;
|
||||
|
@ -154,14 +154,13 @@ namespace Assimp
|
|||
FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs
|
||||
);
|
||||
void WriteAnimationCurveNode(
|
||||
StreamWriterLE& outstream,
|
||||
int64_t uid,
|
||||
const std::string& name, // "T", "R", or "S"
|
||||
aiVector3D default_value,
|
||||
std::string property_name, // "Lcl Translation" etc
|
||||
int64_t animation_layer_uid,
|
||||
int64_t node_uid
|
||||
);
|
||||
StreamWriterLE &outstream,
|
||||
int64_t uid,
|
||||
const std::string &name, // "T", "R", or "S"
|
||||
aiVector3D default_value,
|
||||
const std::string &property_name, // "Lcl Translation" etc
|
||||
int64_t animation_layer_uid,
|
||||
int64_t node_uid);
|
||||
void WriteAnimationCurve(
|
||||
StreamWriterLE& outstream,
|
||||
double default_value,
|
||||
|
|
|
@ -210,6 +210,11 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
|
|||
uvTrans.y = trans.y;
|
||||
}
|
||||
|
||||
const aiVector3D &rotation = PropertyGet<aiVector3D>(*props, "Rotation", ok);
|
||||
if (ok) {
|
||||
uvRotation = rotation.z;
|
||||
}
|
||||
|
||||
// resolve video links
|
||||
if(doc.Settings().readTextures) {
|
||||
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
|
||||
|
|
|
@ -192,6 +192,10 @@ Scope::Scope(Parser& parser,bool topLevel)
|
|||
}
|
||||
|
||||
const std::string& str = n->StringContents();
|
||||
if (str.empty()) {
|
||||
ParseError("unexpected content: empty string.");
|
||||
}
|
||||
|
||||
elements.insert(ElementMap::value_type(str,new_Element(*n,parser)));
|
||||
|
||||
// Element() should stop at the next Key token (or right after a Close token)
|
||||
|
@ -642,8 +646,7 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
|
|||
|
||||
ai_assert(data == end);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
if (dataToRead != buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
|
@ -733,8 +736,7 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
|
|||
|
||||
ai_assert(data == end);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
if (dataToRead != buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
|
@ -816,8 +818,7 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
|
|||
|
||||
ai_assert(data == end);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
if (dataToRead != buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
|
@ -892,8 +893,7 @@ void ParseVectorDataArray(std::vector<int>& out, const Element& el)
|
|||
|
||||
ai_assert(data == end);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * 4;
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
if (dataToRead != buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
|
@ -954,8 +954,7 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
|
|||
|
||||
ai_assert(data == end);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
if (dataToRead != buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
|
@ -1019,8 +1018,7 @@ void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
|
|||
|
||||
ai_assert(data == end);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * 4;
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
if (dataToRead != buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
|
@ -1088,8 +1086,7 @@ void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
|
|||
|
||||
ai_assert(data == end);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * 8;
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
if (dataToRead != buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
|
@ -1150,8 +1147,7 @@ void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el)
|
|||
|
||||
ai_assert(data == end);
|
||||
uint64_t dataToRead = static_cast<uint64_t>(count) * 8;
|
||||
ai_assert(buff.size() == dataToRead);
|
||||
if (dataToRead > buff.size()) {
|
||||
if (dataToRead != buff.size()) {
|
||||
ParseError("Invalid read size (binary)",&el);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "FBXDocumentUtil.h"
|
||||
#include "FBXProperties.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
|
@ -172,10 +174,8 @@ PropertyTable::PropertyTable()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps)
|
||||
: templateProps(templateProps)
|
||||
, element(&element)
|
||||
{
|
||||
PropertyTable::PropertyTable(const Element &element, std::shared_ptr<const PropertyTable> templateProps) :
|
||||
templateProps(std::move(templateProps)), element(&element) {
|
||||
const Scope& scope = GetRequiredScope(element);
|
||||
for(const ElementMap::value_type& v : scope.Elements()) {
|
||||
if(v.first != "P") {
|
||||
|
@ -199,7 +199,6 @@ PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const Prope
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
PropertyTable::~PropertyTable()
|
||||
{
|
||||
|
|
|
@ -513,7 +513,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
|
|||
}
|
||||
|
||||
// we got a list of in-out-combinations of intersections. That should be an even number of intersections, or
|
||||
// we're fucked.
|
||||
// we are facing a non-recoverable error.
|
||||
if ((intersections.size() & 1) != 0) {
|
||||
IFCImporter::LogWarn("Odd number of intersections, can't work with that. Omitting half space boundary check.");
|
||||
continue;
|
||||
|
|
|
@ -740,7 +740,7 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
|
|||
bool fix_orientation = false;
|
||||
std::shared_ptr< TempMesh > meshtmp = std::make_shared<TempMesh>();
|
||||
if(const Schema_2x3::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<Schema_2x3::IfcShellBasedSurfaceModel>()) {
|
||||
for(std::shared_ptr<const Schema_2x3::IfcShell> shell :shellmod->SbsmBoundary) {
|
||||
for (const std::shared_ptr<const Schema_2x3::IfcShell> &shell : shellmod->SbsmBoundary) {
|
||||
try {
|
||||
const ::Assimp::STEP::EXPRESS::ENTITY& e = shell->To<::Assimp::STEP::EXPRESS::ENTITY>();
|
||||
const Schema_2x3::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<Schema_2x3::IfcConnectedFaceSet>();
|
||||
|
|
|
@ -75,7 +75,7 @@ static void FillMaterial(aiMaterial* mat,const IFC::Schema_2x3::IfcSurfaceStyle*
|
|||
mat->AddProperty(&name,AI_MATKEY_NAME);
|
||||
|
||||
// now see which kinds of surface information are present
|
||||
for(std::shared_ptr< const IFC::Schema_2x3::IfcSurfaceStyleElementSelect > sel2 : surf->Styles) {
|
||||
for (const std::shared_ptr<const IFC::Schema_2x3::IfcSurfaceStyleElementSelect> &sel2 : surf->Styles) {
|
||||
if (const IFC::Schema_2x3::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyleShading>(conv.db)) {
|
||||
aiColor4D col_base,col;
|
||||
|
||||
|
@ -134,7 +134,7 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat
|
|||
for(;range.first != range.second; ++range.first) {
|
||||
if(const IFC::Schema_2x3::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr<IFC::Schema_2x3::IfcStyledItem>()) {
|
||||
for(const IFC::Schema_2x3::IfcPresentationStyleAssignment& as : styled->Styles) {
|
||||
for(std::shared_ptr<const IFC::Schema_2x3::IfcPresentationStyleSelect> sel : as.Styles) {
|
||||
for (const std::shared_ptr<const IFC::Schema_2x3::IfcPresentationStyleSelect> &sel : as.Styles) {
|
||||
|
||||
if( const IFC::Schema_2x3::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyle>(conv.db) ) {
|
||||
// try to satisfy from cache
|
||||
|
|
|
@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/mesh.h>
|
||||
#include <assimp/material.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
struct aiNode;
|
||||
|
||||
namespace Assimp {
|
||||
|
@ -137,14 +139,10 @@ struct TempOpening
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
TempOpening(const IFC::Schema_2x3::IfcSolidModel* solid,IfcVector3 extrusionDir,
|
||||
std::shared_ptr<TempMesh> profileMesh,
|
||||
std::shared_ptr<TempMesh> profileMesh2D)
|
||||
: solid(solid)
|
||||
, extrusionDir(extrusionDir)
|
||||
, profileMesh(profileMesh)
|
||||
, profileMesh2D(profileMesh2D)
|
||||
{
|
||||
TempOpening(const IFC::Schema_2x3::IfcSolidModel *solid, IfcVector3 extrusionDir,
|
||||
std::shared_ptr<TempMesh> profileMesh,
|
||||
std::shared_ptr<TempMesh> profileMesh2D) :
|
||||
solid(solid), extrusionDir(extrusionDir), profileMesh(std::move(profileMesh)), profileMesh2D(std::move(profileMesh2D)) {
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
|
|
@ -318,7 +318,7 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
|
|||
} else {
|
||||
++s;
|
||||
}
|
||||
std::string::size_type t = src.path.substr(s).find_last_of(".");
|
||||
std::string::size_type t = src.path.substr(s).find_last_of('.');
|
||||
|
||||
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
|
||||
return;
|
||||
|
|
|
@ -233,12 +233,12 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) {
|
|||
ASSIMP_LOG_DEBUG("M3D: importMaterials ", mScene->mNumMaterials);
|
||||
|
||||
// add a default material as first
|
||||
aiMaterial *mat = new aiMaterial;
|
||||
mat->AddProperty(&name, AI_MATKEY_NAME);
|
||||
aiMaterial *defaultMat = new aiMaterial;
|
||||
defaultMat->AddProperty(&name, AI_MATKEY_NAME);
|
||||
c.a = 1.0f;
|
||||
c.b = c.g = c.r = 0.6f;
|
||||
mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
mScene->mMaterials[0] = mat;
|
||||
defaultMat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
mScene->mMaterials[0] = defaultMat;
|
||||
|
||||
if (!m3d->nummaterial || !m3d->material) {
|
||||
return;
|
||||
|
@ -300,12 +300,12 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) {
|
|||
m->prop[j].value.textureid < m3d->numtexture &&
|
||||
m3d->texture[m->prop[j].value.textureid].name) {
|
||||
name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png"));
|
||||
mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index);
|
||||
newMat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index);
|
||||
n = 0;
|
||||
mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index);
|
||||
newMat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index);
|
||||
}
|
||||
}
|
||||
mScene->mMaterials[i + 1] = mat;
|
||||
mScene->mMaterials[i + 1] = newMat;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,7 +655,7 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// find a node by name
|
||||
aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) {
|
||||
aiNode *M3DImporter::findNode(aiNode *pNode, const aiString &name) {
|
||||
ai_assert(pNode != nullptr);
|
||||
ai_assert(mScene != nullptr);
|
||||
|
||||
|
|
|
@ -89,8 +89,8 @@ private:
|
|||
// helper functions
|
||||
aiColor4D mkColor(uint32_t c);
|
||||
void convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid);
|
||||
aiNode *findNode(aiNode *pNode, aiString name);
|
||||
void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m);
|
||||
aiNode *findNode(aiNode *pNode, const aiString &name);
|
||||
void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m);
|
||||
void populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector<aiFace> *faces, std::vector<aiVector3D> *verteces,
|
||||
std::vector<aiVector3D> *normals, std::vector<aiVector3D> *texcoords, std::vector<aiColor4D> *colors,
|
||||
std::vector<unsigned int> *vertexids);
|
||||
|
|
|
@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
#ifndef AI_M3DWRAPPER_H_INC
|
||||
#define AI_M3DWRAPPER_H_INC
|
||||
|
||||
#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
|
||||
#include <memory>
|
||||
|
@ -55,44 +56,75 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// Assimp specific M3D configuration. Comment out these defines to remove functionality
|
||||
//#define ASSIMP_USE_M3D_READFILECB
|
||||
|
||||
// Share stb_image's PNG loader with other importers/exporters instead of bringing our own copy.
|
||||
#define STBI_ONLY_PNG
|
||||
#include <stb/stb_image.h>
|
||||
|
||||
#include "m3d.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
class IOSystem;
|
||||
|
||||
/// brief The M3D-Wrapper, provudes c++ access to the data.
|
||||
class M3DWrapper {
|
||||
m3d_t *m3d_ = nullptr;
|
||||
unsigned char *saved_output_ = nullptr;
|
||||
|
||||
public:
|
||||
// Construct an empty M3D model
|
||||
/// Construct an empty M3D model
|
||||
explicit M3DWrapper();
|
||||
|
||||
// Construct an M3D model from provided buffer
|
||||
// NOTE: The m3d.h SDK function does not mark the data as const. Have assumed it does not write.
|
||||
// BUG: SECURITY: The m3d.h SDK cannot be informed of the buffer size. BUFFER OVERFLOW IS CERTAIN
|
||||
/// Construct an M3D model from provided buffer
|
||||
/// @note The m3d.h SDK function does not mark the data as const. Have assumed it does not write.
|
||||
/// BUG: SECURITY: The m3d.h SDK cannot be informed of the buffer size. BUFFER OVERFLOW IS CERTAIN
|
||||
explicit M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer);
|
||||
|
||||
~M3DWrapper();
|
||||
/// Theclasss destructor.
|
||||
~M3DWrapper();
|
||||
|
||||
void reset();
|
||||
/// Will reset the wrapper, all data will become nullptr.
|
||||
void reset();
|
||||
|
||||
// Name
|
||||
inline std::string Name() const {
|
||||
if (m3d_) return std::string(m3d_->name);
|
||||
return std::string();
|
||||
}
|
||||
// The Name access, empty string returned when no m3d instance.
|
||||
std::string Name() const;
|
||||
|
||||
// Execute a save
|
||||
/// Executes a save.
|
||||
unsigned char *Save(int quality, int flags, unsigned int &size);
|
||||
|
||||
/// Clearer
|
||||
void ClearSave();
|
||||
|
||||
inline explicit operator bool() const { return m3d_ != nullptr; }
|
||||
/// True for m3d instance exists.
|
||||
explicit operator bool() const;
|
||||
|
||||
// Allow direct access to M3D API
|
||||
inline m3d_t *operator->() const { return m3d_; }
|
||||
inline m3d_t *M3D() const { return m3d_; }
|
||||
m3d_t *operator->() const;
|
||||
m3d_t *M3D() const;
|
||||
|
||||
private:
|
||||
m3d_t *m3d_ = nullptr;
|
||||
unsigned char *saved_output_ = nullptr;
|
||||
};
|
||||
|
||||
inline std::string M3DWrapper::Name() const {
|
||||
if (nullptr != m3d_) {
|
||||
if (nullptr != m3d_->name) {
|
||||
return std::string(m3d_->name);
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
inline M3DWrapper::operator bool() const {
|
||||
return m3d_ != nullptr;
|
||||
}
|
||||
|
||||
inline m3d_t *M3DWrapper::operator->() const {
|
||||
return m3d_;
|
||||
}
|
||||
|
||||
inline m3d_t *M3DWrapper::M3D() const {
|
||||
return m3d_;
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -516,13 +516,13 @@ namespace pmx
|
|||
stream->read((char*) magic, sizeof(char) * 4);
|
||||
if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20)
|
||||
{
|
||||
throw DeadlyImportError("MMD: Invalid magic number.");
|
||||
}
|
||||
throw DeadlyImportError("MMD: Invalid magic number.");
|
||||
}
|
||||
stream->read((char*) &version, sizeof(float));
|
||||
if (version != 2.0f && version != 2.1f)
|
||||
{
|
||||
throw DeadlyImportError("MMD: Unsupported version (must be 2.0 or 2.1): ", ai_to_string(version));
|
||||
}
|
||||
}
|
||||
this->setting.Read(stream);
|
||||
|
||||
this->model_name = ReadString(stream, setting.encoding);
|
||||
|
|
|
@ -162,7 +162,7 @@ void ObjFileImporter::InternReadFile(const std::string &file, aiScene *pScene, I
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Create the data from parsed obj-file
|
||||
void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene *pScene) {
|
||||
if (0L == pModel) {
|
||||
if (nullptr == pModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -468,7 +468,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
|
|||
}
|
||||
|
||||
// Copy all vertex colors
|
||||
if (!pModel->m_VertexColors.empty()) {
|
||||
if (vertex < pModel->m_VertexColors.size()) {
|
||||
const aiVector3D &color = pModel->m_VertexColors[vertex];
|
||||
pMesh->mColors[0][newIndex] = aiColor4D(color.x, color.y, color.z, 1.0);
|
||||
}
|
||||
|
|
|
@ -415,8 +415,8 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr
|
|||
|
||||
// User defined Assimp config property to detect texture type from filename.
|
||||
if (m_detectTextureTypeFromFilename) {
|
||||
size_t posSuffix = textureRef.find_last_of(".");
|
||||
size_t posUnderscore = textureRef.find_last_of("_");
|
||||
size_t posSuffix = textureRef.find_last_of('.');
|
||||
size_t posUnderscore = textureRef.find_last_of('_');
|
||||
|
||||
if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) {
|
||||
string identifier = ai_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore));
|
||||
|
|
|
@ -419,8 +419,7 @@ bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char>
|
|||
if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) {
|
||||
// add the element to the list of elements
|
||||
alElements.push_back(out);
|
||||
} else if ( TokenMatch(buffer, "end_header\r", 11) || //checks for header end with /r/n ending
|
||||
TokenMatch(buffer, "end_header", 10)) { //checks for /n ending, if it doesn't end with /r/n
|
||||
} else if (TokenMatch(buffer, "end_header", 10)) { //checks for /n ending, if it doesn't end with /r/n
|
||||
// we have reached the end of the header
|
||||
break;
|
||||
} else {
|
||||
|
@ -501,6 +500,11 @@ bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM *p_pc
|
|||
}
|
||||
|
||||
streamBuffer.getNextBlock(buffer);
|
||||
|
||||
// remove first char if it's /n in case of file with /r/n
|
||||
if (((char *)&buffer[0])[0] == '\n')
|
||||
buffer.erase(buffer.begin(), buffer.begin() + 1);
|
||||
|
||||
unsigned int bufferSize = static_cast<unsigned int>(buffer.size());
|
||||
const char *pCur = (char *)&buffer[0];
|
||||
if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) {
|
||||
|
|
|
@ -99,7 +99,7 @@ static void extractIds(const std::string &key, int &id1, int &id2) {
|
|||
return;
|
||||
}
|
||||
|
||||
const std::string::size_type pos = key.find(".");
|
||||
const std::string::size_type pos = key.find('.');
|
||||
if (std::string::npos == pos) {
|
||||
return;
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ void Q3BSPFileImporter::separateMapName(const std::string &importName, std::stri
|
|||
return;
|
||||
}
|
||||
|
||||
const std::string::size_type pos = importName.rfind(",");
|
||||
const std::string::size_type pos = importName.rfind(',');
|
||||
if (std::string::npos == pos) {
|
||||
archiveName = importName;
|
||||
return;
|
||||
|
|
|
@ -49,21 +49,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "STEPFileEncoding.h"
|
||||
#include <assimp/TinyFormatter.h>
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
namespace EXPRESS = STEP::EXPRESS;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = "")
|
||||
std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = std::string())
|
||||
{
|
||||
return line == STEP::SyntaxError::LINE_NOT_SPECIFIED ? prefix+s : static_cast<std::string>( (Formatter::format(),prefix,"(line ",line,") ",s) );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::string AddEntityID(const std::string& s,uint64_t entity /*= ENTITY_NOT_SPECIFIED*/, const std::string& prefix = "")
|
||||
std::string AddEntityID(const std::string& s,uint64_t entity /*= ENTITY_NOT_SPECIFIED*/, const std::string& prefix = std::string())
|
||||
{
|
||||
return entity == STEP::TypeError::ENTITY_NOT_SPECIFIED ? prefix+s : static_cast<std::string>( (Formatter::format(),prefix,"(entity #",entity,") ",s));
|
||||
}
|
||||
|
@ -87,7 +88,7 @@ static const char *ISO_Token = "ISO-10303-21;";
|
|||
static const char *FILE_SCHEMA_Token = "FILE_SCHEMA";
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
STEP::DB* STEP::ReadFileHeader(std::shared_ptr<IOStream> stream) {
|
||||
std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
|
||||
std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(std::move(stream)));
|
||||
std::unique_ptr<STEP::DB> db = std::unique_ptr<STEP::DB>(new STEP::DB(reader));
|
||||
|
||||
LineSplitter &splitter = db->GetSplitter();
|
||||
|
|
|
@ -634,7 +634,7 @@ private:
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(std::shared_ptr<LazyObject> lo, T whatever) {
|
||||
inline bool operator==(const std::shared_ptr<LazyObject> &lo, T whatever) {
|
||||
return *lo == whatever; // XXX use std::forward if we have 0x
|
||||
}
|
||||
|
||||
|
@ -816,7 +816,7 @@ public:
|
|||
typedef std::pair<RefMap::const_iterator, RefMap::const_iterator> RefMapRange;
|
||||
|
||||
private:
|
||||
DB(std::shared_ptr<StreamReaderLE> reader) :
|
||||
DB(const std::shared_ptr<StreamReaderLE> &reader) :
|
||||
reader(reader), splitter(*reader, true, true), evaluated_count(), schema(nullptr) {}
|
||||
|
||||
public:
|
||||
|
|
|
@ -175,12 +175,11 @@ void StepExporter::WriteFile()
|
|||
fColor.b = 0.8f;
|
||||
|
||||
int ind = 100; // the start index to be used
|
||||
int faceEntryLen = 30; // number of entries for a triangle/face
|
||||
std::vector<int> faceEntryLen; // numbers of entries for a triangle/face
|
||||
// prepare unique (count triangles and vertices)
|
||||
|
||||
VectorIndexUMap uniqueVerts; // use a map to reduce find complexity to log(n)
|
||||
VectorIndexUMap::iterator it;
|
||||
int countFace = 0;
|
||||
|
||||
for (unsigned int i=0; i<mScene->mNumMeshes; ++i)
|
||||
{
|
||||
|
@ -189,7 +188,7 @@ void StepExporter::WriteFile()
|
|||
{
|
||||
aiFace* face = &(mesh->mFaces[j]);
|
||||
|
||||
if (face->mNumIndices == 3) countFace++;
|
||||
if (face->mNumIndices >= 3) faceEntryLen.push_back(15 + 5 * face->mNumIndices);
|
||||
}
|
||||
for (unsigned int j=0; j<mesh->mNumVertices; ++j)
|
||||
{
|
||||
|
@ -218,10 +217,13 @@ void StepExporter::WriteFile()
|
|||
// write the top of data
|
||||
mOutput << "DATA" << endstr;
|
||||
mOutput << "#1=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION(' ',(";
|
||||
for (int i=0; i<countFace; ++i)
|
||||
size_t countFace = faceEntryLen.size();
|
||||
size_t faceLenIndex = ind + 2 * uniqueVerts.size();
|
||||
for (size_t i=0; i<countFace; ++i)
|
||||
{
|
||||
mOutput << "#" << i*faceEntryLen + ind + 2*uniqueVerts.size();
|
||||
mOutput << "#" << faceLenIndex;
|
||||
if (i!=countFace-1) mOutput << ",";
|
||||
faceLenIndex += faceEntryLen[i];
|
||||
}
|
||||
mOutput << "),#6)" << endstr;
|
||||
|
||||
|
@ -253,10 +255,12 @@ void StepExporter::WriteFile()
|
|||
mOutput << "#27=DIRECTION('',(1.0,0.0,0.0))" << endstr;
|
||||
mOutput << "#28= (NAMED_UNIT(#21)LENGTH_UNIT()SI_UNIT(.MILLI.,.METRE.))" << endstr;
|
||||
mOutput << "#29=CLOSED_SHELL('',(";
|
||||
for (int i=0; i<countFace; ++i)
|
||||
faceLenIndex = ind + 2 * uniqueVerts.size() + 8;
|
||||
for (size_t i=0; i<countFace; ++i)
|
||||
{
|
||||
mOutput << "#" << i*faceEntryLen + ind + 2*uniqueVerts.size() + 8;
|
||||
mOutput << "#" << faceLenIndex;
|
||||
if (i!=countFace-1) mOutput << ",";
|
||||
faceLenIndex += faceEntryLen[i];
|
||||
}
|
||||
mOutput << "))" << endstr;
|
||||
|
||||
|
@ -289,28 +293,29 @@ void StepExporter::WriteFile()
|
|||
{
|
||||
aiFace* face = &(mesh->mFaces[j]);
|
||||
|
||||
if (face->mNumIndices != 3) continue;
|
||||
const int numIndices = face->mNumIndices;
|
||||
if (numIndices < 3) continue;
|
||||
|
||||
aiVector3D* v1 = &(mesh->mVertices[face->mIndices[0]]);
|
||||
aiVector3D* v2 = &(mesh->mVertices[face->mIndices[1]]);
|
||||
aiVector3D* v3 = &(mesh->mVertices[face->mIndices[2]]);
|
||||
aiVector3D dv12 = *v2 - *v1;
|
||||
aiVector3D dv23 = *v3 - *v2;
|
||||
aiVector3D dv31 = *v1 - *v3;
|
||||
aiVector3D dv13 = *v3 - *v1;
|
||||
dv12.Normalize();
|
||||
dv23.Normalize();
|
||||
dv31.Normalize();
|
||||
dv13.Normalize();
|
||||
std::vector<int> pidArray(numIndices, -1); // vertex id
|
||||
std::vector<aiVector3D> dvArray(numIndices); // edge dir
|
||||
for (int k = 0; k < numIndices; ++k)
|
||||
{
|
||||
aiVector3D *v1 = &(mesh->mVertices[face->mIndices[k]]);
|
||||
pidArray[k] = uniqueVerts.find(v1)->second;
|
||||
|
||||
aiVector3D dvY = dv12;
|
||||
aiVector3D dvX = dvY ^ dv13;
|
||||
aiVector3D *v2 = nullptr;
|
||||
if (k + 1 == numIndices)
|
||||
v2 = &(mesh->mVertices[face->mIndices[0]]);
|
||||
else
|
||||
v2 = &(mesh->mVertices[face->mIndices[k + 1]]);
|
||||
dvArray[k] = *v2 - *v1;
|
||||
dvArray[k].Normalize();
|
||||
}
|
||||
|
||||
aiVector3D dvY = dvArray[1];
|
||||
aiVector3D dvX = dvY ^ dvArray[0];
|
||||
dvX.Normalize();
|
||||
|
||||
int pid1 = uniqueVerts.find(v1)->second;
|
||||
int pid2 = uniqueVerts.find(v2)->second;
|
||||
int pid3 = uniqueVerts.find(v3)->second;
|
||||
|
||||
// mean vertex color for the face if available
|
||||
if (mesh->HasVertexColors(0))
|
||||
{
|
||||
|
@ -339,35 +344,62 @@ void StepExporter::WriteFile()
|
|||
|
||||
/* 2 directions of the plane */
|
||||
mOutput << "#" << sid+9 << "=PLANE('',#" << sid+10 << ")" << endstr;
|
||||
mOutput << "#" << sid+10 << "=AXIS2_PLACEMENT_3D('',#" << pid1 << ", #" << sid+11 << ",#" << sid+12 << ")" << endstr;
|
||||
mOutput << "#" << sid+10 << "=AXIS2_PLACEMENT_3D('',#" << pidArray[0] << ",#" << sid+11 << ",#" << sid+12 << ")" << endstr;
|
||||
|
||||
mOutput << "#" << sid + 11 << "=DIRECTION('',(" << dvX.x << "," << dvX.y << "," << dvX.z << "))" << endstr;
|
||||
mOutput << "#" << sid + 12 << "=DIRECTION('',(" << dvY.x << "," << dvY.y << "," << dvY.z << "))" << endstr;
|
||||
|
||||
mOutput << "#" << sid+13 << "=FACE_BOUND('',#" << sid+14 << ",.T.)" << endstr;
|
||||
mOutput << "#" << sid+14 << "=EDGE_LOOP('',(#" << sid+15 << ",#" << sid+16 << ",#" << sid+17 << "))" << endstr;
|
||||
mOutput << "#" << sid+14 << "=EDGE_LOOP('',(";
|
||||
int edgeLoopStart = sid + 15;
|
||||
for (int k = 0; k < numIndices; ++k)
|
||||
{
|
||||
if (k == 0)
|
||||
mOutput << "#";
|
||||
else
|
||||
mOutput << ",#";
|
||||
mOutput << edgeLoopStart + k;
|
||||
}
|
||||
mOutput << "))" << endstr;
|
||||
|
||||
/* edge loop */
|
||||
mOutput << "#" << sid+15 << "=ORIENTED_EDGE('',*,*,#" << sid+18 << ",.T.)" << endstr;
|
||||
mOutput << "#" << sid+16 << "=ORIENTED_EDGE('',*,*,#" << sid+19 << ",.T.)" << endstr;
|
||||
mOutput << "#" << sid+17 << "=ORIENTED_EDGE('',*,*,#" << sid+20 << ",.T.)" << endstr;
|
||||
int orientedEdgesStart = edgeLoopStart + numIndices;
|
||||
for (int k=0; k < numIndices; k++)
|
||||
{
|
||||
mOutput << "#" << edgeLoopStart+k << "=ORIENTED_EDGE('',*,*,#" << orientedEdgesStart + k << ",.T.)" << endstr;
|
||||
}
|
||||
|
||||
/* oriented edges */
|
||||
mOutput << "#" << sid+18 << "=EDGE_CURVE('',#" << pid1+1 << ",#" << pid2+1 << ",#" << sid+21 << ",.F.)" << endstr;
|
||||
mOutput << "#" << sid+19 << "=EDGE_CURVE('',#" << pid2+1 << ",#" << pid3+1 << ",#" << sid+22 << ",.T.)" << endstr;
|
||||
mOutput << "#" << sid+20 << "=EDGE_CURVE('',#" << pid3+1 << ",#" << pid1+1 << ",#" << sid+23 << ",.T.)" << endstr;
|
||||
int lineStart = orientedEdgesStart + numIndices;
|
||||
for (int k=0; k < numIndices; ++k)
|
||||
{
|
||||
if (k == 0)
|
||||
mOutput << "#" << orientedEdgesStart+k << "=EDGE_CURVE('',#" << pidArray[k]+1 << ",#" << pidArray[k+1]+1 << ",#" << lineStart+k << ",.F.)" << endstr;
|
||||
else if (k+1 == numIndices)
|
||||
mOutput << "#" << orientedEdgesStart+k << "=EDGE_CURVE('',#" << pidArray[k]+1 << ",#" << pidArray[0]+1 << ",#" << lineStart+k << ",.T.)" << endstr;
|
||||
else
|
||||
mOutput << "#" << orientedEdgesStart+k << "=EDGE_CURVE('',#" << pidArray[k]+1 << ",#" << pidArray[k+1]+1 << ",#" << lineStart+k << ",.T.)" << endstr;
|
||||
}
|
||||
|
||||
/* 3 lines and 3 vectors for the lines for the 3 edge curves */
|
||||
mOutput << "#" << sid+21 << "=LINE('',#" << pid1 << ",#" << sid+24 << ")" << endstr;
|
||||
mOutput << "#" << sid+22 << "=LINE('',#" << pid2 << ",#" << sid+25 << ")" << endstr;
|
||||
mOutput << "#" << sid+23 << "=LINE('',#" << pid3 << ",#" << sid+26 << ")" << endstr;
|
||||
mOutput << "#" << sid+24 << "=VECTOR('',#" << sid+27 << ",1.0)" << endstr;
|
||||
mOutput << "#" << sid+25 << "=VECTOR('',#" << sid+28 << ",1.0)" << endstr;
|
||||
mOutput << "#" << sid+26 << "=VECTOR('',#" << sid+29 << ",1.0)" << endstr;
|
||||
mOutput << "#" << sid+27 << "=DIRECTION('',(" << dv12.x << "," << dv12.y << "," << dv12.z << "))" << endstr;
|
||||
mOutput << "#" << sid+28 << "=DIRECTION('',(" << dv23.x << "," << dv23.y << "," << dv23.z << "))" << endstr;
|
||||
mOutput << "#" << sid+29 << "=DIRECTION('',(" << dv31.x << "," << dv31.y << "," << dv31.z << "))" << endstr;
|
||||
ind += faceEntryLen; // increase counter
|
||||
/* n lines and n vectors for the lines for the n edge curves */
|
||||
int vectorStart = lineStart + numIndices;
|
||||
for (int k=0; k < numIndices; ++k)
|
||||
{
|
||||
mOutput << "#" << lineStart+k << "=LINE('',#" << pidArray[k] << ",#" << vectorStart+k << ")" << endstr;
|
||||
}
|
||||
|
||||
int directionStart = vectorStart + numIndices;
|
||||
for (int k=0; k < numIndices; ++k)
|
||||
{
|
||||
mOutput << "#" << vectorStart+k << "=VECTOR('',#" << directionStart+k << ",1.0)" << endstr;
|
||||
}
|
||||
|
||||
for (int k=0; k < numIndices; ++k)
|
||||
{
|
||||
const aiVector3D &dv = dvArray[k];
|
||||
mOutput << "#" << directionStart + k << "=DIRECTION('',(" << dv.x << "," << dv.y << "," << dv.z << "))" << endstr;
|
||||
}
|
||||
ind += 15 + 5*numIndices; // increase counter
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -530,8 +530,8 @@ void XFileExporter::writePath(const aiString &path)
|
|||
while( str.find( "\\\\") != std::string::npos)
|
||||
str.replace( str.find( "\\\\"), 2, "\\");
|
||||
|
||||
while( str.find( "\\") != std::string::npos)
|
||||
str.replace( str.find( "\\"), 1, "/");
|
||||
while (str.find('\\') != std::string::npos)
|
||||
str.replace(str.find('\\'), 1, "/");
|
||||
|
||||
mOutput << str;
|
||||
|
||||
|
|
|
@ -667,9 +667,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Materi
|
|||
|
||||
// convert to lower case for easier comparison
|
||||
for ( unsigned int c = 0; c < sz.length(); ++c ) {
|
||||
if ( isalpha( (unsigned char) sz[ c ] ) ) {
|
||||
sz[ c ] = (char) tolower( (unsigned char) sz[ c ] );
|
||||
}
|
||||
sz[ c ] = (char) tolower( (unsigned char) sz[ c ] );
|
||||
}
|
||||
|
||||
// Place texture filename property under the corresponding name
|
||||
|
|
|
@ -63,9 +63,9 @@ class X3DExporter {
|
|||
// empty
|
||||
}
|
||||
|
||||
SAttribute(SAttribute && rhs) :
|
||||
Name(std::move(rhs.Name)),
|
||||
Value(std::move(rhs.Value)) {
|
||||
SAttribute(SAttribute &&rhs) AI_NO_EXCEPT :
|
||||
Name(rhs.Name),
|
||||
Value(rhs.Value) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2890,7 +2890,6 @@ void X3DImporter::Postprocess_CollectMetadata(const CX3DImporter_NodeElement &pN
|
|||
} // if( !meta_list.empty() )
|
||||
}
|
||||
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
} // namespace Assimp
|
||||
|
|
|
@ -250,7 +250,7 @@ void XGLImporter::ReadWorld(XmlNode &node, TempScope &scope) {
|
|||
}
|
||||
}
|
||||
|
||||
aiNode *const nd = ReadObject(node, scope, true);
|
||||
aiNode *const nd = ReadObject(node, scope);
|
||||
if (!nd) {
|
||||
ThrowException("failure reading <world>");
|
||||
}
|
||||
|
@ -296,16 +296,13 @@ aiLight *XGLImporter::ReadDirectionalLight(XmlNode &node) {
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope, bool skipFirst/*, const char *closetag */) {
|
||||
aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope) {
|
||||
aiNode *nd = new aiNode;
|
||||
std::vector<aiNode *> children;
|
||||
std::vector<unsigned int> meshes;
|
||||
|
||||
try {
|
||||
for (XmlNode &child : node.children()) {
|
||||
|
||||
skipFirst = false;
|
||||
|
||||
const std::string &s = ai_stdStrToLower(child.name());
|
||||
if (s == "mesh") {
|
||||
const size_t prev = scope.meshes_linear.size();
|
||||
|
|
|
@ -185,7 +185,7 @@ private:
|
|||
void ReadWorld(XmlNode &node, TempScope &scope);
|
||||
void ReadLighting(XmlNode &node, TempScope &scope);
|
||||
aiLight *ReadDirectionalLight(XmlNode &node);
|
||||
aiNode *ReadObject(XmlNode &node, TempScope &scope, bool skipFirst = false/*, const char *closetag = "object"*/);
|
||||
aiNode *ReadObject(XmlNode &node, TempScope &scope);
|
||||
bool ReadMesh(XmlNode &node, TempScope &scope);
|
||||
void ReadMaterial(XmlNode &node, TempScope &scope);
|
||||
aiVector2D ReadVec2(XmlNode &node);
|
||||
|
|
|
@ -456,11 +456,10 @@ namespace glTF
|
|||
/// \param [in] pDecodedData - pointer to decoded data array.
|
||||
/// \param [in] pDecodedData_Length - size of encoded region, in bytes.
|
||||
/// \param [in] pID - ID of the region.
|
||||
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)
|
||||
{}
|
||||
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()
|
||||
/// \fn ~SEncodedRegion()
|
||||
/// Destructor.
|
||||
~SEncodedRegion() { delete [] DecodedData; }
|
||||
};
|
||||
|
@ -1149,8 +1148,7 @@ namespace glTF
|
|||
|
||||
void ReadExtensionsUsed(Document& doc);
|
||||
|
||||
|
||||
IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
|
||||
IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1377,7 +1377,7 @@ inline void Asset::ReadExtensionsUsed(Document &doc) {
|
|||
#undef CHECK_EXT
|
||||
}
|
||||
|
||||
inline IOStream *Asset::OpenFile(std::string path, const char *mode, bool absolute) {
|
||||
inline IOStream *Asset::OpenFile(const std::string& path, const char *mode, bool absolute) {
|
||||
#ifdef ASSIMP_API
|
||||
(void)absolute;
|
||||
return mIOSystem->Open(path, mode);
|
||||
|
|
|
@ -195,11 +195,11 @@ inline void CopyValue(const glTFCommon::mat4 &v, aiMatrix4x4 &o) {
|
|||
inline std::string getCurrentAssetDir(const std::string &pFile) {
|
||||
std::string path = pFile;
|
||||
int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\')));
|
||||
if (pos != int(std::string::npos)) {
|
||||
path = pFile.substr(0, pos + 1);
|
||||
if (pos == int(std::string::npos)) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return path;
|
||||
return pFile.substr(0, pos + 1);
|
||||
}
|
||||
#if _MSC_VER
|
||||
# pragma warning(pop)
|
||||
|
|
|
@ -408,8 +408,7 @@ void glTFExporter::ExportMaterials()
|
|||
* Search through node hierarchy and find the node containing the given meshID.
|
||||
* Returns true on success, and false otherwise.
|
||||
*/
|
||||
bool FindMeshNode(Ref<Node>& nodeIn, Ref<Node>& meshNode, std::string meshID)
|
||||
{
|
||||
bool FindMeshNode(Ref<Node> &nodeIn, Ref<Node> &meshNode, const std::string &meshID) {
|
||||
for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) {
|
||||
if (meshID.compare(nodeIn->meshes[i]->id) == 0) {
|
||||
meshNode = nodeIn;
|
||||
|
@ -530,6 +529,7 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buf
|
|||
|
||||
#if defined(__has_warning)
|
||||
#if __has_warning("-Wunused-but-set-variable")
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -356,6 +356,53 @@ struct Nullable {
|
|||
isPresent(true) {}
|
||||
};
|
||||
|
||||
struct CustomExtension {
|
||||
//
|
||||
// A struct containing custom extension data added to a glTF2 file
|
||||
// Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum
|
||||
// String, Double, Uint64, and Int64 are stored in the Nullables
|
||||
// Object and Array are stored in the std::vector
|
||||
//
|
||||
std::string name;
|
||||
|
||||
Nullable<std::string> mStringValue;
|
||||
Nullable<double> mDoubleValue;
|
||||
Nullable<uint64_t> mUint64Value;
|
||||
Nullable<int64_t> mInt64Value;
|
||||
Nullable<bool> mBoolValue;
|
||||
|
||||
// std::vector<CustomExtension> handles both Object and Array
|
||||
Nullable<std::vector<CustomExtension>> mValues;
|
||||
|
||||
operator bool() const {
|
||||
return Size() != 0;
|
||||
}
|
||||
|
||||
size_t Size() const {
|
||||
if (mValues.isPresent) {
|
||||
return mValues.value.size();
|
||||
} else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CustomExtension() = default;
|
||||
|
||||
~CustomExtension() = default;
|
||||
|
||||
CustomExtension(const CustomExtension &other) :
|
||||
name(other.name),
|
||||
mStringValue(other.mStringValue),
|
||||
mDoubleValue(other.mDoubleValue),
|
||||
mUint64Value(other.mUint64Value),
|
||||
mInt64Value(other.mInt64Value),
|
||||
mBoolValue(other.mBoolValue),
|
||||
mValues(other.mValues) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
//! Base class for all glTF top-level objects
|
||||
struct Object {
|
||||
int index; //!< The index of this object within its property container
|
||||
|
@ -363,6 +410,9 @@ struct Object {
|
|||
std::string id; //!< The globally unique ID used to reference this object
|
||||
std::string name; //!< The user-defined name of this object
|
||||
|
||||
CustomExtension customExtensions;
|
||||
CustomExtension extras;
|
||||
|
||||
//! Objects marked as special are not exported (used to emulate the binary body buffer)
|
||||
virtual bool IsSpecial() const { return false; }
|
||||
|
||||
|
@ -377,6 +427,9 @@ struct Object {
|
|||
inline Value *FindArray(Value &val, const char *id);
|
||||
inline Value *FindObject(Value &val, const char *id);
|
||||
inline Value *FindExtension(Value &val, const char *extensionId);
|
||||
|
||||
inline void ReadExtensions(Value &val);
|
||||
inline void ReadExtras(Value &val);
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -408,7 +461,7 @@ public:
|
|||
/// \param [in] pDecodedData - pointer to decoded data array.
|
||||
/// \param [in] pDecodedData_Length - size of encoded region, in bytes.
|
||||
/// \param [in] pID - ID of the region.
|
||||
SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string pID) :
|
||||
SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) :
|
||||
Offset(pOffset),
|
||||
EncodedData_Length(pEncodedData_Length),
|
||||
DecodedData(pDecodedData),
|
||||
|
@ -834,50 +887,6 @@ struct Mesh : public Object {
|
|||
void Read(Value &pJSON_Object, Asset &pAsset_Root);
|
||||
};
|
||||
|
||||
struct CustomExtension : public Object {
|
||||
//
|
||||
// A struct containing custom extension data added to a glTF2 file
|
||||
// Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum
|
||||
// String, Double, Uint64, and Int64 are stored in the Nullables
|
||||
// Object and Array are stored in the std::vector
|
||||
//
|
||||
|
||||
Nullable<std::string> mStringValue;
|
||||
Nullable<double> mDoubleValue;
|
||||
Nullable<uint64_t> mUint64Value;
|
||||
Nullable<int64_t> mInt64Value;
|
||||
Nullable<bool> mBoolValue;
|
||||
|
||||
// std::vector<CustomExtension> handles both Object and Array
|
||||
Nullable<std::vector<CustomExtension>> mValues;
|
||||
|
||||
operator bool() const {
|
||||
return Size() != 0;
|
||||
}
|
||||
|
||||
size_t Size() const {
|
||||
if (mValues.isPresent) {
|
||||
return mValues.value.size();
|
||||
} else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CustomExtension() = default;
|
||||
|
||||
CustomExtension(const CustomExtension &other)
|
||||
: Object(other)
|
||||
, mStringValue(other.mStringValue)
|
||||
, mDoubleValue(other.mDoubleValue)
|
||||
, mUint64Value(other.mUint64Value)
|
||||
, mInt64Value(other.mInt64Value)
|
||||
, mBoolValue(other.mBoolValue)
|
||||
, mValues(other.mValues)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct Node : public Object {
|
||||
std::vector<Ref<Node>> children;
|
||||
std::vector<Ref<Mesh>> meshes;
|
||||
|
@ -896,8 +905,6 @@ struct Node : public Object {
|
|||
|
||||
Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
|
||||
|
||||
CustomExtension extensions;
|
||||
|
||||
Node() {}
|
||||
void Read(Value &obj, Asset &r);
|
||||
};
|
||||
|
@ -1188,7 +1195,7 @@ private:
|
|||
void ReadExtensionsUsed(Document &doc);
|
||||
void ReadExtensionsRequired(Document &doc);
|
||||
|
||||
IOStream *OpenFile(std::string path, const char *mode, bool absolute = false);
|
||||
IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
|
||||
};
|
||||
|
||||
inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {
|
||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2021, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
@ -304,6 +303,43 @@ inline Value *FindObject(Document &doc, const char *memberId) {
|
|||
inline Value *FindExtension(Value &val, const char *extensionId) {
|
||||
return FindExtensionInContext(val, extensionId, "the document");
|
||||
}
|
||||
|
||||
inline CustomExtension ReadExtensions(const char *name, Value &obj) {
|
||||
CustomExtension ret;
|
||||
ret.name = name;
|
||||
if (obj.IsObject()) {
|
||||
ret.mValues.isPresent = true;
|
||||
for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) {
|
||||
auto &val = it->value;
|
||||
ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val));
|
||||
}
|
||||
} else if (obj.IsArray()) {
|
||||
ret.mValues.value.reserve(obj.Size());
|
||||
ret.mValues.isPresent = true;
|
||||
for (unsigned int i = 0; i < obj.Size(); ++i) {
|
||||
ret.mValues.value.push_back(ReadExtensions(name, obj[i]));
|
||||
}
|
||||
} else if (obj.IsNumber()) {
|
||||
if (obj.IsUint64()) {
|
||||
ret.mUint64Value.value = obj.GetUint64();
|
||||
ret.mUint64Value.isPresent = true;
|
||||
} else if (obj.IsInt64()) {
|
||||
ret.mInt64Value.value = obj.GetInt64();
|
||||
ret.mInt64Value.isPresent = true;
|
||||
} else if (obj.IsDouble()) {
|
||||
ret.mDoubleValue.value = obj.GetDouble();
|
||||
ret.mDoubleValue.isPresent = true;
|
||||
}
|
||||
} else if (obj.IsString()) {
|
||||
ReadValue(obj, ret.mStringValue);
|
||||
ret.mStringValue.isPresent = true;
|
||||
} else if (obj.IsBool()) {
|
||||
ret.mBoolValue.value = obj.GetBool();
|
||||
ret.mBoolValue.isPresent = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
inline Value *Object::FindString(Value &val, const char *memberId) {
|
||||
|
@ -330,6 +366,18 @@ inline Value *Object::FindExtension(Value &val, const char *extensionId) {
|
|||
return FindExtensionInContext(val, extensionId, id.c_str(), name.c_str());
|
||||
}
|
||||
|
||||
inline void Object::ReadExtensions(Value &val) {
|
||||
if (Value *curExtensions = FindObject(val, "extensions")) {
|
||||
this->customExtensions = glTF2::ReadExtensions("extensions", *curExtensions);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Object::ReadExtras(Value &val) {
|
||||
if (Value *curExtras = FindObject(val, "extras")) {
|
||||
this->extras = glTF2::ReadExtensions("extras", *curExtras);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSIMP_ENABLE_DRACO
|
||||
|
||||
template <typename T>
|
||||
|
@ -569,6 +617,8 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
|
|||
inst->oIndex = i;
|
||||
ReadMember(obj, "name", inst->name);
|
||||
inst->Read(obj, mAsset);
|
||||
inst->ReadExtensions(obj);
|
||||
inst->ReadExtras(obj);
|
||||
|
||||
Ref<T> result = Add(inst.release());
|
||||
mRecursiveReferenceCheck.erase(i);
|
||||
|
@ -733,12 +783,13 @@ inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncod
|
|||
}
|
||||
|
||||
inline void Buffer::EncodedRegion_SetCurrent(const std::string &pID) {
|
||||
if ((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) return;
|
||||
if ((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (SEncodedRegion *reg : EncodedRegion_List) {
|
||||
if (reg->ID == pID) {
|
||||
EncodedRegion_Current = reg;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -788,10 +839,13 @@ inline bool Buffer::ReplaceData_joint(const size_t pBufferData_Offset, const siz
|
|||
}
|
||||
|
||||
inline size_t Buffer::AppendData(uint8_t *data, size_t length) {
|
||||
size_t offset = this->byteLength;
|
||||
const size_t offset = this->byteLength;
|
||||
|
||||
// Force alignment to 4 bits
|
||||
Grow((length + 3) & ~3);
|
||||
const size_t paddedLength = (length + 3) & ~3;
|
||||
Grow(paddedLength);
|
||||
memcpy(mData.get() + offset, data, length);
|
||||
memset(mData.get() + offset + length, 0, paddedLength - length);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -820,9 +874,7 @@ inline void Buffer::Grow(size_t amount) {
|
|||
//
|
||||
// struct BufferView
|
||||
//
|
||||
|
||||
inline void BufferView::Read(Value &obj, Asset &r) {
|
||||
|
||||
if (Value *bufferVal = FindUInt(obj, "buffer")) {
|
||||
buffer = r.buffers.Retrieve(bufferVal->GetUint());
|
||||
}
|
||||
|
@ -842,16 +894,21 @@ inline void BufferView::Read(Value &obj, Asset &r) {
|
|||
}
|
||||
|
||||
inline uint8_t *BufferView::GetPointer(size_t accOffset) {
|
||||
if (!buffer) return nullptr;
|
||||
if (!buffer) {
|
||||
return nullptr;
|
||||
}
|
||||
uint8_t *basePtr = buffer->GetPointer();
|
||||
if (!basePtr) return nullptr;
|
||||
if (!basePtr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t offset = accOffset + byteOffset;
|
||||
if (buffer->EncodedRegion_Current != nullptr) {
|
||||
const size_t begin = buffer->EncodedRegion_Current->Offset;
|
||||
const size_t end = begin + buffer->EncodedRegion_Current->DecodedData_Length;
|
||||
if ((offset >= begin) && (offset < end))
|
||||
if ((offset >= begin) && (offset < end)) {
|
||||
return &buffer->EncodedRegion_Current->DecodedData[offset - begin];
|
||||
}
|
||||
}
|
||||
|
||||
return basePtr + offset;
|
||||
|
@ -877,18 +934,18 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) {
|
|||
while (pIndices != indicesEnd) {
|
||||
size_t offset;
|
||||
switch (indicesType) {
|
||||
case ComponentType_UNSIGNED_BYTE:
|
||||
offset = *pIndices;
|
||||
break;
|
||||
case ComponentType_UNSIGNED_SHORT:
|
||||
offset = *reinterpret_cast<uint16_t *>(pIndices);
|
||||
break;
|
||||
case ComponentType_UNSIGNED_INT:
|
||||
offset = *reinterpret_cast<uint32_t *>(pIndices);
|
||||
break;
|
||||
default:
|
||||
// have fun with float and negative values from signed types as indices.
|
||||
throw DeadlyImportError("Unsupported component type in index.");
|
||||
case ComponentType_UNSIGNED_BYTE:
|
||||
offset = *pIndices;
|
||||
break;
|
||||
case ComponentType_UNSIGNED_SHORT:
|
||||
offset = *reinterpret_cast<uint16_t *>(pIndices);
|
||||
break;
|
||||
case ComponentType_UNSIGNED_INT:
|
||||
offset = *reinterpret_cast<uint32_t *>(pIndices);
|
||||
break;
|
||||
default:
|
||||
// have fun with float and negative values from signed types as indices.
|
||||
throw DeadlyImportError("Unsupported component type in index.");
|
||||
}
|
||||
|
||||
offset *= elementSize;
|
||||
|
@ -900,7 +957,6 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) {
|
|||
}
|
||||
|
||||
inline void Accessor::Read(Value &obj, Asset &r) {
|
||||
|
||||
if (Value *bufferViewVal = FindUInt(obj, "bufferView")) {
|
||||
bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
|
||||
}
|
||||
|
@ -909,9 +965,9 @@ inline void Accessor::Read(Value &obj, Asset &r) {
|
|||
componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
|
||||
{
|
||||
const Value* countValue = FindUInt(obj, "count");
|
||||
if (!countValue || countValue->GetUint() < 1)
|
||||
if (!countValue)
|
||||
{
|
||||
throw DeadlyImportError("A strictly positive count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
|
||||
throw DeadlyImportError("A count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
|
||||
}
|
||||
count = countValue->GetUint();
|
||||
}
|
||||
|
@ -1466,7 +1522,7 @@ inline bool GetAttribTargetVector(Mesh::Primitive &p, const int targetIndex, con
|
|||
|
||||
inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
|
||||
Value *curName = FindMember(pJSON_Object, "name");
|
||||
if (nullptr != curName) {
|
||||
if (nullptr != curName && curName->IsString()) {
|
||||
name = curName->GetString();
|
||||
}
|
||||
|
||||
|
@ -1612,9 +1668,9 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
|
|||
}
|
||||
}
|
||||
|
||||
Value *extras = FindObject(pJSON_Object, "extras");
|
||||
if (nullptr != extras) {
|
||||
if (Value *curTargetNames = FindArray(*extras, "targetNames")) {
|
||||
Value *curExtras = FindObject(pJSON_Object, "extras");
|
||||
if (nullptr != curExtras) {
|
||||
if (Value *curTargetNames = FindArray(*curExtras, "targetNames")) {
|
||||
this->targetNames.resize(curTargetNames->Size());
|
||||
for (unsigned int i = 0; i < curTargetNames->Size(); ++i) {
|
||||
Value &targetNameValue = (*curTargetNames)[i];
|
||||
|
@ -1683,42 +1739,6 @@ inline void Light::Read(Value &obj, Asset & /*r*/) {
|
|||
}
|
||||
}
|
||||
|
||||
inline CustomExtension ReadExtensions(const char *name, Value &obj) {
|
||||
CustomExtension ret;
|
||||
ret.name = name;
|
||||
if (obj.IsObject()) {
|
||||
ret.mValues.isPresent = true;
|
||||
for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) {
|
||||
auto &val = it->value;
|
||||
ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val));
|
||||
}
|
||||
} else if (obj.IsArray()) {
|
||||
ret.mValues.value.reserve(obj.Size());
|
||||
ret.mValues.isPresent = true;
|
||||
for (unsigned int i = 0; i < obj.Size(); ++i) {
|
||||
ret.mValues.value.push_back(ReadExtensions(name, obj[i]));
|
||||
}
|
||||
} else if (obj.IsNumber()) {
|
||||
if (obj.IsUint64()) {
|
||||
ret.mUint64Value.value = obj.GetUint64();
|
||||
ret.mUint64Value.isPresent = true;
|
||||
} else if (obj.IsInt64()) {
|
||||
ret.mInt64Value.value = obj.GetInt64();
|
||||
ret.mInt64Value.isPresent = true;
|
||||
} else if (obj.IsDouble()) {
|
||||
ret.mDoubleValue.value = obj.GetDouble();
|
||||
ret.mDoubleValue.isPresent = true;
|
||||
}
|
||||
} else if (obj.IsString()) {
|
||||
ReadValue(obj, ret.mStringValue);
|
||||
ret.mStringValue.isPresent = true;
|
||||
} else if (obj.IsBool()) {
|
||||
ret.mBoolValue.value = obj.GetBool();
|
||||
ret.mBoolValue.isPresent = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline void Node::Read(Value &obj, Asset &r) {
|
||||
if (name.empty()) {
|
||||
name = id;
|
||||
|
@ -1775,8 +1795,6 @@ inline void Node::Read(Value &obj, Asset &r) {
|
|||
|
||||
Value *curExtensions = FindObject(obj, "extensions");
|
||||
if (nullptr != curExtensions) {
|
||||
this->extensions = ReadExtensions("extensions", *curExtensions);
|
||||
|
||||
if (r.extensionsUsed.KHR_lights_punctual) {
|
||||
if (Value *ext = FindObject(*curExtensions, "KHR_lights_punctual")) {
|
||||
Value *curLight = FindUInt(*ext, "light");
|
||||
|
@ -2132,7 +2150,7 @@ inline void Asset::ReadExtensionsUsed(Document &doc) {
|
|||
#undef CHECK_EXT
|
||||
}
|
||||
|
||||
inline IOStream *Asset::OpenFile(std::string path, const char *mode, bool /*absolute*/) {
|
||||
inline IOStream *Asset::OpenFile(const std::string& path, const char *mode, bool /*absolute*/) {
|
||||
#ifdef ASSIMP_API
|
||||
return mIOSystem->Open(path, mode);
|
||||
#else
|
||||
|
|
|
@ -88,15 +88,13 @@ namespace Assimp {
|
|||
} // end of namespace Assimp
|
||||
|
||||
glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
|
||||
const ExportProperties* pProperties, bool isBinary)
|
||||
const ExportProperties* pProperties, bool isBinary)
|
||||
: mFilename(filename)
|
||||
, mIOSystem(pIOSystem)
|
||||
, mScene(pScene)
|
||||
, mProperties(pProperties)
|
||||
, mAsset(new Asset(pIOSystem))
|
||||
{
|
||||
mScene = pScene;
|
||||
|
||||
mAsset.reset( new Asset( pIOSystem ) );
|
||||
|
||||
// Always on as our triangulation process is aware of this type of encoding
|
||||
mAsset->extensionsUsed.FB_ngon_encoding = true;
|
||||
|
||||
|
@ -436,11 +434,11 @@ inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map)
|
|||
};
|
||||
}
|
||||
|
||||
void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture, aiTextureType tt, unsigned int slot)
|
||||
void glTF2Exporter::GetTexSampler(const aiMaterial& mat, Ref<Texture> texture, aiTextureType tt, unsigned int slot)
|
||||
{
|
||||
aiString aId;
|
||||
std::string id;
|
||||
if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) {
|
||||
if (aiGetMaterialString(&mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) {
|
||||
id = aId.C_Str();
|
||||
}
|
||||
|
||||
|
@ -455,49 +453,52 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture, a
|
|||
SamplerMagFilter filterMag;
|
||||
SamplerMinFilter filterMin;
|
||||
|
||||
if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) {
|
||||
if (aiGetMaterialInteger(&mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) {
|
||||
SetSamplerWrap(texture->sampler->wrapS, mapU);
|
||||
}
|
||||
|
||||
if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) {
|
||||
if (aiGetMaterialInteger(&mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) {
|
||||
SetSamplerWrap(texture->sampler->wrapT, mapV);
|
||||
}
|
||||
|
||||
if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) {
|
||||
if (aiGetMaterialInteger(&mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) {
|
||||
texture->sampler->magFilter = filterMag;
|
||||
}
|
||||
|
||||
if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) {
|
||||
if (aiGetMaterialInteger(&mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) {
|
||||
texture->sampler->minFilter = filterMin;
|
||||
}
|
||||
|
||||
aiString name;
|
||||
if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) {
|
||||
if (aiGetMaterialString(&mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) {
|
||||
texture->sampler->name = name.C_Str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot)
|
||||
void glTF2Exporter::GetMatTexProp(const aiMaterial& mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot)
|
||||
{
|
||||
std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
|
||||
|
||||
mat->Get(textureKey.c_str(), tt, slot, prop);
|
||||
mat.Get(textureKey.c_str(), tt, slot, prop);
|
||||
}
|
||||
|
||||
void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot)
|
||||
void glTF2Exporter::GetMatTexProp(const aiMaterial& mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot)
|
||||
{
|
||||
std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
|
||||
|
||||
mat->Get(textureKey.c_str(), tt, slot, prop);
|
||||
mat.Get(textureKey.c_str(), tt, slot, prop);
|
||||
}
|
||||
|
||||
void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt, unsigned int slot = 0)
|
||||
void glTF2Exporter::GetMatTex(const aiMaterial& mat, Ref<Texture>& texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0)
|
||||
{
|
||||
if (mat->GetTextureCount(tt) > 0) {
|
||||
if (mat.GetTextureCount(tt) > 0) {
|
||||
aiString tex;
|
||||
|
||||
if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
|
||||
// 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 (path.size() > 0) {
|
||||
|
@ -515,9 +516,8 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
|
|||
std::string imgId = mAsset->FindUniqueID("", "image");
|
||||
texture->source = mAsset->images.Create(imgId);
|
||||
|
||||
if (path[0] == '*') { // embedded
|
||||
aiTexture* curTex = mScene->mTextures[atoi(&path[1])];
|
||||
|
||||
const aiTexture* curTex = mScene->GetEmbeddedTexture(path.c_str());
|
||||
if (curTex != nullptr) { // embedded
|
||||
texture->source->name = curTex->mFilename.C_Str();
|
||||
|
||||
//basisu: embedded ktx2, bu
|
||||
|
@ -568,45 +568,45 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
|
|||
}
|
||||
}
|
||||
|
||||
void glTF2Exporter::GetMatTex(const aiMaterial* mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
|
||||
void glTF2Exporter::GetMatTex(const aiMaterial& mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
|
||||
{
|
||||
Ref<Texture>& texture = prop.texture;
|
||||
|
||||
GetMatTex(mat, texture, tt, slot);
|
||||
GetMatTex(mat, texture, prop.texCoord, tt, slot);
|
||||
|
||||
if (texture) {
|
||||
GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
||||
}
|
||||
//if (texture) {
|
||||
// GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
||||
//}
|
||||
}
|
||||
|
||||
void glTF2Exporter::GetMatTex(const aiMaterial* mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
|
||||
void glTF2Exporter::GetMatTex(const aiMaterial& mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
|
||||
{
|
||||
Ref<Texture>& texture = prop.texture;
|
||||
|
||||
GetMatTex(mat, texture, tt, slot);
|
||||
GetMatTex(mat, texture, prop.texCoord, tt, slot);
|
||||
|
||||
if (texture) {
|
||||
GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
||||
//GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
||||
GetMatTexProp(mat, prop.scale, "scale", tt, slot);
|
||||
}
|
||||
}
|
||||
|
||||
void glTF2Exporter::GetMatTex(const aiMaterial* mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
|
||||
void glTF2Exporter::GetMatTex(const aiMaterial& mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
|
||||
{
|
||||
Ref<Texture>& texture = prop.texture;
|
||||
|
||||
GetMatTex(mat, texture, tt, slot);
|
||||
GetMatTex(mat, texture, prop.texCoord, tt, slot);
|
||||
|
||||
if (texture) {
|
||||
GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
||||
//GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
||||
GetMatTexProp(mat, prop.strength, "strength", tt, slot);
|
||||
}
|
||||
}
|
||||
|
||||
aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx)
|
||||
aiReturn glTF2Exporter::GetMatColor(const aiMaterial& mat, vec4& prop, const char* propName, int type, int idx) const
|
||||
{
|
||||
aiColor4D col;
|
||||
aiReturn result = mat->Get(propName, type, idx, col);
|
||||
aiReturn result = mat.Get(propName, type, idx, col);
|
||||
|
||||
if (result == AI_SUCCESS) {
|
||||
prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a;
|
||||
|
@ -615,37 +615,116 @@ aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const cha
|
|||
return result;
|
||||
}
|
||||
|
||||
aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx)
|
||||
aiReturn glTF2Exporter::GetMatColor(const aiMaterial& mat, vec3& prop, const char* propName, int type, int idx) const
|
||||
{
|
||||
aiColor3D col;
|
||||
aiReturn result = mat->Get(propName, type, idx, col);
|
||||
aiReturn result = mat.Get(propName, type, idx, col);
|
||||
|
||||
if (result == AI_SUCCESS) {
|
||||
prop[0] = col.r; prop[1] = col.g; prop[2] = col.b;
|
||||
prop[0] = col.r;
|
||||
prop[1] = col.g;
|
||||
prop[2] = col.b;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool glTF2Exporter::GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlossiness &pbrSG) {
|
||||
bool result = false;
|
||||
// If has Glossiness, a Specular Color or Specular Texture, use the KHR_materials_pbrSpecularGlossiness extension
|
||||
// NOTE: This extension is being considered for deprecation (Dec 2020), may be replaced by KHR_material_specular
|
||||
|
||||
if (mat.Get(AI_MATKEY_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) == AI_SUCCESS) {
|
||||
result = true;
|
||||
} else {
|
||||
// Don't have explicit glossiness, convert from pbr roughness or legacy shininess
|
||||
float shininess;
|
||||
if (mat.Get(AI_MATKEY_ROUGHNESS_FACTOR, shininess) == AI_SUCCESS) {
|
||||
pbrSG.glossinessFactor = 1.0f - shininess; // Extension defines this way
|
||||
} else if (mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
|
||||
pbrSG.glossinessFactor = shininess / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR) == AI_SUCCESS) {
|
||||
result = true;
|
||||
}
|
||||
// Add any appropriate textures
|
||||
GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR);
|
||||
|
||||
result = result || pbrSG.specularGlossinessTexture.texture;
|
||||
|
||||
if (result) {
|
||||
// Likely to always have diffuse
|
||||
GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE);
|
||||
GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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)
|
||||
return false;
|
||||
|
||||
// Default Sheen color factor {0,0,0} disables Sheen, so do not export
|
||||
if (sheen.sheenColorFactor == defaultSheenFactor)
|
||||
return false;
|
||||
|
||||
mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor);
|
||||
|
||||
GetMatTex(mat, sheen.sheenColorTexture, AI_MATKEY_SHEEN_COLOR_TEXTURE);
|
||||
GetMatTex(mat, sheen.sheenRoughnessTexture, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool glTF2Exporter::GetMatClearcoat(const aiMaterial &mat, glTF2::MaterialClearcoat &clearcoat) {
|
||||
if (mat.Get(AI_MATKEY_CLEARCOAT_FACTOR, clearcoat.clearcoatFactor) != aiReturn_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clearcoat factor of zero disables Clearcoat, so do not export
|
||||
if (clearcoat.clearcoatFactor == 0.0f)
|
||||
return false;
|
||||
|
||||
mat.Get(AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat.clearcoatRoughnessFactor);
|
||||
|
||||
GetMatTex(mat, clearcoat.clearcoatTexture, AI_MATKEY_CLEARCOAT_TEXTURE);
|
||||
GetMatTex(mat, clearcoat.clearcoatRoughnessTexture, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE);
|
||||
GetMatTex(mat, clearcoat.clearcoatNormalTexture, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool glTF2Exporter::GetMatTransmission(const aiMaterial &mat, glTF2::MaterialTransmission &transmission) {
|
||||
bool result = mat.Get(AI_MATKEY_TRANSMISSION_FACTOR, transmission.transmissionFactor) == aiReturn_SUCCESS;
|
||||
GetMatTex(mat, transmission.transmissionTexture, AI_MATKEY_TRANSMISSION_TEXTURE);
|
||||
return result || transmission.transmissionTexture.texture;
|
||||
}
|
||||
|
||||
void glTF2Exporter::ExportMaterials()
|
||||
{
|
||||
aiString aiName;
|
||||
for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
|
||||
const aiMaterial* mat = mScene->mMaterials[i];
|
||||
ai_assert(mScene->mMaterials[i] != nullptr);
|
||||
|
||||
const aiMaterial & mat = *(mScene->mMaterials[i]);
|
||||
|
||||
std::string id = "material_" + ai_to_string(i);
|
||||
|
||||
Ref<Material> m = mAsset->materials.Create(id);
|
||||
|
||||
std::string name;
|
||||
if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) {
|
||||
if (mat.Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) {
|
||||
name = aiName.C_Str();
|
||||
}
|
||||
name = mAsset->FindUniqueID(name, "material");
|
||||
|
||||
m->name = name;
|
||||
|
||||
GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE);
|
||||
GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_BASE_COLOR);
|
||||
|
||||
if (!m->pbrMetallicRoughness.baseColorTexture.texture) {
|
||||
//if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture
|
||||
|
@ -654,26 +733,26 @@ void glTF2Exporter::ExportMaterials()
|
|||
|
||||
GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
|
||||
|
||||
if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR) != AI_SUCCESS) {
|
||||
if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_BASE_COLOR) != AI_SUCCESS) {
|
||||
// if baseColorFactor wasn't defined, then the source is likely not a metallic roughness material.
|
||||
//a fallback to any diffuse color should be used instead
|
||||
GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
|
||||
}
|
||||
|
||||
if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) {
|
||||
if (mat.Get(AI_MATKEY_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) {
|
||||
//if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0
|
||||
m->pbrMetallicRoughness.metallicFactor = 0;
|
||||
}
|
||||
|
||||
// get roughness if source is gltf2 file
|
||||
if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) {
|
||||
if (mat.Get(AI_MATKEY_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) {
|
||||
// otherwise, try to derive and convert from specular + shininess values
|
||||
aiColor4D specularColor;
|
||||
ai_real shininess;
|
||||
|
||||
if (
|
||||
mat->Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
|
||||
mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS
|
||||
mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
|
||||
mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS
|
||||
) {
|
||||
// convert specular color to luminance
|
||||
float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f;
|
||||
|
@ -694,103 +773,60 @@ void glTF2Exporter::ExportMaterials()
|
|||
GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE);
|
||||
GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE);
|
||||
|
||||
mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided);
|
||||
mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff);
|
||||
mat.Get(AI_MATKEY_TWOSIDED, m->doubleSided);
|
||||
mat.Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff);
|
||||
|
||||
float opacity;
|
||||
aiString alphaMode;
|
||||
|
||||
if (mat->Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) {
|
||||
if (mat.Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) {
|
||||
if (opacity < 1) {
|
||||
m->alphaMode = "BLEND";
|
||||
m->pbrMetallicRoughness.baseColorFactor[3] *= opacity;
|
||||
}
|
||||
}
|
||||
if (mat.Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) {
|
||||
m->alphaMode = alphaMode.C_Str();
|
||||
} else {
|
||||
float opacity;
|
||||
|
||||
if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) {
|
||||
if (opacity < 1) {
|
||||
m->alphaMode = "BLEND";
|
||||
m->pbrMetallicRoughness.baseColorFactor[3] *= opacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool hasPbrSpecularGlossiness = false;
|
||||
mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS, hasPbrSpecularGlossiness);
|
||||
|
||||
if (hasPbrSpecularGlossiness) {
|
||||
|
||||
if (!mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
|
||||
mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true;
|
||||
}
|
||||
|
||||
{
|
||||
// KHR_materials_pbrSpecularGlossiness extension
|
||||
// NOTE: This extension is being considered for deprecation (Dec 2020)
|
||||
PbrSpecularGlossiness pbrSG;
|
||||
|
||||
GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE);
|
||||
GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR);
|
||||
|
||||
if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) {
|
||||
float shininess;
|
||||
|
||||
if (mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
|
||||
pbrSG.glossinessFactor = shininess / 1000;
|
||||
}
|
||||
if (GetMatSpecGloss(mat, pbrSG)) {
|
||||
mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true;
|
||||
m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
|
||||
}
|
||||
|
||||
GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE);
|
||||
GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR);
|
||||
|
||||
m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
|
||||
}
|
||||
|
||||
bool unlit;
|
||||
if (mat->Get(AI_MATKEY_GLTF_UNLIT, unlit) == AI_SUCCESS && unlit) {
|
||||
// glTFv2 is either PBR or Unlit
|
||||
aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
|
||||
mat.Get(AI_MATKEY_SHADING_MODEL, shadingMode);
|
||||
if (shadingMode == aiShadingMode_Unlit) {
|
||||
mAsset->extensionsUsed.KHR_materials_unlit = true;
|
||||
m->unlit = true;
|
||||
}
|
||||
} else {
|
||||
// These extensions are not compatible with KHR_materials_unlit or KHR_materials_pbrSpecularGlossiness
|
||||
if (!m->pbrSpecularGlossiness.isPresent) {
|
||||
// Sheen
|
||||
MaterialSheen sheen;
|
||||
if (GetMatSheen(mat, sheen)) {
|
||||
mAsset->extensionsUsed.KHR_materials_sheen = true;
|
||||
m->materialSheen = Nullable<MaterialSheen>(sheen);
|
||||
}
|
||||
|
||||
bool hasMaterialSheen = false;
|
||||
mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN, hasMaterialSheen);
|
||||
MaterialClearcoat clearcoat;
|
||||
if (GetMatClearcoat(mat, clearcoat)) {
|
||||
mAsset->extensionsUsed.KHR_materials_clearcoat = true;
|
||||
m->materialClearcoat = Nullable<MaterialClearcoat>(clearcoat);
|
||||
}
|
||||
|
||||
if (hasMaterialSheen) {
|
||||
mAsset->extensionsUsed.KHR_materials_sheen = true;
|
||||
|
||||
MaterialSheen sheen;
|
||||
|
||||
GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR);
|
||||
mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor);
|
||||
GetMatTex(mat, sheen.sheenColorTexture, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE);
|
||||
GetMatTex(mat, sheen.sheenRoughnessTexture, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE);
|
||||
|
||||
m->materialSheen = Nullable<MaterialSheen>(sheen);
|
||||
}
|
||||
|
||||
bool hasMaterialClearcoat = false;
|
||||
mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT, hasMaterialClearcoat);
|
||||
|
||||
if (hasMaterialClearcoat) {
|
||||
mAsset->extensionsUsed.KHR_materials_clearcoat= true;
|
||||
|
||||
MaterialClearcoat clearcoat;
|
||||
|
||||
mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR, clearcoat.clearcoatFactor);
|
||||
mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat.clearcoatRoughnessFactor);
|
||||
GetMatTex(mat, clearcoat.clearcoatTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE);
|
||||
GetMatTex(mat, clearcoat.clearcoatRoughnessTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE);
|
||||
GetMatTex(mat, clearcoat.clearcoatNormalTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE);
|
||||
|
||||
m->materialClearcoat = Nullable<MaterialClearcoat>(clearcoat);
|
||||
}
|
||||
|
||||
bool hasMaterialTransmission = false;
|
||||
mat->Get(AI_MATKEY_GLTF_MATERIAL_TRANSMISSION, hasMaterialTransmission);
|
||||
|
||||
if (hasMaterialTransmission) {
|
||||
mAsset->extensionsUsed.KHR_materials_transmission = true;
|
||||
|
||||
MaterialTransmission transmission;
|
||||
|
||||
mat->Get(AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR, transmission.transmissionFactor);
|
||||
GetMatTex(mat, transmission.transmissionTexture, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE);
|
||||
|
||||
m->materialTransmission = Nullable<MaterialTransmission>(transmission);
|
||||
MaterialTransmission transmission;
|
||||
if (GetMatTransmission(mat, transmission)) {
|
||||
mAsset->extensionsUsed.KHR_materials_transmission = true;
|
||||
m->materialTransmission = Nullable<MaterialTransmission>(transmission);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -799,8 +835,7 @@ void glTF2Exporter::ExportMaterials()
|
|||
* Search through node hierarchy and find the node containing the given meshID.
|
||||
* Returns true on success, and false otherwise.
|
||||
*/
|
||||
bool FindMeshNode(Ref<Node>& nodeIn, Ref<Node>& meshNode, std::string meshID)
|
||||
{
|
||||
bool FindMeshNode(Ref<Node> &nodeIn, Ref<Node> &meshNode, const std::string &meshID) {
|
||||
for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) {
|
||||
if (meshID.compare(nodeIn->meshes[i]->id) == 0) {
|
||||
meshNode = nodeIn;
|
||||
|
@ -1301,8 +1336,11 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref<Node>& parent)
|
|||
|
||||
void glTF2Exporter::ExportScene()
|
||||
{
|
||||
const char* sceneName = "defaultScene";
|
||||
Ref<Scene> scene = mAsset->scenes.Create(sceneName);
|
||||
// Use the name of the scene if specified
|
||||
const std::string sceneName = (mScene->mName.length > 0) ? mScene->mName.C_Str() : "defaultScene";
|
||||
|
||||
// Ensure unique
|
||||
Ref<Scene> scene = mAsset->scenes.Create(mAsset->FindUniqueID(sceneName, ""));
|
||||
|
||||
// root node will be the first one exported (idx 0)
|
||||
if (mAsset->nodes.Size() > 0) {
|
||||
|
|
|
@ -72,6 +72,10 @@ namespace glTF2
|
|||
struct OcclusionTextureInfo;
|
||||
struct Node;
|
||||
struct Texture;
|
||||
struct PbrSpecularGlossiness;
|
||||
struct MaterialSheen;
|
||||
struct MaterialClearcoat;
|
||||
struct MaterialTransmission;
|
||||
|
||||
// Vec/matrix types, as raw float arrays
|
||||
typedef float (vec2)[2];
|
||||
|
@ -97,15 +101,19 @@ namespace Assimp
|
|||
|
||||
protected:
|
||||
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
|
||||
void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
|
||||
void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
|
||||
void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
|
||||
void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt, unsigned int slot);
|
||||
void GetMatTex(const aiMaterial* mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot);
|
||||
void GetMatTex(const aiMaterial* mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot);
|
||||
void GetMatTex(const aiMaterial* mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot);
|
||||
aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx);
|
||||
aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx);
|
||||
void GetTexSampler(const aiMaterial& mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
|
||||
void GetMatTexProp(const aiMaterial& mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
|
||||
void GetMatTexProp(const aiMaterial& mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
|
||||
void GetMatTex(const aiMaterial& mat, glTF2::Ref<glTF2::Texture>& texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot);
|
||||
void GetMatTex(const aiMaterial& mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot);
|
||||
void GetMatTex(const aiMaterial& mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot);
|
||||
void GetMatTex(const aiMaterial& mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot);
|
||||
aiReturn GetMatColor(const aiMaterial& mat, glTF2::vec4& prop, const char* propName, int type, int idx) const;
|
||||
aiReturn GetMatColor(const aiMaterial& mat, glTF2::vec3& prop, const char* propName, int type, int idx) const;
|
||||
bool GetMatSpecGloss(const aiMaterial& mat, glTF2::PbrSpecularGlossiness& pbrSG);
|
||||
bool GetMatSheen(const aiMaterial& mat, glTF2::MaterialSheen& sheen);
|
||||
bool GetMatClearcoat(const aiMaterial& mat, glTF2::MaterialClearcoat& clearcoat);
|
||||
bool GetMatTransmission(const aiMaterial& mat, glTF2::MaterialTransmission& transmission);
|
||||
void ExportMetadata();
|
||||
void ExportMaterials();
|
||||
void ExportMeshes();
|
||||
|
|
|
@ -165,7 +165,8 @@ inline void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
|
|||
}
|
||||
|
||||
mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot));
|
||||
mat->AddProperty(&prop.texCoord, 1, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(texType, texSlot));
|
||||
const int uvIndex = static_cast<int>(prop.texCoord);
|
||||
mat->AddProperty(&uvIndex, 1, AI_MATKEY_UVWSRC(texType, texSlot));
|
||||
|
||||
if (prop.textureTransformSupported) {
|
||||
aiUVTransform transform;
|
||||
|
@ -208,6 +209,11 @@ inline void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
|
|||
if (sampler->minFilter != SamplerMinFilter::UNSET) {
|
||||
mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot));
|
||||
}
|
||||
} else {
|
||||
// Use glTFv2 default sampler
|
||||
const aiTextureMapMode default_wrap = aiTextureMapMode_Wrap;
|
||||
mat->AddProperty(&default_wrap, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
|
||||
mat->AddProperty(&default_wrap, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,16 +244,18 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
|
|||
aimat->AddProperty(&str, AI_MATKEY_NAME);
|
||||
}
|
||||
|
||||
// Set Assimp DIFFUSE and BASE COLOR to the pbrMetallicRoughness base color and texture for backwards compatibility
|
||||
// Technically should not load any pbrMetallicRoughness if extensionsRequired contains KHR_materials_pbrSpecularGlossiness
|
||||
SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
|
||||
SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR);
|
||||
SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_BASE_COLOR);
|
||||
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_BASE_COLOR);
|
||||
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
|
||||
|
||||
aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR);
|
||||
aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR);
|
||||
aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR);
|
||||
aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR);
|
||||
|
||||
float roughnessAsShininess = 1 - mat.pbrMetallicRoughness.roughnessFactor;
|
||||
roughnessAsShininess *= roughnessAsShininess * 1000;
|
||||
|
@ -259,6 +267,7 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
|
|||
SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE);
|
||||
|
||||
aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
|
||||
aimat->AddProperty(&mat.pbrMetallicRoughness.baseColorFactor[3], 1, AI_MATKEY_OPACITY);
|
||||
|
||||
aiString alphaMode(mat.alphaMode);
|
||||
aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE);
|
||||
|
@ -268,52 +277,58 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
|
|||
if (mat.pbrSpecularGlossiness.isPresent) {
|
||||
PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value;
|
||||
|
||||
aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS);
|
||||
SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
|
||||
SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR);
|
||||
|
||||
float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f;
|
||||
aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS);
|
||||
aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR);
|
||||
aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLOSSINESS_FACTOR);
|
||||
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, aiTextureType_DIFFUSE);
|
||||
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR);
|
||||
}
|
||||
|
||||
// glTFv2 is either PBR or Unlit
|
||||
aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
|
||||
if (mat.unlit) {
|
||||
aimat->AddProperty(&mat.unlit, 1, AI_MATKEY_GLTF_UNLIT);
|
||||
shadingMode = aiShadingMode_Unlit;
|
||||
}
|
||||
|
||||
//KHR_materials_sheen
|
||||
aimat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL);
|
||||
|
||||
|
||||
// KHR_materials_sheen
|
||||
if (mat.materialSheen.isPresent) {
|
||||
MaterialSheen &sheen = mat.materialSheen.value;
|
||||
|
||||
aimat->AddProperty(&mat.materialSheen.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN);
|
||||
SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR);
|
||||
aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE);
|
||||
// Default value {0,0,0} disables Sheen
|
||||
if (sheen.sheenColorFactor != defaultSheenFactor) {
|
||||
SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_SHEEN_COLOR_FACTOR);
|
||||
aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_SHEEN_ROUGHNESS_FACTOR);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_SHEEN_COLOR_TEXTURE);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE);
|
||||
}
|
||||
}
|
||||
|
||||
//KHR_materials_clearcoat
|
||||
// KHR_materials_clearcoat
|
||||
if (mat.materialClearcoat.isPresent) {
|
||||
MaterialClearcoat &clearcoat = mat.materialClearcoat.value;
|
||||
|
||||
aimat->AddProperty(&mat.materialClearcoat.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT);
|
||||
aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR);
|
||||
aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE);
|
||||
// Default value 0.0 disables clearcoat
|
||||
if (clearcoat.clearcoatFactor != 0.0f) {
|
||||
aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_CLEARCOAT_FACTOR);
|
||||
aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_CLEARCOAT_TEXTURE);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE);
|
||||
}
|
||||
}
|
||||
|
||||
//KHR_materials_transmission
|
||||
// KHR_materials_transmission
|
||||
if (mat.materialTransmission.isPresent) {
|
||||
MaterialTransmission &transmission = mat.materialTransmission.value;
|
||||
|
||||
aimat->AddProperty(&mat.materialTransmission.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION);
|
||||
aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE);
|
||||
aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_TRANSMISSION_FACTOR);
|
||||
SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_TRANSMISSION_TEXTURE);
|
||||
}
|
||||
|
||||
return aimat;
|
||||
|
@ -977,13 +992,21 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) {
|
|||
metadata->Add(extension.name.c_str(), extension.mBoolValue.value);
|
||||
} else if (extension.mValues.isPresent) {
|
||||
aiMetadata val;
|
||||
for (size_t i = 0; i < extension.mValues.value.size(); ++i) {
|
||||
ParseExtensions(&val, extension.mValues.value[i]);
|
||||
for (auto const & subExtension : extension.mValues.value) {
|
||||
ParseExtensions(&val, subExtension);
|
||||
}
|
||||
metadata->Add(extension.name.c_str(), val);
|
||||
}
|
||||
}
|
||||
|
||||
void ParseExtras(aiMetadata *metadata, const CustomExtension &extension) {
|
||||
if (extension.mValues.isPresent) {
|
||||
for (auto const & subExtension : extension.mValues.value) {
|
||||
ParseExtensions(metadata, subExtension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &meshOffsets, glTF2::Ref<glTF2::Node> &ptr) {
|
||||
Node &node = *ptr;
|
||||
|
||||
|
@ -1002,9 +1025,14 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
|
|||
}
|
||||
}
|
||||
|
||||
if (node.extensions) {
|
||||
if (node.customExtensions || node.extras) {
|
||||
ainode->mMetaData = new aiMetadata;
|
||||
ParseExtensions(ainode->mMetaData, node.extensions);
|
||||
if (node.customExtensions) {
|
||||
ParseExtensions(ainode->mMetaData, node.customExtensions);
|
||||
}
|
||||
if (node.extras) {
|
||||
ParseExtras(ainode->mMetaData, node.extras);
|
||||
}
|
||||
}
|
||||
|
||||
GetNodeTransform(ainode->mTransformation, node);
|
||||
|
@ -1308,6 +1336,23 @@ std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation &an
|
|||
continue;
|
||||
}
|
||||
|
||||
auto& animsampler = anim.samplers[channel.sampler];
|
||||
|
||||
if (!animsampler.input) {
|
||||
ASSIMP_LOG_WARN("Animation ", anim.name, ": Missing sampler input. Skipping.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!animsampler.output) {
|
||||
ASSIMP_LOG_WARN("Animation ", anim.name, ": Missing sampler output. Skipping.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (animsampler.input->count > animsampler.output->count) {
|
||||
ASSIMP_LOG_WARN("Animation ", anim.name, ": Number of keyframes in sampler input ", animsampler.input->count, " exceeds number of keyframes in sampler output ", animsampler.output->count);
|
||||
continue;
|
||||
}
|
||||
|
||||
const unsigned int node_index = channel.target.node.GetIndex();
|
||||
|
||||
AnimationSamplers &sampler = samplers[node_index];
|
||||
|
@ -1442,10 +1487,11 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
|
|||
}
|
||||
}
|
||||
|
||||
if (numEmbeddedTexs == 0)
|
||||
if (numEmbeddedTexs == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASSIMP_LOG_DEBUG("Importing ", numEmbeddedTexs, " embedded textures");
|
||||
ASSIMP_LOG_DEBUG("Importing ", numEmbeddedTexs, " embedded textures");
|
||||
|
||||
mScene->mTextures = new aiTexture *[numEmbeddedTexs];
|
||||
std::fill(mScene->mTextures, mScene->mTextures + numEmbeddedTexs, nullptr);
|
||||
|
@ -1498,7 +1544,8 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) {
|
|||
const bool hasVersion = !a.asset.version.empty();
|
||||
const bool hasGenerator = !a.asset.generator.empty();
|
||||
const bool hasCopyright = !a.asset.copyright.empty();
|
||||
if (hasVersion || hasGenerator || hasCopyright) {
|
||||
const bool hasSceneMetadata = a.scene->customExtensions;
|
||||
if (hasVersion || hasGenerator || hasCopyright || hasSceneMetadata) {
|
||||
mScene->mMetaData = new aiMetadata;
|
||||
if (hasVersion) {
|
||||
mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version));
|
||||
|
@ -1509,6 +1556,9 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) {
|
|||
if (hasCopyright) {
|
||||
mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright));
|
||||
}
|
||||
if (hasSceneMetadata) {
|
||||
ParseExtensions(mScene->mMetaData, a.scene->customExtensions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -822,7 +822,10 @@ ADD_ASSIMP_IMPORTER( GLTF
|
|||
AssetLib/glTF2/glTF2Importer.h
|
||||
)
|
||||
|
||||
ADD_ASSIMP_IMPORTER( 3MF
|
||||
ADD_ASSIMP_IMPORTER(3MF
|
||||
AssetLib/3MF/3MFTypes.h
|
||||
AssetLib/3MF/XmlSerializer.h
|
||||
AssetLib/3MF/XmlSerializer.cpp
|
||||
AssetLib/3MF/D3MFImporter.h
|
||||
AssetLib/3MF/D3MFImporter.cpp
|
||||
AssetLib/3MF/D3MFOpcPackage.h
|
||||
|
@ -875,6 +878,7 @@ ELSE()
|
|||
../contrib/pugixml/src/pugiconfig.hpp
|
||||
../contrib/pugixml/src/pugixml.hpp
|
||||
)
|
||||
INCLUDE_DIRECTORIES("../contrib/pugixml/src")
|
||||
SOURCE_GROUP( Contrib\\Pugixml FILES ${Pugixml_SRCS})
|
||||
ENDIF()
|
||||
|
||||
|
@ -1035,16 +1039,26 @@ IF(ASSIMP_HUNTER_ENABLED)
|
|||
hunter_add_package(RapidJSON)
|
||||
find_package(RapidJSON CONFIG REQUIRED)
|
||||
ELSE()
|
||||
INCLUDE_DIRECTORIES( "../contrib/rapidjson/include" )
|
||||
INCLUDE_DIRECTORIES( "../contrib" )
|
||||
INCLUDE_DIRECTORIES( "../contrib/pugixml/src" )
|
||||
ADD_DEFINITIONS( -DRAPIDJSON_HAS_STDSTRING=1 )
|
||||
INCLUDE_DIRECTORIES("../contrib/rapidjson/include")
|
||||
ADD_DEFINITIONS( -DRAPIDJSON_HAS_STDSTRING=1)
|
||||
option( ASSIMP_RAPIDJSON_NO_MEMBER_ITERATOR "Suppress rapidjson warning on MSVC (NOTE: breaks android build)" ON )
|
||||
if(ASSIMP_RAPIDJSON_NO_MEMBER_ITERATOR)
|
||||
ADD_DEFINITIONS( -DRAPIDJSON_NOMEMBERITERATORCLASS )
|
||||
endif()
|
||||
ENDIF()
|
||||
|
||||
# stb
|
||||
IF(ASSIMP_HUNTER_ENABLED)
|
||||
hunter_add_package(stb)
|
||||
find_package(stb CONFIG REQUIRED)
|
||||
ELSE()
|
||||
SET( stb_SRCS
|
||||
../contrib/stb/stb_image.h
|
||||
)
|
||||
INCLUDE_DIRECTORIES("../contrib")
|
||||
SOURCE_GROUP( Contrib\\stb FILES ${stb_SRCS})
|
||||
ENDIF()
|
||||
|
||||
# VC2010 fixes
|
||||
if(MSVC10)
|
||||
option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
|
||||
|
@ -1103,6 +1117,7 @@ SET( assimp_src
|
|||
${open3dgc_SRCS}
|
||||
${ziplib_SRCS}
|
||||
${Pugixml_SRCS}
|
||||
${stb_SRCS}
|
||||
# Necessary to show the headers in the project when using the VC++ generator:
|
||||
|
||||
${PUBLIC_HEADERS}
|
||||
|
@ -1160,6 +1175,7 @@ IF(ASSIMP_HUNTER_ENABLED)
|
|||
utf8cpp
|
||||
zip::zip
|
||||
pugixml
|
||||
stb::stb
|
||||
)
|
||||
|
||||
if (ASSIMP_BUILD_DRACO)
|
||||
|
|
|
@ -72,12 +72,25 @@ namespace Assimp {
|
|||
// underlying structure for aiPropertyStore
|
||||
typedef BatchLoader::PropertyMap PropertyMap;
|
||||
|
||||
#if defined(__has_warning)
|
||||
#if __has_warning("-Wordered-compare-function-pointers")
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wordered-compare-function-pointers"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Stores the LogStream objects for all active C log streams */
|
||||
struct mpred {
|
||||
bool operator()(const aiLogStream &s0, const aiLogStream &s1) const {
|
||||
return s0.callback < s1.callback && s0.user < s1.user;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__has_warning)
|
||||
#if __has_warning("-Wordered-compare-function-pointers")
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
typedef std::map<aiLogStream, Assimp::LogStream *, mpred> LogStreamMap;
|
||||
|
||||
/** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
|
||||
|
@ -1251,3 +1264,36 @@ ASSIMP_API void aiQuaternionInterpolate(
|
|||
ai_assert(nullptr != end);
|
||||
aiQuaternion::Interpolate(*dst, *start, *end, factor);
|
||||
}
|
||||
|
||||
|
||||
// stb_image is a lightweight image loader. It is shared by:
|
||||
// - M3D import
|
||||
// - PBRT export
|
||||
// Since it's a header-only library, its implementation must be instantiated in some cpp file.
|
||||
// Don't scatter this task over multiple importers/exporters. Maintain it in a central place (here!).
|
||||
|
||||
#define ASSIMP_HAS_PBRT_EXPORT (!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_PBRT_EXPORTER)
|
||||
#define ASSIMP_HAS_M3D ((!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER)
|
||||
|
||||
#if ASSIMP_HAS_PBRT_EXPORT
|
||||
# define ASSIMP_NEEDS_STB_IMAGE 1
|
||||
#elif ASSIMP_HAS_M3D
|
||||
# define ASSIMP_NEEDS_STB_IMAGE 1
|
||||
# define STBI_ONLY_PNG
|
||||
#endif
|
||||
|
||||
#if ASSIMP_NEEDS_STB_IMAGE
|
||||
|
||||
# if _MSC_VER // "unreferenced function has been removed" (SSE2 detection routine in x64 builds)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4505)
|
||||
# endif
|
||||
|
||||
# define STB_IMAGE_IMPLEMENTATION
|
||||
# include "stb/stb_image.h"
|
||||
|
||||
# if _MSC_VER
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -173,7 +173,7 @@ inline static std::string MakeAbsolutePath(const char *in) {
|
|||
free(ret);
|
||||
}
|
||||
#endif
|
||||
if (!ret) {
|
||||
else {
|
||||
// preserve the input path, maybe someone else is able to fix
|
||||
// the path before it is accessed (e.g. our file system filter)
|
||||
ASSIMP_LOG_WARN("Invalid path: ", std::string(in));
|
||||
|
|
|
@ -59,13 +59,16 @@ void CommentRemover::RemoveLineComments(const char* szComment,
|
|||
ai_assert(nullptr != szBuffer);
|
||||
ai_assert(*szComment);
|
||||
|
||||
const size_t len = strlen(szComment);
|
||||
size_t len = strlen(szComment);
|
||||
const size_t lenBuffer = strlen(szBuffer);
|
||||
if (len > lenBuffer) {
|
||||
len = lenBuffer;
|
||||
}
|
||||
while (*szBuffer) {
|
||||
|
||||
// skip over quotes
|
||||
if (*szBuffer == '\"' || *szBuffer == '\'')
|
||||
while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\'');
|
||||
|
||||
if (!strncmp(szBuffer,szComment,len)) {
|
||||
while (!IsLineEnd(*szBuffer))
|
||||
*szBuffer++ = chReplacement;
|
||||
|
|
|
@ -406,11 +406,25 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
|
|||
// Check whether this texture is an embedded texture.
|
||||
// In this case the property looks like this: *<n>,
|
||||
// where n is the index of the texture.
|
||||
aiString &s = *((aiString *)prop->mData);
|
||||
// Copy here because we overwrite the string data in-place and the buffer inside of aiString
|
||||
// will be a lie if we just reinterpret from prop->mData. The size of mData is not guaranteed to be
|
||||
// MAXLEN in size.
|
||||
aiString s(*(aiString *)prop->mData);
|
||||
if ('*' == s.data[0]) {
|
||||
// Offset the index and write it back ..
|
||||
const unsigned int idx = strtoul10(&s.data[1]) + offset[n];
|
||||
ASSIMP_itoa10(&s.data[1], sizeof(s.data) - 1, idx);
|
||||
const unsigned int oldLen = s.length;
|
||||
|
||||
s.length = 1 + ASSIMP_itoa10(&s.data[1], sizeof(s.data) - 1, idx);
|
||||
|
||||
// The string changed in size so we need to reallocate the buffer for the property.
|
||||
if (oldLen < s.length) {
|
||||
prop->mDataLength += s.length - oldLen;
|
||||
delete[] prop->mData;
|
||||
prop->mData = new char[prop->mDataLength];
|
||||
}
|
||||
|
||||
memcpy(prop->mData, static_cast<void*>(&s), prop->mDataLength);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,9 @@ void ScenePreprocessor::ProcessScene() {
|
|||
ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'");
|
||||
|
||||
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
|
||||
if (nullptr == scene->mMeshes[i]) {
|
||||
continue;
|
||||
}
|
||||
scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,10 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/material.h>
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
const char* TextureTypeToString(aiTextureType in)
|
||||
{
|
||||
switch (in)
|
||||
{
|
||||
const char *TextureTypeToString(aiTextureType in) {
|
||||
switch (in) {
|
||||
case aiTextureType_NONE:
|
||||
return "n/a";
|
||||
case aiTextureType_DIFFUSE:
|
||||
|
@ -87,6 +85,12 @@ const char* TextureTypeToString(aiTextureType in)
|
|||
return "DiffuseRoughness";
|
||||
case aiTextureType_AMBIENT_OCCLUSION:
|
||||
return "AmbientOcclusion";
|
||||
case aiTextureType_SHEEN:
|
||||
return "Sheen";
|
||||
case aiTextureType_CLEARCOAT:
|
||||
return "Clearcoat";
|
||||
case aiTextureType_TRANSMISSION:
|
||||
return "Transmission";
|
||||
case aiTextureType_UNKNOWN:
|
||||
return "Unknown";
|
||||
default:
|
||||
|
|
|
@ -555,17 +555,23 @@ uint32_t Assimp::ComputeMaterialHash(const aiMaterial *mat, bool includeMatName
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void aiMaterial::CopyPropertyList(aiMaterial *pcDest,
|
||||
void aiMaterial::CopyPropertyList(aiMaterial *const pcDest,
|
||||
const aiMaterial *pcSrc) {
|
||||
ai_assert(nullptr != pcDest);
|
||||
ai_assert(nullptr != pcSrc);
|
||||
ai_assert(pcDest->mNumProperties <= pcDest->mNumAllocated);
|
||||
ai_assert(pcSrc->mNumProperties <= pcSrc->mNumAllocated);
|
||||
|
||||
unsigned int iOldNum = pcDest->mNumProperties;
|
||||
const unsigned int iOldNum = pcDest->mNumProperties;
|
||||
pcDest->mNumAllocated += pcSrc->mNumAllocated;
|
||||
pcDest->mNumProperties += pcSrc->mNumProperties;
|
||||
|
||||
const unsigned int numAllocated = pcDest->mNumAllocated;
|
||||
aiMaterialProperty **pcOld = pcDest->mProperties;
|
||||
pcDest->mProperties = new aiMaterialProperty *[pcDest->mNumAllocated];
|
||||
pcDest->mProperties = new aiMaterialProperty *[numAllocated];
|
||||
|
||||
ai_assert(!iOldNum || pcOld);
|
||||
ai_assert(iOldNum < numAllocated);
|
||||
|
||||
if (iOldNum && pcOld) {
|
||||
for (unsigned int i = 0; i < iOldNum; ++i) {
|
||||
|
|
|
@ -83,8 +83,7 @@ Other:
|
|||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
#include "stb/stb_image.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
@ -106,14 +105,13 @@ void ExportScenePbrt (
|
|||
} // end of namespace Assimp
|
||||
|
||||
// Constructor
|
||||
PbrtExporter::PbrtExporter (
|
||||
const aiScene* pScene, IOSystem* pIOSystem,
|
||||
const std::string path, const std::string file)
|
||||
: mScene(pScene),
|
||||
mIOSystem(pIOSystem),
|
||||
mPath(path),
|
||||
mFile(file)
|
||||
{
|
||||
PbrtExporter::PbrtExporter(
|
||||
const aiScene *pScene, IOSystem *pIOSystem,
|
||||
const std::string &path, const std::string &file) :
|
||||
mScene(pScene),
|
||||
mIOSystem(pIOSystem),
|
||||
mPath(path),
|
||||
mFile(file) {
|
||||
// Export embedded textures.
|
||||
if (mScene->mNumTextures > 0)
|
||||
if (!mIOSystem->CreateDirectory("textures"))
|
||||
|
@ -210,12 +208,12 @@ void PbrtExporter::WriteMetaData() {
|
|||
aiString* value =
|
||||
static_cast<aiString*>(pMetaData->mValues[i].mData);
|
||||
std::string svalue = value->C_Str();
|
||||
std::size_t found = svalue.find_first_of("\n");
|
||||
std::size_t found = svalue.find_first_of('\n');
|
||||
mOutput << "\n";
|
||||
while (found != std::string::npos) {
|
||||
mOutput << "# " << svalue.substr(0, found) << "\n";
|
||||
svalue = svalue.substr(found + 1);
|
||||
found = svalue.find_first_of("\n");
|
||||
found = svalue.find_first_of('\n');
|
||||
}
|
||||
mOutput << "# " << svalue << "\n";
|
||||
break;
|
||||
|
@ -596,8 +594,8 @@ void PbrtExporter::WriteMaterial(int m) {
|
|||
}
|
||||
mOutput << "\n";
|
||||
|
||||
auto White = [](aiColor3D c) { return c.r == 1 && c.g == 1 && c.b == 1; };
|
||||
auto Black = [](aiColor3D c) { return c.r == 0 && c.g == 0 && c.b == 0; };
|
||||
auto White = [](const aiColor3D &c) { return c.r == 1 && c.g == 1 && c.b == 1; };
|
||||
auto Black = [](const aiColor3D &c) { return c.r == 0 && c.g == 0 && c.b == 0; };
|
||||
|
||||
aiColor3D diffuse, specular, transparency;
|
||||
bool constantDiffuse = (material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse) == AI_SUCCESS &&
|
||||
|
|
|
@ -74,8 +74,8 @@ class PbrtExporter
|
|||
{
|
||||
public:
|
||||
/// Constructor for a specific scene to export
|
||||
PbrtExporter(const aiScene* pScene, IOSystem* pIOSystem,
|
||||
const std::string path, const std::string file);
|
||||
PbrtExporter(const aiScene *pScene, IOSystem *pIOSystem,
|
||||
const std::string &path, const std::string &file);
|
||||
|
||||
/// Destructor
|
||||
virtual ~PbrtExporter();
|
||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2021, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
@ -41,6 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
#include "EmbedTexturesProcess.h"
|
||||
#include <assimp/IOStream.hpp>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include "ProcessHelper.h"
|
||||
|
||||
|
@ -48,11 +49,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
using namespace Assimp;
|
||||
|
||||
EmbedTexturesProcess::EmbedTexturesProcess()
|
||||
: BaseProcess() {
|
||||
EmbedTexturesProcess::EmbedTexturesProcess() :
|
||||
BaseProcess() {
|
||||
// empty
|
||||
}
|
||||
|
||||
EmbedTexturesProcess::~EmbedTexturesProcess() {
|
||||
// empty
|
||||
}
|
||||
|
||||
bool EmbedTexturesProcess::IsActive(unsigned int pFlags) const {
|
||||
|
@ -62,15 +65,16 @@ bool EmbedTexturesProcess::IsActive(unsigned int pFlags) const {
|
|||
void EmbedTexturesProcess::SetupProperties(const Importer* pImp) {
|
||||
mRootPath = pImp->GetPropertyString("sourceFilePath");
|
||||
mRootPath = mRootPath.substr(0, mRootPath.find_last_of("\\/") + 1u);
|
||||
mIOHandler = pImp->GetIOHandler();
|
||||
}
|
||||
|
||||
void EmbedTexturesProcess::Execute(aiScene* pScene) {
|
||||
if (pScene == nullptr || pScene->mRootNode == nullptr) return;
|
||||
if (pScene == nullptr || pScene->mRootNode == nullptr || mIOHandler == nullptr){
|
||||
return;
|
||||
}
|
||||
|
||||
aiString path;
|
||||
|
||||
uint32_t embeddedTexturesCount = 0u;
|
||||
|
||||
for (auto matId = 0u; matId < pScene->mNumMaterials; ++matId) {
|
||||
auto material = pScene->mMaterials[matId];
|
||||
|
||||
|
@ -96,32 +100,36 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) {
|
|||
ASSIMP_LOG_INFO("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." );
|
||||
}
|
||||
|
||||
bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
|
||||
bool EmbedTexturesProcess::addTexture(aiScene *pScene, const std::string &path) const {
|
||||
std::streampos imageSize = 0;
|
||||
std::string imagePath = path;
|
||||
|
||||
// Test path directly
|
||||
std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
|
||||
if ((imageSize = file.tellg()) == std::streampos(-1)) {
|
||||
if (!mIOHandler->Exists(imagePath)) {
|
||||
ASSIMP_LOG_WARN("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder.");
|
||||
|
||||
// Test path in root path
|
||||
imagePath = mRootPath + path;
|
||||
file.open(imagePath, std::ios::binary | std::ios::ate);
|
||||
if ((imageSize = file.tellg()) == std::streampos(-1)) {
|
||||
if (!mIOHandler->Exists(imagePath)) {
|
||||
// Test path basename in root path
|
||||
imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
|
||||
file.open(imagePath, std::ios::binary | std::ios::ate);
|
||||
if ((imageSize = file.tellg()) == std::streampos(-1)) {
|
||||
if (!mIOHandler->Exists(imagePath)) {
|
||||
ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", path, ".");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
IOStream* pFile = mIOHandler->Open(imagePath);
|
||||
if (pFile == nullptr) {
|
||||
ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", path, ".");
|
||||
return false;
|
||||
}
|
||||
imageSize = pFile->FileSize();
|
||||
|
||||
aiTexel* imageContent = new aiTexel[ 1ul + static_cast<unsigned long>( imageSize ) / sizeof(aiTexel)];
|
||||
file.seekg(0, std::ios::beg);
|
||||
file.read(reinterpret_cast<char*>(imageContent), imageSize);
|
||||
pFile->Seek(0, aiOrigin_SET);
|
||||
pFile->Read(reinterpret_cast<char*>(imageContent), imageSize, 1);
|
||||
mIOHandler->Close(pFile);
|
||||
|
||||
// Enlarging the textures table
|
||||
unsigned int textureId = pScene->mNumTextures++;
|
||||
|
|
|
@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
struct aiNode;
|
||||
|
||||
class IOSystem;
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
/**
|
||||
|
@ -76,10 +78,11 @@ public:
|
|||
|
||||
private:
|
||||
// Resolve the path and add the file content to the scene as a texture.
|
||||
bool addTexture(aiScene* pScene, std::string path) const;
|
||||
bool addTexture(aiScene *pScene, const std::string &path) const;
|
||||
|
||||
private:
|
||||
std::string mRootPath;
|
||||
IOSystem* mIOHandler = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Assimp
|
||||
|
|
|
@ -170,7 +170,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list<aiNode *> &n
|
|||
++it;
|
||||
}
|
||||
if (join_master && !join.empty()) {
|
||||
join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i", count_merged++);
|
||||
join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%u", count_merged++);
|
||||
|
||||
unsigned int out_meshes = 0;
|
||||
for (std::list<aiNode *>::const_iterator it = join.cbegin(); it != join.cend(); ++it) {
|
||||
|
|
|
@ -481,7 +481,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
|
|||
pScene->mMeshes[i]->mNumBones = 0;
|
||||
}
|
||||
} else {
|
||||
apcOutMeshes.reserve(pScene->mNumMaterials << 1u);
|
||||
apcOutMeshes.reserve(static_cast<size_t>(pScene->mNumMaterials) << 1u);
|
||||
std::list<unsigned int> aiVFormats;
|
||||
|
||||
std::vector<unsigned int> s(pScene->mNumMeshes, 0);
|
||||
|
|
|
@ -127,7 +127,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
|
|||
unsigned int aiNumMeshesPerPType[4] = { 0, 0, 0, 0 };
|
||||
|
||||
std::vector<aiMesh *> outMeshes;
|
||||
outMeshes.reserve(pScene->mNumMeshes << 1u);
|
||||
outMeshes.reserve(static_cast<size_t>(pScene->mNumMeshes) << 1u);
|
||||
|
||||
bool bAnyChanges = false;
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
2.3.0
|
|
@ -1,31 +0,0 @@
|
|||
cache: ccache
|
||||
language: cpp
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
compiler: clang
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- cmake
|
||||
|
||||
script:
|
||||
# Output version info for compilers, cmake, and make
|
||||
- ${CC} -v
|
||||
- ${CXX} -v
|
||||
- cmake --version
|
||||
- make --version
|
||||
# Clone googletest
|
||||
- pushd .. && git clone https://github.com/google/googletest.git && popd
|
||||
# Configure and build
|
||||
- mkdir _travis_build && cd _travis_build
|
||||
- cmake -G "Unix Makefiles" -DENABLE_TESTS=ON ..
|
||||
- make -j10
|
||||
- ./draco_tests
|
|
@ -804,7 +804,7 @@ else()
|
|||
draco_points_enc)
|
||||
|
||||
# Library targets that consume the object collections.
|
||||
if(MSVC OR WIN32)
|
||||
if(MSVC)
|
||||
# In order to produce a DLL and import library the Windows tools require
|
||||
# that the exported symbols are part of the DLL target. The unfortunate side
|
||||
# effect of this is that a single configuration cannot output both the
|
||||
|
@ -889,9 +889,6 @@ else()
|
|||
# For Mac, we need to build a .bundle for the unity plugin.
|
||||
if(APPLE)
|
||||
set_target_properties(dracodec_unity PROPERTIES BUNDLE true)
|
||||
elseif(NOT unity_decoder_lib_type STREQUAL STATIC)
|
||||
set_target_properties(dracodec_unity
|
||||
PROPERTIES SOVERSION ${DRACO_SOVERSION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -916,9 +913,6 @@ else()
|
|||
# For Mac, we need to build a .bundle for the plugin.
|
||||
if(APPLE)
|
||||
set_target_properties(draco_maya_wrapper PROPERTIES BUNDLE true)
|
||||
else()
|
||||
set_target_properties(draco_maya_wrapper
|
||||
PROPERTIES SOVERSION ${DRACO_SOVERSION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
<img width="350px" src="docs/artwork/draco3d-vert.svg" />
|
||||
</p>
|
||||
|
||||
![Build Status: master](https://travis-ci.org/google/draco.svg?branch=master)
|
||||
[![Build Status](https://github.com/google/draco/workflows/Build/badge.svg)](https://github.com/google/draco/actions?query=workflow%3ABuild)
|
||||
|
||||
News
|
||||
=======
|
||||
### Version 1.4.1 release
|
||||
* Using the versioned gstatic.com WASM and Javascript decoders is now
|
||||
* Using the versioned www.gstatic.com WASM and Javascript decoders is now
|
||||
recommended. To use v1.4.1, use this URL:
|
||||
* https://www.gstatic.com/draco/versioned/decoders/1.4.1/*
|
||||
* Replace the * with the files to load. E.g.
|
||||
* https://gstatic.com/draco/versioned/decoders/1.4.1/draco_decoder.js
|
||||
* https://www.gstatic.com/draco/versioned/decoders/1.4.1/draco_decoder.js
|
||||
* This works with the v1.3.6 and v1.4.0 releases, and will work with future
|
||||
Draco releases.
|
||||
* Bug fixes
|
||||
|
|
|
@ -6,7 +6,7 @@ set(DRACO_CMAKE_DRACO_BUILD_DEFINITIONS_CMAKE_ 1)
|
|||
# Utility for controlling the main draco library dependency. This changes in
|
||||
# shared builds, and when an optional target requires a shared library build.
|
||||
macro(set_draco_target)
|
||||
if(MSVC OR WIN32)
|
||||
if(MSVC)
|
||||
set(draco_dependency draco)
|
||||
set(draco_plugin_dependency ${draco_dependency})
|
||||
else()
|
||||
|
@ -63,6 +63,11 @@ macro(draco_set_build_definitions)
|
|||
if(BUILD_SHARED_LIBS)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
endif()
|
||||
else()
|
||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
||||
# Ensure 64-bit platforms can support large files.
|
||||
list(APPEND draco_defines "_LARGEFILE_SOURCE" "_FILE_OFFSET_BITS=64")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
|
@ -114,4 +119,6 @@ macro(draco_set_build_definitions)
|
|||
draco_check_emscripten_environment()
|
||||
draco_get_required_emscripten_flags(FLAG_LIST_VAR draco_base_cxx_flags)
|
||||
endif()
|
||||
|
||||
draco_configure_sanitizer()
|
||||
endmacro()
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
if(DRACO_CMAKE_DRACO_FEATURES_CMAKE_)
|
||||
return()
|
||||
endif()
|
||||
set(DRACO_CMAKE_DRACO_FEATURES_CMAKE_ 1)
|
||||
|
||||
set(draco_features_file_name "${draco_build_dir}/draco/draco_features.h")
|
||||
set(draco_features_list)
|
||||
|
||||
# Macro that handles tracking of Draco preprocessor symbols for the purpose of
|
||||
# producing draco_features.h.
|
||||
#
|
||||
# draco_enable_feature(FEATURE <feature_name> [TARGETS <target_name>]) FEATURE
|
||||
# is required. It should be a Draco preprocessor symbol. TARGETS is optional. It
|
||||
# can be one or more draco targets.
|
||||
#
|
||||
# When the TARGETS argument is not present the preproc symbol is added to
|
||||
# draco_features.h. When it is draco_features.h is unchanged, and
|
||||
# target_compile_options() is called for each target specified.
|
||||
macro(draco_enable_feature)
|
||||
set(def_flags)
|
||||
set(def_single_arg_opts FEATURE)
|
||||
set(def_multi_arg_opts TARGETS)
|
||||
cmake_parse_arguments(DEF "${def_flags}" "${def_single_arg_opts}"
|
||||
"${def_multi_arg_opts}" ${ARGN})
|
||||
if("${DEF_FEATURE}" STREQUAL "")
|
||||
message(FATAL_ERROR "Empty FEATURE passed to draco_enable_feature().")
|
||||
endif()
|
||||
|
||||
# Do nothing/return early if $DEF_FEATURE is already in the list.
|
||||
list(FIND draco_features_list ${DEF_FEATURE} df_index)
|
||||
if(NOT df_index EQUAL -1)
|
||||
return()
|
||||
endif()
|
||||
|
||||
list(LENGTH DEF_TARGETS df_targets_list_length)
|
||||
if(${df_targets_list_length} EQUAL 0)
|
||||
list(APPEND draco_features_list ${DEF_FEATURE})
|
||||
else()
|
||||
foreach(target ${DEF_TARGETS})
|
||||
target_compile_definitions(${target} PRIVATE ${DEF_FEATURE})
|
||||
endforeach()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Function for generating draco_features.h.
|
||||
function(draco_generate_features_h)
|
||||
file(WRITE "${draco_features_file_name}.new"
|
||||
"// GENERATED FILE -- DO NOT EDIT\n\n" "#ifndef DRACO_FEATURES_H_\n"
|
||||
"#define DRACO_FEATURES_H_\n\n")
|
||||
|
||||
foreach(feature ${draco_features_list})
|
||||
file(APPEND "${draco_features_file_name}.new" "#define ${feature}\n")
|
||||
endforeach()
|
||||
|
||||
file(APPEND "${draco_features_file_name}.new"
|
||||
"\n#endif // DRACO_FEATURES_H_")
|
||||
|
||||
# Will replace ${draco_features_file_name} only if the file content has
|
||||
# changed. This prevents forced Draco rebuilds after CMake runs.
|
||||
configure_file("${draco_features_file_name}.new"
|
||||
"${draco_features_file_name}")
|
||||
file(REMOVE "${draco_features_file_name}.new")
|
||||
endfunction()
|
|
@ -80,6 +80,12 @@ macro(draco_test_cxx_flag)
|
|||
# Run the actual compile test.
|
||||
unset(draco_all_cxx_flags_pass CACHE)
|
||||
message("--- Running combined CXX flags test, flags: ${all_cxx_flags}")
|
||||
|
||||
# check_cxx_compiler_flag() requires that the flags are a string. When flags
|
||||
# are passed as a list it will remove the list separators, and attempt to run
|
||||
# a compile command using list entries concatenated together as a single
|
||||
# argument. Avoid the problem by forcing the argument to be a string.
|
||||
draco_set_and_stringify(SOURCE_VARS all_cxx_flags DEST all_cxx_flags)
|
||||
check_cxx_compiler_flag("${all_cxx_flags}" draco_all_cxx_flags_pass)
|
||||
|
||||
if(cxx_test_FLAG_REQUIRED AND NOT draco_all_cxx_flags_pass)
|
||||
|
@ -194,6 +200,9 @@ macro(draco_test_exe_linker_flag)
|
|||
else()
|
||||
unset(CMAKE_EXE_LINKER_FLAGS)
|
||||
endif()
|
||||
|
||||
list(APPEND DRACO_EXE_LINKER_FLAGS ${${link_FLAG_LIST_VAR_NAME}})
|
||||
list(REMOVE_DUPLICATES DRACO_EXE_LINKER_FLAGS)
|
||||
endmacro()
|
||||
|
||||
# Runs the draco compiler tests. This macro builds up the list of list var(s)
|
||||
|
|
|
@ -55,7 +55,7 @@ macro(draco_setup_install_target)
|
|||
install(TARGETS draco_encoder DESTINATION
|
||||
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
|
||||
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
install(TARGETS draco DESTINATION
|
||||
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
else()
|
||||
|
|
|
@ -5,28 +5,28 @@ set(DRACO_CMAKE_DRACO_SANITIZER_CMAKE_ 1)
|
|||
|
||||
# Handles the details of enabling sanitizers.
|
||||
macro(draco_configure_sanitizer)
|
||||
if(DRACO_SANITIZE AND NOT MSVC)
|
||||
if(DRACO_SANITIZE AND NOT EMSCRIPTEN AND NOT MSVC)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
if(DRACO_SANITIZE MATCHES "cfi")
|
||||
list(APPEND DRACO_CXX_FLAGS "-flto" "-fno-sanitize-trap=cfi")
|
||||
list(APPEND DRACO_EXE_LINKER_FLAGS "-flto" "-fno-sanitize-trap=cfi"
|
||||
list(APPEND SAN_CXX_FLAGS "-flto" "-fno-sanitize-trap=cfi")
|
||||
list(APPEND SAN_LINKER_FLAGS "-flto" "-fno-sanitize-trap=cfi"
|
||||
"-fuse-ld=gold")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 4
|
||||
AND DRACO_SANITIZE MATCHES "integer|undefined")
|
||||
list(APPEND DRACO_EXE_LINKER_FLAGS "--rtlib=compiler-rt" "-lgcc_s")
|
||||
list(APPEND SAN_LINKER_FLAGS "--rtlib=compiler-rt" "-lgcc_s")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND DRACO_CXX_FLAGS "-fsanitize=${DRACO_SANITIZE}")
|
||||
list(APPEND DRACO_EXE_LINKER_FLAGS "-fsanitize=${DRACO_SANITIZE}")
|
||||
list(APPEND SAN_CXX_FLAGS "-fsanitize=${DRACO_SANITIZE}")
|
||||
list(APPEND SAN_LINKER_FLAGS "-fsanitize=${DRACO_SANITIZE}")
|
||||
|
||||
# Make sanitizer callstacks accurate.
|
||||
list(APPEND DRACO_CXX_FLAGS "-fno-omit-frame-pointer"
|
||||
"-fno-optimize-sibling-calls")
|
||||
list(APPEND SAN_CXX_FLAGS "-fno-omit-frame-pointer")
|
||||
list(APPEND SAN_CXX_FLAGS "-fno-optimize-sibling-calls")
|
||||
|
||||
draco_test_cxx_flag(FLAG_LIST_VAR_NAMES DRACO_CXX_FLAGS FLAG_REQUIRED)
|
||||
draco_test_exe_linker_flag(FLAG_LIST_VAR_NAME DRACO_EXE_LINKER_FLAGS)
|
||||
draco_test_cxx_flag(FLAG_LIST_VAR_NAMES SAN_CXX_FLAGS FLAG_REQUIRED)
|
||||
draco_test_exe_linker_flag(FLAG_LIST_VAR_NAME SAN_LINKER_FLAGS)
|
||||
endif()
|
||||
endmacro()
|
||||
|
|
|
@ -87,6 +87,7 @@ macro(draco_add_executable)
|
|||
endif()
|
||||
|
||||
add_executable(${exe_NAME} ${exe_SOURCES})
|
||||
set_target_properties(${exe_NAME} PROPERTIES VERSION ${DRACO_VERSION})
|
||||
|
||||
if(exe_OUTPUT_NAME)
|
||||
set_target_properties(${exe_NAME} PROPERTIES OUTPUT_NAME ${exe_OUTPUT_NAME})
|
||||
|
@ -109,10 +110,11 @@ macro(draco_add_executable)
|
|||
|
||||
if(exe_LINK_FLAGS OR DRACO_EXE_LINKER_FLAGS)
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
set(link_flags ${exe_LINK_FLAGS} ${DRACO_EXE_LINKER_FLAGS})
|
||||
list(APPEND exe_LINK_FLAGS "${DRACO_EXE_LINKER_FLAGS}")
|
||||
# LINK_FLAGS is managed as a string.
|
||||
draco_set_and_stringify(SOURCE "${exe_LINK_FLAGS}" DEST exe_LINK_FLAGS)
|
||||
set_target_properties(${exe_NAME}
|
||||
PROPERTIES LINK_FLAGS ${exe_LINK_FLAGS}
|
||||
${DRACO_EXE_LINKER_FLAGS})
|
||||
PROPERTIES LINK_FLAGS "${exe_LINK_FLAGS}")
|
||||
else()
|
||||
target_link_options(${exe_NAME} PRIVATE ${exe_LINK_FLAGS}
|
||||
${DRACO_EXE_LINKER_FLAGS})
|
||||
|
@ -130,7 +132,7 @@ macro(draco_add_executable)
|
|||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS AND (MSVC OR WIN32))
|
||||
target_compile_definitions(${lib_NAME} PRIVATE "DRACO_BUILDING_DLL=0")
|
||||
target_compile_definitions(${exe_NAME} PRIVATE "DRACO_BUILDING_DLL=0")
|
||||
endif()
|
||||
|
||||
if(exe_LIB_DEPS)
|
||||
|
@ -163,8 +165,8 @@ endmacro()
|
|||
# cmake-format: off
|
||||
# - OUTPUT_NAME: Override output file basename. Target basename defaults to
|
||||
# NAME. OUTPUT_NAME is ignored when BUILD_SHARED_LIBS is enabled and CMake
|
||||
# is generating a build for which MSVC or WIN32 are true. This is to avoid
|
||||
# output basename collisions with DLL import libraries.
|
||||
# is generating a build for which MSVC is true. This is to avoid output
|
||||
# basename collisions with DLL import libraries.
|
||||
# - TEST: Flag. Presence means treat library as a test.
|
||||
# - DEFINES: List of preprocessor macro definitions.
|
||||
# - INCLUDES: list of include directories for the target.
|
||||
|
@ -259,7 +261,7 @@ macro(draco_add_library)
|
|||
endif()
|
||||
|
||||
if(lib_OUTPUT_NAME)
|
||||
if(NOT (BUILD_SHARED_LIBS AND (MSVC OR WIN32)))
|
||||
if(NOT (BUILD_SHARED_LIBS AND MSVC))
|
||||
set_target_properties(${lib_NAME}
|
||||
PROPERTIES OUTPUT_NAME ${lib_OUTPUT_NAME})
|
||||
endif()
|
||||
|
@ -318,8 +320,12 @@ macro(draco_add_library)
|
|||
set_target_properties(${lib_NAME} PROPERTIES PREFIX "")
|
||||
endif()
|
||||
|
||||
if(lib_TYPE STREQUAL SHARED AND NOT MSVC)
|
||||
set_target_properties(${lib_NAME} PROPERTIES SOVERSION ${DRACO_SOVERSION})
|
||||
# VERSION and SOVERSION as necessary
|
||||
if(NOT lib_TYPE STREQUAL STATIC AND NOT lib_TYPE STREQUAL MODULE)
|
||||
set_target_properties(${lib_NAME} PROPERTIES VERSION ${DRACO_VERSION})
|
||||
if(NOT MSVC)
|
||||
set_target_properties(${lib_NAME} PROPERTIES SOVERSION ${DRACO_SOVERSION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS AND (MSVC OR WIN32))
|
||||
|
|
|
@ -17,31 +17,31 @@
|
|||
namespace draco {
|
||||
void DracoTimer::Start() {
|
||||
#ifdef _WIN32
|
||||
QueryPerformanceCounter(&tv_start);
|
||||
QueryPerformanceCounter(&tv_start_);
|
||||
#else
|
||||
gettimeofday(&tv_start, nullptr);
|
||||
gettimeofday(&tv_start_, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DracoTimer::Stop() {
|
||||
#ifdef _WIN32
|
||||
QueryPerformanceCounter(&tv_end);
|
||||
QueryPerformanceCounter(&tv_end_);
|
||||
#else
|
||||
gettimeofday(&tv_end, nullptr);
|
||||
gettimeofday(&tv_end_, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t DracoTimer::GetInMs() {
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER elapsed = {0};
|
||||
elapsed.QuadPart = tv_end.QuadPart - tv_start.QuadPart;
|
||||
elapsed.QuadPart = tv_end_.QuadPart - tv_start_.QuadPart;
|
||||
|
||||
LARGE_INTEGER frequency = {0};
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
return elapsed.QuadPart * 1000 / frequency.QuadPart;
|
||||
#else
|
||||
const int64_t seconds = (tv_end.tv_sec - tv_start.tv_sec) * 1000;
|
||||
const int64_t milliseconds = (tv_end.tv_usec - tv_start.tv_usec) / 1000;
|
||||
const int64_t seconds = (tv_end_.tv_sec - tv_start_.tv_sec) * 1000;
|
||||
const int64_t milliseconds = (tv_end_.tv_usec - tv_start_.tv_usec) / 1000;
|
||||
return seconds + milliseconds;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -20,9 +20,10 @@
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
typedef LARGE_INTEGER timeval;
|
||||
typedef LARGE_INTEGER DracoTimeVal;
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
typedef timeval DracoTimeVal;
|
||||
#endif
|
||||
|
||||
#include <cinttypes>
|
||||
|
@ -39,8 +40,8 @@ class DracoTimer {
|
|||
int64_t GetInMs();
|
||||
|
||||
private:
|
||||
timeval tv_start;
|
||||
timeval tv_end;
|
||||
DracoTimeVal tv_start_;
|
||||
DracoTimeVal tv_end_;
|
||||
};
|
||||
|
||||
typedef DracoTimer CycleTimer;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
namespace draco {
|
||||
namespace parser {
|
||||
|
@ -252,7 +253,7 @@ DecoderBuffer ParseLineIntoDecoderBuffer(DecoderBuffer *buffer) {
|
|||
|
||||
std::string ToLower(const std::string &str) {
|
||||
std::string out;
|
||||
std::transform(str.begin(), str.end(), std::back_inserter(out), [](unsigned char c){return tolower(c);});
|
||||
std::transform(str.begin(), str.end(), std::back_inserter(out), tolower);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -268,14 +268,14 @@ std::vector<std::string> PlyReader::SplitWords(const std::string &line) {
|
|||
while ((end = line.find_first_of(" \t\n\v\f\r", start)) !=
|
||||
std::string::npos) {
|
||||
const std::string word(line.substr(start, end - start));
|
||||
if (!std::all_of(word.begin(), word.end(), [](unsigned char c){return isspace(c);})) {
|
||||
if (!std::all_of(word.begin(), word.end(), isspace)) {
|
||||
output.push_back(word);
|
||||
}
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
const std::string last_word(line.substr(start));
|
||||
if (!std::all_of(last_word.begin(), last_word.end(), [](unsigned char c){return isspace(c);})) {
|
||||
if (!std::all_of(last_word.begin(), last_word.end(), isspace)) {
|
||||
output.push_back(last_word);
|
||||
}
|
||||
return output;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue