Merge remote-tracking branch 'origin/master' into HEAD

pull/3985/head
Rahul Sheth 2021-07-07 16:35:29 -04:00
commit 0a5e49252d
78 changed files with 2740 additions and 696 deletions

View File

@ -269,6 +269,8 @@ ELSEIF(MSVC)
ADD_COMPILE_OPTIONS(/wd4351) ADD_COMPILE_OPTIONS(/wd4351)
ENDIF() ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
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" ) ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD 11)

View File

@ -348,16 +348,16 @@ struct Texture {
// empty // 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)), mMapName(std::move(other.mMapName)),
mOffsetU(std::move(other.mOffsetU)), mOffsetU(other.mOffsetU),
mOffsetV(std::move(other.mOffsetV)), mOffsetV(other.mOffsetV),
mScaleU(std::move(other.mScaleU)), mScaleU(other.mScaleU),
mScaleV(std::move(other.mScaleV)), mScaleV(other.mScaleV),
mRotation(std::move(other.mRotation)), mRotation(other.mRotation),
mMapMode(std::move(other.mMapMode)), mMapMode(other.mMapMode),
bPrivate(std::move(other.bPrivate)), bPrivate(other.bPrivate),
iUVSrc(std::move(other.iUVSrc)) { iUVSrc(other.iUVSrc) {
// empty // empty
} }
@ -366,16 +366,16 @@ struct Texture {
return *this; return *this;
} }
mTextureBlend = std::move(other.mTextureBlend); mTextureBlend = other.mTextureBlend;
mMapName = std::move(other.mMapName); mMapName = std::move(other.mMapName);
mOffsetU = std::move(other.mOffsetU); mOffsetU = other.mOffsetU;
mOffsetV = std::move(other.mOffsetV); mOffsetV = other.mOffsetV;
mScaleU = std::move(other.mScaleU); mScaleU = other.mScaleU;
mScaleV = std::move(other.mScaleV); mScaleV = other.mScaleV;
mRotation = std::move(other.mRotation); mRotation = other.mRotation;
mMapMode = std::move(other.mMapMode); mMapMode = other.mMapMode;
bPrivate = std::move(other.bPrivate); bPrivate = other.bPrivate;
iUVSrc = std::move(other.iUVSrc); iUVSrc = other.iUVSrc;
return *this; return *this;
} }
@ -461,13 +461,13 @@ struct Material {
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)), Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)),
mDiffuse(std::move(other.mDiffuse)), mDiffuse(other.mDiffuse),
mSpecularExponent(std::move(other.mSpecularExponent)), mSpecularExponent(other.mSpecularExponent),
mShininessStrength(std::move(other.mShininessStrength)), mShininessStrength(other.mShininessStrength),
mSpecular(std::move(other.mSpecular)), mSpecular(other.mSpecular),
mAmbient(std::move(other.mAmbient)), mAmbient(other.mAmbient),
mShading(std::move(other.mShading)), mShading(other.mShading),
mTransparency(std::move(other.mTransparency)), mTransparency(other.mTransparency),
sTexDiffuse(std::move(other.sTexDiffuse)), sTexDiffuse(std::move(other.sTexDiffuse)),
sTexOpacity(std::move(other.sTexOpacity)), sTexOpacity(std::move(other.sTexOpacity)),
sTexSpecular(std::move(other.sTexSpecular)), sTexSpecular(std::move(other.sTexSpecular)),
@ -475,10 +475,10 @@ struct Material {
sTexBump(std::move(other.sTexBump)), sTexBump(std::move(other.sTexBump)),
sTexEmissive(std::move(other.sTexEmissive)), sTexEmissive(std::move(other.sTexEmissive)),
sTexShininess(std::move(other.sTexShininess)), sTexShininess(std::move(other.sTexShininess)),
mBumpHeight(std::move(other.mBumpHeight)), mBumpHeight(other.mBumpHeight),
mEmissive(std::move(other.mEmissive)), mEmissive(other.mEmissive),
sTexAmbient(std::move(other.sTexAmbient)), sTexAmbient(std::move(other.sTexAmbient)),
mTwoSided(std::move(other.mTwoSided)) { mTwoSided(other.mTwoSided) {
// empty // empty
} }
@ -488,13 +488,13 @@ struct Material {
} }
mName = std::move(other.mName); mName = std::move(other.mName);
mDiffuse = std::move(other.mDiffuse); mDiffuse = other.mDiffuse;
mSpecularExponent = std::move(other.mSpecularExponent); mSpecularExponent = other.mSpecularExponent;
mShininessStrength = std::move(other.mShininessStrength), mShininessStrength = other.mShininessStrength,
mSpecular = std::move(other.mSpecular); mSpecular = other.mSpecular;
mAmbient = std::move(other.mAmbient); mAmbient = other.mAmbient;
mShading = std::move(other.mShading); mShading = other.mShading;
mTransparency = std::move(other.mTransparency); mTransparency = other.mTransparency;
sTexDiffuse = std::move(other.sTexDiffuse); sTexDiffuse = std::move(other.sTexDiffuse);
sTexOpacity = std::move(other.sTexOpacity); sTexOpacity = std::move(other.sTexOpacity);
sTexSpecular = std::move(other.sTexSpecular); sTexSpecular = std::move(other.sTexSpecular);
@ -502,10 +502,10 @@ struct Material {
sTexBump = std::move(other.sTexBump); sTexBump = std::move(other.sTexBump);
sTexEmissive = std::move(other.sTexEmissive); sTexEmissive = std::move(other.sTexEmissive);
sTexShininess = std::move(other.sTexShininess); sTexShininess = std::move(other.sTexShininess);
mBumpHeight = std::move(other.mBumpHeight); mBumpHeight = other.mBumpHeight;
mEmissive = std::move(other.mEmissive); mEmissive = other.mEmissive;
sTexAmbient = std::move(other.sTexAmbient); sTexAmbient = std::move(other.sTexAmbient);
mTwoSided = std::move(other.mTwoSided); mTwoSided = other.mTwoSided;
return *this; return *this;
} }

View File

@ -95,8 +95,8 @@ struct Material : public D3DS::Material {
Material(Material &&other) AI_NO_EXCEPT Material(Material &&other) AI_NO_EXCEPT
: D3DS::Material(std::move(other)), : D3DS::Material(std::move(other)),
avSubMaterials(std::move(other.avSubMaterials)), avSubMaterials(std::move(other.avSubMaterials)),
pcInstance(std::move(other.pcInstance)), pcInstance(other.pcInstance),
bNeed(std::move(other.bNeed)) { bNeed(other.bNeed) {
other.pcInstance = nullptr; other.pcInstance = nullptr;
} }
@ -108,8 +108,8 @@ struct Material : public D3DS::Material {
//D3DS::Material::operator=(std::move(other)); //D3DS::Material::operator=(std::move(other));
avSubMaterials = std::move(other.avSubMaterials); avSubMaterials = std::move(other.avSubMaterials);
pcInstance = std::move(other.pcInstance); pcInstance = other.pcInstance;
bNeed = std::move(other.bNeed); bNeed = other.bNeed;
other.pcInstance = nullptr; other.pcInstance = nullptr;

View File

@ -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 #ifdef DEBUG_B3D
ASSIMP_LOG_ERROR("Error in B3D file data: ", str); ASSIMP_LOG_ERROR("Error in B3D file data: ", str);
#endif #endif

View File

@ -96,7 +96,7 @@ private:
}; };
AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX; 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 ReadTEXS();
void ReadBRUS(); void ReadBRUS();

View File

@ -679,7 +679,7 @@ void BlenderImporter::BuildMaterials(ConversionData &conv_data) {
BuildDefaultMaterial(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 // reset per material global counters
for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) { for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) {

View File

@ -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); const aiString path(tex->path);
out->AddProperty(&path, AI_MATKEY_TEXTURE(type, 0)); out->AddProperty(&path, AI_MATKEY_TEXTURE(type, 0));
out->AddProperty(&tex->transform, 1, AI_MATKEY_UVTRANSFORM(type, 0)); out->AddProperty(&tex->transform, 1, AI_MATKEY_UVTRANSFORM(type, 0));

View File

@ -453,7 +453,7 @@ void ColladaParser::PostProcessRootAnimations() {
temp.mSubAnims.push_back(clip); temp.mSubAnims.push_back(clip);
for (std::string animationID : it.second) { for (const std::string &animationID : it.second) {
AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID); AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID);
if (animation != mAnimationLibrary.end()) { if (animation != mAnimationLibrary.end()) {

View File

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

View File

@ -1766,6 +1766,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
// XXX handle all kinds of UV transformations // XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation(); uvTrafo.mTranslation = tex->UVTranslation();
uvTrafo.mRotation = tex->UVRotation();
out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0); out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0);
const PropertyTable &props = tex->Props(); const PropertyTable &props = tex->Props();
@ -1885,6 +1886,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
// XXX handle all kinds of UV transformations // XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation(); uvTrafo.mTranslation = tex->UVTranslation();
uvTrafo.mRotation = tex->UVRotation();
out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex); out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex);
const PropertyTable &props = tex->Props(); const PropertyTable &props = tex->Props();
@ -2324,6 +2326,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
// XXX handle all kinds of UV transformations // XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation(); uvTrafo.mTranslation = tex->UVTranslation();
uvTrafo.mRotation = tex->UVRotation();
out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0); out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0);
int uvIndex = 0; int uvIndex = 0;
@ -2599,7 +2602,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
anim->mMorphMeshChannels = new aiMeshMorphAnim *[numMorphMeshChannels]; anim->mMorphMeshChannels = new aiMeshMorphAnim *[numMorphMeshChannels];
anim->mNumMorphMeshChannels = numMorphMeshChannels; anim->mNumMorphMeshChannels = numMorphMeshChannels;
unsigned int i = 0; unsigned int i = 0;
for (auto morphAnimIt : morphAnimDatas) { for (const auto &morphAnimIt : morphAnimDatas) {
morphAnimData *animData = morphAnimIt.second; morphAnimData *animData = morphAnimIt.second;
unsigned int numKeys = static_cast<unsigned int>(animData->size()); unsigned int numKeys = static_cast<unsigned int>(animData->size());
aiMeshMorphAnim *meshMorphAnim = new aiMeshMorphAnim(); aiMeshMorphAnim *meshMorphAnim = new aiMeshMorphAnim();

View File

@ -57,9 +57,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <memory>
#include <functional> #include <functional>
#include <map> #include <map>
#include <memory>
#include <utility>
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
@ -248,10 +249,8 @@ Object::~Object()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props) FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<const PropertyTable> props) :
: props(props) props(std::move(props)), doc(doc) {
, doc(doc)
{
// empty // empty
} }

View File

