summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandreykproductengine <akleshchev@productengine.com>2016-11-15 20:16:01 +0200
committerandreykproductengine <akleshchev@productengine.com>2016-11-15 20:16:01 +0200
commit4ae6f32ee16b21aed2235e96b99e18eebfdd82c6 (patch)
tree212e54201405225784a3e23c5ee847f0e688ac24
parent2e52d12ef1ecc53f1affdf7b6d2150e9256eee65 (diff)
MAINT-6901 Fixes upload assigning different scale to parts of the model
-rw-r--r--indra/llprimitive/lldaeloader.cpp13
-rw-r--r--indra/llprimitive/llmodel.cpp159
-rw-r--r--indra/llprimitive/llmodel.h1
3 files changed, 165 insertions, 8 deletions
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 031befe63a..de02c5c188 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -999,6 +999,11 @@ bool LLDAELoader::OpenFile(const std::string& filename)
std::sort(mModelList.begin(), mModelList.end(), ModelSort());
+ if (!mNoNormalize)
+ {
+ LLModel::normalizeModels(mModelList);
+ }
+
model_list::iterator model_iter = mModelList.begin();
while (model_iter != mModelList.end())
{
@@ -2408,8 +2413,6 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
//
ret->sortVolumeFacesByMaterialName();
- bool normalized = false;
-
int submodelID = 0;
// remove all faces that definitely won't fit into one model and submodel limit
@@ -2424,12 +2427,6 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
{
// Insure we do this once with the whole gang and not per-model
//
- if (!normalized && !mNoNormalize)
- {
- normalized = true;
- ret->normalizeVolumeFaces();
- }
-
ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder);
if (!mNoOptimize)
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index e494c55250..3270722ccb 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -174,6 +174,165 @@ void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remain
}
}
+// Shrink group of models to fit
+// on a 1x1x1 cube centered at the origin.
+void LLModel::normalizeModels(std::vector<LLPointer<LLModel>> model_list)
+{
+ std::vector<LLPointer<LLModel > >::iterator iter = model_list.begin();
+
+ LLVector4a min, max;
+ while (iter != model_list.end() && (*iter)->mVolumeFaces.empty())
+ {
+ iter++;
+ }
+ if (iter == model_list.end())
+ {
+ // no models with faces
+ return;
+ }
+
+ min = (*iter)->mVolumeFaces[0].mExtents[0];
+ max = (*iter)->mVolumeFaces[0].mExtents[1];
+
+ // Treat models as a group - each model out of 1x1x1 cube
+ // needs scaling and will affect whole group scale
+ while (iter != model_list.end())
+ {
+ LLPointer<LLModel> model = *iter++;
+
+ if (model.get() && model->mVolumeFaces.empty())
+ {
+ // For all of the volume faces
+ // in the model, loop over
+ // them and see what the extents
+ // of the volume along each axis.
+
+ for (U32 i = 0; i < model->mVolumeFaces.size(); ++i)
+ {
+ LLVolumeFace& face = model->mVolumeFaces[i];
+
+ update_min_max(min, max, face.mExtents[0]);
+ update_min_max(min, max, face.mExtents[1]);
+
+ if (face.mTexCoords)
+ {
+ LLVector2& min_tc = face.mTexCoordExtents[0];
+ LLVector2& max_tc = face.mTexCoordExtents[1];
+
+ min_tc = face.mTexCoords[0];
+ max_tc = face.mTexCoords[0];
+
+ for (U32 j = 1; j < face.mNumVertices; ++j)
+ {
+ update_min_max(min_tc, max_tc, face.mTexCoords[j]);
+ }
+ }
+ else
+ {
+ face.mTexCoordExtents[0].set(0, 0);
+ face.mTexCoordExtents[1].set(1, 1);
+ }
+ }
+ }
+ }
+
+ // Now that we have the extents of the model
+ // we can compute the offset needed to center
+ // the model at the origin.
+
+ // Compute center of the model
+ // and make it negative to get translation
+ // needed to center at origin.
+ LLVector4a trans;
+ trans.setAdd(min, max);
+ trans.mul(-0.5f);
+
+ // Compute the total size along all
+ // axes of the model.
+ LLVector4a size;
+ size.setSub(max, min);
+
+ // Prevent division by zero.
+ F32 x = size[0];
+ F32 y = size[1];
+ F32 z = size[2];
+ F32 w = size[3];
+ if (fabs(x) < F_APPROXIMATELY_ZERO)
+ {
+ x = 1.0;
+ }
+ if (fabs(y) < F_APPROXIMATELY_ZERO)
+ {
+ y = 1.0;
+ }
+ if (fabs(z) < F_APPROXIMATELY_ZERO)
+ {
+ z = 1.0;
+ }
+ size.set(x, y, z, w);
+
+ // Compute scale as reciprocal of size
+ LLVector4a scale;
+ scale.splat(1.f);
+ scale.div(size);
+
+ LLVector4a inv_scale(1.f);
+ inv_scale.div(scale);
+
+ iter = model_list.begin();
+ // apply fixed scale and trans to all models as a single group
+ while (iter != model_list.end())
+ {
+ LLPointer<LLModel> model = *iter++;
+
+ if (model->mVolumeFaces.empty())
+ {
+ continue;
+ }
+
+ for (U32 i = 0; i < model->mVolumeFaces.size(); ++i)
+ {
+ LLVolumeFace& face = model->mVolumeFaces[i];
+
+ // We shrink the extents so
+ // that they fall within
+ // the unit cube.
+ face.mExtents[0].add(trans);
+ face.mExtents[0].mul(scale);
+
+ face.mExtents[1].add(trans);
+ face.mExtents[1].mul(scale);
+
+ // For all the positions, we scale
+ // the positions to fit within the unit cube.
+ LLVector4a* pos = (LLVector4a*)face.mPositions;
+ LLVector4a* norm = (LLVector4a*)face.mNormals;
+
+ for (U32 j = 0; j < face.mNumVertices; ++j)
+ {
+ pos[j].add(trans);
+ pos[j].mul(scale);
+ if (norm && !norm[j].equals3(LLVector4a::getZero()))
+ {
+ norm[j].mul(inv_scale);
+ norm[j].normalize3();
+ }
+ }
+ }
+
+ // mNormalizedScale is the scale at which
+ // we would need to multiply the model
+ // by to get the original size of the
+ // model instead of the normalized size.
+ LLVector4a normalized_scale;
+ normalized_scale.splat(1.f);
+ normalized_scale.div(scale);
+ model->mNormalizedScale.set(normalized_scale.getF32ptr());
+ model->mNormalizedTranslation.set(trans.getF32ptr());
+ model->mNormalizedTranslation *= -1.f;
+ }
+}
+
// Shrink the model to fit
// on a 1x1x1 cube centered at the origin.
// The positions and extents
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index ae602c09df..8fe025a352 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -172,6 +172,7 @@ public:
void addFace(const LLVolumeFace& face);
void sortVolumeFacesByMaterialName();
+ static void normalizeModels(std::vector<LLPointer<LLModel>> model_list);
void normalizeVolumeFaces();
void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
void optimizeVolumeFaces();