diff options
author | RunitaiLinden <davep@lindenlab.com> | 2024-04-30 21:57:42 -0500 |
---|---|---|
committer | RunitaiLinden <davep@lindenlab.com> | 2024-04-30 21:57:42 -0500 |
commit | 170765fd3505410dced83b342f87030fd9151e35 (patch) | |
tree | f3665586f2d731a04bf645bc1155bbddc6c5f7e8 /indra/newview/gltf | |
parent | 5e2bac01cb6e8d3de3cc0e496d94a729e4740247 (diff) |
#1357 Proof of concept on decomposing a GLTF scene into its component parts
Diffstat (limited to 'indra/newview/gltf')
-rw-r--r-- | indra/newview/gltf/accessor.cpp | 18 | ||||
-rw-r--r-- | indra/newview/gltf/accessor.h | 4 | ||||
-rw-r--r-- | indra/newview/gltf/asset.cpp | 102 | ||||
-rw-r--r-- | indra/newview/gltf/asset.h | 11 |
4 files changed, 134 insertions, 1 deletions
diff --git a/indra/newview/gltf/accessor.cpp b/indra/newview/gltf/accessor.cpp index 55d36b7a32..9bfdc2afa6 100644 --- a/indra/newview/gltf/accessor.cpp +++ b/indra/newview/gltf/accessor.cpp @@ -30,6 +30,24 @@ using namespace LL::GLTF; +void Buffer::erase(Asset& asset, S32 offset, S32 length) +{ + S32 idx = this - &asset.mBuffers[0]; + + mData.erase(mData.begin() + offset, mData.begin() + offset + length); + + for (BufferView& view : asset.mBufferViews) + { + if (view.mBuffer == idx) + { + if (view.mByteOffset >= offset) + { + view.mByteOffset -= length; + } + } + } +} + const Buffer& Buffer::operator=(const tinygltf::Buffer& src) { mData = src.data; diff --git a/indra/newview/gltf/accessor.h b/indra/newview/gltf/accessor.h index 9b8265d8da..6849cd8609 100644 --- a/indra/newview/gltf/accessor.h +++ b/indra/newview/gltf/accessor.h @@ -45,6 +45,10 @@ namespace LL std::string mName; std::string mUri; + // erase the given range from this buffer. + // also updates all buffer views in given asset that reference this buffer + void erase(Asset& asset, S32 offset, S32 length); + const Buffer& operator=(const tinygltf::Buffer& src); }; diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 233faac545..475cbcb6e5 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -30,9 +30,11 @@ #include "llvolumeoctree.h" #include "../llviewershadermgr.h" #include "../llviewercontrol.h" +#include "../llviewertexturelist.h" using namespace LL::GLTF; +#pragma optimize("", off) namespace LL { @@ -821,6 +823,106 @@ void Asset::save(tinygltf::Model& dst) LL::GLTF::copy(*this, dst); } +void Asset::decompose(const std::string& filename) +{ + // get folder path + std::string folder = gDirUtilp->getDirName(filename); + + // decompose images + for (auto& image : mImages) + { + image.decompose(*this, folder); + } +} + +void Asset::eraseBufferView(S32 bufferView) +{ + mBufferViews.erase(mBufferViews.begin() + bufferView); + + for (auto& accessor : mAccessors) + { + if (accessor.mBufferView > bufferView) + { + accessor.mBufferView--; + } + } + + for (auto& image : mImages) + { + if (image.mBufferView > bufferView) + { + image.mBufferView--; + } + } + +} + +void Image::decompose(Asset& asset, const std::string& folder) +{ + std::string name = mName; + if (name.empty()) + { + S32 idx = this - asset.mImages.data(); + name = llformat("image_%d", idx); + } + + if (mBufferView != INVALID_INDEX) + { + // save original image + BufferView& bufferView = asset.mBufferViews[mBufferView]; + Buffer& buffer = asset.mBuffers[bufferView.mBuffer]; + + std::string extension; + + if (mMimeType == "image/jpeg") + { + extension = ".jpg"; + } + else if (mMimeType == "image/png") + { + extension = ".png"; + } + else + { + extension = ".bin"; + } + + std::string filename = folder + "/" + name + "." + extension; + + // set URI to non-j2c file for now, but later we'll want to reference the j2c hash + mUri = name + "." + extension; + + 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 (!mData.empty()) + { + // save j2c image + std::string filename = folder + "/" + name + ".j2c"; + + LLPointer<LLImageRaw> raw = new LLImageRaw(mWidth, mHeight, mComponent); + U8* data = raw->allocateData(); + llassert(mData.size() == raw->getDataSize()); + memcpy(data, mData.data(), mData.size()); + + LLViewerTextureList::createUploadFile(raw, filename, 4096); + + mData.clear(); + } + + mWidth = -1; + mHeight = -1; + mComponent = -1; + mBits = -1; + mPixelType = -1; + mMimeType = ""; + +} const Material::TextureInfo& Material::TextureInfo::operator=(const tinygltf::TextureInfo& src) { diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index b8300c2d8a..cb28c4a572 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -254,6 +254,9 @@ namespace LL return *this; } + // save image clear local data, and set uri + void decompose(Asset& asset, const std::string& filename); + void allocateGLResources() { // allocate texture @@ -322,7 +325,13 @@ namespace LL // save the asset to a tinygltf model void save(tinygltf::Model& dst); - + + // decompose the asset to the given .gltf file + void decompose(const std::string& filename); + + // remove the bufferview at the given index + // updates all bufferview indices in this Asset as needed + void eraseBufferView(S32 bufferView); }; } } |