@ -500,6 +500,10 @@ public:
return uvScaling; return uvScaling;
} }
const ai_real &UVRotation() const {
return uvRotation;
}
const PropertyTable& Props() const { const PropertyTable& Props() const {
ai_assert(props.get()); ai_assert(props.get());
return *props.get(); return *props.get();
@ -517,6 +521,7 @@ public:
private: private:
aiVector2D uvTrans; aiVector2D uvTrans;
aiVector2D uvScaling; aiVector2D uvScaling;
ai_real uvRotation;
std::string type; std::string type;
std::string relativeFileName; std::string relativeFileName;

View File

@ -144,9 +144,8 @@ void FBX::Node::AddP70time(
// public member functions for writing nodes to stream // public member functions for writing nodes to stream
void FBX::Node::Dump( void FBX::Node::Dump(
std::shared_ptr<Assimp::IOStream> outfile, const std::shared_ptr<Assimp::IOStream> &outfile,
bool binary, int indent bool binary, int indent) {
) {
if (binary) { if (binary) {
Assimp::StreamWriterLE outstream(outfile); Assimp::StreamWriterLE outstream(outfile);
DumpBinary(outstream); DumpBinary(outstream);

View File

@ -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 // write the full node to the given file or stream
void Dump( void Dump(
std::shared_ptr<Assimp::IOStream> outfile, const std::shared_ptr<Assimp::IOStream> &outfile,
bool binary, int indent bool binary, int indent);
);
void Dump(Assimp::StreamWriterLE &s, bool binary, int indent); void Dump(Assimp::StreamWriterLE &s, bool binary, int indent);
// these other functions are for writing data piece by piece. // these other functions are for writing data piece by piece.

View File

@ -541,10 +541,17 @@ void FBXExporter::WriteReferences ()
// (before any actual data is written) // (before any actual data is written)
// --------------------------------------------------------------- // ---------------------------------------------------------------
size_t count_nodes(const aiNode* n) { size_t count_nodes(const aiNode* n, const aiNode* root) {
size_t count = 1; 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) { for (size_t i = 0; i < n->mNumChildren; ++i) {
count += count_nodes(n->mChildren[i]); count += count_nodes(n->mChildren[i], root);
} }
return count; return count;
} }
@ -714,7 +721,7 @@ void FBXExporter::WriteDefinitions ()
// Model / FbxNode // Model / FbxNode
// <~~ node hierarchy // <~~ 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) { if (count) {
n = FBX::Node("ObjectType", "Model"); n = FBX::Node("ObjectType", "Model");
n.AddChild("Count", count); n.AddChild("Count", count);
@ -1681,6 +1688,10 @@ void FBXExporter::WriteObjects ()
// link the image data to the texture // link the image data to the texture
connections.emplace_back("C", "OO", image_uid, texture_uid); connections.emplace_back("C", "OO", image_uid, texture_uid);
aiUVTransform trafo;
unsigned int max = sizeof(aiUVTransform);
aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE, 0), (float *)&trafo, &max);
// now write the actual texture node // now write the actual texture node
FBX::Node tnode("Texture"); FBX::Node tnode("Texture");
// TODO: some way to determine texture name? // TODO: some way to determine texture name?
@ -1691,6 +1702,9 @@ void FBXExporter::WriteObjects ()
tnode.AddChild("Version", int32_t(202)); tnode.AddChild("Version", int32_t(202));
tnode.AddChild("TextureName", texture_name); tnode.AddChild("TextureName", texture_name);
FBX::Node p("Properties70"); 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.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify
//p.AddP70string("UVSet", ""); // TODO: how should this work? //p.AddP70string("UVSet", ""); // TODO: how should this work?
p.AddP70bool("UseMaterial", 1); p.AddP70bool("UseMaterial", 1);
@ -2196,7 +2210,65 @@ void FBXExporter::WriteObjects ()
bpnode.Dump(outstream, binary, indent); 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) // write nodes (i.e. model hierarchy)
// start at root node // start at root node
@ -2600,10 +2672,19 @@ void FBXExporter::WriteModelNodes(
// and connect them // and connect them
connections.emplace_back("C", "OO", node_attribute_uid, node_uid); connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
} else { } else {
// generate a null node so we can add children to it const auto& lightIt = lights_uids.find(node->mName.C_Str());
WriteModelNode( if(lightIt != lights_uids.end()) {
outstream, binary, node, node_uid, "Null", transform_chain // 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 // if more than one child mesh, make nodes for each mesh
@ -2625,17 +2706,14 @@ void FBXExporter::WriteModelNodes(
], ],
new_node_uid new_node_uid
); );
// write model node
FBX::Node m("Model"); aiNode new_node;
// take name from mesh name, if it exists // take name from mesh name, if it exists
std::string name = mScene->mMeshes[node->mMeshes[i]]->mName.C_Str(); new_node.mName = mScene->mMeshes[node->mMeshes[i]]->mName;
name += FBX::SEPARATOR + "Model"; // write model node
m.AddProperties(new_node_uid, name, "Mesh"); WriteModelNode(
m.AddChild("Version", int32_t(232)); outstream, binary, &new_node, new_node_uid, "Mesh", std::vector<std::pair<std::string,aiVector3D>>()
FBX::Node p("Properties70"); );
p.AddP70enum("InheritType", 1);
m.AddChild(p);
m.Dump(outstream, binary, 1);
} }
} }
@ -2647,16 +2725,14 @@ void FBXExporter::WriteModelNodes(
} }
} }
void FBXExporter::WriteAnimationCurveNode( void FBXExporter::WriteAnimationCurveNode(
StreamWriterLE& outstream, StreamWriterLE &outstream,
int64_t uid, int64_t uid,
const std::string& name, // "T", "R", or "S" const std::string &name, // "T", "R", or "S"
aiVector3D default_value, aiVector3D default_value,
std::string property_name, // "Lcl Translation" etc const std::string &property_name, // "Lcl Translation" etc
int64_t layer_uid, int64_t layer_uid,
int64_t node_uid int64_t node_uid) {
) {
FBX::Node n("AnimationCurveNode"); FBX::Node n("AnimationCurveNode");
n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", ""); n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", "");
FBX::Node p("Properties70"); FBX::Node p("Properties70");
@ -2671,7 +2747,6 @@ void FBXExporter::WriteAnimationCurveNode(
this->connections.emplace_back("C", "OP", uid, node_uid, property_name); this->connections.emplace_back("C", "OP", uid, node_uid, property_name);
} }
void FBXExporter::WriteAnimationCurve( void FBXExporter::WriteAnimationCurve(
StreamWriterLE& outstream, StreamWriterLE& outstream,
double default_value, double default_value,

View File

@ -63,10 +63,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiScene; struct aiScene;
struct aiNode; struct aiNode;
//struct aiMaterial; struct aiLight;
namespace Assimp namespace Assimp {
{
class IOSystem; class IOSystem;
class IOStream; class IOStream;
class ExportProperties; class ExportProperties;
@ -95,6 +94,7 @@ namespace Assimp
std::vector<int64_t> mesh_uids; std::vector<int64_t> mesh_uids;
std::vector<int64_t> material_uids; std::vector<int64_t> material_uids;
std::map<const aiNode*,int64_t> node_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 // this crude unique-ID system is actually fine
int64_t last_uid = 999999; int64_t last_uid = 999999;
@ -154,14 +154,13 @@ namespace Assimp
FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs
); );
void WriteAnimationCurveNode( void WriteAnimationCurveNode(
StreamWriterLE& outstream, StreamWriterLE &outstream,
int64_t uid, int64_t uid,
const std::string& name, // "T", "R", or "S" const std::string &name, // "T", "R", or "S"
aiVector3D default_value, aiVector3D default_value,
std::string property_name, // "Lcl Translation" etc const std::string &property_name, // "Lcl Translation" etc
int64_t animation_layer_uid, int64_t animation_layer_uid,
int64_t node_uid int64_t node_uid);
);
void WriteAnimationCurve( void WriteAnimationCurve(
StreamWriterLE& outstream, StreamWriterLE& outstream,
double default_value, double default_value,

View File

@ -210,6 +210,11 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
uvTrans.y = trans.y; uvTrans.y = trans.y;
} }
const aiVector3D &rotation = PropertyGet<aiVector3D>(*props, "Rotation", ok);
if (ok) {
uvRotation = rotation.z;
}
// resolve video links // resolve video links
if(doc.Settings().readTextures) { if(doc.Settings().readTextures) {
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID()); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());

View File

@ -52,6 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXDocumentUtil.h" #include "FBXDocumentUtil.h"
#include "FBXProperties.h" #include "FBXProperties.h"
#include <utility>
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
@ -172,10 +174,8 @@ PropertyTable::PropertyTable()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps) PropertyTable::PropertyTable(const Element &element, std::shared_ptr<const PropertyTable> templateProps) :
: templateProps(templateProps) templateProps(std::move(templateProps)), element(&element) {
, element(&element)
{
const Scope& scope = GetRequiredScope(element); const Scope& scope = GetRequiredScope(element);
for(const ElementMap::value_type& v : scope.Elements()) { for(const ElementMap::value_type& v : scope.Elements()) {
if(v.first != "P") { if(v.first != "P") {
@ -199,7 +199,6 @@ PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const Prope
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
PropertyTable::~PropertyTable() PropertyTable::~PropertyTable()
{ {

View File

@ -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 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) { if ((intersections.size() & 1) != 0) {
IFCImporter::LogWarn("Odd number of intersections, can't work with that. Omitting half space boundary check."); IFCImporter::LogWarn("Odd number of intersections, can't work with that. Omitting half space boundary check.");
continue; continue;

View File

@ -740,7 +740,7 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
bool fix_orientation = false; bool fix_orientation = false;
std::shared_ptr< TempMesh > meshtmp = std::make_shared<TempMesh>(); std::shared_ptr< TempMesh > meshtmp = std::make_shared<TempMesh>();
if(const Schema_2x3::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<Schema_2x3::IfcShellBasedSurfaceModel>()) { 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 { try {
const ::Assimp::STEP::EXPRESS::ENTITY& e = shell->To<::Assimp::STEP::EXPRESS::ENTITY>(); 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>(); const Schema_2x3::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<Schema_2x3::IfcConnectedFaceSet>();

View File

@ -75,7 +75,7 @@ static void FillMaterial(aiMaterial* mat,const IFC::Schema_2x3::IfcSurfaceStyle*
mat->AddProperty(&name,AI_MATKEY_NAME); mat->AddProperty(&name,AI_MATKEY_NAME);
// now see which kinds of surface information are present // 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)) { if (const IFC::Schema_2x3::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyleShading>(conv.db)) {
aiColor4D col_base,col; aiColor4D col_base,col;
@ -124,7 +124,7 @@ static void FillMaterial(aiMaterial* mat,const IFC::Schema_2x3::IfcSurfaceStyle*
} }
} }
} }
} }
} }
} }
@ -134,7 +134,7 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat
for(;range.first != range.second; ++range.first) { 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>()) { 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(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) ) { if( const IFC::Schema_2x3::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyle>(conv.db) ) {
// try to satisfy from cache // try to satisfy from cache

View File

@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <utility>
struct aiNode; struct aiNode;
namespace Assimp { namespace Assimp {
@ -137,14 +139,10 @@ struct TempOpening
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
TempOpening(const IFC::Schema_2x3::IfcSolidModel* solid,IfcVector3 extrusionDir, TempOpening(const IFC::Schema_2x3::IfcSolidModel *solid, IfcVector3 extrusionDir,
std::shared_ptr<TempMesh> profileMesh, std::shared_ptr<TempMesh> profileMesh,
std::shared_ptr<TempMesh> profileMesh2D) std::shared_ptr<TempMesh> profileMesh2D) :
: solid(solid) solid(solid), extrusionDir(extrusionDir), profileMesh(std::move(profileMesh)), profileMesh2D(std::move(profileMesh2D)) {
, extrusionDir(extrusionDir)
, profileMesh(profileMesh)
, profileMesh2D(profileMesh2D)
{
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------

View File

@ -318,7 +318,7 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
} else { } else {
++s; ++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); nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
return; return;

View File

@ -655,7 +655,7 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// find a node by name // 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(pNode != nullptr);
ai_assert(mScene != nullptr); ai_assert(mScene != nullptr);

View File

@ -89,8 +89,8 @@ private:
// helper functions // helper functions
aiColor4D mkColor(uint32_t c); aiColor4D mkColor(uint32_t c);
void convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid); void convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid);
aiNode *findNode(aiNode *pNode, aiString name); aiNode *findNode(aiNode *pNode, const aiString &name);
void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m); void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m);
void populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector<aiFace> *faces, std::vector<aiVector3D> *verteces, 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<aiVector3D> *normals, std::vector<aiVector3D> *texcoords, std::vector<aiColor4D> *colors,
std::vector<unsigned int> *vertexids); std::vector<unsigned int> *vertexids);

View File

@ -415,8 +415,8 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr
// User defined Assimp config property to detect texture type from filename. // User defined Assimp config property to detect texture type from filename.
if (m_detectTextureTypeFromFilename) { if (m_detectTextureTypeFromFilename) {
size_t posSuffix = textureRef.find_last_of("."); size_t posSuffix = textureRef.find_last_of('.');
size_t posUnderscore = textureRef.find_last_of("_"); size_t posUnderscore = textureRef.find_last_of('_');
if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) { if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) {
string identifier = ai_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore)); string identifier = ai_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore));

View File

@ -99,7 +99,7 @@ static void extractIds(const std::string &key, int &id1, int &id2) {
return; return;
} }
const std::string::size_type pos = key.find("."); const std::string::size_type pos = key.find('.');
if (std::string::npos == pos) { if (std::string::npos == pos) {
return; return;
} }
@ -208,7 +208,7 @@ void Q3BSPFileImporter::separateMapName(const std::string &importName, std::stri
return; return;
} }
const std::string::size_type pos = importName.rfind(","); const std::string::size_type pos = importName.rfind(',');
if (std::string::npos == pos) { if (std::string::npos == pos) {
archiveName = importName; archiveName = importName;
return; return;

View File

@ -49,8 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "STEPFileEncoding.h" #include "STEPFileEncoding.h"
#include <assimp/TinyFormatter.h> #include <assimp/TinyFormatter.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <memory>
#include <functional> #include <functional>
#include <memory>
#include <utility>
using namespace Assimp; using namespace Assimp;
@ -87,7 +88,7 @@ static const char *ISO_Token = "ISO-10303-21;";
static const char *FILE_SCHEMA_Token = "FILE_SCHEMA"; static const char *FILE_SCHEMA_Token = "FILE_SCHEMA";
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
STEP::DB* STEP::ReadFileHeader(std::shared_ptr<IOStream> stream) { 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)); std::unique_ptr<STEP::DB> db = std::unique_ptr<STEP::DB>(new STEP::DB(reader));
LineSplitter &splitter = db->GetSplitter(); LineSplitter &splitter = db->GetSplitter();

View File

@ -634,7 +634,7 @@ private:
}; };
template <typename T> 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 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; typedef std::pair<RefMap::const_iterator, RefMap::const_iterator> RefMapRange;
private: private:
DB(std::shared_ptr<StreamReaderLE> reader) : DB(const std::shared_ptr<StreamReaderLE> &reader) :
reader(reader), splitter(*reader, true, true), evaluated_count(), schema(nullptr) {} reader(reader), splitter(*reader, true, true), evaluated_count(), schema(nullptr) {}
public: public:

