summaryrefslogtreecommitdiff
path: root/indra/newview/gltf
diff options
context:
space:
mode:
authorRunitaiLinden <davep@lindenlab.com>2024-04-17 16:12:49 -0500
committerGitHub <noreply@github.com>2024-04-17 16:12:49 -0500
commitbc93177ea0788a245554882b6d721eae2e057206 (patch)
tree5b15cf6b55ff8e200e763ae720771f3f91ead8f3 /indra/newview/gltf
parentd46811d60d8fca4a9908b4e989b14905345928bd (diff)
1176 integrate llgltfnode with selection manager and llmaniptranslate/rotate (#1258)
* #1176 Somewhat working GLTF Node support for translate tool * #1176 Missing file from last commit * #1176 Better translation for rotated nodes. * #1176 Fix for objects snapping back to original position * #1176 GLTF Samples compatibility pass -- attempt at improving rotation manip support, incidental cleanup, GLTF node debug display * #1176 Clean out some unused and not working functions. * #1176 Fix for mac build, incidental cleanup * Mac build fix
Diffstat (limited to 'indra/newview/gltf')
-rw-r--r--indra/newview/gltf/asset.cpp128
-rw-r--r--indra/newview/gltf/asset.h68
-rw-r--r--indra/newview/gltf/primitive.cpp180
3 files changed, 286 insertions, 90 deletions
diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp
index 092b6e5d4b..7181c5fa53 100644
--- a/indra/newview/gltf/asset.cpp
+++ b/indra/newview/gltf/asset.cpp
@@ -69,9 +69,12 @@ void Node::updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix)
matMul(mMatrix, parentMatrix, mAssetMatrix);
mAssetMatrixInv = inverse(mAssetMatrix);
+ S32 my_index = this - &asset.mNodes[0];
+
for (auto& childIndex : mChildren)
{
Node& child = asset.mNodes[childIndex];
+ child.mParent = my_index;
child.updateTransforms(asset, mAssetMatrix);
}
}
@@ -208,4 +211,129 @@ S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
return node_hit;
}
+const Node& Node::operator=(const tinygltf::Node& src)
+{
+ F32* dstMatrix = mMatrix.getF32ptr();
+
+ if (src.matrix.size() == 16)
+ {
+ // Node has a transformation matrix, just copy it
+ for (U32 i = 0; i < 16; ++i)
+ {
+ dstMatrix[i] = (F32)src.matrix[i];
+ }
+ }
+ else if (!src.rotation.empty() || !src.translation.empty() || !src.scale.empty())
+ {
+ // node has rotation/translation/scale, convert to matrix
+ glh::quaternionf rotation;
+ if (src.rotation.size() == 4)
+ {
+ rotation = glh::quaternionf((F32)src.rotation[0], (F32)src.rotation[1], (F32)src.rotation[2], (F32)src.rotation[3]);
+ }
+
+ glh::vec3f translation;
+ if (src.translation.size() == 3)
+ {
+ translation = glh::vec3f((F32)src.translation[0], (F32)src.translation[1], (F32)src.translation[2]);
+ }
+
+ glh::vec3f scale;
+ if (src.scale.size() == 3)
+ {
+ scale = glh::vec3f((F32)src.scale[0], (F32)src.scale[1], (F32)src.scale[2]);
+ }
+ else
+ {
+ scale.set_value(1.f, 1.f, 1.f);
+ }
+
+ glh::matrix4f rot;
+ rotation.get_value(rot);
+
+ glh::matrix4f trans;
+ trans.set_translate(translation);
+
+ glh::matrix4f sc;
+ sc.set_scale(scale);
+
+ glh::matrix4f t;
+ //t = sc * rot * trans;
+ //t = trans * rot * sc; // best so far, still wrong on negative scale
+ //t = sc * trans * rot;
+ t = trans * sc * rot;
+
+ mMatrix.loadu(t.m);
+ }
+ else
+ {
+ // node specifies no transformation, set to identity
+ mMatrix.setIdentity();
+ }
+
+ mChildren = src.children;
+ mMesh = src.mesh;
+ mName = src.name;
+
+ return *this;
+}
+
+void Asset::render(bool opaque)
+{
+ for (auto& node : mNodes)
+ {
+ if (node.mMesh != INVALID_INDEX)
+ {
+ Mesh& mesh = mMeshes[node.mMesh];
+ for (auto& primitive : mesh.mPrimitives)
+ {
+ gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix);
+ bool cull = true;
+ if (primitive.mMaterial != INVALID_INDEX)
+ {
+ Material& material = mMaterials[primitive.mMaterial];
+
+ if ((material.mMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND) == opaque)
+ {
+ continue;
+ }
+ material.mMaterial->bind();
+ cull = !material.mMaterial->mDoubleSided;
+ }
+ else
+ {
+ if (!opaque)
+ {
+ continue;
+ }
+ LLFetchedGLTFMaterial::sDefault.bind();
+ }
+
+ LLGLDisable cull_face(!cull ? GL_CULL_FACE : 0);
+
+ primitive.mVertexBuffer->setBuffer();
+ if (primitive.mVertexBuffer->getNumIndices() > 0)
+ {
+ primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0);
+ }
+ else
+ {
+ primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts());
+ }
+
+ }
+ }
+ }
+}
+
+void Asset::renderOpaque()
+{
+ render(true);
+}
+
+void Asset::renderTransparent()
+{
+ render(false);
+}
+
diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h
index 0f1d4e8993..acf9ba77df 100644
--- a/indra/newview/gltf/asset.h
+++ b/indra/newview/gltf/asset.h
@@ -171,31 +171,12 @@ namespace LL
LLMatrix4a mAssetMatrixInv; //transform from asset to local space
std::vector<S32> mChildren;
+ S32 mParent = INVALID_INDEX;
+
S32 mMesh = INVALID_INDEX;
std::string mName;
- const Node& operator=(const tinygltf::Node& src)
- {
- F32* dstMatrix = mMatrix.getF32ptr();
-
- if (src.matrix.size() != 16)
- {
- mMatrix.setIdentity();
- }
- else
- {
- for (U32 i = 0; i < 16; ++i)
- {
- dstMatrix[i] = (F32)src.matrix[i];
- }
- }
-
- mChildren = src.children;
- mMesh = src.mesh;
- mName = src.name;
-
- return *this;
- }
+ 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
@@ -314,21 +295,23 @@ namespace LL
void allocateGLResources(const std::string& filename, const tinygltf::Model& model)
{
- for (auto& mesh : mMeshes)
- {
- mesh.allocateGLResources(*this);
- }
-
+ // do images first as materials may depend on images
for (auto& image : mImages)
{
image.allocateGLResources();
}
+ // do materials before meshes as meshes may depend on materials
for (U32 i = 0; i < mMaterials.size(); ++i)
{
mMaterials[i].allocateGLResources(*this);
LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true);
}
+
+ for (auto& mesh : mMeshes)
+ {
+ mesh.allocateGLResources(*this);
+ }
}
// update asset-to-node and node-to-asset transforms
@@ -337,34 +320,9 @@ namespace LL
// update node render transforms
void updateRenderTransforms(const LLMatrix4a& modelview);
- void renderOpaque()
- {
- for (auto& node : mNodes)
- {
- if (node.mMesh != INVALID_INDEX)
- {
- Mesh& mesh = mMeshes[node.mMesh];
- for (auto& primitive : mesh.mPrimitives)
- {
- gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix);
- if (primitive.mMaterial != INVALID_INDEX)
- {
- Material& material = mMaterials[primitive.mMaterial];
- material.mMaterial->bind();
- }
- primitive.mVertexBuffer->setBuffer();
- if (primitive.mVertexBuffer->getNumIndices() > 0)
- {
- primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0);
- }
- else
- {
- primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts());
- }
- }
- }
- }
- }
+ void render(bool opaque);
+ 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
diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp
index 71654dcfdd..b5d59e1b24 100644
--- a/indra/newview/gltf/primitive.cpp
+++ b/indra/newview/gltf/primitive.cpp
@@ -162,10 +162,25 @@ void Primitive::copyAttribute(Asset& asset, S32 accessorIdx, LLStrider<T>& dst)
{
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() << "Unsupported component type" << LL_ENDL;
+ LL_ERRS("GLTF") << "Unsupported component type" << LL_ENDL;
}
}
@@ -179,11 +194,11 @@ void Primitive::allocateGLResources(Asset& asset)
// get the number of vertices
U32 numVertices = 0;
- for (auto& it : mAttributes)
+ if (!mAttributes.empty())
{
- const Accessor& accessor = asset.mAccessors[it.second];
+ auto it = mAttributes.begin();
+ const Accessor& accessor = asset.mAccessors[it->second];
numVertices = accessor.mCount;
- break;
}
// get the number of indices
@@ -294,6 +309,14 @@ void Primitive::allocateGLResources(Asset& asset)
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;
@@ -317,6 +340,22 @@ void Primitive::allocateGLResources(Asset& asset)
}
}
+ // 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)
+ {
+ LLColor4 col = *dst;
+ *dst = LLColor4U(baseColor * col);
+ dst++;
+ }
+ }
+
if (needs_texcoord)
{ // set default texcoord
LLStrider<LLVector2> dst;
@@ -368,15 +407,51 @@ void Primitive::allocateGLResources(Asset& asset)
mVertexBuffer->unmapBuffer();
}
+void initOctreeTriangle(LLVolumeTriangle* tri, F32 scaler, S32 i0, S32 i1, S32 i2, const LLVector4a& v0, const LLVector4a& v1, const LLVector4a& v2)
+{
+ //store pointers to vertex data
+ tri->mV[0] = &v0;
+ tri->mV[1] = &v1;
+ tri->mV[2] = &v2;
+
+ //store indices
+ tri->mIndex[0] = i0;
+ tri->mIndex[1] = i1;
+ tri->mIndex[2] = i2;
+
+ //get minimum point
+ LLVector4a min = v0;
+ min.setMin(min, v1);
+ min.setMin(min, v2);
+
+ //get maximum point
+ LLVector4a max = v0;
+ max.setMax(max, v1);
+ max.setMax(max, v2);
+
+ //compute center
+ LLVector4a center;
+ center.setAdd(min, max);
+ center.mul(0.5f);
+
+ tri->mPositionGroup = center;
+
+ //compute "radius"
+ LLVector4a size;
+ size.setSub(max, min);
+
+ tri->mRadius = size.getLength3().getF32() * scaler;
+}
+
void Primitive::createOctree()
{
// create octree
mOctree = new LLVolumeOctree();
+ F32 scaler = 0.25f;
+
if (mMode == TINYGLTF_MODE_TRIANGLES)
{
- F32 scaler = 0.25f;
-
const U32 num_triangles = mVertexBuffer->getNumIndices() / 3;
// Initialize all the triangles we need
mOctreeTriangles.resize(num_triangles);
@@ -388,47 +463,82 @@ void Primitive::createOctree()
{ //for each triangle
const U32 index = triangle_index * 3;
LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index];
- const LLVector4a& v0 = pos[indices[index]];
- const LLVector4a& v1 = pos[indices[index + 1]];
- const LLVector4a& v2 = pos[indices[index + 2]];
+ S32 i0 = indices[index];
+ S32 i1 = indices[index + 1];
+ S32 i2 = indices[index + 2];
+
+ const LLVector4a& v0 = pos[i0];
+ const LLVector4a& v1 = pos[i1];
+ const LLVector4a& v2 = pos[i2];
+
+ initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2);
+
+ //insert
+ mOctree->insert(tri);
+ }
+ }
+ else if (mMode == TINYGLTF_MODE_TRIANGLE_STRIP)
+ {
+ const U32 num_triangles = mVertexBuffer->getNumIndices() - 2;
+ // Initialize all the triangles we need
+ mOctreeTriangles.resize(num_triangles);
- //store pointers to vertex data
- tri->mV[0] = &v0;
- tri->mV[1] = &v1;
- tri->mV[2] = &v2;
+ LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX));
+ U16* indices = (U16*)mVertexBuffer->getMappedIndices();
- //store indices
- tri->mIndex[0] = indices[index];
- tri->mIndex[1] = indices[index + 1];
- tri->mIndex[2] = indices[index + 2];
+ 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];
+
+ const LLVector4a& v0 = pos[i0];
+ const LLVector4a& v1 = pos[i1];
+ const LLVector4a& v2 = pos[i2];
- //get minimum point
- LLVector4a min = v0;
- min.setMin(min, v1);
- min.setMin(min, v2);
+ initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2);
- //get maximum point
- LLVector4a max = v0;
- max.setMax(max, v1);
- max.setMax(max, v2);
+ //insert
+ mOctree->insert(tri);
+ }
+ }
+ else if (mMode == TINYGLTF_MODE_TRIANGLE_FAN)
+ {
+ const U32 num_triangles = mVertexBuffer->getNumIndices() - 2;
+ // Initialize all the triangles we need
+ mOctreeTriangles.resize(num_triangles);
- //compute center
- LLVector4a center;
- center.setAdd(min, max);
- center.mul(0.5f);
+ LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX));
+ U16* indices = (U16*)mVertexBuffer->getMappedIndices();
- tri->mPositionGroup = center;
+ 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];
- //compute "radius"
- LLVector4a size;
- size.setSub(max, min);
+ const LLVector4a& v0 = pos[i0];
+ const LLVector4a& v1 = pos[i1];
+ const LLVector4a& v2 = pos[i2];
- tri->mRadius = size.getLength3().getF32() * scaler;
+ initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2);
//insert
mOctree->insert(tri);
}
}
+ else if (mMode == TINYGLTF_MODE_POINTS ||
+ mMode == TINYGLTF_MODE_LINE ||
+ mMode == TINYGLTF_MODE_LINE_LOOP ||
+ mMode == TINYGLTF_MODE_LINE_STRIP)
+ {
+ // nothing to do, no volume... maybe add some collision geometry around these primitive types?
+ }
+
else
{
LL_ERRS() << "Unsupported Primitive mode" << LL_ENDL;