summaryrefslogtreecommitdiff
path: root/indra/newview/gltf
diff options
context:
space:
mode:
authorRunitaiLinden <davep@lindenlab.com>2024-04-30 21:57:42 -0500
committerRunitaiLinden <davep@lindenlab.com>2024-04-30 21:57:42 -0500
commit170765fd3505410dced83b342f87030fd9151e35 (patch)
treef3665586f2d731a04bf645bc1155bbddc6c5f7e8 /indra/newview/gltf
parent5e2bac01cb6e8d3de3cc0e496d94a729e4740247 (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.cpp18
-rw-r--r--indra/newview/gltf/accessor.h4
-rw-r--r--indra/newview/gltf/asset.cpp102
-rw-r--r--indra/newview/gltf/asset.h11
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);
};
}
}