View File

@ -530,8 +530,8 @@ void XFileExporter::writePath(const aiString &path)
while( str.find( "\\\\") != std::string::npos) while( str.find( "\\\\") != std::string::npos)
str.replace( str.find( "\\\\"), 2, "\\"); str.replace( str.find( "\\\\"), 2, "\\");
while( str.find( "\\") != std::string::npos) while (str.find('\\') != std::string::npos)
str.replace( str.find( "\\"), 1, "/"); str.replace(str.find('\\'), 1, "/");
mOutput << str; mOutput << str;

View File

@ -63,9 +63,9 @@ class X3DExporter {
// empty // empty
} }
SAttribute(SAttribute && rhs) : SAttribute(SAttribute &&rhs) AI_NO_EXCEPT :
Name(std::move(rhs.Name)), Name(rhs.Name),
Value(std::move(rhs.Value)) { Value(rhs.Value) {
// empty // empty
} }
}; };

View File

@ -456,11 +456,10 @@ namespace glTF
/// \param [in] pDecodedData - pointer to decoded data array. /// \param [in] pDecodedData - pointer to decoded data array.
/// \param [in] pDecodedData_Length - size of encoded region, in bytes. /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
/// \param [in] pID - ID of the region. /// \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), DecodedData_Length(pDecodedData_Length), ID(pID) Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) {}
{}
/// \fn ~SEncodedRegion() /// \fn ~SEncodedRegion()
/// Destructor. /// Destructor.
~SEncodedRegion() { delete [] DecodedData; } ~SEncodedRegion() { delete [] DecodedData; }
}; };
@ -1149,8 +1148,7 @@ namespace glTF
void ReadExtensionsUsed(Document& doc); void ReadExtensionsUsed(Document& doc);
IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
}; };
} }

View File

