summaryrefslogtreecommitdiff
path: root/indra/llprimitive
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2022-09-12 19:48:33 -0500
committerDave Parks <davep@lindenlab.com>2022-09-12 19:48:33 -0500
commite49d602bd99f5a3b1257ba1bc7ded133eab1eb1c (patch)
tree403cf561e8a8d3524de9eb27943310383e94250e /indra/llprimitive
parentc5af5d10edb26d255d0aa2e27eedbbd3f514024e (diff)
SL-18095 Add tangents to mesh assets so we can calculate mikktspace tangents in the mesh's original coordinate frame.
Diffstat (limited to 'indra/llprimitive')
-rw-r--r--indra/llprimitive/lldaeloader.cpp12
-rw-r--r--indra/llprimitive/llmodel.cpp41
-rw-r--r--indra/llprimitive/llmodel.h1
3 files changed, 50 insertions, 4 deletions
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 50f4a4306e..9470146ce4 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -2551,6 +2551,9 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
LLVolume::face_list_t remainder;
do
{
+ // generate tangents and cache optimize before normalizing
+ ret->preprocessVolumeFaces();
+
// Insure we do this once with the whole gang and not per-model
//
if (!normalized && !mNoNormalize)
@@ -2561,10 +2564,11 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder);
- if (!mNoOptimize)
- {
- ret->remapVolumeFaces();
- }
+ // remove unused/redundant vertices after normalizing
+ //if (!mNoOptimize)
+ //{
+ // ret->remapVolumeFaces();
+ //}
volume_faces = remainder.size();
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 285c5f656b..1ce287d773 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -187,6 +187,15 @@ void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remain
}
}
+// generate mikkt space tangents and cache optimize
+void LLModel::preprocessVolumeFaces()
+{
+ for (auto& face : mVolumeFaces)
+ {
+ face.cacheOptimize();
+ }
+}
+
// Shrink the model to fit
// on a 1x1x1 cube centered at the origin.
// The positions and extents
@@ -296,6 +305,7 @@ void LLModel::normalizeVolumeFaces()
// the positions to fit within the unit cube.
LLVector4a* pos = (LLVector4a*) face.mPositions;
LLVector4a* norm = (LLVector4a*) face.mNormals;
+ LLVector4a* t = (LLVector4a*)face.mMikktSpaceTangents;
for (U32 j = 0; j < face.mNumVertices; ++j)
{
@@ -306,6 +316,14 @@ void LLModel::normalizeVolumeFaces()
norm[j].mul(inv_scale);
norm[j].normalize3();
}
+
+ if (t)
+ {
+ F32 w = t[j].getF32ptr()[3];
+ t[j].mul(inv_scale);
+ t[j].normalize3();
+ t[j].getF32ptr()[3] = w;
+ }
}
}
@@ -726,10 +744,12 @@ LLSD LLModel::writeModel(
LLSD::Binary verts(face.mNumVertices*3*2);
LLSD::Binary tc(face.mNumVertices*2*2);
LLSD::Binary normals(face.mNumVertices*3*2);
+ LLSD::Binary tangents(face.mNumVertices * 4 * 2);
LLSD::Binary indices(face.mNumIndices*2);
U32 vert_idx = 0;
U32 norm_idx = 0;
+ U32 tan_idx = 0;
U32 tc_idx = 0;
LLVector2* ftc = (LLVector2*) face.mTexCoords;
@@ -782,6 +802,22 @@ LLSD LLModel::writeModel(
normals[norm_idx++] = buff[1];
}
}
+
+ if (face.mMikktSpaceTangents)
+ { //normals
+ F32* tangent = face.mMikktSpaceTangents[j].getF32ptr();
+
+ for (U32 k = 0; k < 4; ++k)
+ { //for each component
+ //convert to 16-bit normalized
+ U16 val = (U16)((tangent[k] + 1.f) * 0.5f * 65535);
+ U8* buff = (U8*)&val;
+
+ //write to binary buffer
+ tangents[tan_idx++] = buff[0];
+ tangents[tan_idx++] = buff[1];
+ }
+ }
//texcoord
if (face.mTexCoords)
@@ -819,6 +855,11 @@ LLSD LLModel::writeModel(
mdl[model_names[idx]][i]["Normal"] = normals;
}
+ if (face.mMikktSpaceTangents)
+ {
+ mdl[model_names[idx]][i]["Tangent"] = tangents;
+ }
+
if (face.mTexCoords)
{
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 354ceb26b7..ea97851ce8 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -182,6 +182,7 @@ public:
void addFace(const LLVolumeFace& face);
void sortVolumeFacesByMaterialName();
+ void preprocessVolumeFaces();
void normalizeVolumeFaces();
void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
void remapVolumeFaces();