diff options
Diffstat (limited to 'indra/newview/gltf/asset.h')
-rw-r--r-- | indra/newview/gltf/asset.h | 329 |
1 files changed, 261 insertions, 68 deletions
diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index 5ceac74a8a..27821659db 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -28,13 +28,21 @@ #include "llvertexbuffer.h" #include "llvolumeoctree.h" -#include "../lltinygltfhelper.h" #include "accessor.h" #include "primitive.h" #include "animation.h" +#include "boost/json.hpp" +#include "common.h" +#include "../llviewertexture.h" +#include "llglslshader.h" extern F32SecondsImplicit gFrameTimeSeconds; +// wingdi defines OPAQUE, which conflicts with our enum +#if defined(OPAQUE) +#undef OPAQUE +#endif + // LL GLTF Implementation namespace LL { @@ -42,18 +50,118 @@ namespace LL { class Asset; + class Extension + { + public: + // true if this extension is present in the gltf file + // otherwise false + bool mPresent = false; + }; + + class TextureTransform : public Extension // KHR_texture_transform implementation + { + public: + vec2 mOffset = vec2(0.f, 0.f); + F32 mRotation = 0.f; + vec2 mScale = vec2(1.f, 1.f); + S32 mTexCoord = INVALID_INDEX; + + // get the texture transform as a packed array of vec4's + // dst MUST point to at least 2 vec4's + void getPacked(vec4* dst) const; + + const TextureTransform& operator=(const Value& src); + void serialize(boost::json::object& dst) const; + }; + + class TextureInfo + { + public: + S32 mIndex = INVALID_INDEX; + S32 mTexCoord = 0; + + TextureTransform mTextureTransform; + + bool operator==(const TextureInfo& rhs) const; + bool operator!=(const TextureInfo& rhs) const; + + // get the UV channel that should be used for sampling this texture + // returns mTextureTransform.mTexCoord if present and valid, otherwise mTexCoord + S32 getTexCoord() const; + + const TextureInfo& operator=(const Value& src); + void serialize(boost::json::object& dst) const; + }; + + class NormalTextureInfo : public TextureInfo + { + public: + F32 mScale = 1.0f; + + const NormalTextureInfo& operator=(const Value& src); + void serialize(boost::json::object& dst) const; + }; + + class OcclusionTextureInfo : public TextureInfo + { + public: + F32 mStrength = 1.0f; + + const OcclusionTextureInfo& operator=(const Value& src); + void serialize(boost::json::object& dst) const; + }; + class Material { public: - // use LLFetchedGLTFMaterial for now, but eventually we'll want to use - // a more flexible GLTF material implementation instead of the fixed packing - // version we use for sharable GLTF material assets - LLPointer<LLFetchedGLTFMaterial> mMaterial; + + 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, + MASK, + BLEND + }; + + + class PbrMetallicRoughness + { + public: + vec4 mBaseColorFactor = vec4(1.f,1.f,1.f,1.f); + TextureInfo mBaseColorTexture; + F32 mMetallicFactor = 1.0f; + F32 mRoughnessFactor = 1.0f; + TextureInfo mMetallicRoughnessTexture; + + bool operator==(const PbrMetallicRoughness& rhs) const; + bool operator!=(const PbrMetallicRoughness& rhs) const; + const PbrMetallicRoughness& operator=(const Value& src); + void serialize(boost::json::object& dst) const; + }; + + + PbrMetallicRoughness mPbrMetallicRoughness; + NormalTextureInfo mNormalTexture; + OcclusionTextureInfo mOcclusionTexture; + TextureInfo mEmissiveTexture; + std::string mName; + vec3 mEmissiveFactor = vec3(0.f, 0.f, 0.f); + AlphaMode mAlphaMode = AlphaMode::OPAQUE; + F32 mAlphaCutoff = 0.5f; + bool mDoubleSided = false; + Unlit mUnlit; - const Material& operator=(const tinygltf::Material& src); + bool isMultiUV() const; - void allocateGLResources(Asset& asset); + const Material& operator=(const Value& src); + void serialize(boost::json::object& dst) const; }; class Mesh @@ -63,22 +171,22 @@ namespace LL std::vector<double> mWeights; std::string mName; - const Mesh& operator=(const tinygltf::Mesh& src); + const Mesh& operator=(const Value& src); + void serialize(boost::json::object& dst) const; - void allocateGLResources(Asset& asset); + bool prep(Asset& asset); }; class Node { public: - LLMatrix4a mMatrix; //local transform - LLMatrix4a mRenderMatrix; //transform for rendering - LLMatrix4a mAssetMatrix; //transform from local to asset space - LLMatrix4a mAssetMatrixInv; //transform from asset to local space + mat4 mMatrix = glm::identity<mat4>(); //local transform + mat4 mAssetMatrix; //transform from local to asset space + mat4 mAssetMatrixInv; //transform from asset to local space - glh::vec3f mTranslation; - glh::quaternionf mRotation; - glh::vec3f mScale; + vec3 mTranslation = vec3(0,0,0); + quat mRotation = glm::identity<quat>(); + vec3 mScale = vec3(1.f,1.f,1.f); // if true, mMatrix is valid and up to date bool mMatrixValid = false; @@ -96,14 +204,11 @@ namespace LL std::string mName; - const Node& operator=(const tinygltf::Node& src); - - // Set mRenderMatrix to a transform that can be used for the current render pass - // modelview -- parent's render matrix - void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview); + const Node& operator=(const Value& src); + void serialize(boost::json::object& dst) const; // update mAssetMatrix and mAssetMatrixInv - void updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix); + void updateTransforms(Asset& asset, const mat4& parentMatrix); // ensure mMatrix is valid -- if mMatrixValid is false and mTRSValid is true, will update mMatrix to match Translation/Rotation/Scale void makeMatrixValid(); @@ -113,30 +218,35 @@ namespace LL // Set rotation of this node // SIDE EFFECT: invalidates mMatrix - void setRotation(const glh::quaternionf& rotation); + void setRotation(const quat& rotation); // Set translation of this node // SIDE EFFECT: invalidates mMatrix - void setTranslation(const glh::vec3f& translation); + void setTranslation(const vec3& translation); // Set scale of this node // SIDE EFFECT: invalidates mMatrix - void setScale(const glh::vec3f& scale); + void setScale(const vec3& scale); }; class Skin { public: + ~Skin(); + S32 mInverseBindMatrices = INVALID_INDEX; S32 mSkeleton = INVALID_INDEX; + + U32 mUBO = 0; std::vector<S32> mJoints; std::string mName; - std::vector<glh::matrix4f> mInverseBindMatricesData; + std::vector<mat4> mInverseBindMatricesData; - void allocateGLResources(Asset& asset); - void uploadMatrixPalette(Asset& asset, Node& node); + bool prep(Asset& asset); + void uploadMatrixPalette(Asset& asset); - const Skin& operator=(const tinygltf::Skin& src); + const Skin& operator=(const Value& src); + void serialize(boost::json::object& dst) const; }; class Scene @@ -145,10 +255,11 @@ namespace LL std::vector<S32> mNodes; std::string mName; - const Scene& operator=(const tinygltf::Scene& src); + const Scene& operator=(const Value& src); + void serialize(boost::json::object& dst) const; void updateTransforms(Asset& asset); - void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview); + void updateRenderTransforms(Asset& asset, const mat4& modelview); }; class Texture @@ -158,19 +269,21 @@ namespace LL S32 mSource = INVALID_INDEX; std::string mName; - const Texture& operator=(const tinygltf::Texture& src); + const Texture& operator=(const Value& src); + void serialize(boost::json::object& dst) const; }; class Sampler { public: - S32 mMagFilter; - S32 mMinFilter; - S32 mWrapS; - S32 mWrapT; + S32 mMagFilter = LINEAR; + S32 mMinFilter = LINEAR_MIPMAP_LINEAR; + S32 mWrapS = REPEAT; + S32 mWrapT = REPEAT; std::string mName; - const Sampler& operator=(const tinygltf::Sampler& src); + const Sampler& operator=(const Value& src); + void serialize(boost::json::object& dst) const; }; class Image @@ -179,38 +292,64 @@ namespace LL std::string mName; std::string mUri; std::string mMimeType; - std::vector<U8> mData; - S32 mWidth; - S32 mHeight; - S32 mComponent; - S32 mBits; + + S32 mBufferView = INVALID_INDEX; + + S32 mWidth = -1; + S32 mHeight = -1; + S32 mComponent = -1; + S32 mBits = -1; + S32 mPixelType = -1; + LLPointer<LLViewerFetchedTexture> mTexture; - const Image& operator=(const tinygltf::Image& src) - { - mName = src.name; - mUri = src.uri; - mMimeType = src.mimeType; - mData = src.image; - mWidth = src.width; - mHeight = src.height; - mComponent = src.component; - mBits = src.bits; - - return *this; - } - - void allocateGLResources() + const Image& operator=(const Value& src); + void serialize(boost::json::object& dst) const; + + // save image to disk + // may remove image data from bufferviews and convert to + // file uri if necessary + bool save(Asset& asset, const std::string& filename); + + // erase the buffer view associated with this image + // free any associated GLTF resources + // preserve only uri and name + void clearData(Asset& asset); + + bool prep(Asset& asset); + }; + + // Render Batch -- vertex buffer and list of primitives to render using + // said vertex buffer + class RenderBatch + { + public: + struct PrimitiveData { - // allocate texture + S32 mPrimitiveIndex = INVALID_INDEX; + S32 mNodeIndex = INVALID_INDEX; + }; + + LLPointer<LLVertexBuffer> mVertexBuffer; + std::vector<PrimitiveData> mPrimitives; + }; - } + class RenderData + { + public: + // list of render batches + // indexed by [material index + 1](0 is reserved for default material) + // there should be exactly one render batch per material per variant + std::vector<RenderBatch> mBatches[LLGLSLShader::NUM_GLTF_VARIANTS]; }; + // C++ representation of a GLTF Asset - class Asset : public LLRefCount + class Asset { public: + + static const std::string minVersion_default; std::vector<Scene> mScenes; std::vector<Node> mNodes; std::vector<Mesh> mMeshes; @@ -223,12 +362,38 @@ 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; + std::string mMinVersion; + std::string mCopyright; + + S32 mScene = INVALID_INDEX; + Value mExtras; + + U32 mPendingBuffers = 0; + + // local file this asset was loaded from (if any) + std::string mFilename; // the last time update() was called according to gFrameTimeSeconds F32 mLastUpdateTime = gFrameTimeSeconds; - // prepare the asset for rendering - void allocateGLResources(const std::string& filename, const tinygltf::Model& model); + // data used for rendering + // 0 - single sided + // 1 - double sided + RenderData mRenderData[2]; + + // UBO for storing node transforms + U32 mNodesUBO = 0; + + // UBO for storing material data + U32 mMaterialsUBO = 0; + + // prepare for first time use + bool prep(); // Called periodically (typically once per frame) // Any ongoing work (such as animations) should be handled here @@ -240,12 +405,11 @@ namespace LL // update asset-to-node and node-to-asset transforms void updateTransforms(); - // update node render transforms - void updateRenderTransforms(const LLMatrix4a& modelview); + // upload matrices to UBO + void uploadTransforms(); - void render(bool opaque, bool rigged = false); - void renderOpaque(); - void renderTransparent(); + // upload materils to UBO + void uploadMaterials(); // return the index of the node that the line segment intersects with, or -1 if no hit // input and output values must be in this asset's local coordinate frame @@ -257,8 +421,37 @@ namespace LL S32* primitive_hitp = nullptr // return the index of the primitive that was hit ); - const Asset& operator=(const tinygltf::Model& src); + Asset() = default; + Asset(const Value& src); + + // load from given file + // accepts .gltf and .glb files + // Any existing data will be lost + // returns result of prep() on success + bool load(std::string_view filename); + + // load .glb contents from memory + // data - binary contents of .glb file + // returns result of prep() on success + bool loadBinary(const std::string& data); + const Asset& operator=(const Value& src); + void serialize(boost::json::object& dst) const; + + // save the asset to the given .gltf file + // saves images and bins alongside the gltf file + bool save(const std::string& filename); + + // remove the bufferview at the given index + // updates all bufferview indices in this Asset as needed + void eraseBufferView(S32 bufferView); + + // return true if this Asset has been loaded as a local preview + // Local previews may be uploaded or exported to disk + bool isLocalPreview() { return !mFilename.empty(); } }; + + Material::AlphaMode gltf_alpha_mode_to_enum(const std::string& alpha_mode); + std::string enum_to_gltf_alpha_mode(Material::AlphaMode alpha_mode); } } |