Working read, import, export, and write of gltf2 (pbr) material

pull/1423/head
Daniel Hritzkiv 2017-08-30 17:25:11 -04:00
parent 6b4286abf6
commit 11cb9ac139
No known key found for this signature in database
GPG Key ID: D1D19875679D5CBF
6 changed files with 329 additions and 135 deletions

View File

@ -133,7 +133,6 @@ namespace glTF2
struct Light; struct Light;
struct Skin; struct Skin;
// Vec/matrix types, as raw float arrays // Vec/matrix types, as raw float arrays
typedef float (vec3)[3]; typedef float (vec3)[3];
typedef float (vec4)[4]; typedef float (vec4)[4];
@ -671,20 +670,30 @@ namespace glTF2
inline void SetData(uint8_t* data, size_t length, Asset& r); inline void SetData(uint8_t* data, size_t length, Asset& r);
}; };
struct ColorProperty struct TextureInfo
{
union {
vec4, vec3
} color;
}
//! Holds a material property that can be a texture or a color (fallback for glTF 1)
struct FallbackTexProperty
{ {
Ref<Texture> texture; Ref<Texture> texture;
ColorProperty color; unsigned int index;
unsigned int texCoord = 0;
}; };
struct NormalTextureInfo : TextureInfo
{
float scale = 1;
};
struct OcclusionTextureInfo : TextureInfo
{
float strength = 1;
};
//! Holds a material property that can be a texture or a color (fallback for glTF 1)
/*struct FallbackTexProperty
{
Ref<Texture> texture;
vec4 color;
};*/
//! The material appearance of a primitive. //! The material appearance of a primitive.
struct Material : public Object struct Material : public Object
{ {
@ -702,26 +711,26 @@ namespace glTF2
}; };
//PBR metallic roughness properties //PBR metallic roughness properties
ColorProperty baseColor; vec4 baseColorFactor;
Ref<Texture> baseColorTexture; TextureInfo baseColorTexture;
Ref<Texture> metallicRoughnessTexture; TextureInfo metallicRoughnessTexture;
float metallicFactor; float metallicFactor;
float roughnessFactor; float roughnessFactor;
//other basic material properties //other basic material properties
Ref<Texture> normalTexture; NormalTextureInfo normalTexture;
Ref<Texture> occlusionTexture; OcclusionTextureInfo occlusionTexture;
Ref<Texture> emissiveTexture; TextureInfo emissiveTexture;
ColorProperty emissiveFactor; vec3 emissiveFactor;
std::string alphaMode; std::string alphaMode;
float alphaCutoff; float alphaCutoff;
bool doubleSided; bool doubleSided;
//fallback material properties (compatible with non-pbr defintions) //fallback material properties (compatible with non-pbr defintions)
FallbackTexProperty diffuse; /*FallbackTexProperty diffuse;
FallbackTexProperty emissive; FallbackTexProperty emission;
FallbackTexProperty specular; FallbackTexProperty specular;
Ref<Texture> normal; Ref<Texture> normal;*/
Technique technique; Technique technique;

View File

@ -128,6 +128,12 @@ namespace {
return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
} }
inline Value* FindNumber(Value& val, const char* id)
{
Value::MemberIterator it = val.FindMember(id);
return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
}
inline Value* FindUInt(Value& val, const char* id) inline Value* FindUInt(Value& val, const char* id)
{ {
Value::MemberIterator it = val.FindMember(id); Value::MemberIterator it = val.FindMember(id);
@ -225,7 +231,7 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i)
} }
T* inst = new T(); T* inst = new T();
inst->id = std::string(mDictId) + "[" + std::to_string(i) + "]"; inst->id = std::string(mDictId) + "_" + std::to_string(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);
@ -706,15 +712,42 @@ inline void Texture::Read(Value& obj, Asset& r)
} }
namespace { namespace {
inline void ReadMaterialProperty(Asset& r, Value& vals, const char* propName, TexProperty& out) inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out)
{ {
//@TODO: update this format if (Value* index = FindUInt(*prop, "index")) {
if (Value* prop = FindMember(vals, propName)) { out.texture = r.textures.Retrieve(index->GetUint());
if (prop->IsUint()) {
out.texture = r.textures.Retrieve(prop->GetUint());
} }
else {
ReadValue(*prop, out.color); if (Value* texcoord = FindUInt(*prop, "texCoord")) {
out.texCoord = texcoord->GetUint();
}
}
inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, TextureInfo& out)
{
if (Value* prop = FindMember(vals, propName)) {
SetTextureProperties(r, prop, out);
}
}
inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, NormalTextureInfo& out)
{
if (Value* prop = FindMember(vals, propName)) {
SetTextureProperties(r, prop, out);
if (Value* scale = FindNumber(*prop, "scale")) {
out.scale = scale->GetDouble();
}
}
}
inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, OcclusionTextureInfo& out)
{
if (Value* prop = FindMember(vals, propName)) {
SetTextureProperties(r, prop, out);
if (Value* strength = FindNumber(*prop, "strength")) {
out.strength = strength->GetDouble();
} }
} }
} }
@ -724,33 +757,24 @@ inline void Material::Read(Value& material, Asset& r)
{ {
SetDefaults(); SetDefaults();
if (Value* values = FindObject(material, "values")) {
ReadMember(*values, "transparency", transparency);
}
if (Value* values = FindObject(material, "pbrMetallicRoughness")) { if (Value* values = FindObject(material, "pbrMetallicRoughness")) {
//pbr ReadMember(*values, "baseColorFactor", this->baseColorFactor);
ReadMaterialProperty(r, *values, "baseColorFactor", this->baseColor); ReadTextureProperty(r, *values, "baseColorTexture", this->baseColorTexture);
ReadMaterialProperty(r, *values, "baseColorTexture", this->baseColorTexture); ReadTextureProperty(r, *values, "metallicRoughnessTexture", this->metallicRoughnessTexture);
ReadMember(*values, "metallicFactor", this->metallicFactor);
//non-pbr fallback ReadMember(*values, "roughnessFactor", this->roughnessFactor);
ReadMaterialProperty(r, *values, "baseColorFactor", this->diffuse);
ReadMaterialProperty(r, *values, "baseColorTexture", this->diffuse);
ReadMember(*values, "metallicFactor", metallicFactor);
} }
ReadMaterialProperty(r, *values, "normalTexture", this->normalTexture); ReadTextureProperty(r, material, "normalTexture", this->normalTexture);
ReadMaterialProperty(r, *values, "normalTexture", this->normal); ReadTextureProperty(r, material, "occlusionTexture", this->occlusionTexture);
ReadMaterialProperty(r, *values, "occlusionTexture", this->occlusionTexture); ReadTextureProperty(r, material, "emissiveTexture", this->emissiveTexture);
ReadMaterialProperty(r, *values, "emissiveTexture", this->emissiveTexture); ReadMember(material, "emissiveFactor", this->emissiveFactor);
ReadMember(*values, "metallicFactor", emissiveFactor);
ReadMember(material, "doubleSided", doubleSided); ReadMember(material, "doubleSided", this->doubleSided);
ReadMember(material, "alphaMode", this->alphaMode);
ReadMember(material, "alphaCutoff", this->alphaCutoff);
if (Value* extensions = FindObject(material, "extensions")) { /* if (Value* extensions = FindObject(material, "extensions")) {
if (r.extensionsUsed.KHR_materials_common) { if (r.extensionsUsed.KHR_materials_common) {
if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { if (Value* ext = FindObject(*extensions, "KHR_materials_common")) {
if (Value* tnq = FindString(*ext, "technique")) { if (Value* tnq = FindString(*ext, "technique")) {
@ -762,9 +786,9 @@ inline void Material::Read(Value& material, Asset& r)
} }
if (Value* values = FindObject(*ext, "values")) { if (Value* values = FindObject(*ext, "values")) {
ReadMaterialProperty(r, *values, "ambient", this->ambient); ReadTextureProperty(r, *values, "ambient", this->ambient);
ReadMaterialProperty(r, *values, "diffuse", this->diffuse); ReadTextureProperty(r, *values, "diffuse", this->diffuse);
ReadMaterialProperty(r, *values, "specular", this->specular); ReadTextureProperty(r, *values, "specular", this->specular);
ReadMember(*values, "doubleSided", doubleSided); ReadMember(*values, "doubleSided", doubleSided);
ReadMember(*values, "transparent", transparent); ReadMember(*values, "transparent", transparent);
@ -773,25 +797,28 @@ inline void Material::Read(Value& material, Asset& r)
} }
} }
} }
} } */
} }
namespace { namespace {
void SetVector(vec4& v, float x, float y, float z, float w) void SetVector(vec4& v, float x, float y, float z, float w)
{ v[0] = x; v[1] = y; v[2] = z; v[3] = w; } { v[0] = x; v[1] = y; v[2] = z; v[3] = w; }
void SetVector(vec3& v, float x, float y, float z)
{ v[0] = x; v[1] = y; v[2] = z; }
} }
inline void Material::SetDefaults() inline void Material::SetDefaults()
{ {
SetVector(ambient.color, 0, 0, 0, 1); //pbr materials
SetVector(diffuse.color, 0, 0, 0, 1); SetVector(baseColorFactor, 1, 1, 1, 1);
SetVector(specular.color, 0, 0, 0, 1); SetVector(emissiveFactor, 0, 0, 0);
SetVector(emission.color, 0, 0, 0, 1); metallicFactor = 1.0;
roughnessFactor = 1.0;
alphaMode = "OPAQUE";
alphaCutoff = 0.5;
doubleSided = false; doubleSided = false;
transparent = false;
transparency = 1.0;
shininess = 0.0;
technique = Technique_undefined; technique = Technique_undefined;
} }
@ -833,6 +860,10 @@ namespace {
inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
{ {
if (Value* name = FindMember(pJSON_Object, "name")) {
this->name = name->GetString();
}
/****************** Mesh primitives ******************/ /****************** Mesh primitives ******************/
if (Value* primitives = FindArray(pJSON_Object, "primitives")) { if (Value* primitives = FindArray(pJSON_Object, "primitives")) {
this->primitives.resize(primitives->Size()); this->primitives.resize(primitives->Size());
@ -1055,7 +1086,7 @@ inline void Node::Read(Value& obj, Asset& r)
// TODO load "skeletons", "skin", "jointName" // TODO load "skeletons", "skin", "jointName"
if (Value* extensions = FindObject(obj, "extensions")) { /*if (Value* extensions = FindObject(obj, "extensions")) {
if (r.extensionsUsed.KHR_materials_common) { if (r.extensionsUsed.KHR_materials_common) {
if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { if (Value* ext = FindObject(*extensions, "KHR_materials_common")) {
@ -1065,7 +1096,7 @@ inline void Node::Read(Value& obj, Asset& r)
} }
} }
} }*/
} }
inline void Scene::Read(Value& obj, Asset& r) inline void Scene::Read(Value& obj, Asset& r)

View File

@ -72,6 +72,12 @@ namespace glTF2 {
return val; return val;
} }
inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& al) {
val.SetDouble(r);
return val;
}
template<class T> template<class T>
inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) { inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) {
if (v.empty()) return; if (v.empty()) return;
@ -196,51 +202,148 @@ namespace glTF2 {
} }
namespace { namespace {
inline void WriteTex(Value& obj, Ref<Texture> texture, const char* propName, MemoryPoolAllocator<>& al) inline void SetTexBasic(TextureInfo t, Value& tex, MemoryPoolAllocator<>& al)
{ {
if (texture) {
Value tex;
tex.SetObject(); tex.SetObject();
tex.AddMember("index", texture->index, al); tex.AddMember("index", t.texture->index, al);
if (t.texCoord != 0) {
tex.AddMember("texCoord", t.texCoord, al);
}
}
inline void WriteTex(Value& obj, TextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
{
if (t.texture) {
Value tex;
SetTexBasic(t, tex, al);
obj.AddMember(StringRef(propName), tex, al); obj.AddMember(StringRef(propName), tex, al);
} }
} }
inline void WriteColorOrTex(Value& obj, TexProperty& prop, const char* propName, MemoryPoolAllocator<>& al) inline void WriteTex(Value& obj, NormalTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
{ {
WriteTex(obj, prop.texture, propName, al);
if (!prop.texture) { if (t.texture) {
Value col; Value tex;
obj.AddMember(StringRef(propName), MakeValue(col, prop.color, al), al);
SetTexBasic(t, tex, al);
if (t.scale != 1) {
tex.AddMember("scale", t.scale, al);
} }
obj.AddMember(StringRef(propName), tex, al);
}
}
inline void WriteTex(Value& obj, OcclusionTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
{
if (t.texture) {
Value tex;
SetTexBasic(t, tex, al);
if (t.strength != 1) {
tex.AddMember("strength", t.strength, al);
}
obj.AddMember(StringRef(propName), tex, al);
}
}
template<size_t N>
inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, MemoryPoolAllocator<>& al)
{
Value arr;
obj.AddMember(StringRef(propName), MakeValue(arr, prop, al), al);
}
template<size_t N>
inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, float(&defaultVal)[N], MemoryPoolAllocator<>& al)
{
if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) {
WriteVec(obj, prop, propName, al);
}
}
inline void WriteFloat(Value& obj, float prop, const char* propName, MemoryPoolAllocator<>& al)
{
Value num;
obj.AddMember(StringRef(propName), MakeValue(num, prop, al), al);
} }
} }
inline void Write(Value& obj, Material& m, AssetWriter& w) inline void Write(Value& obj, Material& m, AssetWriter& w)
{ {
if (m.transparent) { if (!m.name.empty()) {
obj.AddMember("alphaMode", "BLEND", w.mAl); obj.AddMember("name", m.name, w.mAl);
} }
Value v; Value pbrMetallicRoughness;
pbrMetallicRoughness.SetObject();
{
WriteTex(pbrMetallicRoughness, m.baseColorTexture, "baseColorTexture", w.mAl);
WriteTex(pbrMetallicRoughness, m.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl);
//@TODO: define this as a constant?
vec4 defaultEmissiveFactor = {1, 1, 1, 1};
WriteVec(pbrMetallicRoughness, m.baseColorFactor, "baseColorFactor", defaultEmissiveFactor, w.mAl);
if (m.metallicFactor != 1) {
WriteFloat(pbrMetallicRoughness, m.metallicFactor, "metallicFactor", w.mAl);
}
if (m.roughnessFactor != 1) {
WriteFloat(pbrMetallicRoughness, m.roughnessFactor, "roughnessFactor", w.mAl);
}
}
if (pbrMetallicRoughness.MemberCount() > 0) {
obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl);
}
WriteTex(obj, m.normalTexture, "normalTexture", w.mAl);
WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl);
WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl);
//@TODO: define this as a constant?
vec3 defaultEmissiveFactor = {0, 0, 0};
WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl);
if (m.alphaCutoff != 0.5) {
WriteFloat(obj, m.alphaCutoff, "alphaCutoff", w.mAl);
}
if (m.alphaMode != "OPAQUE") {
obj.AddMember("alphaMode", m.alphaMode, w.mAl);
}
if (m.doubleSided) {
obj.AddMember("doubleSided", m.doubleSided, w.mAl);
}
/*Value v;
v.SetObject(); v.SetObject();
{ {
if (m.transparent && !m.diffuse.texture) { if (m.transparent && !m.diffuse.texture) {
m.diffuse.color[3] = m.transparency; m.diffuse.color[3] = m.transparency;
} }
WriteColorOrTex(v, m.ambient, m.ambient.texture ? "ambientTexture" : "ambientFactor", w.mAl); WriteVecOrTex(v, m.ambient, m.ambient.texture ? "ambientTexture" : "ambientFactor", w.mAl);
WriteColorOrTex(v, m.diffuse, m.diffuse.texture ? "diffuseTexture" : "diffuseFactor", w.mAl); WriteVecOrTex(v, m.diffuse, m.diffuse.texture ? "diffuseTexture" : "diffuseFactor", w.mAl);
WriteColorOrTex(v, m.specular, m.specular.texture ? "specularTexture" : "specularFactor", w.mAl); WriteVecOrTex(v, m.specular, m.specular.texture ? "specularTexture" : "specularFactor", w.mAl);
WriteColorOrTex(v, m.emission, m.emission.texture ? "emissionTexture" : "emissionFactor", w.mAl); WriteVecOrTex(v, m.emission, m.emission.texture ? "emissionTexture" : "emissionFactor", w.mAl);
v.AddMember("shininessFactor", m.shininess, w.mAl); v.AddMember("shininessFactor", m.shininess, w.mAl);
} }
v.AddMember("type", "commonPhong", w.mAl); v.AddMember("type", "commonPhong", w.mAl);
Value ext; Value ext;
ext.SetObject(); ext.SetObject();
ext.AddMember("KHR_materials_common", v, w.mAl); ext.AddMember("KHR_materials_common", v, w.mAl);
obj.AddMember("extensions", ext, w.mAl); obj.AddMember("extensions", ext, w.mAl);*/
WriteTex(obj, m.normal, "normalTexture", w.mAl);
} }
namespace { namespace {
@ -263,8 +366,6 @@ namespace glTF2 {
inline void Write(Value& obj, Mesh& m, AssetWriter& w) inline void Write(Value& obj, Mesh& m, AssetWriter& w)
{ {
/********************* Name **********************/
obj.AddMember("name", m.name, w.mAl);
/**************** Mesh extensions ****************/ /**************** Mesh extensions ****************/
if(m.Extension.size() > 0) if(m.Extension.size() > 0)
@ -617,7 +718,7 @@ namespace glTF2 {
exts.PushBack(StringRef("KHR_binary_glTF"), mAl); exts.PushBack(StringRef("KHR_binary_glTF"), mAl);
// This is used to export common materials with GLTF 2. // This is used to export common materials with GLTF 2.
exts.PushBack(StringRef("KHR_materials_common"), mAl); //exts.PushBack(StringRef("KHR_materials_common"), mAl);
} }
if (!exts.Empty()) if (!exts.Empty())

View File

@ -234,12 +234,6 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
return acc; return acc;
} }
namespace {
void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) {
if (mat->Get(propName, type, idx, val) == AI_SUCCESS) {}
}
}
void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture) void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture)
{ {
std::string samplerId = mAsset->FindUniqueID("", "sampler"); std::string samplerId = mAsset->FindUniqueID("", "sampler");
@ -286,11 +280,11 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture)
texture->sampler->minFilter = SamplerMinFilter_Linear_Mipmap_Linear; texture->sampler->minFilter = SamplerMinFilter_Linear_Mipmap_Linear;
} }
void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt) void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt, unsigned int slot = 0)
{ {
aiString tex; aiString tex;
if (mat->GetTextureCount(tt) > 0) { if (mat->GetTextureCount(tt) > 0) {
if (mat->Get(AI_MATKEY_TEXTURE(tt, 0), tex) == AI_SUCCESS) { 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) {
@ -332,15 +326,21 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
} }
} }
void glTF2Exporter::GetMatColorOrTex(const aiMaterial* mat, TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt) void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx)
{ {
aiColor4D col; aiColor4D col;
if (mat->Get(propName, type, idx, col) == AI_SUCCESS) { if (mat->Get(propName, type, idx, col) == AI_SUCCESS) {
prop.color[0] = col.r; prop.color[1] = col.g; prop.color[2] = col.b; prop.color[3] = col.a; prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a;
} }
GetMatTex(mat, prop.texture, tt);
} }
void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx)
{
aiColor3D col;
if (mat->Get(propName, type, idx, col) == AI_SUCCESS) {
prop[0] = col.r; prop[1] = col.g; prop[2] = col.b;
}
}
void glTF2Exporter::ExportMaterials() void glTF2Exporter::ExportMaterials()
{ {
@ -348,7 +348,6 @@ void glTF2Exporter::ExportMaterials()
for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
const aiMaterial* mat = mScene->mMaterials[i]; const aiMaterial* mat = mScene->mMaterials[i];
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();
@ -357,15 +356,20 @@ void glTF2Exporter::ExportMaterials()
Ref<Material> m = mAsset->materials.Create(name); Ref<Material> m = mAsset->materials.Create(name);
GetMatColorOrTex(mat, m->ambient, AI_MATKEY_COLOR_AMBIENT, aiTextureType_AMBIENT); GetMatTex(mat, m->baseColorTexture.texture, aiTextureType_DIFFUSE);
GetMatColorOrTex(mat, m->diffuse, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_DIFFUSE); GetMatTex(mat, m->metallicRoughnessTexture.texture, aiTextureType_UNKNOWN, 0);//get unknown slot
GetMatColorOrTex(mat, m->specular, AI_MATKEY_COLOR_SPECULAR, aiTextureType_SPECULAR); GetMatTex(mat, m->emissiveTexture.texture, aiTextureType_EMISSIVE);
GetMatColorOrTex(mat, m->emission, AI_MATKEY_COLOR_EMISSIVE, aiTextureType_EMISSIVE); GetMatTex(mat, m->normalTexture.texture, aiTextureType_NORMALS);
GetMatTex(mat, m->normal, aiTextureType_NORMALS); GetMatTex(mat, m->occlusionTexture.texture, aiTextureType_LIGHTMAP);
m->transparent = mat->Get(AI_MATKEY_OPACITY, m->transparency) == aiReturn_SUCCESS && m->transparency != 1.0; GetMatColor(mat, m->baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE);
GetMatScalar(mat, m->shininess, AI_MATKEY_SHININESS); mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided);
mat->Get("$mat.gltf.alphaCutoff", 0, 0, m->alphaCutoff);
mat->Get("$mat.gltf.metallicFactor", 0, 0, m->metallicFactor);
mat->Get("$mat.gltf.roughnessFactor", 0, 0, m->roughnessFactor);
mat->Get("$mat.gltf.alphaMode", 0, 0, m->alphaMode);
} }
} }
@ -568,11 +572,15 @@ void glTF2Exporter::ExportMeshes()
comp_allow = false; comp_allow = false;
} }
std::string meshId = mAsset->FindUniqueID(aim->mName.C_Str(), "mesh"); std::string name = aim->mName.C_Str();
std::string meshId = mAsset->FindUniqueID(name, "mesh");
Ref<Mesh> m = mAsset->meshes.Create(meshId); Ref<Mesh> m = mAsset->meshes.Create(meshId);
m->primitives.resize(1); m->primitives.resize(1);
Mesh::Primitive& p = m->primitives.back(); Mesh::Primitive& p = m->primitives.back();
m->name = name;
p.material = mAsset->materials.Get(aim->mMaterialIndex); p.material = mAsset->materials.Get(aim->mMaterialIndex);
/******************* Vertices ********************/ /******************* Vertices ********************/

