summaryrefslogtreecommitdiff
path: root/indra/newview/gltf/asset.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/gltf/asset.cpp')
-rw-r--r--indra/newview/gltf/asset.cpp725
1 files changed, 600 insertions, 125 deletions
diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp
index 5f2217a075..c64d48662c 100644
--- a/indra/newview/gltf/asset.cpp
+++ b/indra/newview/gltf/asset.cpp
@@ -31,13 +31,51 @@
#include "../llviewershadermgr.h"
#include "../llviewercontrol.h"
#include "../llviewertexturelist.h"
+#include "../pipeline.h"
+#include "buffer_util.h"
using namespace LL::GLTF;
+using namespace boost::json;
namespace LL
{
namespace GLTF
{
+ Material::AlphaMode gltf_alpha_mode_to_enum(const std::string& alpha_mode)
+ {
+ if (alpha_mode == "OPAQUE")
+ {
+ return Material::AlphaMode::OPAQUE;
+ }
+ else if (alpha_mode == "MASK")
+ {
+ return Material::AlphaMode::MASK;
+ }
+ else if (alpha_mode == "BLEND")
+ {
+ return Material::AlphaMode::BLEND;
+ }
+ else
+ {
+ return Material::AlphaMode::OPAQUE;
+ }
+ }
+
+ std::string enum_to_gltf_alpha_mode(Material::AlphaMode alpha_mode)
+ {
+ switch (alpha_mode)
+ {
+ case Material::AlphaMode::OPAQUE:
+ return "OPAQUE";
+ case Material::AlphaMode::MASK:
+ return "MASK";
+ case Material::AlphaMode::BLEND:
+ return "BLEND";
+ default:
+ return "OPAQUE";
+ }
+ }
+
template <typename T, typename U>
void copy(const std::vector<T>& src, std::vector<U>& dst)
{
@@ -45,49 +83,48 @@ namespace LL
for (U32 i = 0; i < src.size(); ++i)
{
copy(src[i], dst[i]);
- }
+ }
}
void copy(const Node& src, tinygltf::Node& dst)
{
if (src.mMatrixValid)
{
- if (!src.mMatrix.asMatrix4().isIdentity())
+ if (src.mMatrix != glm::identity<mat4>())
{
dst.matrix.resize(16);
+ const F32* m = glm::value_ptr(src.mMatrix);
for (U32 i = 0; i < 16; ++i)
{
- dst.matrix[i] = src.mMatrix.getF32ptr()[i];
+ dst.matrix[i] = m[i];
}
}
}
else if (src.mTRSValid)
{
- if (!src.mRotation.equals(glh::quaternionf::identity(), FLT_EPSILON))
+ if (src.mRotation != glm::identity<quat>())
{
dst.rotation.resize(4);
- for (U32 i = 0; i < 4; ++i)
- {
- dst.rotation[i] = src.mRotation.get_value()[i];
- }
- }
+ dst.rotation[0] = src.mRotation.x;
+ dst.rotation[1] = src.mRotation.y;
+ dst.rotation[2] = src.mRotation.z;
+ dst.rotation[3] = src.mRotation.w;
+ }
- if (src.mTranslation != glh::vec3f(0.f, 0.f, 0.f))
+ if (src.mTranslation != vec3(0.f, 0.f, 0.f))
{
dst.translation.resize(3);
- for (U32 i = 0; i < 3; ++i)
- {
- dst.translation[i] = src.mTranslation.v[i];
- }
+ dst.translation[0] = src.mTranslation.x;
+ dst.translation[1] = src.mTranslation.y;
+ dst.translation[2] = src.mTranslation.z;
}
- if (src.mScale != glh::vec3f(1.f, 1.f, 1.f))
+ if (src.mScale != vec3(1.f, 1.f, 1.f))
{
dst.scale.resize(3);
- for (U32 i = 0; i < 3; ++i)
- {
- dst.scale[i] = src.mScale.v[i];
- }
+ dst.scale[0] = src.mScale.x;
+ dst.scale[1] = src.mScale.y;
+ dst.scale[2] = src.mScale.z;
}
}
@@ -143,7 +180,7 @@ namespace LL
void copy(const Material::PbrMetallicRoughness& src, tinygltf::PbrMetallicRoughness& dst)
{
- dst.baseColorFactor = { src.mBaseColorFactor.v[0], src.mBaseColorFactor.v[1], src.mBaseColorFactor.v[2], src.mBaseColorFactor.v[3] };
+ dst.baseColorFactor = { src.mBaseColorFactor.r, src.mBaseColorFactor.g, src.mBaseColorFactor.b, src.mBaseColorFactor.a };
copy(src.mBaseColorTexture, dst.baseColorTexture);
dst.metallicFactor = src.mMetallicFactor;
dst.roughnessFactor = src.mRoughnessFactor;
@@ -154,7 +191,7 @@ namespace LL
{
material.name = src.mName;
- material.emissiveFactor = { src.mEmissiveFactor.v[0], src.mEmissiveFactor.v[1], src.mEmissiveFactor.v[2] };
+ material.emissiveFactor = { src.mEmissiveFactor.r, src.mEmissiveFactor.g, src.mEmissiveFactor.b };
copy(src.mPbrMetallicRoughness, material.pbrMetallicRoughness);
copy(src.mNormalTexture, material.normalTexture);
copy(src.mEmissiveTexture, material.emissiveTexture);
@@ -193,7 +230,7 @@ namespace LL
accessor.maxValues = src.mMax;
accessor.count = src.mCount;
- accessor.type = src.mType;
+ accessor.type = (S32) src.mType;
accessor.normalized = src.mNormalized;
accessor.name = src.mName;
}
@@ -278,7 +315,8 @@ namespace LL
dst.asset.version = src.mVersion;
dst.asset.minVersion = src.mMinVersion;
dst.asset.generator = "Linden Lab Experimental GLTF Export";
- dst.asset.extras = src.mExtras;
+
+ // NOTE: extras are lost in the conversion for now
copy(src.mScenes, dst.scenes);
copy(src.mNodes, dst.nodes);
@@ -297,8 +335,8 @@ namespace LL
}
void Scene::updateTransforms(Asset& asset)
{
- LLMatrix4a identity;
- identity.setIdentity();
+ mat4 identity = glm::identity<mat4>();
+
for (auto& nodeIndex : mNodes)
{
Node& node = asset.mNodes[nodeIndex];
@@ -306,7 +344,7 @@ void Scene::updateTransforms(Asset& asset)
}
}
-void Scene::updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview)
+void Scene::updateRenderTransforms(Asset& asset, const mat4& modelview)
{
for (auto& nodeIndex : mNodes)
{
@@ -315,9 +353,9 @@ void Scene::updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview)
}
}
-void Node::updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview)
+void Node::updateRenderTransforms(Asset& asset, const mat4& modelview)
{
- matMul(mMatrix, modelview, mRenderMatrix);
+ mRenderMatrix = modelview * mMatrix;
for (auto& childIndex : mChildren)
{
@@ -326,13 +364,12 @@ void Node::updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview)
}
}
-LLMatrix4a inverse(const LLMatrix4a& mat);
-
-void Node::updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix)
+void Node::updateTransforms(Asset& asset, const mat4& parentMatrix)
{
makeMatrixValid();
- matMul(mMatrix, parentMatrix, mAssetMatrix);
- mAssetMatrixInv = inverse(mAssetMatrix);
+ mAssetMatrix = parentMatrix * mMatrix;
+
+ mAssetMatrixInv = glm::inverse(mAssetMatrix);
S32 my_index = this - &asset.mNodes[0];
@@ -352,26 +389,13 @@ void Asset::updateTransforms()
}
}
-void Asset::updateRenderTransforms(const LLMatrix4a& modelview)
+void Asset::updateRenderTransforms(const mat4& modelview)
{
-#if 0
- // traverse hierarchy and update render transforms from scratch
- for (auto& scene : mScenes)
- {
- scene.updateRenderTransforms(*this, modelview);
- }
-#else
// use mAssetMatrix to update render transforms from node list
for (auto& node : mNodes)
{
- //if (node.mMesh != INVALID_INDEX)
- {
- matMul(node.mAssetMatrix, modelview, node.mRenderMatrix);
- }
+ node.mRenderMatrix = modelview * node.mAssetMatrix;
}
-
-#endif
-
}
S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
@@ -398,9 +422,11 @@ S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
bool newHit = false;
+ LLMatrix4a ami;
+ ami.loadu(glm::value_ptr(node.mAssetMatrixInv));
// transform start and end to this node's local space
- node.mAssetMatrixInv.affineTransform(start, local_start);
- node.mAssetMatrixInv.affineTransform(asset_end, local_end);
+ ami.affineTransform(start, local_start);
+ ami.affineTransform(asset_end, local_end);
Mesh& mesh = mMeshes[node.mMesh];
for (auto& primitive : mesh.mPrimitives)
@@ -423,8 +449,10 @@ S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
if (newHit)
{
+ LLMatrix4a am;
+ am.loadu(glm::value_ptr(node.mAssetMatrix));
// shorten line segment on hit
- node.mAssetMatrix.affineTransform(p, asset_end);
+ am.affineTransform(p, asset_end);
// transform results back to asset space
if (intersection)
@@ -434,12 +462,10 @@ S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
if (normal || tangent)
{
- LLMatrix4 normalMatrix(node.mAssetMatrixInv.getF32ptr());
-
- normalMatrix.transpose();
+ mat4 normalMatrix = glm::transpose(node.mAssetMatrixInv);
LLMatrix4a norm_mat;
- norm_mat.loadu((F32*)normalMatrix.mMatrix);
+ norm_mat.loadu(glm::value_ptr(normalMatrix));
if (normal)
{
@@ -481,22 +507,7 @@ void Node::makeMatrixValid()
{
if (!mMatrixValid && mTRSValid)
{
- glh::matrix4f rot;
- mRotation.get_value(rot);
-
- glh::matrix4f trans;
- trans.set_translate(mTranslation);
-
- glh::matrix4f sc;
- sc.set_scale(mScale);
-
- glh::matrix4f t;
- //t = sc * rot * trans;
- //t = trans * rot * sc; // best so far, still wrong on negative scale
- //t = sc * trans * rot;
- t = trans * sc * rot;
-
- mMatrix.loadu(t.m);
+ mMatrix = glm::recompose(mScale, mRotation, mTranslation, vec3(0,0,0), vec4(0,0,0,1));
mMatrixValid = true;
}
@@ -507,43 +518,72 @@ void Node::makeTRSValid()
{
if (!mTRSValid && mMatrixValid)
{
- glh::matrix4f t(mMatrix.getF32ptr());
-
- glh::vec4f p = t.get_column(3);
- mTranslation.set_value(p.v[0], p.v[1], p.v[2]);
-
- mScale.set_value(t.get_column(0).length(), t.get_column(1).length(), t.get_column(2).length());
- mRotation.set_value(t);
+ vec3 skew;
+ vec4 perspective;
+ glm::decompose(mMatrix, mScale, mRotation, mTranslation, skew, perspective);
+
mTRSValid = true;
}
llassert(mTRSValid);
}
-void Node::setRotation(const glh::quaternionf& q)
+void Node::setRotation(const quat& q)
{
makeTRSValid();
mRotation = q;
mMatrixValid = false;
}
-void Node::setTranslation(const glh::vec3f& t)
+void Node::setTranslation(const vec3& t)
{
makeTRSValid();
mTranslation = t;
mMatrixValid = false;
}
-void Node::setScale(const glh::vec3f& s)
+void Node::setScale(const vec3& s)
{
makeTRSValid();
mScale = s;
mMatrixValid = false;
}
+void Node::serialize(object& dst) const
+{
+ write(mName, "name", dst);
+ write(mMatrix, "matrix", dst, glm::identity<mat4>());
+ write(mRotation, "rotation", dst);
+ write(mTranslation, "translation", dst);
+ write(mScale, "scale", dst, vec3(1.f,1.f,1.f));
+ write(mChildren, "children", dst);
+ write(mMesh, "mesh", dst, INVALID_INDEX);
+ write(mSkin, "skin", dst, INVALID_INDEX);
+}
+
+const Node& Node::operator=(const Value& src)
+{
+ copy(src, "name", mName);
+ mMatrixValid = copy(src, "matrix", mMatrix);
+
+ copy(src, "rotation", mRotation);
+ copy(src, "translation", mTranslation);
+ copy(src, "scale", mScale);
+ copy(src, "children", mChildren);
+ copy(src, "mesh", mMesh);
+ copy(src, "skin", mSkin);
+
+ if (!mMatrixValid)
+ {
+ mTRSValid = true;
+ }
+
+ return *this;
+}
+
const Node& Node::operator=(const tinygltf::Node& src)
{
- F32* dstMatrix = mMatrix.getF32ptr();
+ F32* dstMatrix = glm::value_ptr(mMatrix);
if (src.matrix.size() == 16)
{
@@ -560,22 +600,21 @@ const Node& Node::operator=(const tinygltf::Node& src)
// node has rotation/translation/scale, convert to matrix
if (src.rotation.size() == 4)
{
- mRotation = glh::quaternionf((F32)src.rotation[0], (F32)src.rotation[1], (F32)src.rotation[2], (F32)src.rotation[3]);
+ mRotation = quat((F32)src.rotation[3], (F32)src.rotation[0], (F32)src.rotation[1], (F32)src.rotation[2]);
}
if (src.translation.size() == 3)
{
- mTranslation = glh::vec3f((F32)src.translation[0], (F32)src.translation[1], (F32)src.translation[2]);
+ mTranslation = vec3((F32)src.translation[0], (F32)src.translation[1], (F32)src.translation[2]);
}
- glh::vec3f scale;
if (src.scale.size() == 3)
{
- mScale = glh::vec3f((F32)src.scale[0], (F32)src.scale[1], (F32)src.scale[2]);
+ mScale = vec3((F32)src.scale[0], (F32)src.scale[1], (F32)src.scale[2]);
}
else
{
- mScale.set_value(1.f, 1.f, 1.f);
+ mScale = vec3(1.f, 1.f, 1.f);
}
mTRSValid = true;
@@ -583,7 +622,7 @@ const Node& Node::operator=(const tinygltf::Node& src)
else
{
// node specifies no transformation, set to identity
- mMatrix.setIdentity();
+ mMatrix = glm::identity<mat4>();
mMatrixValid = true;
}
@@ -595,6 +634,50 @@ const Node& Node::operator=(const tinygltf::Node& src)
return *this;
}
+void Image::serialize(object& dst) const
+{
+ write(mUri, "uri", dst);
+ write(mMimeType, "mimeType", dst);
+ write(mBufferView, "bufferView", dst, INVALID_INDEX);
+ write(mName, "name", dst);
+ write(mWidth, "width", dst, -1);
+ write(mHeight, "height", dst, -1);
+ write(mComponent, "component", dst, -1);
+ write(mBits, "bits", dst, -1);
+ write(mPixelType, "pixelType", dst, -1);
+}
+
+const Image& Image::operator=(const Value& src)
+{
+ copy(src, "uri", mUri);
+ copy(src, "mimeType", mMimeType);
+ copy(src, "bufferView", mBufferView);
+ copy(src, "name", mName);
+ copy(src, "width", mWidth);
+ copy(src, "height", mHeight);
+ copy(src, "component", mComponent);
+ copy(src, "bits", mBits);
+ copy(src, "pixelType", mPixelType);
+
+ return *this;
+}
+
+const Image& Image::operator=(const tinygltf::Image& src)
+{
+ mName = src.name;
+ mWidth = src.width;
+ mHeight = src.height;
+ mComponent = src.component;
+ mBits = src.bits;
+ mPixelType = src.pixel_type;
+ mUri = src.uri;
+ mBufferView = src.bufferView;
+ mMimeType = src.mimeType;
+ mData = src.image;
+ return *this;
+}
+
+
void Asset::render(bool opaque, bool rigged)
{
if (rigged)
@@ -623,7 +706,6 @@ void Asset::render(bool opaque, bool rigged)
continue;
}
-
if (node.mMesh != INVALID_INDEX)
{
Mesh& mesh = mMeshes[node.mMesh];
@@ -631,19 +713,28 @@ void Asset::render(bool opaque, bool rigged)
{
if (!rigged)
{
- gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix);
+ gGL.loadMatrix((F32*)glm::value_ptr(node.mRenderMatrix));
}
bool cull = true;
if (primitive.mMaterial != INVALID_INDEX)
{
Material& material = mMaterials[primitive.mMaterial];
+ bool mat_opaque = material.mAlphaMode != Material::AlphaMode::BLEND;
- if ((material.mMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND) == opaque)
+ if (mat_opaque != opaque)
{
continue;
}
- material.mMaterial->bind();
- cull = !material.mMaterial->mDoubleSided;
+
+ if (mMaterials[primitive.mMaterial].mMaterial.notNull())
+ {
+ material.mMaterial->bind();
+ }
+ else
+ {
+ material.bind(*this);
+ }
+ cull = !material.mDoubleSided;
}
else
{
@@ -709,11 +800,16 @@ void Asset::allocateGLResources(const std::string& filename, const tinygltf::Mod
image.allocateGLResources();
}
+
// do materials before meshes as meshes may depend on materials
- for (U32 i = 0; i < mMaterials.size(); ++i)
+ if (!filename.empty())
{
- mMaterials[i].allocateGLResources(*this);
- LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true);
+ for (U32 i = 0; i < mMaterials.size(); ++i)
+ {
+ // HACK: local preview mode, load material from model for now
+ mMaterials[i].allocateGLResources(*this);
+ LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true);
+ }
}
for (auto& mesh : mMeshes)
@@ -732,16 +828,26 @@ void Asset::allocateGLResources(const std::string& filename, const tinygltf::Mod
}
}
+Asset::Asset(const tinygltf::Model& src)
+{
+ *this = src;
+}
+
+Asset::Asset(const Value& src)
+{
+ *this = src;
+}
+
const Asset& Asset::operator=(const tinygltf::Model& src)
{
mVersion = src.asset.version;
mMinVersion = src.asset.minVersion;
mGenerator = src.asset.generator;
mCopyright = src.asset.copyright;
- mExtras = src.asset.extras;
+
+ // note: extras are lost in the conversion for now
mDefaultScene = src.defaultScene;
-
mScenes.resize(src.scenes.size());
for (U32 i = 0; i < src.scenes.size(); ++i)
@@ -818,11 +924,69 @@ const Asset& Asset::operator=(const tinygltf::Model& src)
return *this;
}
+const Asset& Asset::operator=(const Value& src)
+{
+ if (src.is_object())
+ {
+ const object& obj = src.as_object();
+
+ const auto it = obj.find("asset");
+
+ if (it != obj.end())
+ {
+ const Value& asset = it->value();
+
+ copy(asset, "version", mVersion);
+ copy(asset, "minVersion", mMinVersion);
+ copy(asset, "generator", mGenerator);
+ copy(asset, "copyright", mCopyright);
+ copy(asset, "extras", mExtras);
+ }
+
+ copy(obj, "defaultScene", mDefaultScene);
+ copy(obj, "scenes", mScenes);
+ copy(obj, "nodes", mNodes);
+ copy(obj, "meshes", mMeshes);
+ copy(obj, "materials", mMaterials);
+ copy(obj, "buffers", mBuffers);
+ copy(obj, "bufferViews", mBufferViews);
+ copy(obj, "textures", mTextures);
+ copy(obj, "samplers", mSamplers);
+ copy(obj, "images", mImages);
+ copy(obj, "accessors", mAccessors);
+ copy(obj, "animations", mAnimations);
+ copy(obj, "skins", mSkins);
+ }
+
+ return *this;
+}
+
void Asset::save(tinygltf::Model& dst)
{
LL::GLTF::copy(*this, dst);
}
+void Asset::serialize(object& dst) const
+{
+ write(mVersion, "version", dst);
+ write(mMinVersion, "minVersion", dst, std::string());
+ write(mGenerator, "generator", dst);
+ write(mDefaultScene, "defaultScene", dst, 0);
+
+ write(mScenes, "scenes", dst);
+ write(mNodes, "nodes", dst);
+ write(mMeshes, "meshes", dst);
+ write(mMaterials, "materials", dst);
+ write(mBuffers, "buffers", dst);
+ write(mBufferViews, "bufferViews", dst);
+ write(mTextures, "textures", dst);
+ write(mSamplers, "samplers", dst);
+ write(mImages, "images", dst);
+ write(mAccessors, "accessors", dst);
+ write(mAnimations, "animations", dst);
+ write(mSkins, "skins", dst);
+}
+
void Asset::decompose(const std::string& filename)
{
// get folder path
@@ -857,6 +1021,41 @@ void Asset::eraseBufferView(S32 bufferView)
}
+LLViewerFetchedTexture* fetch_texture(const LLUUID& id);
+
+void Image::allocateGLResources()
+{
+ LLUUID id;
+ if (LLUUID::parseUUID(mUri, &id) && id.notNull())
+ {
+ mTexture = fetch_texture(id);
+ }
+}
+
+
+void Image::clearData(Asset& asset)
+{
+ if (mBufferView != INVALID_INDEX)
+ {
+ // remove data from buffer
+ BufferView& bufferView = asset.mBufferViews[mBufferView];
+ Buffer& buffer = asset.mBuffers[bufferView.mBuffer];
+
+ buffer.erase(asset, bufferView.mByteOffset, bufferView.mByteLength);
+
+ asset.eraseBufferView(mBufferView);
+ }
+
+ mData.clear();
+ mBufferView = INVALID_INDEX;
+ mWidth = -1;
+ mHeight = -1;
+ mComponent = -1;
+ mBits = -1;
+ mPixelType = -1;
+ mMimeType = "";
+}
+
void Image::decompose(Asset& asset, const std::string& folder)
{
std::string name = mName;
@@ -894,12 +1093,9 @@ void Image::decompose(Asset& asset, const std::string& folder)
std::ofstream file(filename, std::ios::binary);
file.write((const char*)buffer.mData.data() + bufferView.mByteOffset, bufferView.mByteLength);
-
- buffer.erase(asset, bufferView.mByteOffset, bufferView.mByteLength);
-
- asset.eraseBufferView(mBufferView);
}
+#if 0
if (!mData.empty())
{
// save j2c image
@@ -907,21 +1103,44 @@ void Image::decompose(Asset& asset, const std::string& folder)
LLPointer<LLImageRaw> raw = new LLImageRaw(mWidth, mHeight, mComponent);
U8* data = raw->allocateData();
- llassert(mData.size() == raw->getDataSize());
+ llassert_always(mData.size() == raw->getDataSize());
memcpy(data, mData.data(), mData.size());
LLViewerTextureList::createUploadFile(raw, filename, 4096);
mData.clear();
}
+#endif
- mWidth = -1;
- mHeight = -1;
- mComponent = -1;
- mBits = -1;
- mPixelType = -1;
- mMimeType = "";
+ clearData(asset);
+}
+
+void Material::TextureInfo::serialize(object& dst) const
+{
+ write(mIndex, "index", dst, INVALID_INDEX);
+ write(mTexCoord, "texCoord", dst, 0);
+}
+
+const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src)
+{
+ if (src.is_object())
+ {
+ copy(src, "index", mIndex);
+ copy(src, "texCoord", mTexCoord);
+ }
+
+ return *this;
+}
+
+bool Material::TextureInfo::operator==(const Material::TextureInfo& rhs) const
+{
+ return mIndex == rhs.mIndex && mTexCoord == rhs.mTexCoord;
+}
+
+bool Material::TextureInfo::operator!=(const Material::TextureInfo& rhs) const
+{
+ return !(*this == rhs);
}
const Material::TextureInfo& Material::TextureInfo::operator=(const tinygltf::TextureInfo& src)
@@ -931,6 +1150,25 @@ const Material::TextureInfo& Material::TextureInfo::operator=(const tinygltf::Te
return *this;
}
+void Material::OcclusionTextureInfo::serialize(object& dst) const
+{
+ write(mIndex, "index", dst, INVALID_INDEX);
+ write(mTexCoord, "texCoord", dst, 0);
+ write(mStrength, "strength", dst, 1.f);
+}
+
+const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(const Value& src)
+{
+ if (src.is_object())
+ {
+ copy(src, "index", mIndex);
+ copy(src, "texCoord", mTexCoord);
+ copy(src, "strength", mStrength);
+ }
+
+ return *this;
+}
+
const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(const tinygltf::OcclusionTextureInfo& src)
{
mIndex = src.index;
@@ -939,6 +1177,24 @@ const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(
return *this;
}
+void Material::NormalTextureInfo::serialize(object& dst) const
+{
+ write(mIndex, "index", dst, INVALID_INDEX);
+ write(mTexCoord, "texCoord", dst, 0);
+ write(mScale, "scale", dst, 1.f);
+}
+
+const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const Value& src)
+{
+ if (src.is_object())
+ {
+ copy(src, "index", mIndex);
+ copy(src, "texCoord", mTexCoord);
+ copy(src, "scale", mScale);
+ }
+
+ return *this;
+}
const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const tinygltf::NormalTextureInfo& src)
{
mIndex = src.index;
@@ -947,11 +1203,48 @@ const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const
return *this;
}
+const Material::PbrMetallicRoughness& Material::PbrMetallicRoughness::operator=(const Value& src)
+{
+ if (src.is_object())
+ {
+ copy(src, "baseColorFactor", mBaseColorFactor);
+ copy(src, "baseColorTexture", mBaseColorTexture);
+ copy(src, "metallicFactor", mMetallicFactor);
+ copy(src, "roughnessFactor", mRoughnessFactor);
+ copy(src, "metallicRoughnessTexture", mMetallicRoughnessTexture);
+ }
+
+ return *this;
+}
+
+void Material::PbrMetallicRoughness::serialize(object& dst) const
+{
+ write(mBaseColorFactor, "baseColorFactor", dst, vec4(1.f, 1.f, 1.f, 1.f));
+ write(mBaseColorTexture, "baseColorTexture", dst);
+ write(mMetallicFactor, "metallicFactor", dst, 1.f);
+ write(mRoughnessFactor, "roughnessFactor", dst, 1.f);
+ write(mMetallicRoughnessTexture, "metallicRoughnessTexture", dst);
+}
+
+bool Material::PbrMetallicRoughness::operator==(const Material::PbrMetallicRoughness& rhs) const
+{
+ return mBaseColorFactor == rhs.mBaseColorFactor &&
+ mBaseColorTexture == rhs.mBaseColorTexture &&
+ mMetallicFactor == rhs.mMetallicFactor &&
+ mRoughnessFactor == rhs.mRoughnessFactor &&
+ mMetallicRoughnessTexture == rhs.mMetallicRoughnessTexture;
+}
+
+bool Material::PbrMetallicRoughness::operator!=(const Material::PbrMetallicRoughness& rhs) const
+{
+ return !(*this == rhs);
+}
+
const Material::PbrMetallicRoughness& Material::PbrMetallicRoughness::operator=(const tinygltf::PbrMetallicRoughness& src)
{
if (src.baseColorFactor.size() == 4)
{
- mBaseColorFactor.set_value(src.baseColorFactor[0], src.baseColorFactor[1], src.baseColorFactor[2], src.baseColorFactor[3]);
+ mBaseColorFactor = vec4(src.baseColorFactor[0], src.baseColorFactor[1], src.baseColorFactor[2], src.baseColorFactor[3]);
}
mBaseColorTexture = src.baseColorTexture;
@@ -961,13 +1254,129 @@ const Material::PbrMetallicRoughness& Material::PbrMetallicRoughness::operator=(
return *this;
}
+
+static void bindTexture(Asset& asset, S32 uniform, Material::TextureInfo& info, LLViewerTexture* fallback)
+{
+ if (info.mIndex != INVALID_INDEX)
+ {
+ LLViewerTexture* tex = asset.mImages[asset.mTextures[info.mIndex].mSource].mTexture;
+ if (tex)
+ {
+ tex->addTextureStats(2048.f * 2048.f);
+ LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, tex);
+ }
+ else
+ {
+ LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, fallback);
+ }
+ }
+ else
+ {
+ LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, fallback);
+ }
+}
+
+void Material::bind(Asset& asset)
+{
+ // bind for rendering (derived from LLFetchedGLTFMaterial::bind)
+ // glTF 2.0 Specification 3.9.4. Alpha Coverage
+ // mAlphaCutoff is only valid for LLGLTFMaterial::ALPHA_MODE_MASK
+ F32 min_alpha = -1.0;
+
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+
+ if (!LLPipeline::sShadowRender || (mAlphaMode == Material::AlphaMode::BLEND))
+ {
+ if (mAlphaMode == Material::AlphaMode::MASK)
+ {
+ // dividing the alpha cutoff by transparency here allows the shader to compare against
+ // the alpha value of the texture without needing the transparency value
+ if (mPbrMetallicRoughness.mBaseColorFactor.a > 0.f)
+ {
+ min_alpha = mAlphaCutoff / mPbrMetallicRoughness.mBaseColorFactor.a;
+ }
+ else
+ {
+ min_alpha = 1024.f;
+ }
+ }
+ shader->uniform1f(LLShaderMgr::MINIMUM_ALPHA, min_alpha);
+ }
+
+ bindTexture(asset, LLShaderMgr::DIFFUSE_MAP, mPbrMetallicRoughness.mBaseColorTexture, LLViewerFetchedTexture::sWhiteImagep);
+
+ F32 base_color_packed[8];
+ //mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed);
+ LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed);
+ shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)base_color_packed);
+
+ if (!LLPipeline::sShadowRender)
+ {
+ bindTexture(asset, LLShaderMgr::BUMP_MAP, mNormalTexture, LLViewerFetchedTexture::sFlatNormalImagep);
+ bindTexture(asset, LLShaderMgr::SPECULAR_MAP, mPbrMetallicRoughness.mMetallicRoughnessTexture, LLViewerFetchedTexture::sWhiteImagep);
+ bindTexture(asset, LLShaderMgr::EMISSIVE_MAP, mEmissiveTexture, LLViewerFetchedTexture::sWhiteImagep);
+
+ // NOTE: base color factor is baked into vertex stream
+
+ shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, mPbrMetallicRoughness.mRoughnessFactor);
+ shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mPbrMetallicRoughness.mMetallicFactor);
+ shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, glm::value_ptr(mEmissiveFactor));
+
+ F32 normal_packed[8];
+ //mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
+ LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
+ shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, (F32*)normal_packed);
+
+ F32 metallic_roughness_packed[8];
+ //mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed);
+ LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed);
+ shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, (F32*)metallic_roughness_packed);
+
+ F32 emissive_packed[8];
+ //mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed);
+ LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed);
+ shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, (F32*)emissive_packed);
+ }
+}
+
+void Material::serialize(object& dst) const
+{
+ write(mName, "name", dst);
+ write(mEmissiveFactor, "emissiveFactor", dst, vec3(0.f, 0.f, 0.f));
+ write(mPbrMetallicRoughness, "pbrMetallicRoughness", dst);
+ write(mNormalTexture, "normalTexture", dst);
+ write(mOcclusionTexture, "occlusionTexture", dst);
+ write(mEmissiveTexture, "emissiveTexture", dst);
+ write(mAlphaMode, "alphaMode", dst, Material::AlphaMode::OPAQUE);
+ write(mAlphaCutoff, "alphaCutoff", dst, 0.5f);
+ write(mDoubleSided, "doubleSided", dst, false);
+}
+
+const Material& Material::operator=(const Value& src)
+{
+ if (src.is_object())
+ {
+ copy(src, "name", mName);
+ copy(src, "emissiveFactor", mEmissiveFactor);
+ copy(src, "pbrMetallicRoughness", mPbrMetallicRoughness);
+ copy(src, "normalTexture", mNormalTexture);
+ copy(src, "occlusionTexture", mOcclusionTexture);
+ copy(src, "emissiveTexture", mEmissiveTexture);
+ copy(src, "alphaMode", mAlphaMode);
+ copy(src, "alphaCutoff", mAlphaCutoff);
+ copy(src, "doubleSided", mDoubleSided);
+ }
+ return *this;
+}
+
+
const Material& Material::operator=(const tinygltf::Material& src)
{
mName = src.name;
if (src.emissiveFactor.size() == 3)
{
- mEmissiveFactor.set_value(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2]);
+ mEmissiveFactor = vec3(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2]);
}
mPbrMetallicRoughness = src.pbrMetallicRoughness;
@@ -975,7 +1384,7 @@ const Material& Material::operator=(const tinygltf::Material& src)
mOcclusionTexture = src.occlusionTexture;
mEmissiveTexture = src.emissiveTexture;
- mAlphaMode = src.alphaMode;
+ mAlphaMode = gltf_alpha_mode_to_enum(src.alphaMode);
mAlphaCutoff = src.alphaCutoff;
mDoubleSided = src.doubleSided;
@@ -984,10 +1393,31 @@ const Material& Material::operator=(const tinygltf::Material& src)
void Material::allocateGLResources(Asset& asset)
{
- // allocate material
+ // HACK: allocate an LLFetchedGLTFMaterial for now
+ // later we'll render directly from the GLTF Images
+ // and BufferViews
mMaterial = new LLFetchedGLTFMaterial();
}
+void Mesh::serialize(object& dst) const
+{
+ write(mPrimitives, "primitives", dst);
+ write(mWeights, "weights", dst);
+ write(mName, "name", dst);
+}
+
+const Mesh& Mesh::operator=(const Value& src)
+{
+ if (src.is_object())
+ {
+ copy(src, "primitives", mPrimitives);
+ copy(src, "weights", mWeights);
+ copy(src, "name", mName);
+ }
+
+ return *this;
+
+}
const Mesh& Mesh::operator=(const tinygltf::Mesh& src)
{
mPrimitives.resize(src.primitives.size());
@@ -1010,6 +1440,20 @@ void Mesh::allocateGLResources(Asset& asset)
}
}
+void Scene::serialize(object& dst) const
+{
+ write(mNodes, "nodes", dst);
+ write(mName, "name", dst);
+}
+
+const Scene& Scene::operator=(const Value& src)
+{
+ copy(src, "nodes", mNodes);
+ copy(src, "name", mName);
+
+ return *this;
+}
+
const Scene& Scene::operator=(const tinygltf::Scene& src)
{
mNodes = src.nodes;
@@ -1018,6 +1462,25 @@ const Scene& Scene::operator=(const tinygltf::Scene& src)
return *this;
}
+void Texture::serialize(object& dst) const
+{
+ write(mSampler, "sampler", dst, INVALID_INDEX);
+ write(mSource, "source", dst, INVALID_INDEX);
+ write(mName, "name", dst);
+}
+
+const Texture& Texture::operator=(const Value& src)
+{
+ if (src.is_object())
+ {
+ copy(src, "sampler", mSampler);
+ copy(src, "source", mSource);
+ copy(src, "name", mName);
+ }
+
+ return *this;
+}
+
const Texture& Texture::operator=(const tinygltf::Texture& src)
{
mSampler = src.sampler;
@@ -1027,6 +1490,27 @@ const Texture& Texture::operator=(const tinygltf::Texture& src)
return *this;
}
+
+void Sampler::serialize(object& dst) const
+{
+ write(mMagFilter, "magFilter", dst, LINEAR);
+ write(mMinFilter, "minFilter", dst, LINEAR_MIPMAP_LINEAR);
+ write(mWrapS, "wrapS", dst, REPEAT);
+ write(mWrapT, "wrapT", dst, REPEAT);
+ write(mName, "name", dst);
+}
+
+const Sampler& Sampler::operator=(const Value& src)
+{
+ copy(src, "magFilter", mMagFilter);
+ copy(src, "minFilter", mMinFilter);
+ copy(src, "wrapS", mWrapS);
+ copy(src, "wrapT", mWrapT);
+ copy(src, "name", mName);
+
+ return *this;
+}
+
const Sampler& Sampler::operator=(const tinygltf::Sampler& src)
{
mMagFilter = src.magFilter;
@@ -1043,23 +1527,14 @@ void Skin::uploadMatrixPalette(Asset& asset, Node& node)
// prepare matrix palette
// modelview will be applied by the shader, so assume matrix palette is in asset space
- std::vector<glh::matrix4f> t_mp;
+ std::vector<mat4> t_mp;
t_mp.resize(mJoints.size());
for (U32 i = 0; i < mJoints.size(); ++i)
{
Node& joint = asset.mNodes[mJoints[i]];
-
- //t_mp[i].set_value(joint.mRenderMatrix.getF32ptr());
- //t_mp[i] = t_mp[i] * mInverseBindMatricesData[i];
-
- //t_mp[i].set_value(joint.mRenderMatrix.getF32ptr());
- //t_mp[i] = mInverseBindMatricesData[i] * t_mp[i];
-
- t_mp[i].set_value(joint.mRenderMatrix.getF32ptr());
- t_mp[i] = t_mp[i] * mInverseBindMatricesData[i];
-
+ t_mp[i] = joint.mRenderMatrix * mInverseBindMatricesData[i];
}
std::vector<F32> glmp;
@@ -1070,7 +1545,7 @@ void Skin::uploadMatrixPalette(Asset& asset, Node& node)
for (U32 i = 0; i < mJoints.size(); ++i)
{
- F32* m = (F32*)t_mp[i].m;
+ F32* m = glm::value_ptr(t_mp[i]);
U32 idx = i * 12;