diff options
author | RunitaiLinden <davep@lindenlab.com> | 2024-04-24 09:51:15 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-24 09:51:15 -0500 |
commit | cadc1a02cc7289dabd368dd1a1d237c042e9f82e (patch) | |
tree | 7493c7a7a8a8b395bc9fc98a1a9dd018098c4147 /indra/newview/gltf/primitive.cpp | |
parent | f1b7e806eb30a343876036eff5caef7c03309aa6 (diff) |
1285 GLTF Animation Prototype
Diffstat (limited to 'indra/newview/gltf/primitive.cpp')
-rw-r--r-- | indra/newview/gltf/primitive.cpp | 488 |
1 files changed, 147 insertions, 341 deletions
diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index b5d59e1b24..b57a0af18d 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -27,163 +27,12 @@ #include "../llviewerprecompiledheaders.h" #include "asset.h" +#include "buffer_util.h" + #include "../lltinygltfhelper.h" using namespace LL::GLTF; -#ifdef _MSC_VER -#define LL_FUNCSIG __FUNCSIG__ -#else -#define LL_FUNCSIG __PRETTY_FUNCTION__ -#endif - -// copy one vec3 from src to dst -template<class S, class T> -void copyVec2(S* src, T& dst) -{ - LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; -} - -// copy one vec3 from src to dst -template<class S, class T> -void copyVec3(S* src, T& dst) -{ - LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; -} - -// copy one vec4 from src to dst -template<class S, class T> -void copyVec4(S* src, T& dst) -{ - LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; -} - -template<> -void copyVec2<F32, LLVector2>(F32* src, LLVector2& dst) -{ - dst.set(src[0], src[1]); -} - -template<> -void copyVec3<F32, LLVector4a>(F32* src, LLVector4a& dst) -{ - dst.load3(src); -} - -template<> -void copyVec3<U16, LLColor4U>(U16* src, LLColor4U& dst) -{ - dst.set(src[0], src[1], src[2], 255); -} - -template<> -void copyVec4<F32, LLVector4a>(F32* src, LLVector4a& dst) -{ - dst.loadua(src); -} - -// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy -template<class S, class T> -void copyVec2(S* src, LLStrider<T> dst, S32 stride, S32 count) -{ - for (S32 i = 0; i < count; ++i) - { - copyVec2(src, *dst); - dst++; - src = (S*)((U8*)src + stride); - } -} - -// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy -template<class S, class T> -void copyVec3(S* src, LLStrider<T> dst, S32 stride, S32 count) -{ - for (S32 i = 0; i < count; ++i) - { - copyVec3(src, *dst); - dst++; - src = (S*)((U8*)src + stride); - } -} - -// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy -template<class S, class T> -void copyVec4(S* src, LLStrider<T> dst, S32 stride, S32 count) -{ - for (S32 i = 0; i < count; ++i) - { - copyVec3(src, *dst); - dst++; - src = (S*)((U8*)src + stride); - } -} - -template<class S, class T> -void copyAttributeArray(Asset& asset, const Accessor& accessor, const S* src, LLStrider<T>& dst, S32 byteStride) -{ - if (accessor.mType == TINYGLTF_TYPE_VEC2) - { - S32 stride = byteStride == 0 ? sizeof(S) * 2 : byteStride; - copyVec2((S*)src, dst, stride, accessor.mCount); - } - else if (accessor.mType == TINYGLTF_TYPE_VEC3) - { - S32 stride = byteStride == 0 ? sizeof(S) * 3 : byteStride; - copyVec3((S*)src, dst, stride, accessor.mCount); - } - else if (accessor.mType == TINYGLTF_TYPE_VEC4) - { - S32 stride = byteStride == 0 ? sizeof(S) * 4 : byteStride; - copyVec4((S*)src, dst, stride, accessor.mCount); - } - else - { - LL_ERRS("GLTF") << "Unsupported accessor type" << LL_ENDL; - } -} - -template <class T> -void Primitive::copyAttribute(Asset& asset, S32 accessorIdx, LLStrider<T>& dst) -{ - const Accessor& accessor = asset.mAccessors[accessorIdx]; - const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView]; - const Buffer& buffer = asset.mBuffers[bufferView.mBuffer]; - const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset; - - if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_FLOAT) - { - copyAttributeArray(asset, accessor, (const F32*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) - { - copyAttributeArray(asset, accessor, (const U16*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) - { - copyAttributeArray(asset, accessor, (const U32*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) - { - copyAttributeArray(asset, accessor, (const U8*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_SHORT) - { - copyAttributeArray(asset, accessor, (const S16*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_BYTE) - { - copyAttributeArray(asset, accessor, (const S8*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_DOUBLE) - { - copyAttributeArray(asset, accessor, (const F64*)src, dst, bufferView.mByteStride); - } - else - { - LL_ERRS("GLTF") << "Unsupported component type" << LL_ENDL; - } -} - void Primitive::allocateGLResources(Asset& asset) { // allocate vertex buffer @@ -192,219 +41,138 @@ void Primitive::allocateGLResources(Asset& asset) // For our engine, though, it's better to rearrange the buffers at load time into a layout that's more consistent. // The GLTF native approach undoubtedly works well if you can count on VAOs, but VAOs perform much worse with our scenes. - // get the number of vertices - U32 numVertices = 0; - if (!mAttributes.empty()) - { - auto it = mAttributes.begin(); - const Accessor& accessor = asset.mAccessors[it->second]; - numVertices = accessor.mCount; - } - - // get the number of indices - U32 numIndices = 0; - if (mIndices != INVALID_INDEX) - { - const Accessor& accessor = asset.mAccessors[mIndices]; - numIndices = accessor.mCount; - } - - // create vertex buffer - mVertexBuffer = new LLVertexBuffer(ATTRIBUTE_MASK); - mVertexBuffer->allocateBuffer(numVertices, numIndices); - - bool needs_color = true; - bool needs_texcoord = true; - bool needs_normal = true; - bool needs_tangent = true; - // load vertex data for (auto& it : mAttributes) { const std::string& attribName = it.first; + Accessor& accessor = asset.mAccessors[it.second]; // load vertex data if (attribName == "POSITION") { - // load position data - LLStrider<LLVector4a> dst; - mVertexBuffer->getVertexStrider(dst); - - copyAttribute(asset, it.second, dst); + copy(asset, accessor, mPositions); } else if (attribName == "NORMAL") { - needs_normal = false; - // load normal data - LLStrider<LLVector4a> dst; - mVertexBuffer->getNormalStrider(dst); - - copyAttribute(asset, it.second, dst); + copy(asset, accessor, mNormals); } else if (attribName == "TANGENT") { - needs_tangent = false; - // load tangent data - - LLStrider<LLVector4a> dst; - mVertexBuffer->getTangentStrider(dst); - - copyAttribute(asset, it.second, dst); + copy(asset, accessor, mTangents); } else if (attribName == "COLOR_0") { - needs_color = false; - // load color data - - LLStrider<LLColor4U> dst; - mVertexBuffer->getColorStrider(dst); - - copyAttribute(asset, it.second, dst); + copy(asset, accessor, mColors); } else if (attribName == "TEXCOORD_0") { - needs_texcoord = false; - // load texcoord data - LLStrider<LLVector2> dst; - mVertexBuffer->getTexCoord0Strider(dst); - - LLStrider<LLVector2> tc = dst; - copyAttribute(asset, it.second, dst); - - // convert to OpenGL coordinate space - for (U32 i = 0; i < numVertices; ++i) - { - tc->mV[1] = 1.0f - tc->mV[1];; - tc++; - } + copy(asset, accessor, mTexCoords); + } + else if (attribName == "JOINTS_0") + { + copy(asset, accessor, mJoints); + } + else if (attribName == "WEIGHTS_0") + { + copy(asset, accessor, mWeights); } } // copy index buffer if (mIndices != INVALID_INDEX) { - const Accessor& accessor = asset.mAccessors[mIndices]; - const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView]; - const Buffer& buffer = asset.mBuffers[bufferView.mBuffer]; + Accessor& accessor = asset.mAccessors[mIndices]; + copy(asset, accessor, mIndexArray); + } - const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset; + U32 mask = ATTRIBUTE_MASK; + + if (!mWeights.empty()) + { + mask |= LLVertexBuffer::MAP_WEIGHT4; + } - LLStrider<U16> dst; - mVertexBuffer->getIndexStrider(dst); - mIndexArray.resize(numIndices); + mVertexBuffer = new LLVertexBuffer(mask); + mVertexBuffer->allocateBuffer(mPositions.size(), mIndexArray.size()*2); // double the size of the index buffer for 32-bit indices - if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) - { - for (U32 i = 0; i < numIndices; ++i) - { - *(dst++) = (U16) * (U32*)src; - src += sizeof(U32); - } - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) - { - for (U32 i = 0; i < numIndices; ++i) - { - *(dst++) = *(U16*)src; - src += sizeof(U16); - } - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) - { - for (U32 i = 0; i < numIndices; ++i) - { - *(dst++) = *(U8*)src; - src += sizeof(U8); - } - } - else - { - LL_ERRS("GLTF") << "Unsupported component type for indices" << LL_ENDL; - } + mVertexBuffer->setBuffer(); + mVertexBuffer->setPositionData(mPositions.data()); - U16* idx = (U16*)mVertexBuffer->getMappedIndices(); - for (U32 i = 0; i < numIndices; ++i) - { - mIndexArray[i] = idx[i]; - } + if (!mIndexArray.empty()) + { + mVertexBuffer->setIndexData(mIndexArray.data()); } - // fill in default values for missing attributes - if (needs_color) - { // set default color - LLStrider<LLColor4U> dst; - mVertexBuffer->getColorStrider(dst); - for (U32 i = 0; i < numVertices; ++i) - { - *(dst++) = LLColor4U(255, 255, 255, 255); - } + if (mTexCoords.empty()) + { + mTexCoords.resize(mPositions.size()); + } + + // flip texcoord y, upload, then flip back (keep the off-spec data in vram only) + for (auto& tc : mTexCoords) + { + tc[1] = 1.f - tc[1]; } + mVertexBuffer->setTexCoordData(mTexCoords.data()); + for (auto& tc : mTexCoords) + { + tc[1] = 1.f - tc[1]; + } + + if (mColors.empty()) + { + mColors.resize(mPositions.size(), LLColor4U::white); + } + // bake material basecolor into color array if (mMaterial != INVALID_INDEX) { const Material& material = asset.mMaterials[mMaterial]; LLColor4 baseColor = material.mMaterial->mBaseColor; - LLStrider<LLColor4U> dst; - mVertexBuffer->getColorStrider(dst); - - for (U32 i = 0; i < numVertices; ++i) + for (auto& dst : mColors) { - LLColor4 col = *dst; - *dst = LLColor4U(baseColor * col); - dst++; + dst = LLColor4U(baseColor * LLColor4(dst)); } } - if (needs_texcoord) - { // set default texcoord - LLStrider<LLVector2> dst; - mVertexBuffer->getTexCoord0Strider(dst); - for (U32 i = 0; i < numVertices; ++i) - { - *(dst++) = LLVector2(0.0f, 0.0f); - } - } + mVertexBuffer->setColorData(mColors.data()); - if (needs_normal) - { // set default normal - LLStrider<LLVector4a> dst; - mVertexBuffer->getNormalStrider(dst); - for (U32 i = 0; i < numVertices; ++i) - { - *(dst++) = LLVector4a(0.0f, 0.0f, 1.0f, 0.0f); - } + if (mNormals.empty()) + { + mNormals.resize(mPositions.size(), LLVector4a(0, 0, 1, 0)); } + + mVertexBuffer->setNormalData(mNormals.data()); - if (needs_tangent) - { // TODO: generate tangents if needed - LLStrider<LLVector4a> dst; - mVertexBuffer->getTangentStrider(dst); - for (U32 i = 0; i < numVertices; ++i) - { - *(dst++) = LLVector4a(1.0f, 0.0f, 0.0f, 1.0f); - } + if (mTangents.empty()) + { + // TODO: generate tangents if needed + mTangents.resize(mPositions.size(), LLVector4a(1, 0, 0, 1)); } - mPositions.resize(numVertices); - mTexCoords.resize(numVertices); - mNormals.resize(numVertices); - mTangents.resize(numVertices); + mVertexBuffer->setTangentData(mTangents.data()); - LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); - LLVector2* tc = (LLVector2*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TEXCOORD0)); - LLVector4a* norm = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_NORMAL)); - LLVector4a* tangent = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TANGENT)); - for (U32 i = 0; i < numVertices; ++i) + if (!mWeights.empty()) { - mPositions[i] = pos[i]; - mTexCoords[i] = tc[i]; - mNormals[i] = norm[i]; - mTangents[i] = tangent[i]; + std::vector<LLVector4a> weight_data; + weight_data.resize(mWeights.size()); + + F32 max_weight = 1.f - FLT_EPSILON*100.f; + LLVector4a maxw(max_weight, max_weight, max_weight, max_weight); + for (U32 i = 0; i < mWeights.size(); ++i) + { + LLVector4a& w = weight_data[i]; + w.setMin(mWeights[i], maxw); + w.add(mJoints[i]); + }; + + mVertexBuffer->setWeight4Data(weight_data.data()); } + createOctree(); - mVertexBuffer->unmapBuffer(); + mVertexBuffer->unbind(); } void initOctreeTriangle(LLVolumeTriangle* tri, F32 scaler, S32 i0, S32 i1, S32 i2, const LLVector4a& v0, const LLVector4a& v1, const LLVector4a& v2) @@ -456,20 +224,17 @@ void Primitive::createOctree() // Initialize all the triangles we need mOctreeTriangles.resize(num_triangles); - LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); - U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) { //for each triangle const U32 index = triangle_index * 3; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - S32 i0 = indices[index]; - S32 i1 = indices[index + 1]; - S32 i2 = indices[index + 2]; + S32 i0 = mIndexArray[index]; + S32 i1 = mIndexArray[index + 1]; + S32 i2 = mIndexArray[index + 2]; - const LLVector4a& v0 = pos[i0]; - const LLVector4a& v1 = pos[i1]; - const LLVector4a& v2 = pos[i2]; + const LLVector4a& v0 = mPositions[i0]; + const LLVector4a& v1 = mPositions[i1]; + const LLVector4a& v2 = mPositions[i2]; initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); @@ -483,20 +248,17 @@ void Primitive::createOctree() // Initialize all the triangles we need mOctreeTriangles.resize(num_triangles); - LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); - U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) { //for each triangle const U32 index = triangle_index + 2; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - S32 i0 = indices[index]; - S32 i1 = indices[index - 1]; - S32 i2 = indices[index - 2]; + S32 i0 = mIndexArray[index]; + S32 i1 = mIndexArray[index - 1]; + S32 i2 = mIndexArray[index - 2]; - const LLVector4a& v0 = pos[i0]; - const LLVector4a& v1 = pos[i1]; - const LLVector4a& v2 = pos[i2]; + const LLVector4a& v0 = mPositions[i0]; + const LLVector4a& v1 = mPositions[i1]; + const LLVector4a& v2 = mPositions[i2]; initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); @@ -510,20 +272,17 @@ void Primitive::createOctree() // Initialize all the triangles we need mOctreeTriangles.resize(num_triangles); - LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); - U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) { //for each triangle const U32 index = triangle_index + 2; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - S32 i0 = indices[0]; - S32 i1 = indices[index - 1]; - S32 i2 = indices[index - 2]; + S32 i0 = mIndexArray[0]; + S32 i1 = mIndexArray[index - 1]; + S32 i2 = mIndexArray[index - 2]; - const LLVector4a& v0 = pos[i0]; - const LLVector4a& v1 = pos[i1]; - const LLVector4a& v2 = pos[i2]; + const LLVector4a& v0 = mPositions[i0]; + const LLVector4a& v1 = mPositions[i1]; + const LLVector4a& v2 = mPositions[i2]; initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); @@ -571,7 +330,7 @@ const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start, face.mTexCoords = mTexCoords.data(); face.mNormals = mNormals.data(); face.mTangents = mTangents.data(); - face.mIndices = mIndexArray.data(); + face.mIndices = nullptr; // unreferenced face.mNumIndices = mIndexArray.size(); face.mNumVertices = mPositions.size(); @@ -592,3 +351,50 @@ Primitive::~Primitive() mOctree = nullptr; } + +const Primitive& Primitive::operator=(const tinygltf::Primitive& src) +{ + // load material + mMaterial = src.material; + + // load mode + mMode = src.mode; + + // load indices + mIndices = src.indices; + + // load attributes + for (auto& it : src.attributes) + { + mAttributes[it.first] = it.second; + } + + switch (mMode) + { + case TINYGLTF_MODE_POINTS: + mGLMode = LLRender::POINTS; + break; + case TINYGLTF_MODE_LINE: + mGLMode = LLRender::LINES; + break; + case TINYGLTF_MODE_LINE_LOOP: + mGLMode = LLRender::LINE_LOOP; + break; + case TINYGLTF_MODE_LINE_STRIP: + mGLMode = LLRender::LINE_STRIP; + break; + case TINYGLTF_MODE_TRIANGLES: + mGLMode = LLRender::TRIANGLES; + break; + case TINYGLTF_MODE_TRIANGLE_STRIP: + mGLMode = LLRender::TRIANGLE_STRIP; + break; + case TINYGLTF_MODE_TRIANGLE_FAN: + mGLMode = LLRender::TRIANGLE_FAN; + break; + default: + mGLMode = GL_TRIANGLES; + } + + return *this; +} |