Merge branch 'master' into zero

pull/3959/head
Kim Kulling 2021-06-24 17:00:43 +02:00 committed by GitHub
commit 012ce30577
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 2306 additions and 328 deletions

View File

@ -64,10 +64,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiScene; struct aiScene;
struct aiNode; struct aiNode;
struct aiLight; struct aiLight;
//struct aiMaterial;
namespace Assimp namespace Assimp {
{
class IOSystem; class IOSystem;
class IOStream; class IOStream;
class ExportProperties; class ExportProperties;

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

@ -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,8 @@ 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;
//! 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 +426,8 @@ 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);
}; };
// //
@ -834,50 +885,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 +903,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);
}; };

View File

@ -304,6 +304,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 +367,12 @@ 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);
}
}
#ifdef ASSIMP_ENABLE_DRACO #ifdef ASSIMP_ENABLE_DRACO
template <typename T> template <typename T>
@ -569,6 +612,7 @@ 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);
Ref<T> result = Add(inst.release()); Ref<T> result = Add(inst.release());
mRecursiveReferenceCheck.erase(i); mRecursiveReferenceCheck.erase(i);
@ -1685,42 +1729,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;
@ -1777,8 +1785,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");

View File

@ -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,9 +518,8 @@ 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
@ -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,17 +775,17 @@ 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);
aiString alphaMode; aiString alphaMode;
if (mat->Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) {
m->alphaMode = alphaMode.C_Str(); m->alphaMode = alphaMode.C_Str();
} else { } else {
float opacity; float opacity;
if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) {
if (opacity < 1) { if (opacity < 1) {
m->alphaMode = "BLEND"; m->alphaMode = "BLEND";
m->pbrMetallicRoughness.baseColorFactor[3] *= opacity; m->pbrMetallicRoughness.baseColorFactor[3] *= opacity;
@ -712,87 +793,46 @@ void glTF2Exporter::ExportMaterials()
} }
} }
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);
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); m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
} }
bool unlit;
if (mat->Get(AI_MATKEY_GLTF_UNLIT, unlit) == AI_SUCCESS && unlit) {
mAsset->extensionsUsed.KHR_materials_unlit = true;
m->unlit = true;
} }
bool hasMaterialSheen = false; // glTFv2 is either PBR or Unlit
mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN, hasMaterialSheen); aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
mat.Get(AI_MATKEY_SHADING_MODEL, shadingMode);
if (hasMaterialSheen) { if (shadingMode == aiShadingMode_Unlit) {
mAsset->extensionsUsed.KHR_materials_sheen = true; mAsset->extensionsUsed.KHR_materials_unlit = true;
m->unlit = true;
} else {
// These extensions are not compatible with KHR_materials_unlit or KHR_materials_pbrSpecularGlossiness
if (!m->pbrSpecularGlossiness.isPresent) {
// Sheen
MaterialSheen sheen; MaterialSheen sheen;
if (GetMatSheen(mat, sheen)) {
GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR); mAsset->extensionsUsed.KHR_materials_sheen = true;
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); 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; MaterialClearcoat clearcoat;
if (GetMatClearcoat(mat, clearcoat)) {
mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR, clearcoat.clearcoatFactor); mAsset->extensionsUsed.KHR_materials_clearcoat = true;
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); 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; MaterialTransmission transmission;
if (GetMatTransmission(mat, transmission)) {
mat->Get(AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR, transmission.transmissionFactor); mAsset->extensionsUsed.KHR_materials_transmission = true;
GetMatTex(mat, transmission.transmissionTexture, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE);
m->materialTransmission = Nullable<MaterialTransmission>(transmission); m->materialTransmission = Nullable<MaterialTransmission>(transmission);
} }
} }
}
}
} }
/* /*

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;
@ -268,52 +276,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;
@ -1002,9 +1016,9 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
} }
} }
if (node.extensions) { if (node.customExtensions) {
ainode->mMetaData = new aiMetadata; ainode->mMetaData = new aiMetadata;
ParseExtensions(ainode->mMetaData, node.extensions); ParseExtensions(ainode->mMetaData, node.customExtensions);
} }
GetNodeTransform(ainode->mTransformation, node); GetNodeTransform(ainode->mTransformation, node);
@ -1498,7 +1512,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 +1524,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

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

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

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