summaryrefslogtreecommitdiff
path: root/indra/llprimitive
diff options
context:
space:
mode:
authorBrad Kittenbrink <brad@lindenlab.com>2022-04-28 14:05:49 -0700
committerBrad Kittenbrink <brad@lindenlab.com>2022-04-28 14:05:49 -0700
commitcc04903379c3a5dc094e0c9582cf41f022406ef5 (patch)
tree41dabc7b9c53a17591c8c4d6da93207a52a1b793 /indra/llprimitive
parentc9ef206e39063c46c1fbab355c1a015e3e8b022e (diff)
parentb08742d0b3e0000430b8ae772c7c4d25cfe084fa (diff)
Merge remote-tracking branch 'origin/euclid-17277' into brad/SL-17116-material-messaging
Diffstat (limited to 'indra/llprimitive')
-rw-r--r--indra/llprimitive/lldaeloader.cpp92
-rw-r--r--indra/llprimitive/llmodel.cpp43
-rw-r--r--indra/llprimitive/llmodel.h22
3 files changed, 136 insertions, 21 deletions
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 33e90555fa..e89690438e 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -149,7 +149,11 @@ bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S
return true;
}
-LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri)
+LLModel::EModelStatus load_face_from_dom_triangles(
+ std::vector<LLVolumeFace>& face_list,
+ std::vector<std::string>& materials,
+ domTrianglesRef& tri,
+ LLSD& log_msg)
{
LLVolumeFace face;
std::vector<LLVolumeFace::VertexData> verts;
@@ -169,12 +173,18 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
{
+ LLSD args;
+ args["Message"] = "ParsingErrorBadElement";
+ log_msg.append(args);
return LLModel::BAD_ELEMENT;
}
if (!pos_source || !pos_source->getFloat_array())
{
LL_WARNS() << "Unable to process mesh without position data; invalid model; invalid model." << LL_ENDL;
+ LLSD args;
+ args["Message"] = "ParsingErrorPositionInvalidModel";
+ log_msg.append(args);
return LLModel::BAD_ELEMENT;
}
@@ -354,7 +364,11 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
return LLModel::NO_ERRORS ;
}
-LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly, LLSD& log_msg)
+LLModel::EModelStatus load_face_from_dom_polylist(
+ std::vector<LLVolumeFace>& face_list,
+ std::vector<std::string>& materials,
+ domPolylistRef& poly,
+ LLSD& log_msg)
{
domPRef p = poly->getP();
domListOfUInts& idx = p->getValue();
@@ -381,6 +395,10 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
{
+ LL_WARNS() << "Bad element." << LL_ENDL;
+ LLSD args;
+ args["Message"] = "ParsingErrorBadElement";
+ log_msg.append(args);
return LLModel::BAD_ELEMENT;
}
@@ -432,6 +450,9 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (!cv.getPosition().isFinite3())
{
LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL;
+ LLSD args;
+ args["Message"] = "PositionNaN";
+ log_msg.append(args);
return LLModel::BAD_ELEMENT;
}
}
@@ -464,6 +485,10 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (!cv.getNormal().isFinite3())
{
LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL;
+ LLSD args;
+ args["Message"] = "NormalsNaN";
+ log_msg.append(args);
+
return LLModel::BAD_ELEMENT;
}
}
@@ -781,6 +806,9 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
}
}
+ // Viewer can only fit U16 vertices, shouldn't we do some checks here and return overflow if result has more?
+ llassert(vert_idx.size() < U16_MAX);
+
//build vertex array from map
std::vector<LLVolumeFace::VertexData> new_verts;
new_verts.resize(vert_idx.size());
@@ -798,7 +826,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
for (U32 i = 0; i < verts.size(); ++i)
{
indices[i] = vert_idx[verts[i]];
- llassert(!i || (indices[i-1] != indices[i]));
+ if (i % 3 != 0) // assumes GL_TRIANGLES, compare 0-1, 1-2, 3-4, 4-5 but not 2-3 or 5-6
+ {
+ // A faulty degenerate triangle detection (triangle with 0 area),
+ // probably should be a warning and not an assert
+ llassert(!i || (indices[i-1] != indices[i]));
+ }
}
// DEBUG just build an expanded triangle list
@@ -918,6 +951,9 @@ bool LLDAELoader::OpenFile(const std::string& filename)
if (!dom)
{
LL_INFOS() <<" Error with dae - traditionally indicates a corrupt file."<<LL_ENDL;
+ LLSD args;
+ args["Message"] = "ParsingErrorCorrupt";
+ mWarningsArray.append(args);
setLoadState( ERROR_PARSING );
return false;
}
@@ -945,6 +981,9 @@ bool LLDAELoader::OpenFile(const std::string& filename)
if (!doc)
{
LL_WARNS() << "can't find internal doc" << LL_ENDL;
+ LLSD args;
+ args["Message"] = "ParsingErrorNoDoc";
+ mWarningsArray.append(args);
return false;
}
@@ -952,6 +991,9 @@ bool LLDAELoader::OpenFile(const std::string& filename)
if (!root)
{
LL_WARNS() << "document has no root" << LL_ENDL;
+ LLSD args;
+ args["Message"] = "ParsingErrorNoRoot";
+ mWarningsArray.append(args);
return false;
}
@@ -967,6 +1009,9 @@ bool LLDAELoader::OpenFile(const std::string& filename)
if (!result)
{
LL_INFOS() << "Could not verify controller" << LL_ENDL;
+ LLSD args;
+ args["Message"] = "ParsingErrorBadElement";
+ mWarningsArray.append(args);
setLoadState( ERROR_PARSING );
return true;
}
@@ -1100,6 +1145,9 @@ bool LLDAELoader::OpenFile(const std::string& filename)
if (!scene)
{
LL_WARNS() << "document has no visual_scene" << LL_ENDL;
+ LLSD args;
+ args["Message"] = "ParsingErrorNoScene";
+ mWarningsArray.append(args);
setLoadState( ERROR_PARSING );
return true;
}
@@ -1108,11 +1156,14 @@ bool LLDAELoader::OpenFile(const std::string& filename)
bool badElement = false;
- processElement( scene, badElement, &dae );
+ processElement( scene, badElement, &dae);
if ( badElement )
{
LL_INFOS()<<"Scene could not be parsed"<<LL_ENDL;
+ LLSD args;
+ args["Message"] = "ParsingErrorCantParseScene";
+ mWarningsArray.append(args);
setLoadState( ERROR_PARSING );
}
@@ -1184,17 +1235,19 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
LLMeshSkinInfo& skin_info = model->mSkinInfo;
+ LLMatrix4 mat;
for (int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
- skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4];
+ mat.mMatrix[i][j] = dom_value[i + j*4];
}
}
- LLMatrix4 trans = normalized_transformation;
- trans *= skin_info.mBindShapeMatrix;
- skin_info.mBindShapeMatrix = trans;
+ skin_info.mBindShapeMatrix.loadu(mat);
+
+ LLMatrix4a trans(normalized_transformation);
+ matMul(trans, skin_info.mBindShapeMatrix, skin_info.mBindShapeMatrix);
}
@@ -1412,7 +1465,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
mat.mMatrix[i][j] = transform[k*16 + i + j*4];
}
}
- model->mSkinInfo.mInvBindMatrix.push_back(mat);
+ model->mSkinInfo.mInvBindMatrix.push_back(LLMatrix4a(mat));
}
}
}
@@ -1486,9 +1539,9 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
if (mJointMap.find(lookingForJoint) != mJointMap.end()
&& model->mSkinInfo.mInvBindMatrix.size() > i)
{
- LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];
+ LLMatrix4 newInverse = LLMatrix4(model->mSkinInfo.mInvBindMatrix[i].getF32ptr());
newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() );
- model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse );
+ model->mSkinInfo.mAlternateBindMatrix.push_back( LLMatrix4a(newInverse) );
}
else
{
@@ -1951,7 +2004,7 @@ daeElement* LLDAELoader::getChildFromElement( daeElement* pElement, std::string
return NULL;
}
-void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* dae )
+void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* dae)
{
LLMatrix4 saved_transform;
bool pushed_mat = false;
@@ -2045,6 +2098,11 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da
if (mTransform.determinant() < 0)
{ //negative scales are not supported
LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL;
+ LLSD args;
+ args["Message"] = "NegativeScaleTrans";
+ args["LABEL"] = getElementLabel(instance_geo);
+ mWarningsArray.append(args);
+
badElement = true;
}
@@ -2068,6 +2126,10 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da
if (transformation.determinant() < 0)
{ //negative scales are not supported
LL_INFOS() << "Negative scale detected, unsupported post-normalization transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL;
+ LLSD args;
+ args["Message"] = "NegativeScaleNormTrans";
+ args["LABEL"] = getElementLabel(instance_geo);
+ mWarningsArray.append(args);
badElement = true;
}
@@ -2109,6 +2171,9 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da
else
{
LL_INFOS()<<"Unable to resolve geometry URL."<<LL_ENDL;
+ LLSD args;
+ args["Message"] = "CantResolveGeometryUrl";
+ mWarningsArray.append(args);
badElement = true;
}
@@ -2399,7 +2464,7 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh, LLSD&
{
domTrianglesRef& tri = tris.get(i);
- status = load_face_from_dom_triangles(pModel->getVolumeFaces(), pModel->getMaterialList(), tri);
+ status = load_face_from_dom_triangles(pModel->getVolumeFaces(), pModel->getMaterialList(), tri, log_msg);
pModel->mStatus = status;
if(status != LLModel::NO_ERRORS)
{
@@ -2426,6 +2491,7 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh, LLSD&
for (U32 i = 0; i < polygons.getCount(); ++i)
{
domPolygonsRef& poly = polygons.get(i);
+
status = load_face_from_dom_polygons(pModel->getVolumeFaces(), pModel->getMaterialList(), poly);
if(status != LLModel::NO_ERRORS)
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 1b34068ece..204ff63712 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -31,6 +31,7 @@
#include "llconvexdecomposition.h"
#include "llsdserialize.h"
#include "llvector4a.h"
+#include "llmd5.h"
#ifdef LL_USESYSTEMLIBS
# include <zlib.h>
@@ -1404,7 +1405,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
}
}
- mInvBindMatrix.push_back(mat);
+ mInvBindMatrix.push_back(LLMatrix4a(mat));
}
if (mJointNames.size() != mInvBindMatrix.size())
@@ -1418,13 +1419,15 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
if (skin.has("bind_shape_matrix"))
{
+ LLMatrix4 mat;
for (U32 j = 0; j < 4; j++)
{
for (U32 k = 0; k < 4; k++)
{
- mBindShapeMatrix.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal();
+ mat.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal();
}
}
+ mBindShapeMatrix.loadu(mat);
}
if (skin.has("alt_inverse_bind_matrix"))
@@ -1440,7 +1443,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
}
}
- mAlternateBindMatrix.push_back(mat);
+ mAlternateBindMatrix.push_back(LLMatrix4a(mat));
}
}
@@ -1457,6 +1460,8 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
{
mLockScaleIfJointPosition = false;
}
+
+ updateHash();
}
LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_position) const
@@ -1508,6 +1513,38 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi
return ret;
}
+void LLMeshSkinInfo::updateHash()
+{
+ // get hash of data relevant to render batches
+ LLMD5 hash;
+
+ //mJointNames
+ for (auto& name : mJointNames)
+ {
+ hash.update(name);
+ }
+
+ //mJointNums
+ hash.update((U8*)&(mJointNums[0]), sizeof(S32) * mJointNums.size());
+
+ //mInvBindMatrix
+ F32* src = mInvBindMatrix[0].getF32ptr();
+
+ for (int i = 0; i < mInvBindMatrix.size() * 16; ++i)
+ {
+ S32 t = llround(src[i] * 10000.f);
+ hash.update((U8*)&t, sizeof(S32));
+ }
+ //hash.update((U8*)&(mInvBindMatrix[0]), sizeof(LLMatrix4a) * mInvBindMatrix.size());
+
+ hash.finalize();
+
+ U64 digest[2];
+ hash.raw_digest((U8*) digest);
+
+ mHash = digest[0];
+}
+
LLModel::Decomposition::Decomposition(LLSD& data)
{
fromLLSD(data);
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 51fa2f8079..3881b1338c 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -33,34 +33,44 @@
#include "m4math.h"
#include <queue>
+#include <boost/align/aligned_allocator.hpp>
+
class daeElement;
class domMesh;
#define MAX_MODEL_FACES 8
+LL_ALIGN_PREFIX(16)
class LLMeshSkinInfo
{
+ LL_ALIGN_NEW
public:
LLMeshSkinInfo();
LLMeshSkinInfo(LLSD& data);
void fromLLSD(LLSD& data);
LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const;
+ void updateHash();
LLUUID mMeshID;
std::vector<std::string> mJointNames;
mutable std::vector<S32> mJointNums;
- std::vector<LLMatrix4> mInvBindMatrix;
- std::vector<LLMatrix4> mAlternateBindMatrix;
+ typedef std::vector<LLMatrix4a, boost::alignment::aligned_allocator<LLMatrix4a, 16>> matrix_list_t;
+ matrix_list_t mInvBindMatrix;
+ matrix_list_t mAlternateBindMatrix;
+
+ LL_ALIGN_16(LLMatrix4a mBindShapeMatrix);
- LLMatrix4 mBindShapeMatrix;
float mPelvisOffset;
bool mLockScaleIfJointPosition;
bool mInvalidJointsScrubbed;
bool mJointNumsInitialized;
-};
+ U64 mHash = 0;
+} LL_ALIGN_POSTFIX(16);
+LL_ALIGN_PREFIX(16)
class LLModel : public LLVolume
{
+ LL_ALIGN_NEW
public:
enum
@@ -281,8 +291,10 @@ public:
EModelStatus mStatus ;
+ // A model/object can only have 8 faces, spillover faces will
+ // be moved to new model/object and assigned a submodel id.
int mSubmodelID;
-};
+} LL_ALIGN_POSTFIX(16);
typedef std::vector<LLPointer<LLModel> > model_list;
typedef std::queue<LLPointer<LLModel> > model_queue;