View File

@ -66,8 +66,13 @@ namespace glTF2
class Asset; class Asset;
struct TexProperty; struct TexProperty;
struct TextureInfo;
struct Node; struct Node;
struct Texture; struct Texture;
// Vec/matrix types, as raw float arrays
typedef float (vec3)[3];
typedef float (vec4)[4];
} }
namespace Assimp namespace Assimp
@ -102,8 +107,9 @@ namespace Assimp
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); void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture);
void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt); void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt, unsigned int slot);
void GetMatColorOrTex(const aiMaterial* mat, glTF2::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt); void GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx);
void GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx);
void ExportMetadata(); void ExportMetadata();
void ExportMaterials(); void ExportMaterials();
void ExportMeshes(); void ExportMeshes();

View File

@ -141,6 +141,11 @@ static void CopyValue(const glTF2::vec4& v, aiColor3D& out)
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.r = v[0]; out.g = v[1]; out.b = v[2];
} }
static void CopyValue(const glTF2::vec3& v, aiColor4D& out)
{
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0;
}
static void CopyValue(const glTF2::vec3& v, aiVector3D& out) static void CopyValue(const glTF2::vec3& v, aiVector3D& out)
{ {
out.x = v[0]; out.y = v[1]; out.z = v[2]; out.x = v[0]; out.y = v[1]; out.z = v[2];
@ -159,11 +164,28 @@ static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o)
o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15]; o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
} }
inline void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TexProperty prop, aiMaterial* mat, inline void SetMaterialColorProperty(Asset& r, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx)
{ {
if (prop.texture) { aiColor4D col;
if (prop.texture->source) { CopyValue(prop, col);
mat->AddProperty(&col, 1, pKey, type, idx);
}
inline void SetMaterialColorProperty(Asset& r, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
{
vec4 prop4;
prop4[0] = prop[0];
prop4[1] = prop[1];
prop4[2] = prop[2];
prop4[3] = 1;
return SetMaterialColorProperty(r, prop4, mat, pKey, type, idx);
}
inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, int texSlot)
{
if (prop.texture && prop.texture->source) {
aiString uri(prop.texture->source->uri); aiString uri(prop.texture->source->uri);
int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()];
@ -173,15 +195,26 @@ inline void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& r
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
} }
if (texSlot < 0) {
mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0); mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
} }
}
else { else {
aiColor4D col; mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType,
CopyValue(prop.color, col); texSlot));
mat->AddProperty(&col, 1, pKey, type, idx);
} }
} }
}
//import textures that are only supported in pbr contexts
inline void SetMaterialPBRTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, unsigned int texSlot)
{
return SetMaterialTextureProperty(embeddedTexIdxs, r, prop, mat, aiTextureType_UNKNOWN, texSlot);
}
inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType)
{
return SetMaterialTextureProperty(embeddedTexIdxs, r, prop, mat, texType, -1);
}
void glTF2Importer::ImportMaterials(glTF2::Asset& r) void glTF2Importer::ImportMaterials(glTF2::Asset& r)
{ {
@ -193,18 +226,23 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r)
Material& mat = r.materials[i]; Material& mat = r.materials[i];
/*if (!mat.name.empty())*/ { aiString str(mat.id);
aiString str(mat.id /*mat.name*/);
aimat->AddProperty(&str, AI_MATKEY_NAME); aimat->AddProperty(&str, AI_MATKEY_NAME);
}
SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); SetMaterialColorProperty(r, mat.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.baseColorTexture, aimat, aiTextureType_DIFFUSE);
SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); SetMaterialPBRTextureProperty(embeddedTexIdxs, r, mat.metallicRoughnessTexture, aimat, 0);
aimat->AddProperty(&mat.metallicFactor, 1, "$mat.gltf.metallicFactor");
aimat->AddProperty(&mat.roughnessFactor, 1, "$mat.gltf.roughnessFactor");
if (mat.shininess > 0.f) { SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS);
aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP);
} SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE);
SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE);
aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
aimat->AddProperty(&mat.alphaMode, 1, "$mat.gltf.alphaMode");
aimat->AddProperty(&mat.alphaCutoff, 1, "$mat.gltf.alphaCutoff");
} }
} }
@ -295,7 +333,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
aiMesh* aim = new aiMesh(); aiMesh* aim = new aiMesh();
meshes.push_back(aim); meshes.push_back(aim);
aim->mName = mesh.id; aim->mName = mesh.name.empty() ? mesh.id : mesh.name;
if (mesh.primitives.size() > 1) { if (mesh.primitives.size() > 1) {
size_t& len = aim->mName.length; size_t& len = aim->mName.length;
aim->mName.data[len] = '-'; aim->mName.data[len] = '-';