/** * @file llgltfasset.h * @brief LL GLTF Implementation * * $LicenseInfo:firstyear=2024&license=viewergpl$ * * Copyright (c) 2024, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ #ifndef LL_LLGLTFASSET_H #define LL_LLGLTFASSET_H // *TODO: get rid of this (again) ! HB #include "glh_linear.h" #include "llgltfaccessor.h" #include "llgltfanimation.h" #include "llgltfmaterial.h" #include "llgltfprimitive.h" // Saves from including "tinygltf/tiny_gltf.h" here. HB namespace tinygltf { class Model; class Node; struct Image; struct Material; struct Mesh; struct Sampler; struct Scene; struct Skin; struct Texture; } namespace LLGLTF { class Asset; class Material { public: const Material& operator=(const tinygltf::Material& src); void allocateGLResources(Asset& asset); public: // Use LLFetchedGLTFMaterial for now, but eventually we will want to // use a more flexible GLTF material implementation instead of the // fixed packing version we use for sharable GLTF material assets. // Note: to avoid importing newview structures and keep this module // inside a separate llgltf library, I use a LLGLTFMaterial pointer // (i.e. a pointer of the parent class type) one, and instead of // calling two methods specific to LLFetchedGLTFMaterial (new() and // bind()), I use two exported wrapper functions implemented in // llfetchedgltfmaterial.cpp. HB LLPointer mMaterial; std::string mName; }; // Note 16-byte aligned because we use a vector of Primitive. HB class alignas(16) Mesh { public: LL_ALIGNED16_NEW_DELETE const Mesh& operator=(const tinygltf::Mesh& src); bool allocateGLResources(Asset& asset); public: // Aligned member first... std::vector mPrimitives; // ... then the rest. std::vector mWeights; std::string mName; }; // Note 16-byte aligned because we use LLMatrix4a member variables. HB class alignas(16) Node { public: LL_ALIGNED16_NEW_DELETE Node(); const Node& operator=(const tinygltf::Node& src); // Sets mRenderMatrix to a transform that can be used for the current // render pass. 'modelview' is the parent's render matrix. void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview); // Updates mAssetMatrix and mAssetMatrixInv void updateTransforms(Asset& asset, const LLMatrix4a& parent_matrix); // Ensures mMatrix is valid; if mMatrixValid is false and mTRSValid is // true, will update mMatrix to match Translation/Rotation/Scale void makeMatrixValid(); // Ensures Translation/Rotation/Scale are valid; if mTRSValid is false // and mMatrixValid is true, will update Translation/Rotation/Scale to // match mMatrix. void makeTRSValid(); // Sets rotation of this node // SIDE EFFECT: invalidates mMatrix void setRotation(const glh::quaternionf& rotation); // Sets translation of this node // SIDE EFFECT: invalidates mMatrix void setTranslation(const glh::vec3f& translation); // Sets scale of this node // SIDE EFFECT: invalidates mMatrix void setScale(const glh::vec3f& scale); public: // Aligned members first... LLMatrix4a mMatrix; // Local transform LLMatrix4a mRenderMatrix; // Transform for rendering LLMatrix4a mAssetMatrix; // Local to asset space transf. LLMatrix4a mAssetMatrixInv; // Asset to local space transf. // ... then the rest. glh::quaternionf mRotation; glh::vec3f mTranslation; glh::vec3f mScale; std::string mName; std::vector mChildren; S32 mParent; S32 mMesh; S32 mSkin; // If true, mMatrix is valid and up to date bool mMatrixValid; // If true, translation/rotation/scale are valid and up to date bool mTRSValid; bool mNeedsApplyMatrix; }; class Skin { public: Skin(); void allocateGLResources(Asset& asset); void uploadMatrixPalette(Asset& asset, Node& node); const Skin& operator=(const tinygltf::Skin& src); public: std::string mName; std::vector mJoints; std::vector mInverseBindMatricesData; S32 mInverseBindMatrices; S32 mSkeleton; }; class Scene { public: const Scene& operator=(const tinygltf::Scene& src); void updateTransforms(Asset& asset); void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview); public: std::string mName; std::vector mNodes; }; class Texture { public: Texture(); const Texture& operator=(const tinygltf::Texture& src); public: std::string mName; S32 mSampler; S32 mSource; }; class Sampler { public: const Sampler& operator=(const tinygltf::Sampler& src); public: std::string mName; S32 mMagFilter; S32 mMinFilter; S32 mWrapS; S32 mWrapT; }; class Image { public: const Image& operator=(const tinygltf::Image& src); LL_INLINE void allocateGLResources() {} public: std::string mName; std::string mUri; std::string mMimeType; std::vector mData; S32 mWidth; S32 mHeight; S32 mComponent; S32 mBits; }; // C++ representation of a GLTF Asset // Note 16-byte aligned because we use a vectors of Node and Mesh. HB class alignas(16) Asset : public LLRefCount { public: LL_ALIGNED16_NEW_DELETE Asset(); // Prepares the asset for rendering. // Returns true on success, or false on failure (at which point this // asset must be destroyed and never used). HB bool allocateGLResources(const std::string& filename, const tinygltf::Model& model); // Called periodically (typically once per frame). Any ongoing work // (such as animations) should be handled here NOT guaranteed to be // called every frame. MAY be called more than once per frame. Upon // return, all Node Matrix transforms should be up to date. void update(); // Updates asset-to-node and node-to-asset transforms void updateTransforms(); // Updates node render transforms void updateRenderTransforms(const LLMatrix4a& modelview); void render(bool opaque, bool rigged = false); void renderOpaque(); void renderTransparent(); // 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 S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersectp = NULL, LLVector2* tcoordp = NULL, LLVector4a* normp = NULL, LLVector4a* tangentp = NULL, S32* prim_hitp = NULL); const Asset& operator=(const tinygltf::Model& src); public: // Aligned members first... std::vector mNodes; std::vector mMeshes; // ... then the rest. std::vector mScenes; std::vector mMaterials; std::vector mBuffers; std::vector mBufferViews; std::vector mTextures; std::vector mSamplers; std::vector mImages; std::vector mAccessors; std::vector mAnimations; std::vector mSkins; // The last time update() was called according to gFrameTimeSeconds F32 mLastUpdateTime; }; } #endif // LL_LLGLTFASSET_H