@ -1377,7 +1377,7 @@ inline void Asset::ReadExtensionsUsed(Document &doc) {
#undef CHECK_EXT #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 #ifdef ASSIMP_API
(void)absolute; (void)absolute;
return mIOSystem->Open(path, mode); return mIOSystem->Open(path, mode);

View File

@ -405,8 +405,7 @@ void glTFExporter::ExportMaterials()
* Search through node hierarchy and find the node containing the given meshID. * Search through node hierarchy and find the node containing the given meshID.
* Returns true on success, and false otherwise. * 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) { for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) {
if (meshID.compare(nodeIn->meshes[i]->id) == 0) { if (meshID.compare(nodeIn->meshes[i]->id) == 0) {
meshNode = nodeIn; meshNode = nodeIn;

View File

@ -356,6 +356,53 @@ struct Nullable {
isPresent(true) {} 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 //! Base class for all glTF top-level objects
struct Object { struct Object {
int index; //!< The index of this object within its property container 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 id; //!< The globally unique ID used to reference this object
std::string name; //!< The user-defined name of 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) //! Objects marked as special are not exported (used to emulate the binary body buffer)
virtual bool IsSpecial() const { return false; } virtual bool IsSpecial() const { return false; }
@ -377,6 +427,9 @@ struct Object {
inline Value *FindArray(Value &val, const char *id); inline Value *FindArray(Value &val, const char *id);
inline Value *FindObject(Value &val, const char *id); inline Value *FindObject(Value &val, const char *id);
inline Value *FindExtension(Value &val, const char *extensionId); 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 - pointer to decoded data array.
/// \param [in] pDecodedData_Length - size of encoded region, in bytes. /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
/// \param [in] pID - ID of the region. /// \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), Offset(pOffset),
EncodedData_Length(pEncodedData_Length), EncodedData_Length(pEncodedData_Length),
DecodedData(pDecodedData), DecodedData(pDecodedData),
@ -834,50 +887,6 @@ struct Mesh : public Object {
void Read(Value &pJSON_Object, Asset &pAsset_Root); 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 { struct Node : public Object {
std::vector<Ref<Node>> children; std::vector<Ref<Node>> children;
std::vector<Ref<Mesh>> meshes; 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. Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
CustomExtension extensions;
Node() {} Node() {}
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
@ -1188,7 +1195,7 @@ private:
void ReadExtensionsUsed(Document &doc); void ReadExtensionsUsed(Document &doc);
void ReadExtensionsRequired(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) { inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2021, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -304,6 +303,43 @@ inline Value *FindObject(Document &doc, const char *memberId) {
inline Value *FindExtension(Value &val, const char *extensionId) { inline Value *FindExtension(Value &val, const char *extensionId) {
return FindExtensionInContext(val, extensionId, "the document"); 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 } // namespace
inline Value *Object::FindString(Value &val, const char *memberId) { 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()); 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 #ifdef ASSIMP_ENABLE_DRACO
template <typename T> template <typename T>
@ -569,6 +617,8 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
inst->oIndex = i; inst->oIndex = i;
ReadMember(obj, "name", inst->name); ReadMember(obj, "name", inst->name);
inst->Read(obj, mAsset); inst->Read(obj, mAsset);
inst->ReadExtensions(obj);
inst->ReadExtras(obj);
Ref<T> result = Add(inst.release()); Ref<T> result = Add(inst.release());
mRecursiveReferenceCheck.erase(i); 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) { 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) { for (SEncodedRegion *reg : EncodedRegion_List) {
if (reg->ID == pID) { if (reg->ID == pID) {
EncodedRegion_Current = reg; EncodedRegion_Current = reg;
return; 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) { 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 // Force alignment to 4 bits
Grow((length + 3) & ~3); const size_t paddedLength = (length + 3) & ~3;
Grow(paddedLength);
memcpy(mData.get() + offset, data, length); memcpy(mData.get() + offset, data, length);
memset(mData.get() + offset + length, 0, paddedLength - length);
return offset; return offset;
} }
@ -820,9 +874,7 @@ inline void Buffer::Grow(size_t amount) {
// //
// struct BufferView // struct BufferView
// //
inline void BufferView::Read(Value &obj, Asset &r) { inline void BufferView::Read(Value &obj, Asset &r) {
if (Value *bufferVal = FindUInt(obj, "buffer")) { if (Value *bufferVal = FindUInt(obj, "buffer")) {
buffer = r.buffers.Retrieve(bufferVal->GetUint()); 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) { inline uint8_t *BufferView::GetPointer(size_t accOffset) {
if (!buffer) return nullptr; if (!buffer) {
return nullptr;
}
uint8_t *basePtr = buffer->GetPointer(); uint8_t *basePtr = buffer->GetPointer();
if (!basePtr) return nullptr; if (!basePtr) {
return nullptr;
}
size_t offset = accOffset + byteOffset; size_t offset = accOffset + byteOffset;
if (buffer->EncodedRegion_Current != nullptr) { if (buffer->EncodedRegion_Current != nullptr) {
const size_t begin = buffer->EncodedRegion_Current->Offset; const size_t begin = buffer->EncodedRegion_Current->Offset;
const size_t end = begin + buffer->EncodedRegion_Current->DecodedData_Length; 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 &buffer->EncodedRegion_Current->DecodedData[offset - begin];
}
} }
return basePtr + offset; return basePtr + offset;
@ -877,18 +934,18 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) {
while (pIndices != indicesEnd) { while (pIndices != indicesEnd) {
size_t offset; size_t offset;
switch (indicesType) { switch (indicesType) {
case ComponentType_UNSIGNED_BYTE: case ComponentType_UNSIGNED_BYTE:
offset = *pIndices; offset = *pIndices;
break; break;
case ComponentType_UNSIGNED_SHORT: case ComponentType_UNSIGNED_SHORT:
offset = *reinterpret_cast<uint16_t *>(pIndices); offset = *reinterpret_cast<uint16_t *>(pIndices);
break; break;
case ComponentType_UNSIGNED_INT: case ComponentType_UNSIGNED_INT:
offset = *reinterpret_cast<uint32_t *>(pIndices); offset = *reinterpret_cast<uint32_t *>(pIndices);
break; break;
default: default:
// have fun with float and negative values from signed types as indices. // have fun with float and negative values from signed types as indices.
throw DeadlyImportError("Unsupported component type in index."); throw DeadlyImportError("Unsupported component type in index.");
} }
offset *= elementSize; offset *= elementSize;
@ -900,7 +957,6 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) {
} }
inline void Accessor::Read(Value &obj, Asset &r) { inline void Accessor::Read(Value &obj, Asset &r) {
if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { if (Value *bufferViewVal = FindUInt(obj, "bufferView")) {
bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
} }
@ -1612,9 +1668,9 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
} }
} }
Value *extras = FindObject(pJSON_Object, "extras"); Value *curExtras = FindObject(pJSON_Object, "extras");
if (nullptr != extras) { if (nullptr != curExtras) {
if (Value *curTargetNames = FindArray(*extras, "targetNames")) { if (Value *curTargetNames = FindArray(*curExtras, "targetNames")) {
this->targetNames.resize(curTargetNames->Size()); this->targetNames.resize(curTargetNames->Size());
for (unsigned int i = 0; i < curTargetNames->Size(); ++i) { for (unsigned int i = 0; i < curTargetNames->Size(); ++i) {
Value &targetNameValue = (*curTargetNames)[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) { inline void Node::Read(Value &obj, Asset &r) {
if (name.empty()) { if (name.empty()) {
name = id; name = id;
@ -1775,8 +1795,6 @@ inline void Node::Read(Value &obj, Asset &r) {
Value *curExtensions = FindObject(obj, "extensions"); Value *curExtensions = FindObject(obj, "extensions");
if (nullptr != curExtensions) { if (nullptr != curExtensions) {
this->extensions = ReadExtensions("extensions", *curExtensions);
if (r.extensionsUsed.KHR_lights_punctual) { if (r.extensionsUsed.KHR_lights_punctual) {
if (Value *ext = FindObject(*curExtensions, "KHR_lights_punctual")) { if (Value *ext = FindObject(*curExtensions, "KHR_lights_punctual")) {
Value *curLight = FindUInt(*ext, "light"); Value *curLight = FindUInt(*ext, "light");
@ -2132,7 +2150,7 @@ inline void Asset::ReadExtensionsUsed(Document &doc) {
#undef CHECK_EXT #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 #ifdef ASSIMP_API
return mIOSystem->Open(path, mode); return mIOSystem->Open(path, mode);
#else #else

View File

@ -118,14 +118,14 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
ExportScene(); ExportScene();
ExportAnimations(); ExportAnimations();
// export extras // export extras
if(mProperties->HasPropertyCallback("extras")) if(mProperties->HasPropertyCallback("extras"))
{ {
std::function<void*(void*)> ExportExtras = mProperties->GetPropertyCallback("extras"); std::function<void*(void*)> ExportExtras = mProperties->GetPropertyCallback("extras");
mAsset->extras = (rapidjson::Value*)ExportExtras(0); mAsset->extras = (rapidjson::Value*)ExportExtras(0);
} }
AssetWriter writer(*mAsset); AssetWriter writer(*mAsset);
if (isBinary) { if (isBinary) {
@ -436,11 +436,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; aiString aId;
std::string id; 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(); id = aId.C_Str();
} }
@ -455,49 +455,52 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture, a
SamplerMagFilter filterMag; SamplerMagFilter filterMag;
SamplerMinFilter filterMin; 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); 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); 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; 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; texture->sampler->minFilter = filterMin;
} }
aiString name; 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(); 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; 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; 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; 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(); std::string path = tex.C_Str();
if (path.size() > 0) { if (path.size() > 0) {
@ -515,11 +518,10 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
std::string imgId = mAsset->FindUniqueID("", "image"); std::string imgId = mAsset->FindUniqueID("", "image");
texture->source = mAsset->images.Create(imgId); texture->source = mAsset->images.Create(imgId);
if (path[0] == '*') { // embedded const aiTexture* curTex = mScene->GetEmbeddedTexture(path.c_str());
aiTexture* curTex = mScene->mTextures[atoi(&path[1])]; if (curTex != nullptr) { // embedded
texture->source->name = curTex->mFilename.C_Str(); texture->source->name = curTex->mFilename.C_Str();
//basisu: embedded ktx2, bu //basisu: embedded ktx2, bu
if (curTex->achFormatHint[0]) { if (curTex->achFormatHint[0]) {
std::string mimeType = "image/"; std::string mimeType = "image/";
@ -541,7 +543,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
mimeType += curTex->achFormatHint; mimeType += curTex->achFormatHint;
texture->source->mimeType = mimeType; texture->source->mimeType = mimeType;
} }
// The asset has its own buffer, see Image::SetData // The asset has its own buffer, see Image::SetData
//basisu: "image/ktx2", "image/basis" as is //basisu: "image/ktx2", "image/basis" as is
texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset); texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset);
@ -554,7 +556,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
useBasisUniversal = true; useBasisUniversal = true;
} }
} }
//basisu //basisu
if(useBasisUniversal) { if(useBasisUniversal) {
mAsset->extensionsUsed.KHR_texture_basisu = true; mAsset->extensionsUsed.KHR_texture_basisu = true;
@ -568,45 +570,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; Ref<Texture>& texture = prop.texture;
GetMatTex(mat, texture, tt, slot); GetMatTex(mat, texture, prop.texCoord, tt, slot);
if (texture) { //if (texture) {
GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); // 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; Ref<Texture>& texture = prop.texture;
GetMatTex(mat, texture, tt, slot); GetMatTex(mat, texture, prop.texCoord, tt, slot);
if (texture) { if (texture) {
GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); //GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
GetMatTexProp(mat, prop.scale, "scale", 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; Ref<Texture>& texture = prop.texture;
GetMatTex(mat, texture, tt, slot); GetMatTex(mat, texture, prop.texCoord, tt, slot);
if (texture) { if (texture) {
GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); //GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
GetMatTexProp(mat, prop.strength, "strength", 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; aiColor4D col;
aiReturn result = mat->Get(propName, type, idx, col); aiReturn result = mat.Get(propName, type, idx, col);
if (result == AI_SUCCESS) { if (result == AI_SUCCESS) {
prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a; prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a;
@ -615,37 +617,116 @@ aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const cha
return result; 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; aiColor3D col;
aiReturn result = mat->Get(propName, type, idx, col); aiReturn result = mat.Get(propName, type, idx, col);
if (result == AI_SUCCESS) { 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; 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() void glTF2Exporter::ExportMaterials()
{ {
aiString aiName; aiString aiName;
for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { 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); std::string id = "material_" + ai_to_string(i);
Ref<Material> m = mAsset->materials.Create(id); Ref<Material> m = mAsset->materials.Create(id);
std::string name; 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 = aiName.C_Str();
} }
name = mAsset->FindUniqueID(name, "material"); name = mAsset->FindUniqueID(name, "material");
m->name = name; 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 (!m->pbrMetallicRoughness.baseColorTexture.texture) {
//if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture //if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture
@ -654,26 +735,26 @@ void glTF2Exporter::ExportMaterials()
GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); 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. // 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 //a fallback to any diffuse color should be used instead
GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); 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 //if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0
m->pbrMetallicRoughness.metallicFactor = 0; m->pbrMetallicRoughness.metallicFactor = 0;
} }
// get roughness if source is gltf2 file // 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 // otherwise, try to derive and convert from specular + shininess values
aiColor4D specularColor; aiColor4D specularColor;
ai_real shininess; ai_real shininess;
if ( if (
mat->Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS
) { ) {
// convert specular color to luminance // convert specular color to luminance
float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f; float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f;
@ -694,103 +775,60 @@ void glTF2Exporter::ExportMaterials()
GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE); GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE);
GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE); GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE);
mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); mat.Get(AI_MATKEY_TWOSIDED, m->doubleSided);
mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff); mat.Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff);
float opacity;
aiString alphaMode; 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(); 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); // KHR_materials_pbrSpecularGlossiness extension
// NOTE: This extension is being considered for deprecation (Dec 2020)
if (hasPbrSpecularGlossiness) {
if (!mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true;
}
PbrSpecularGlossiness pbrSG; PbrSpecularGlossiness pbrSG;
if (GetMatSpecGloss(mat, pbrSG)) {
GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE); mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true;
GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR); m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
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;
}
} }
GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE);
GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR);
m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
} }
bool unlit; // glTFv2 is either PBR or Unlit
if (mat->Get(AI_MATKEY_GLTF_UNLIT, unlit) == AI_SUCCESS && unlit) { aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
mat.Get(AI_MATKEY_SHADING_MODEL, shadingMode);
if (shadingMode == aiShadingMode_Unlit) {
mAsset->extensionsUsed.KHR_materials_unlit = true; mAsset->extensionsUsed.KHR_materials_unlit = true;
m->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; MaterialClearcoat clearcoat;
mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN, hasMaterialSheen); if (GetMatClearcoat(mat, clearcoat)) {
mAsset->extensionsUsed.KHR_materials_clearcoat = true;
m->materialClearcoat = Nullable<MaterialClearcoat>(clearcoat);
}
if (hasMaterialSheen) { MaterialTransmission transmission;
mAsset->extensionsUsed.KHR_materials_sheen = true; if (GetMatTransmission(mat, transmission)) {
mAsset->extensionsUsed.KHR_materials_transmission = true;
MaterialSheen sheen; m->materialTransmission = Nullable<MaterialTransmission>(transmission);
}
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);
} }
} }
} }
@ -799,8 +837,7 @@ void glTF2Exporter::ExportMaterials()
* Search through node hierarchy and find the node containing the given meshID. * Search through node hierarchy and find the node containing the given meshID.
* Returns true on success, and false otherwise. * 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) { for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) {
if (meshID.compare(nodeIn->meshes[i]->id) == 0) { if (meshID.compare(nodeIn->meshes[i]->id) == 0) {
meshNode = nodeIn; meshNode = nodeIn;

View File

@ -72,6 +72,10 @@ namespace glTF2
struct OcclusionTextureInfo; struct OcclusionTextureInfo;
struct Node; struct Node;
struct Texture; struct Texture;
struct PbrSpecularGlossiness;
struct MaterialSheen;
struct MaterialClearcoat;
struct MaterialTransmission;
// Vec/matrix types, as raw float arrays // Vec/matrix types, as raw float arrays
typedef float (vec2)[2]; typedef float (vec2)[2];
@ -97,15 +101,19 @@ namespace Assimp
protected: protected:
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot); 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, 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 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::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::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::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial* mat, glTF2::OcclusionTextureInfo& 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::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); 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 ExportMetadata();
void ExportMaterials(); void ExportMaterials();
void ExportMeshes(); void ExportMeshes();

View File

@ -165,7 +165,8 @@ inline void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
} }
mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); 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) { if (prop.textureTransformSupported) {
aiUVTransform transform; aiUVTransform transform;
@ -208,6 +209,11 @@ inline void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
if (sampler->minFilter != SamplerMinFilter::UNSET) { if (sampler->minFilter != SamplerMinFilter::UNSET) {
mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot)); 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); 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_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, 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); 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.metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR);
aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR); aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR);
float roughnessAsShininess = 1 - mat.pbrMetallicRoughness.roughnessFactor; float roughnessAsShininess = 1 - mat.pbrMetallicRoughness.roughnessFactor;
roughnessAsShininess *= roughnessAsShininess * 1000; 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); SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE);
aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED); aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
aimat->AddProperty(&mat.pbrMetallicRoughness.baseColorFactor[3], 1, AI_MATKEY_OPACITY);
aiString alphaMode(mat.alphaMode); aiString alphaMode(mat.alphaMode);
aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_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) { if (mat.pbrSpecularGlossiness.isPresent) {
PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value; 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.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR); SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR);
float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f; float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f;
aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS); 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.diffuseTexture, aimat, aiTextureType_DIFFUSE);
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR); SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR);
} }
// glTFv2 is either PBR or Unlit
aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
if (mat.unlit) { 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) { if (mat.materialSheen.isPresent) {
MaterialSheen &sheen = mat.materialSheen.value; MaterialSheen &sheen = mat.materialSheen.value;
// Default value {0,0,0} disables Sheen
aimat->AddProperty(&mat.materialSheen.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN); if (sheen.sheenColorFactor != defaultSheenFactor) {
SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR); SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_SHEEN_COLOR_FACTOR);
aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR); aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_SHEEN_ROUGHNESS_FACTOR);
SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE); SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_SHEEN_COLOR_TEXTURE);
SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE); SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE);
}
} }
//KHR_materials_clearcoat // KHR_materials_clearcoat
if (mat.materialClearcoat.isPresent) { if (mat.materialClearcoat.isPresent) {
MaterialClearcoat &clearcoat = mat.materialClearcoat.value; MaterialClearcoat &clearcoat = mat.materialClearcoat.value;
// Default value 0.0 disables clearcoat
aimat->AddProperty(&mat.materialClearcoat.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT); if (clearcoat.clearcoatFactor != 0.0f) {
aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR); aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_CLEARCOAT_FACTOR);
aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR); aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR);
SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE); SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_CLEARCOAT_TEXTURE);
SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE); SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE);
SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE); SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE);
}
} }
//KHR_materials_transmission // KHR_materials_transmission
if (mat.materialTransmission.isPresent) { if (mat.materialTransmission.isPresent) {
MaterialTransmission &transmission = mat.materialTransmission.value; MaterialTransmission &transmission = mat.materialTransmission.value;
aimat->AddProperty(&mat.materialTransmission.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION); aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_TRANSMISSION_FACTOR);
aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR); SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_TRANSMISSION_TEXTURE);
SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE);
} }
return aimat; return aimat;
@ -489,7 +504,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
"\" does not match the vertex count"); "\" does not match the vertex count");
continue; continue;
} }
auto componentType = attr.color[c]->componentType; auto componentType = attr.color[c]->componentType;
if (componentType == glTF2::ComponentType_FLOAT) { if (componentType == glTF2::ComponentType_FLOAT) {
attr.color[c]->ExtractData(aim->mColors[c]); attr.color[c]->ExtractData(aim->mColors[c]);
@ -984,6 +999,14 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) {
} }
} }
void ParseExtras(aiMetadata *metadata, const CustomExtension &extension) {
if (extension.mValues.isPresent) {
for (size_t i = 0; i < extension.mValues.value.size(); ++i) {
ParseExtensions(metadata, extension.mValues.value[i]);
}
}
}
aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &meshOffsets, glTF2::Ref<glTF2::Node> &ptr) { aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &meshOffsets, glTF2::Ref<glTF2::Node> &ptr) {
Node &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; 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); GetNodeTransform(ainode->mTransformation, node);
@ -1498,7 +1526,8 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) {
const bool hasVersion = !a.asset.version.empty(); const bool hasVersion = !a.asset.version.empty();
const bool hasGenerator = !a.asset.generator.empty(); const bool hasGenerator = !a.asset.generator.empty();
const bool hasCopyright = !a.asset.copyright.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; mScene->mMetaData = new aiMetadata;
if (hasVersion) { if (hasVersion) {
mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version));
@ -1509,6 +1538,9 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) {
if (hasCopyright) { if (hasCopyright) {
mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright)); mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright));
} }
if (hasSceneMetadata) {
ParseExtensions(mScene->mMetaData, a.scene->customExtensions);
}
} }
} }

View File

@ -406,11 +406,25 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
// Check whether this texture is an embedded texture. // Check whether this texture is an embedded texture.
// In this case the property looks like this: *<n>, // In this case the property looks like this: *<n>,
// where n is the index of the texture. // 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]) { if ('*' == s.data[0]) {
// Offset the index and write it back .. // Offset the index and write it back ..
const unsigned int idx = strtoul10(&s.data[1]) + offset[n]; 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);
} }
} }

View File

@ -47,10 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/material.h> #include <assimp/material.h>
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
const char* TextureTypeToString(aiTextureType in) const char *TextureTypeToString(aiTextureType in) {
{ switch (in) {
switch (in)
{
case aiTextureType_NONE: case aiTextureType_NONE:
return "n/a"; return "n/a";
case aiTextureType_DIFFUSE: case aiTextureType_DIFFUSE:
@ -87,6 +85,12 @@ const char* TextureTypeToString(aiTextureType in)
return "DiffuseRoughness"; return "DiffuseRoughness";
case aiTextureType_AMBIENT_OCCLUSION: case aiTextureType_AMBIENT_OCCLUSION:
return "AmbientOcclusion"; return "AmbientOcclusion";
case aiTextureType_SHEEN:
return "Sheen";
case aiTextureType_CLEARCOAT:
return "Clearcoat";
case aiTextureType_TRANSMISSION:
return "Transmission";
case aiTextureType_UNKNOWN: case aiTextureType_UNKNOWN:
return "Unknown"; return "Unknown";
default: default:

View File

@ -105,14 +105,13 @@ void ExportScenePbrt (
} // end of namespace Assimp } // end of namespace Assimp
// Constructor // Constructor
PbrtExporter::PbrtExporter ( PbrtExporter::PbrtExporter(
const aiScene* pScene, IOSystem* pIOSystem, const aiScene *pScene, IOSystem *pIOSystem,
const std::string path, const std::string file) const std::string &path, const std::string &file) :
: mScene(pScene), mScene(pScene),
mIOSystem(pIOSystem), mIOSystem(pIOSystem),
mPath(path), mPath(path),
mFile(file) mFile(file) {
{
// Export embedded textures. // Export embedded textures.
if (mScene->mNumTextures > 0) if (mScene->mNumTextures > 0)
if (!mIOSystem->CreateDirectory("textures")) if (!mIOSystem->CreateDirectory("textures"))
@ -209,12 +208,12 @@ void PbrtExporter::WriteMetaData() {
aiString* value = aiString* value =
static_cast<aiString*>(pMetaData->mValues[i].mData); static_cast<aiString*>(pMetaData->mValues[i].mData);
std::string svalue = value->C_Str(); 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"; mOutput << "\n";
while (found != std::string::npos) { while (found != std::string::npos) {
mOutput << "# " << svalue.substr(0, found) << "\n"; mOutput << "# " << svalue.substr(0, found) << "\n";
svalue = svalue.substr(found + 1); svalue = svalue.substr(found + 1);
found = svalue.find_first_of("\n"); found = svalue.find_first_of('\n');
} }
mOutput << "# " << svalue << "\n"; mOutput << "# " << svalue << "\n";
break; break;
@ -595,8 +594,8 @@ void PbrtExporter::WriteMaterial(int m) {
} }
mOutput << "\n"; mOutput << "\n";
auto White = [](aiColor3D c) { return c.r == 1 && c.g == 1 && c.b == 1; }; auto White = [](const 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 Black = [](const aiColor3D &c) { return c.r == 0 && c.g == 0 && c.b == 0; };
aiColor3D diffuse, specular, transparency; aiColor3D diffuse, specular, transparency;
bool constantDiffuse = (material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse) == AI_SUCCESS && bool constantDiffuse = (material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse) == AI_SUCCESS &&

View File

@ -74,8 +74,8 @@ class PbrtExporter
{ {
public: public:
/// Constructor for a specific scene to export /// Constructor for a specific scene to export
PbrtExporter(const aiScene* pScene, IOSystem* pIOSystem, PbrtExporter(const aiScene *pScene, IOSystem *pIOSystem,
const std::string path, const std::string file); const std::string &path, const std::string &file);
/// Destructor /// Destructor
virtual ~PbrtExporter(); virtual ~PbrtExporter();

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2021, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -41,6 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "EmbedTexturesProcess.h" #include "EmbedTexturesProcess.h"
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include "ProcessHelper.h" #include "ProcessHelper.h"
@ -48,11 +49,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
EmbedTexturesProcess::EmbedTexturesProcess() EmbedTexturesProcess::EmbedTexturesProcess() :
: BaseProcess() { BaseProcess() {
// empty
} }
EmbedTexturesProcess::~EmbedTexturesProcess() { EmbedTexturesProcess::~EmbedTexturesProcess() {
// empty
} }
bool EmbedTexturesProcess::IsActive(unsigned int pFlags) const { bool EmbedTexturesProcess::IsActive(unsigned int pFlags) const {
@ -62,15 +65,16 @@ bool EmbedTexturesProcess::IsActive(unsigned int pFlags) const {
void EmbedTexturesProcess::SetupProperties(const Importer* pImp) { void EmbedTexturesProcess::SetupProperties(const Importer* pImp) {
mRootPath = pImp->GetPropertyString("sourceFilePath"); mRootPath = pImp->GetPropertyString("sourceFilePath");
mRootPath = mRootPath.substr(0, mRootPath.find_last_of("\\/") + 1u); mRootPath = mRootPath.substr(0, mRootPath.find_last_of("\\/") + 1u);
mIOHandler = pImp->GetIOHandler();
} }
void EmbedTexturesProcess::Execute(aiScene* pScene) { void EmbedTexturesProcess::Execute(aiScene* pScene) {
if (pScene == nullptr || pScene->mRootNode == nullptr) return; if (pScene == nullptr || pScene->mRootNode == nullptr || mIOHandler == nullptr){
return;
}
aiString path; aiString path;
uint32_t embeddedTexturesCount = 0u; uint32_t embeddedTexturesCount = 0u;
for (auto matId = 0u; matId < pScene->mNumMaterials; ++matId) { for (auto matId = 0u; matId < pScene->mNumMaterials; ++matId) {
auto material = pScene->mMaterials[matId]; auto material = pScene->mMaterials[matId];
@ -96,32 +100,36 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) {
ASSIMP_LOG_INFO("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." ); 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::streampos imageSize = 0;
std::string imagePath = path; std::string imagePath = path;
// Test path directly // Test path directly
std::ifstream file(imagePath, std::ios::binary | std::ios::ate); if (!mIOHandler->Exists(imagePath)) {
if ((imageSize = file.tellg()) == std::streampos(-1)) {
ASSIMP_LOG_WARN("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder."); ASSIMP_LOG_WARN("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder.");
// Test path in root path // Test path in root path
imagePath = mRootPath + path; imagePath = mRootPath + path;
file.open(imagePath, std::ios::binary | std::ios::ate); if (!mIOHandler->Exists(imagePath)) {
if ((imageSize = file.tellg()) == std::streampos(-1)) {
// Test path basename in root path // Test path basename in root path
imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u); imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
file.open(imagePath, std::ios::binary | std::ios::ate); if (!mIOHandler->Exists(imagePath)) {
if ((imageSize = file.tellg()) == std::streampos(-1)) {
ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", path, "."); ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", path, ".");
return false; 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)]; aiTexel* imageContent = new aiTexel[ 1ul + static_cast<unsigned long>( imageSize ) / sizeof(aiTexel)];
file.seekg(0, std::ios::beg); pFile->Seek(0, aiOrigin_SET);
file.read(reinterpret_cast<char*>(imageContent), imageSize); pFile->Read(reinterpret_cast<char*>(imageContent), imageSize, 1);
mIOHandler->Close(pFile);
// Enlarging the textures table // Enlarging the textures table
unsigned int textureId = pScene->mNumTextures++; unsigned int textureId = pScene->mNumTextures++;

View File

@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiNode; struct aiNode;
class IOSystem;
namespace Assimp { namespace Assimp {
/** /**
@ -76,10 +78,11 @@ public:
private: private:
// Resolve the path and add the file content to the scene as a texture. // 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: private:
std::string mRootPath; std::string mRootPath;
IOSystem* mIOHandler = nullptr;
}; };
} // namespace Assimp } // namespace Assimp

View File

@ -1 +0,0 @@
2.3.0

View File

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

View File

@ -804,7 +804,7 @@ else()
draco_points_enc) draco_points_enc)
# Library targets that consume the object collections. # 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 # 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 # 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 # 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. # For Mac, we need to build a .bundle for the unity plugin.
if(APPLE) if(APPLE)
set_target_properties(dracodec_unity PROPERTIES BUNDLE true) 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()
endif() endif()
@ -916,9 +913,6 @@ else()
# For Mac, we need to build a .bundle for the plugin. # For Mac, we need to build a .bundle for the plugin.
if(APPLE) if(APPLE)
set_target_properties(draco_maya_wrapper PROPERTIES BUNDLE true) set_target_properties(draco_maya_wrapper PROPERTIES BUNDLE true)
else()
set_target_properties(draco_maya_wrapper
PROPERTIES SOVERSION ${DRACO_SOVERSION})
endif() endif()
endif() endif()

View File

@ -2,16 +2,16 @@
<img width="350px" src="docs/artwork/draco3d-vert.svg" /> <img width="350px" src="docs/artwork/draco3d-vert.svg" />
</p> </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 News
======= =======
### Version 1.4.1 release ### 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: recommended. To use v1.4.1, use this URL:
* https://www.gstatic.com/draco/versioned/decoders/1.4.1/* * https://www.gstatic.com/draco/versioned/decoders/1.4.1/*
* Replace the * with the files to load. E.g. * 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 * This works with the v1.3.6 and v1.4.0 releases, and will work with future
Draco releases. Draco releases.
* Bug fixes * Bug fixes

View File

@ -6,7 +6,7 @@ set(DRACO_CMAKE_DRACO_BUILD_DEFINITIONS_CMAKE_ 1)
# Utility for controlling the main draco library dependency. This changes in # Utility for controlling the main draco library dependency. This changes in
# shared builds, and when an optional target requires a shared library build. # shared builds, and when an optional target requires a shared library build.
macro(set_draco_target) macro(set_draco_target)
if(MSVC OR WIN32) if(MSVC)
set(draco_dependency draco) set(draco_dependency draco)
set(draco_plugin_dependency ${draco_dependency}) set(draco_plugin_dependency ${draco_dependency})
else() else()
@ -63,6 +63,11 @@ macro(draco_set_build_definitions)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
endif() 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() endif()
if(ANDROID) if(ANDROID)
@ -114,4 +119,6 @@ macro(draco_set_build_definitions)
draco_check_emscripten_environment() draco_check_emscripten_environment()
draco_get_required_emscripten_flags(FLAG_LIST_VAR draco_base_cxx_flags) draco_get_required_emscripten_flags(FLAG_LIST_VAR draco_base_cxx_flags)
endif() endif()
draco_configure_sanitizer()
endmacro() endmacro()

View File

@ -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()

View File

@ -80,6 +80,12 @@ macro(draco_test_cxx_flag)
# Run the actual compile test. # Run the actual compile test.
unset(draco_all_cxx_flags_pass CACHE) unset(draco_all_cxx_flags_pass CACHE)
message("--- Running combined CXX flags test, flags: ${all_cxx_flags}") 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) check_cxx_compiler_flag("${all_cxx_flags}" draco_all_cxx_flags_pass)
if(cxx_test_FLAG_REQUIRED AND NOT 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() else()
unset(CMAKE_EXE_LINKER_FLAGS) unset(CMAKE_EXE_LINKER_FLAGS)
endif() endif()
list(APPEND DRACO_EXE_LINKER_FLAGS ${${link_FLAG_LIST_VAR_NAME}})
list(REMOVE_DUPLICATES DRACO_EXE_LINKER_FLAGS)
endmacro() endmacro()
# Runs the draco compiler tests. This macro builds up the list of list var(s) # Runs the draco compiler tests. This macro builds up the list of list var(s)

View File

@ -55,7 +55,7 @@ macro(draco_setup_install_target)
install(TARGETS draco_encoder DESTINATION install(TARGETS draco_encoder DESTINATION
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
if(WIN32) if(MSVC)
install(TARGETS draco DESTINATION install(TARGETS draco DESTINATION
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
else() else()

View File

@ -5,28 +5,28 @@ set(DRACO_CMAKE_DRACO_SANITIZER_CMAKE_ 1)
# Handles the details of enabling sanitizers. # Handles the details of enabling sanitizers.
macro(draco_configure_sanitizer) 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(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(DRACO_SANITIZE MATCHES "cfi") if(DRACO_SANITIZE MATCHES "cfi")
list(APPEND DRACO_CXX_FLAGS "-flto" "-fno-sanitize-trap=cfi") list(APPEND SAN_CXX_FLAGS "-flto" "-fno-sanitize-trap=cfi")
list(APPEND DRACO_EXE_LINKER_FLAGS "-flto" "-fno-sanitize-trap=cfi" list(APPEND SAN_LINKER_FLAGS "-flto" "-fno-sanitize-trap=cfi"
"-fuse-ld=gold") "-fuse-ld=gold")
endif() endif()
if(${CMAKE_SIZEOF_VOID_P} EQUAL 4 if(${CMAKE_SIZEOF_VOID_P} EQUAL 4
AND DRACO_SANITIZE MATCHES "integer|undefined") 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()
endif() endif()
list(APPEND DRACO_CXX_FLAGS "-fsanitize=${DRACO_SANITIZE}") list(APPEND SAN_CXX_FLAGS "-fsanitize=${DRACO_SANITIZE}")
list(APPEND DRACO_EXE_LINKER_FLAGS "-fsanitize=${DRACO_SANITIZE}") list(APPEND SAN_LINKER_FLAGS "-fsanitize=${DRACO_SANITIZE}")
# Make sanitizer callstacks accurate. # Make sanitizer callstacks accurate.
list(APPEND DRACO_CXX_FLAGS "-fno-omit-frame-pointer" list(APPEND SAN_CXX_FLAGS "-fno-omit-frame-pointer")
"-fno-optimize-sibling-calls") list(APPEND SAN_CXX_FLAGS "-fno-optimize-sibling-calls")
draco_test_cxx_flag(FLAG_LIST_VAR_NAMES DRACO_CXX_FLAGS FLAG_REQUIRED) draco_test_cxx_flag(FLAG_LIST_VAR_NAMES SAN_CXX_FLAGS FLAG_REQUIRED)
draco_test_exe_linker_flag(FLAG_LIST_VAR_NAME DRACO_EXE_LINKER_FLAGS) draco_test_exe_linker_flag(FLAG_LIST_VAR_NAME SAN_LINKER_FLAGS)
endif() endif()
endmacro() endmacro()

View File

@ -87,6 +87,7 @@ macro(draco_add_executable)
endif() endif()
add_executable(${exe_NAME} ${exe_SOURCES}) add_executable(${exe_NAME} ${exe_SOURCES})
set_target_properties(${exe_NAME} PROPERTIES VERSION ${DRACO_VERSION})
if(exe_OUTPUT_NAME) if(exe_OUTPUT_NAME)
set_target_properties(${exe_NAME} PROPERTIES OUTPUT_NAME ${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(exe_LINK_FLAGS OR DRACO_EXE_LINKER_FLAGS)
if(${CMAKE_VERSION} VERSION_LESS "3.13") 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} set_target_properties(${exe_NAME}
PROPERTIES LINK_FLAGS ${exe_LINK_FLAGS} PROPERTIES LINK_FLAGS "${exe_LINK_FLAGS}")
${DRACO_EXE_LINKER_FLAGS})
else() else()
target_link_options(${exe_NAME} PRIVATE ${exe_LINK_FLAGS} target_link_options(${exe_NAME} PRIVATE ${exe_LINK_FLAGS}
${DRACO_EXE_LINKER_FLAGS}) ${DRACO_EXE_LINKER_FLAGS})
@ -130,7 +132,7 @@ macro(draco_add_executable)
endif() endif()
if(BUILD_SHARED_LIBS AND (MSVC OR WIN32)) 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() endif()
if(exe_LIB_DEPS) if(exe_LIB_DEPS)
@ -163,8 +165,8 @@ endmacro()
# cmake-format: off # cmake-format: off
# - OUTPUT_NAME: Override output file basename. Target basename defaults to # - OUTPUT_NAME: Override output file basename. Target basename defaults to
# NAME. OUTPUT_NAME is ignored when BUILD_SHARED_LIBS is enabled and CMake # 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 # is generating a build for which MSVC is true. This is to avoid output
# output basename collisions with DLL import libraries. # basename collisions with DLL import libraries.
# - TEST: Flag. Presence means treat library as a test. # - TEST: Flag. Presence means treat library as a test.
# - DEFINES: List of preprocessor macro definitions. # - DEFINES: List of preprocessor macro definitions.
# - INCLUDES: list of include directories for the target. # - INCLUDES: list of include directories for the target.
@ -259,7 +261,7 @@ macro(draco_add_library)
endif() endif()
if(lib_OUTPUT_NAME) 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} set_target_properties(${lib_NAME}
PROPERTIES OUTPUT_NAME ${lib_OUTPUT_NAME}) PROPERTIES OUTPUT_NAME ${lib_OUTPUT_NAME})
endif() endif()
@ -318,8 +320,12 @@ macro(draco_add_library)
set_target_properties(${lib_NAME} PROPERTIES PREFIX "") set_target_properties(${lib_NAME} PROPERTIES PREFIX "")
endif() endif()
if(lib_TYPE STREQUAL SHARED AND NOT MSVC) # VERSION and SOVERSION as necessary
set_target_properties(${lib_NAME} PROPERTIES SOVERSION ${DRACO_SOVERSION}) 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() endif()
if(BUILD_SHARED_LIBS AND (MSVC OR WIN32)) if(BUILD_SHARED_LIBS AND (MSVC OR WIN32))

View File

@ -17,31 +17,31 @@
namespace draco { namespace draco {
void DracoTimer::Start() { void DracoTimer::Start() {
#ifdef _WIN32 #ifdef _WIN32
QueryPerformanceCounter(&tv_start); QueryPerformanceCounter(&tv_start_);
#else #else
gettimeofday(&tv_start, nullptr); gettimeofday(&tv_start_, nullptr);
#endif #endif
} }
void DracoTimer::Stop() { void DracoTimer::Stop() {
#ifdef _WIN32 #ifdef _WIN32
QueryPerformanceCounter(&tv_end); QueryPerformanceCounter(&tv_end_);
#else #else
gettimeofday(&tv_end, nullptr); gettimeofday(&tv_end_, nullptr);
#endif #endif
} }
int64_t DracoTimer::GetInMs() { int64_t DracoTimer::GetInMs() {
#ifdef _WIN32 #ifdef _WIN32
LARGE_INTEGER elapsed = {0}; LARGE_INTEGER elapsed = {0};
elapsed.QuadPart = tv_end.QuadPart - tv_start.QuadPart; elapsed.QuadPart = tv_end_.QuadPart - tv_start_.QuadPart;
LARGE_INTEGER frequency = {0}; LARGE_INTEGER frequency = {0};
QueryPerformanceFrequency(&frequency); QueryPerformanceFrequency(&frequency);
return elapsed.QuadPart * 1000 / frequency.QuadPart; return elapsed.QuadPart * 1000 / frequency.QuadPart;
#else #else
const int64_t seconds = (tv_end.tv_sec - tv_start.tv_sec) * 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; const int64_t milliseconds = (tv_end_.tv_usec - tv_start_.tv_usec) / 1000;
return seconds + milliseconds; return seconds + milliseconds;
#endif #endif
} }

View File

@ -20,9 +20,10 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
typedef LARGE_INTEGER timeval; typedef LARGE_INTEGER DracoTimeVal;
#else #else
#include <sys/time.h> #include <sys/time.h>
typedef timeval DracoTimeVal;
#endif #endif
#include <cinttypes> #include <cinttypes>
@ -39,8 +40,8 @@ class DracoTimer {
int64_t GetInMs(); int64_t GetInMs();
private: private:
timeval tv_start; DracoTimeVal tv_start_;
timeval tv_end; DracoTimeVal tv_end_;
}; };
typedef DracoTimer CycleTimer; typedef DracoTimer CycleTimer;

View File

@ -18,6 +18,7 @@
#include <cctype> #include <cctype>
#include <cmath> #include <cmath>
#include <iterator> #include <iterator>
#include <limits>
namespace draco { namespace draco {
namespace parser { namespace parser {
@ -252,7 +253,7 @@ DecoderBuffer ParseLineIntoDecoderBuffer(DecoderBuffer *buffer) {
std::string ToLower(const std::string &str) { std::string ToLower(const std::string &str) {
std::string out; 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; return out;
} }

View File

@ -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)) != while ((end = line.find_first_of(" \t\n\v\f\r", start)) !=
std::string::npos) { std::string::npos) {
const std::string word(line.substr(start, end - start)); 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); output.push_back(word);
} }
start = end + 1; start = end + 1;
} }
const std::string last_word(line.substr(start)); 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); output.push_back(last_word);
} }
return output; return output;

View File

@ -87,7 +87,14 @@ size_t StdioFileReader::GetFileSize() {
return false; return false;
} }
#if _FILE_OFFSET_BITS == 64
const size_t file_size = static_cast<size_t>(ftello(file_));
#elif defined _WIN64
const size_t file_size = static_cast<size_t>(_ftelli64(file_));
#else
const size_t file_size = static_cast<size_t>(ftell(file_)); const size_t file_size = static_cast<size_t>(ftell(file_));
#endif
rewind(file_); rewind(file_);
return file_size; return file_size;

View File

@ -129,7 +129,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
EdgeEvent( tcx, ep, *p1, triangle, *p1 ); EdgeEvent( tcx, ep, *p1, triangle, *p1 );
} else { } else {
// ASSIMP_CHANGE (aramis_acg) // ASSIMP_CHANGE (aramis_acg)
std::runtime_error("EdgeEvent - collinear points not supported"); throw std::runtime_error("EdgeEvent - collinear points not supported");
} }
return; return;
} }

View File

@ -144,7 +144,7 @@ enum aiTextureMapMode {
enum aiTextureMapping { enum aiTextureMapping {
/** The mapping coordinates are taken from an UV channel. /** The mapping coordinates are taken from an UV channel.
* *
* The #AI_MATKEY_UVWSRC key specifies from which UV channel * #AI_MATKEY_UVWSRC property specifies from which UV channel
* the texture coordinates are to be taken from (remember, * the texture coordinates are to be taken from (remember,
* meshes can have more than one UV channel). * meshes can have more than one UV channel).
*/ */
@ -202,11 +202,15 @@ enum aiTextureType {
/** The texture is combined with the result of the diffuse /** The texture is combined with the result of the diffuse
* lighting equation. * lighting equation.
* OR
* PBR Specular/Glossiness
*/ */
aiTextureType_DIFFUSE = 1, aiTextureType_DIFFUSE = 1,
/** The texture is combined with the result of the specular /** The texture is combined with the result of the specular
* lighting equation. * lighting equation.
* OR
* PBR Specular/Glossiness
*/ */
aiTextureType_SPECULAR = 2, aiTextureType_SPECULAR = 2,
@ -288,6 +292,32 @@ enum aiTextureType {
aiTextureType_DIFFUSE_ROUGHNESS = 16, aiTextureType_DIFFUSE_ROUGHNESS = 16,
aiTextureType_AMBIENT_OCCLUSION = 17, aiTextureType_AMBIENT_OCCLUSION = 17,
/** PBR Material Modifiers
* Some modern renderers have further PBR modifiers that may be overlaid
* on top of the 'base' PBR materials for additional realism.
* These use multiple texture maps, so only the base type is directly defined
*/
/** Sheen
* Generally used to simulate textiles that are covered in a layer of microfibers
* eg velvet
* https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_sheen
*/
aiTextureType_SHEEN = 19,
/** Clearcoat
* Simulates a layer of 'polish' or 'laquer' layered on top of a PBR substrate
* https://autodesk.github.io/standard-surface/#closures/coating
* https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat
*/
aiTextureType_CLEARCOAT = 20,
/** Transmission
* Simulates transmission through the surface
* May include further information such as wall thickness
*/
aiTextureType_TRANSMISSION = 21,
/** Unknown texture /** Unknown texture
* *
* A texture reference that does not match any of the definitions * A texture reference that does not match any of the definitions
@ -309,7 +339,9 @@ ASSIMP_API const char *TextureTypeToString(enum aiTextureType in);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Defines all shading models supported by the library /** @brief Defines all shading models supported by the library
* *
* Property: #AI_MATKEY_SHADING_MODEL
*
* The list of shading modes has been taken from Blender. * The list of shading modes has been taken from Blender.
* See Blender documentation for more information. The API does * See Blender documentation for more information. The API does
* not distinguish between "specular" and "diffuse" shaders (thus the * not distinguish between "specular" and "diffuse" shaders (thus the
@ -318,6 +350,7 @@ ASSIMP_API const char *TextureTypeToString(enum aiTextureType in);
* Again, this value is just a hint. Assimp tries to select the shader whose * Again, this value is just a hint. Assimp tries to select the shader whose
* most common implementation matches the original rendering results of the * most common implementation matches the original rendering results of the
* 3D modeler which wrote a particular model as closely as possible. * 3D modeler which wrote a particular model as closely as possible.
*
*/ */
enum aiShadingMode { enum aiShadingMode {
/** Flat shading. Shading is done on per-face base, /** Flat shading. Shading is done on per-face base,
@ -364,13 +397,28 @@ enum aiShadingMode {
aiShadingMode_CookTorrance = 0x8, aiShadingMode_CookTorrance = 0x8,
/** No shading at all. Constant light influence of 1.0. /** No shading at all. Constant light influence of 1.0.
* Also known as "Unlit"
*/ */
aiShadingMode_NoShading = 0x9, aiShadingMode_NoShading = 0x9,
aiShadingMode_Unlit = aiShadingMode_NoShading, // Alias
/** Fresnel shading /** Fresnel shading
*/ */
aiShadingMode_Fresnel = 0xa, aiShadingMode_Fresnel = 0xa,
/** Physically-Based Rendering (PBR) shading using
* Bidirectional scattering/reflectance distribution function (BSDF/BRDF)
* There are multiple methods under this banner, and model files may provide
* data for more than one PBR-BRDF method.
* Applications should use the set of provided properties to determine which
* of their preferred PBR rendering methods are likely to be available
* eg:
* - If AI_MATKEY_METALLIC_FACTOR is set, then a Metallic/Roughness is available
* - If AI_MATKEY_GLOSSINESS_FACTOR is set, then a Specular/Glossiness is available
* Note that some PBR methods allow layering of techniques
*/
aiShadingMode_PBR_BRDF = 0xb,
#ifndef SWIG #ifndef SWIG
_aiShadingMode_Force32Bit = INT_MAX _aiShadingMode_Force32Bit = INT_MAX
#endif #endif
@ -922,12 +970,66 @@ extern "C" {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// PBR material support // PBR material support
// --------------------
// Properties defining PBR rendering techniques
#define AI_MATKEY_USE_COLOR_MAP "$mat.useColorMap", 0, 0 #define AI_MATKEY_USE_COLOR_MAP "$mat.useColorMap", 0, 0
// Metallic/Roughness Workflow
// ---------------------------
// Base RGBA color factor. Will be multiplied by final base color texture values if extant
// Note: Importers may choose to copy this into AI_MATKEY_COLOR_DIFFUSE for compatibility
// with renderers and formats that do not support Metallic/Roughness PBR
#define AI_MATKEY_BASE_COLOR "$clr.base", 0, 0 #define AI_MATKEY_BASE_COLOR "$clr.base", 0, 0
#define AI_MATKEY_BASE_COLOR_TEXTURE aiTextureType_BASE_COLOR, 0
#define AI_MATKEY_USE_METALLIC_MAP "$mat.useMetallicMap", 0, 0 #define AI_MATKEY_USE_METALLIC_MAP "$mat.useMetallicMap", 0, 0
// Metallic factor. 0.0 = Full Dielectric, 1.0 = Full Metal
#define AI_MATKEY_METALLIC_FACTOR "$mat.metallicFactor", 0, 0 #define AI_MATKEY_METALLIC_FACTOR "$mat.metallicFactor", 0, 0
#define AI_MATKEY_METALLIC_TEXTURE aiTextureType_METALNESS, 0
#define AI_MATKEY_USE_ROUGHNESS_MAP "$mat.useRoughnessMap", 0, 0 #define AI_MATKEY_USE_ROUGHNESS_MAP "$mat.useRoughnessMap", 0, 0
// Roughness factor. 0.0 = Perfectly Smooth, 1.0 = Completely Rough
#define AI_MATKEY_ROUGHNESS_FACTOR "$mat.roughnessFactor", 0, 0 #define AI_MATKEY_ROUGHNESS_FACTOR "$mat.roughnessFactor", 0, 0
#define AI_MATKEY_ROUGHNESS_TEXTURE aiTextureType_DIFFUSE_ROUGHNESS, 0
// Specular/Glossiness Workflow
// ---------------------------
// Diffuse/Albedo Color. Note: Pure Metals have a diffuse of {0,0,0}
// AI_MATKEY_COLOR_DIFFUSE
// Specular Color.
// Note: Metallic/Roughness may also have a Specular Color
// AI_MATKEY_COLOR_SPECULAR
#define AI_MATKEY_SPECULAR_FACTOR "$mat.specularFactor", 0, 0
// Glossiness factor. 0.0 = Completely Rough, 1.0 = Perfectly Smooth
#define AI_MATKEY_GLOSSINESS_FACTOR "$mat.glossinessFactor", 0, 0
// Sheen
// -----
// Sheen base RGB color. Default {0,0,0}
#define AI_MATKEY_SHEEN_COLOR_FACTOR "$clr.sheen.factor", 0, 0
// Sheen Roughness Factor.
#define AI_MATKEY_SHEEN_ROUGHNESS_FACTOR "$mat.sheen.roughnessFactor", 0, 0
#define AI_MATKEY_SHEEN_COLOR_TEXTURE aiTextureType_SHEEN, 0
#define AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE aiTextureType_SHEEN, 1
// Clearcoat
// ---------
// Clearcoat layer intensity. 0.0 = none (disabled)
#define AI_MATKEY_CLEARCOAT_FACTOR "$mat.clearcoat.factor", 0, 0
#define AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR "$mat.clearcoat.roughnessFactor", 0, 0
#define AI_MATKEY_CLEARCOAT_TEXTURE aiTextureType_CLEARCOAT, 0
#define AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_CLEARCOAT, 1
#define AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE aiTextureType_CLEARCOAT, 2
// Transmission
// ------------
// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission
// Base percentage of light transmitted through the surface. 0.0 = Opaque, 1.0 = Fully transparent
#define AI_MATKEY_TRANSMISSION_FACTOR "$mat.transmission.factor", 0, 0
// Texture defining percentage of light transmitted through the surface.
// Multiplied by AI_MATKEY_TRANSMISSION_FACTOR
#define AI_MATKEY_TRANSMISSION_TEXTURE aiTextureType_TRANSMISSION, 0
// Emissive
// --------
#define AI_MATKEY_USE_EMISSIVE_MAP "$mat.useEmissiveMap", 0, 0 #define AI_MATKEY_USE_EMISSIVE_MAP "$mat.useEmissiveMap", 0, 0
#define AI_MATKEY_EMISSIVE_INTENSITY "$mat.emissiveIntensity", 0, 0 #define AI_MATKEY_EMISSIVE_INTENSITY "$mat.emissiveIntensity", 0, 0
#define AI_MATKEY_USE_AO_MAP "$mat.useAOMap", 0, 0 #define AI_MATKEY_USE_AO_MAP "$mat.useAOMap", 0, 0
@ -1397,8 +1499,6 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray(
ai_real *pOut, ai_real *pOut,
unsigned int *pMax); unsigned int *pMax);
#ifdef __cplusplus
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Retrieve a single float property with a specific key from the material. /** @brief Retrieve a single float property with a specific key from the material.
* *
@ -1418,7 +1518,7 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray(
* @return Specifies whether the key has been found. If not, the output * @return Specifies whether the key has been found. If not, the output
* float remains unmodified.*/ * float remains unmodified.*/
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
inline aiReturn aiGetMaterialFloat(const aiMaterial *pMat, inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial *pMat,
const char *pKey, const char *pKey,
unsigned int type, unsigned int type,
unsigned int index, unsigned int index,
@ -1426,14 +1526,6 @@ inline aiReturn aiGetMaterialFloat(const aiMaterial *pMat,
return aiGetMaterialFloatArray(pMat, pKey, type, index, pOut, (unsigned int *)0x0); return aiGetMaterialFloatArray(pMat, pKey, type, index, pOut, (unsigned int *)0x0);
} }
#else
// Use our friend, the C preprocessor
#define aiGetMaterialFloat (pMat, type, index, pKey, pOut) \
aiGetMaterialFloatArray(pMat, type, index, pKey, pOut, NULL)
#endif //!__cplusplus
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Retrieve an array of integer values with a specific key /** @brief Retrieve an array of integer values with a specific key
* from a material * from a material
@ -1446,8 +1538,6 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial *
int *pOut, int *pOut,
unsigned int *pMax); unsigned int *pMax);
#ifdef __cplusplus
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Retrieve an integer property with a specific key from a material /** @brief Retrieve an integer property with a specific key from a material
* *
@ -1461,14 +1551,6 @@ inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial *pMat,
return aiGetMaterialIntegerArray(pMat, pKey, type, index, pOut, (unsigned int *)0x0); return aiGetMaterialIntegerArray(pMat, pKey, type, index, pOut, (unsigned int *)0x0);
} }
#else
// use our friend, the C preprocessor
#define aiGetMaterialInteger (pMat, type, index, pKey, pOut) \
aiGetMaterialIntegerArray(pMat, type, index, pKey, pOut, NULL)
#endif //!__cplusplus
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Retrieve a color value from the material property table /** @brief Retrieve a color value from the material property table
* *

View File

@ -432,7 +432,7 @@ struct aiMetadata {
/// Check whether there is a metadata entry for the given key. /// Check whether there is a metadata entry for the given key.
/// \param [in] Key - the key value value to check for. /// \param [in] Key - the key value value to check for.
inline bool HasKey(const char *key) { inline bool HasKey(const char *key) const {
if (nullptr == key) { if (nullptr == key) {
return false; return false;
} }

View File

@ -50,32 +50,32 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pragma GCC system_header # pragma GCC system_header
#endif #endif
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0 //#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 //#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0 //#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1 //#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0 #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0
#define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0 #define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0
#define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0 #define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 //#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 //#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0
#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0 //#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_SHEEN "$mat.gltf.materialSheen", 0, 0 //#define AI_MATKEY_GLTF_MATERIAL_SHEEN "$mat.gltf.materialSheen", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR "$mat.gltf.materialSheen.sheenColorFactor", 0, 0 //#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR "$mat.gltf.materialSheen.sheenColorFactor", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR "$mat.gltf.materialSheen.sheenRoughnessFactor", 0, 0 //#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR "$mat.gltf.materialSheen.sheenRoughnessFactor", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE aiTextureType_UNKNOWN, 1 //#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE aiTextureType_UNKNOWN, 1
#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 2 //#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 2
#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT "$mat.gltf.materialClearcoat", 0, 0 //#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT "$mat.gltf.materialClearcoat", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR "$mat.gltf.materialClearcoat.clearcoatFactor", 0, 0 //#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR "$mat.gltf.materialClearcoat.clearcoatFactor", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR "$mat.gltf.materialClearcoat.clearcoatRoughnessFactor", 0, 0 //#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR "$mat.gltf.materialClearcoat.clearcoatRoughnessFactor", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE aiTextureType_UNKNOWN, 3 //#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE aiTextureType_UNKNOWN, 3
#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 4 //#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 4
#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE aiTextureType_NORMALS, 1 //#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE aiTextureType_NORMALS, 1
#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION "$mat.gltf.materialTransmission", 0, 0 //#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION "$mat.gltf.materialTransmission", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR "$mat.gltf.materialTransmission.transmissionFactor", 0, 0 //#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR "$mat.gltf.materialTransmission.transmissionFactor", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE aiTextureType_UNKNOWN, 5 //#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE aiTextureType_UNKNOWN, 5
#define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord" //#define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord"
#define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname" #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname"
#define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid" #define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid"
#define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag" #define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag"
@ -83,7 +83,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define _AI_MATKEY_GLTF_SCALE_BASE "$tex.scale" #define _AI_MATKEY_GLTF_SCALE_BASE "$tex.scale"
#define _AI_MATKEY_GLTF_STRENGTH_BASE "$tex.strength" #define _AI_MATKEY_GLTF_STRENGTH_BASE "$tex.strength"
#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD(type, N) _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N //#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD(type, N) _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N
#define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N
#define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N
#define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2021, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -397,22 +395,35 @@ struct aiScene
//! Returns an embedded texture //! Returns an embedded texture
const aiTexture* GetEmbeddedTexture(const char* filename) const { const aiTexture* GetEmbeddedTexture(const char* filename) const {
return GetEmbeddedTextureAndIndex(filename).first;
}
//! Returns an embedded texture and its index
std::pair<const aiTexture*, int> GetEmbeddedTextureAndIndex(const char* filename) const {
if(nullptr==filename) {
return std::make_pair(nullptr, -1);
}
// lookup using texture ID (if referenced like: "*1", "*2", etc.) // lookup using texture ID (if referenced like: "*1", "*2", etc.)
if ('*' == *filename) { if ('*' == *filename) {
int index = std::atoi(filename + 1); int index = std::atoi(filename + 1);
if (0 > index || mNumTextures <= static_cast<unsigned>(index)) if (0 > index || mNumTextures <= static_cast<unsigned>(index)) {
return nullptr; return std::make_pair(nullptr, -1);
return mTextures[index]; }
return std::make_pair(mTextures[index], index);
} }
// lookup using filename // lookup using filename
const char* shortFilename = GetShortFilename(filename); const char* shortFilename = GetShortFilename(filename);
if (nullptr == shortFilename) {
return std::make_pair(nullptr, -1);
}
for (unsigned int i = 0; i < mNumTextures; i++) { for (unsigned int i = 0; i < mNumTextures; i++) {
const char* shortTextureFilename = GetShortFilename(mTextures[i]->mFilename.C_Str()); const char* shortTextureFilename = GetShortFilename(mTextures[i]->mFilename.C_Str());
if (strcmp(shortTextureFilename, shortFilename) == 0) { if (strcmp(shortTextureFilename, shortFilename) == 0) {
return mTextures[i]; return std::make_pair(mTextures[i], i);
} }
} }
return nullptr; return std::make_pair(nullptr, -1);
} }
#endif // __cplusplus #endif // __cplusplus

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -53,8 +53,8 @@ class utTypes : public ::testing::Test {
TEST_F( utTypes, Color3dCpmpareOpTest ) { TEST_F( utTypes, Color3dCpmpareOpTest ) {
aiColor3D col1( 1, 2, 3 ); aiColor3D col1( 1, 2, 3 );
aiColor3D col2( 4, 5, 6 ); aiColor3D col2( 4, 5, 6 );
aiColor3D col3( col1 ); const aiColor3D &col3(col1);
EXPECT_FALSE( col1 == col2 ); EXPECT_FALSE( col1 == col2 );
EXPECT_FALSE( col2 == col3 ); EXPECT_FALSE( col2 == col3 );
EXPECT_TRUE( col1 == col3 ); EXPECT_TRUE( col1 == col3 );

View File

@ -57,10 +57,9 @@ using namespace Assimp;
class utglTF2ImportExport : public AbstractImportExportBase { class utglTF2ImportExport : public AbstractImportExportBase {
public: public:
virtual bool importerTest() { virtual bool importerMatTest(const char *file, bool spec_gloss, std::array<aiTextureMapMode, 2> exp_modes = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", const aiScene *scene = importer.ReadFile(file, aiProcess_ValidateDataStructure);
aiProcess_ValidateDataStructure);
EXPECT_NE(scene, nullptr); EXPECT_NE(scene, nullptr);
if (!scene) { if (!scene) {
return false; return false;
@ -72,13 +71,49 @@ public:
} }
const aiMaterial *material = scene->mMaterials[0]; const aiMaterial *material = scene->mMaterials[0];
// This Material should be a PBR
aiShadingMode shadingMode;
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_SHADING_MODEL, shadingMode));
EXPECT_EQ(aiShadingMode_PBR_BRDF, shadingMode);
// Should import the texture as diffuse and as base color
aiString path; aiString path;
aiTextureMapMode modes[2]; std::array<aiTextureMapMode,2> modes;
EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr,
nullptr, nullptr, modes)); nullptr, nullptr, modes.data()));
EXPECT_STREQ(path.C_Str(), "CesiumLogoFlat.png"); EXPECT_STREQ(path.C_Str(), "CesiumLogoFlat.png");
EXPECT_EQ(modes[0], aiTextureMapMode_Mirror); EXPECT_EQ(exp_modes, modes);
EXPECT_EQ(modes[1], aiTextureMapMode_Clamp);
// Also as Base Color
EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_BASE_COLOR, 0, &path, nullptr, nullptr,
nullptr, nullptr, modes.data()));
EXPECT_STREQ(path.C_Str(), "CesiumLogoFlat.png");
EXPECT_EQ(exp_modes, modes);
// Should have a MetallicFactor (default is 1.0)
ai_real metal_factor = ai_real(0.5);
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_METALLIC_FACTOR, metal_factor));
EXPECT_EQ(ai_real(0.0), metal_factor);
// And a roughness factor (default is 1.0)
ai_real roughness_factor = ai_real(0.5);
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_ROUGHNESS_FACTOR, roughness_factor));
EXPECT_EQ(ai_real(1.0), roughness_factor);
aiColor3D spec_color = { 0, 0, 0 };
ai_real glossiness = ai_real(0.5);
if (spec_gloss) {
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color));
constexpr ai_real spec_val(0.20000000298023225); // From the file
EXPECT_EQ(spec_val, spec_color.r);
EXPECT_EQ(spec_val, spec_color.g);
EXPECT_EQ(spec_val, spec_color.b);
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness));
EXPECT_EQ(ai_real(1.0), glossiness);
} else {
EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color));
EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness));
}
return true; return true;
} }
@ -105,14 +140,89 @@ public:
}; };
TEST_F(utglTF2ImportExport, importglTF2FromFileTest) { TEST_F(utglTF2ImportExport, importglTF2FromFileTest) {
EXPECT_TRUE(importerTest()); EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", false, {aiTextureMapMode_Mirror, aiTextureMapMode_Clamp}));
} }
TEST_F(utglTF2ImportExport, importBinaryglTF2FromFileTest) { TEST_F(utglTF2ImportExport, importBinaryglTF2FromFileTest) {
EXPECT_TRUE(binaryImporterTest()); EXPECT_TRUE(binaryImporterTest());
} }
TEST_F(utglTF2ImportExport, importglTF2_KHR_materials_pbrSpecularGlossiness) {
EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf", true));
}
void VerifyClearCoatScene(const aiScene *scene) {
ASSERT_NE(nullptr, scene);
ASSERT_TRUE(scene->HasMaterials());
// Find a specific Clearcoat material and check the values
const aiString partial_coated("Partial_Coated");
bool found_partial_coat = false;
for (size_t i = 0; i < scene->mNumMaterials; ++i) {
const aiMaterial *material = scene->mMaterials[i];
ASSERT_NE(nullptr, material);
if (material->GetName() == partial_coated) {
found_partial_coat = true;
ai_real clearcoat_factor(0.0f);
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_CLEARCOAT_FACTOR, clearcoat_factor));
EXPECT_EQ(ai_real(1.0f), clearcoat_factor);
ai_real clearcoat_rough_factor(0.0f);
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat_rough_factor));
EXPECT_EQ(ai_real(0.03f), clearcoat_rough_factor);
// Should import the texture as diffuse and as base color
aiString path;
std::array<aiTextureMapMode, 2> modes;
static const std::array<aiTextureMapMode, 2> exp_modes = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap };
EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_CLEARCOAT_TEXTURE, &path, nullptr, nullptr,
nullptr, nullptr, modes.data()));
EXPECT_STREQ(path.C_Str(), "PartialCoating.png");
EXPECT_EQ(exp_modes, modes);
}
}
EXPECT_TRUE(found_partial_coat);
}
TEST_F(utglTF2ImportExport, importglTF2_KHR_materials_clearcoat) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest.gltf", aiProcess_ValidateDataStructure);
VerifyClearCoatScene(scene);
}
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
TEST_F(utglTF2ImportExport, importglTF2AndExport_KHR_materials_clearcoat) {
{
Assimp::Importer importer;
Assimp::Exporter exporter;
const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest.gltf", aiProcess_ValidateDataStructure);
ASSERT_NE(nullptr, scene);
// Export
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest_out.glb"));
}
// And re-import
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest_out.glb", aiProcess_ValidateDataStructure);
VerifyClearCoatScene(scene);
}
TEST_F(utglTF2ImportExport, importglTF2AndExport_KHR_materials_pbrSpecularGlossiness) {
Assimp::Importer importer;
Assimp::Exporter exporter;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf",
aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
// Export
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb"));
// And re-import
EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", true));
}
TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) { TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {
Assimp::Importer importer; Assimp::Importer importer;
Assimp::Exporter exporter; Assimp::Exporter exporter;
@ -130,6 +240,7 @@ TEST_F(utglTF2ImportExport, importglTF2EmbeddedAndExportToOBJ) {
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj")); EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj"));
} }
#endif // ASSIMP_BUILD_NO_EXPORT #endif // ASSIMP_BUILD_NO_EXPORT
TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePointsWithoutIndices) { TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePointsWithoutIndices) {
@ -492,32 +603,58 @@ TEST_F(utglTF2ImportExport, sceneMetadata) {
} }
TEST_F(utglTF2ImportExport, texcoords) { TEST_F(utglTF2ImportExport, texcoords) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", aiProcess_ValidateDataStructure);
aiProcess_ValidateDataStructure); ASSERT_NE(scene, nullptr);
ASSERT_TRUE(scene->HasMaterials());
const aiMaterial *material = scene->mMaterials[0];
aiString path;
unsigned int uvIndex = 255;
aiTextureMapMode modes[2];
EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_BASE_COLOR_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes));
EXPECT_STREQ(path.C_Str(), "texture.png");
EXPECT_EQ(uvIndex, 0);
uvIndex = 255;
EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes));
EXPECT_STREQ(path.C_Str(), "texture.png");
EXPECT_EQ(uvIndex, 1);
}
#ifndef ASSIMP_BUILD_NO_EXPORT
TEST_F(utglTF2ImportExport, texcoords_export) {
{
Assimp::Importer importer;
Assimp::Exporter exporter;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", aiProcess_ValidateDataStructure);
ASSERT_NE(scene, nullptr);
ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf_out.glb"));
}
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", aiProcess_ValidateDataStructure);
ASSERT_NE(scene, nullptr); ASSERT_NE(scene, nullptr);
ASSERT_TRUE(scene->HasMaterials()); ASSERT_TRUE(scene->HasMaterials());
const aiMaterial *material = scene->mMaterials[0]; const aiMaterial *material = scene->mMaterials[0];
aiString path; aiString path;
unsigned int uvIndex = 255;
aiTextureMapMode modes[2]; aiTextureMapMode modes[2];
EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_BASE_COLOR_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes));
nullptr, nullptr, modes));
EXPECT_STREQ(path.C_Str(), "texture.png"); EXPECT_STREQ(path.C_Str(), "texture.png");
int uvIndex = -1;
EXPECT_EQ(aiGetMaterialInteger(material, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(aiTextureType_DIFFUSE, 0), &uvIndex), aiReturn_SUCCESS);
EXPECT_EQ(uvIndex, 0); EXPECT_EQ(uvIndex, 0);
// Using manual macro expansion of AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE here. uvIndex = 255;
// The following works with some but not all compilers: EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes));
// #define APPLY(X, Y) X(Y) EXPECT_STREQ(path.C_Str(), "texture.png");
// ..., APPLY(AI_MATKEY_GLTF_TEXTURE_TEXCOORD, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE), ...
EXPECT_EQ(aiGetMaterialInteger(material, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(aiTextureType_UNKNOWN, 0), &uvIndex), aiReturn_SUCCESS);
EXPECT_EQ(uvIndex, 1); EXPECT_EQ(uvIndex, 1);
} }
#endif // ASSIMP_BUILD_NO_EXPORT
TEST_F(utglTF2ImportExport, recursive_nodes) { TEST_F(utglTF2ImportExport, recursive_nodes) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/RecursiveNodes/RecursiveNodes.gltf", aiProcess_ValidateDataStructure); const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/RecursiveNodes/RecursiveNodes.gltf", aiProcess_ValidateDataStructure);

View File

@ -39,9 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
#include "assimp_view.h" #include "AnimEvaluator.h"
#include <tuple> #include <assimp/anim.h>
#include <assimp/ai_assert.h>
using namespace AssimpView; using namespace AssimpView;

View File

@ -1,4 +1,3 @@
/** Calculates a pose for a given time of an animation */
/* /*
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
@ -40,11 +39,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
#pragma once
#ifndef AV_ANIMEVALUATOR_H_INCLUDED #ifndef AV_ANIMEVALUATOR_H_INCLUDED
#define AV_ANIMEVALUATOR_H_INCLUDED #define AV_ANIMEVALUATOR_H_INCLUDED
/** Calculates a pose for a given time of an animation */
#include <tuple> #include <tuple>
#include <vector> #include <vector>
#include <assimp/matrix4x4.h>
struct aiAnimation;
namespace AssimpView { namespace AssimpView {
@ -63,18 +68,19 @@ public:
/// @brief The class destructor. /// @brief The class destructor.
~AnimEvaluator(); ~AnimEvaluator();
/** Evaluates the animation tracks for a given time stamp. The calculated pose can be retrieved as a /// @brief Evaluates the animation tracks for a given time stamp.
* array of transformation matrices afterwards by calling GetTransformations(). /// The calculated pose can be retrieved as an array of transformation
* @param pTime The time for which you want to evaluate the animation, in seconds. Will be mapped into the animation cycle, so /// matrices afterwards by calling GetTransformations().
* it can be an arbitrary value. Best use with ever-increasing time stamps. /// @param pTime The time for which you want to evaluate the animation, in seconds.
*/ /// Will be mapped into the animation cycle, so it can get an arbitrary
/// value. Best use with ever-increasing time stamps.
void Evaluate(double pTime); void Evaluate(double pTime);
/** Returns the transform matrices calculated at the last Evaluate() call. The array matches the mChannels array of /// @brief Returns the transform matrices calculated at the last Evaluate() call.
* the aiAnimation. */ /// The array matches the mChannels array of the aiAnimation.
const std::vector<aiMatrix4x4> &GetTransformations() const { return mTransforms; } const std::vector<aiMatrix4x4> &GetTransformations() const { return mTransforms; }
protected: private:
const aiAnimation *mAnim; const aiAnimation *mAnim;
double mLastTime; double mLastTime;
std::vector<std::tuple<unsigned int, unsigned int, unsigned int>> mLastPositions; std::vector<std::tuple<unsigned int, unsigned int, unsigned int>> mLastPositions;

View File

@ -489,7 +489,7 @@ int CreateAssetData() {
nidx = 3; nidx = 3;
break; break;
default: default:
ai_assert(false); CLogWindow::Instance().WriteLine("Unknown primitiv type");
break; break;
}; };
@ -500,8 +500,7 @@ int CreateAssetData() {
// check whether we can use 16 bit indices // check whether we can use 16 bit indices
if (numIndices >= 65536) { if (numIndices >= 65536) {
// create 32 bit index buffer // create 32 bit index buffer
if (FAILED(g_piDevice->CreateIndexBuffer(4 * if (FAILED(g_piDevice->CreateIndexBuffer(4 * numIndices,
numIndices,
D3DUSAGE_WRITEONLY | dwUsage, D3DUSAGE_WRITEONLY | dwUsage,
D3DFMT_INDEX32, D3DFMT_INDEX32,
D3DPOOL_DEFAULT, D3DPOOL_DEFAULT,
@ -523,7 +522,7 @@ int CreateAssetData() {
} else { } else {
// create 16 bit index buffer // create 16 bit index buffer
if (FAILED(g_piDevice->CreateIndexBuffer(2 * if (FAILED(g_piDevice->CreateIndexBuffer(2 *
numIndices, numIndices,
D3DUSAGE_WRITEONLY | dwUsage, D3DUSAGE_WRITEONLY | dwUsage,
D3DFMT_INDEX16, D3DFMT_INDEX16,
D3DPOOL_DEFAULT, D3DPOOL_DEFAULT,