parent
4705362a33
commit
4522f33d2b
|
|
@ -151,7 +151,7 @@ void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle, LL
|
|||
U32 idx1 = tri->mIndex[1];
|
||||
U32 idx2 = tri->mIndex[2];
|
||||
|
||||
if (mTexCoord != NULL)
|
||||
if (mTexCoord != NULL && mFace->mTexCoords)
|
||||
{
|
||||
LLVector2* tc = (LLVector2*) mFace->mTexCoords;
|
||||
*mTexCoord = ((1.f - a - b) * tc[idx0] +
|
||||
|
|
@ -160,7 +160,7 @@ void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle, LL
|
|||
|
||||
}
|
||||
|
||||
if (mNormal != NULL)
|
||||
if (mNormal != NULL && mFace->mNormals)
|
||||
{
|
||||
LLVector4a* norm = mFace->mNormals;
|
||||
|
||||
|
|
@ -180,7 +180,7 @@ void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle, LL
|
|||
*mNormal = n1;
|
||||
}
|
||||
|
||||
if (mTangent != NULL)
|
||||
if (mTangent != NULL && mFace->mTangents)
|
||||
{
|
||||
LLVector4a* tangents = mFace->mTangents;
|
||||
|
||||
|
|
|
|||
|
|
@ -39,10 +39,15 @@
|
|||
using namespace LL::GLTF;
|
||||
using namespace boost::json;
|
||||
|
||||
|
||||
namespace LL
|
||||
{
|
||||
namespace GLTF
|
||||
{
|
||||
static std::unordered_set<std::string> ExtensionsSupported = {
|
||||
"KHR_materials_unlit"
|
||||
};
|
||||
|
||||
Material::AlphaMode gltf_alpha_mode_to_enum(const std::string& alpha_mode)
|
||||
{
|
||||
if (alpha_mode == "OPAQUE")
|
||||
|
|
@ -382,6 +387,22 @@ void Asset::update()
|
|||
|
||||
bool Asset::prep()
|
||||
{
|
||||
// check required extensions and fail if not supported
|
||||
bool unsupported = false;
|
||||
for (auto& extension : mExtensionsRequired)
|
||||
{
|
||||
if (ExtensionsSupported.find(extension) == ExtensionsSupported.end())
|
||||
{
|
||||
LL_WARNS() << "Unsupported extension: " << extension << LL_ENDL;
|
||||
unsupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (unsupported)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// do buffers first as other resources depend on them
|
||||
for (auto& buffer : mBuffers)
|
||||
{
|
||||
|
|
@ -600,6 +621,8 @@ const Asset& Asset::operator=(const Value& src)
|
|||
copy(obj, "accessors", mAccessors);
|
||||
copy(obj, "animations", mAnimations);
|
||||
copy(obj, "skins", mSkins);
|
||||
copy(obj, "extensionsUsed", mExtensionsUsed);
|
||||
copy(obj, "extensionsRequired", mExtensionsRequired);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
|
@ -628,6 +651,8 @@ void Asset::serialize(object& dst) const
|
|||
write(mAccessors, "accessors", dst);
|
||||
write(mAnimations, "animations", dst);
|
||||
write(mSkins, "skins", dst);
|
||||
write(mExtensionsUsed, "extensionsUsed", dst);
|
||||
write(mExtensionsRequired, "extensionsRequired", dst);
|
||||
}
|
||||
|
||||
bool Asset::save(const std::string& filename)
|
||||
|
|
@ -979,6 +1004,17 @@ bool Material::PbrMetallicRoughness::operator!=(const Material::PbrMetallicRough
|
|||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
const Material::Unlit& Material::Unlit::operator=(const Value& src)
|
||||
{
|
||||
mPresent = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Material::Unlit::serialize(object& dst) const
|
||||
{
|
||||
// no members and object has already been created, nothing to do
|
||||
}
|
||||
|
||||
void Material::serialize(object& dst) const
|
||||
{
|
||||
write(mName, "name", dst);
|
||||
|
|
@ -990,6 +1026,7 @@ void Material::serialize(object& dst) const
|
|||
write(mAlphaMode, "alphaMode", dst, Material::AlphaMode::OPAQUE);
|
||||
write(mAlphaCutoff, "alphaCutoff", dst, 0.5f);
|
||||
write(mDoubleSided, "doubleSided", dst, false);
|
||||
write_extensions(dst, &mUnlit, "KHR_materials_unlit");
|
||||
}
|
||||
|
||||
const Material& Material::operator=(const Value& src)
|
||||
|
|
@ -1005,6 +1042,8 @@ const Material& Material::operator=(const Value& src)
|
|||
copy(src, "alphaMode", mAlphaMode);
|
||||
copy(src, "alphaCutoff", mAlphaCutoff);
|
||||
copy(src, "doubleSided", mDoubleSided);
|
||||
copy_extensions(src,
|
||||
"KHR_materials_unlit", &mUnlit );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -1027,7 +1066,6 @@ const Mesh& Mesh::operator=(const Value& src)
|
|||
}
|
||||
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
bool Mesh::prep(Asset& asset)
|
||||
|
|
|
|||
|
|
@ -49,10 +49,26 @@ namespace LL
|
|||
{
|
||||
class Asset;
|
||||
|
||||
class Extension
|
||||
{
|
||||
public:
|
||||
// true if this extension is present in the gltf file
|
||||
// otherwise false
|
||||
bool mPresent = false;
|
||||
};
|
||||
|
||||
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
|
||||
class Unlit : public Extension // KHR_materials_unlit implementation
|
||||
{
|
||||
public:
|
||||
const Unlit& operator=(const Value& src);
|
||||
void serialize(boost::json::object& dst) const;
|
||||
};
|
||||
|
||||
enum class AlphaMode
|
||||
{
|
||||
OPAQUE,
|
||||
|
|
@ -117,6 +133,7 @@ namespace LL
|
|||
AlphaMode mAlphaMode = AlphaMode::OPAQUE;
|
||||
F32 mAlphaCutoff = 0.5f;
|
||||
bool mDoubleSided = false;
|
||||
Unlit mUnlit;
|
||||
|
||||
const Material& operator=(const Value& src);
|
||||
void serialize(boost::json::object& dst) const;
|
||||
|
|
@ -300,6 +317,8 @@ namespace LL
|
|||
std::vector<Accessor> mAccessors;
|
||||
std::vector<Animation> mAnimations;
|
||||
std::vector<Skin> mSkins;
|
||||
std::vector<std::string> mExtensionsUsed;
|
||||
std::vector<std::string> mExtensionsRequired;
|
||||
|
||||
std::string mVersion;
|
||||
std::string mGenerator;
|
||||
|
|
|
|||
|
|
@ -519,6 +519,104 @@ namespace LL
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
// to/from extension
|
||||
|
||||
// for internal use only, use copy_extensions instead
|
||||
template<typename T>
|
||||
inline bool _copy_extension(const boost::json::object& extensions, std::string_view member, T* dst)
|
||||
{
|
||||
if (extensions.contains(member))
|
||||
{
|
||||
return copy(extensions.at(member), *dst);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy all extensions from src.extensions to provided destinations
|
||||
// Usage:
|
||||
// copy_extensions(src,
|
||||
// "KHR_materials_unlit", &mUnlit,
|
||||
// "KHR_materials_pbrSpecularGlossiness", &mPbrSpecularGlossiness);
|
||||
// returns true if any of the extensions are copied
|
||||
template<class... Types>
|
||||
inline bool copy_extensions(const boost::json::value& src, Types... args)
|
||||
{
|
||||
// extract the extensions object (don't assume it exists and verify that it is an object)
|
||||
if (src.is_object())
|
||||
{
|
||||
boost::json::object obj = src.get_object();
|
||||
if (obj.contains("extensions"))
|
||||
{
|
||||
const boost::json::value& extensions = obj.at("extensions");
|
||||
if (extensions.is_object())
|
||||
{
|
||||
const boost::json::object& ext_obj = extensions.as_object();
|
||||
bool success = false;
|
||||
// copy each extension, return true if any of them succeed, do not short circuit on success
|
||||
U32 count = sizeof...(args);
|
||||
for (U32 i = 0; i < count; i += 2)
|
||||
{
|
||||
if (_copy_extension(ext_obj, args...))
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// internal use aonly, use write_extensions instead
|
||||
template<typename T>
|
||||
inline bool _write_extension(boost::json::object& extensions, const T* src, string_view member)
|
||||
{
|
||||
if (src->mPresent)
|
||||
{
|
||||
Value v;
|
||||
if (write(*src, v))
|
||||
{
|
||||
extensions[member] = v;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write all extensions to dst.extensions
|
||||
// Usage:
|
||||
// write_extensions(dst,
|
||||
// "KHR_materials_unlit", mUnlit,
|
||||
// "KHR_materials_pbrSpecularGlossiness", mPbrSpecularGlossiness);
|
||||
// returns true if any of the extensions are written
|
||||
template<class... Types>
|
||||
inline bool write_extensions(boost::json::object& dst, Types... args)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
boost::json::object extensions;
|
||||
U32 count = sizeof...(args) - 1;
|
||||
|
||||
for (U32 i = 0; i < count; i += 2)
|
||||
{
|
||||
if (_write_extension(extensions, args...))
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
dst["extensions"] = extensions;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// conditionally write a member to an object if the member
|
||||
// is not the default value
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -313,6 +313,10 @@ bool Primitive::prep(Asset& asset)
|
|||
// TODO: support colorless vertex buffers
|
||||
mask |= LLVertexBuffer::MAP_COLOR;
|
||||
|
||||
mShaderVariant = 0;
|
||||
|
||||
bool unlit = false;
|
||||
|
||||
// bake material basecolor into color array
|
||||
if (mMaterial != INVALID_INDEX)
|
||||
{
|
||||
|
|
@ -322,11 +326,15 @@ bool Primitive::prep(Asset& asset)
|
|||
{
|
||||
dst = LLColor4U(baseColor * LLColor4(dst));
|
||||
}
|
||||
|
||||
if (material.mUnlit.mPresent)
|
||||
{ // material uses KHR_materials_unlit
|
||||
mShaderVariant |= LLGLSLShader::GLTFVariant::UNLIT;
|
||||
unlit = true;
|
||||
}
|
||||
}
|
||||
|
||||
mShaderVariant = 0;
|
||||
|
||||
if (mNormals.empty())
|
||||
if (mNormals.empty() && !unlit)
|
||||
{
|
||||
mTangents.clear();
|
||||
|
||||
|
|
@ -334,6 +342,7 @@ bool Primitive::prep(Asset& asset)
|
|||
{ //no normals and no surfaces, this primitive is unlit
|
||||
mTangents.clear();
|
||||
mShaderVariant |= LLGLSLShader::GLTFVariant::UNLIT;
|
||||
unlit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -350,8 +359,6 @@ bool Primitive::prep(Asset& asset)
|
|||
}
|
||||
}
|
||||
|
||||
bool unlit = (mShaderVariant & LLGLSLShader::GLTFVariant::UNLIT) != 0;
|
||||
|
||||
if (mTangents.empty() && !unlit)
|
||||
{ // NOTE: must be done last because tangent generation rewrites the other arrays
|
||||
// adapted from usage of Mikktspace in llvolume.cpp
|
||||
|
|
@ -388,10 +395,13 @@ bool Primitive::prep(Asset& asset)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (!unlit)
|
||||
if (!mNormals.empty())
|
||||
{
|
||||
mask |= LLVertexBuffer::MAP_NORMAL;
|
||||
}
|
||||
|
||||
if (!mTangents.empty())
|
||||
{
|
||||
mask |= LLVertexBuffer::MAP_TANGENT;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue