summaryrefslogtreecommitdiff
path: root/indra/llprimitive
diff options
context:
space:
mode:
authorBrad Payne (Vir Linden) <vir@lindenlab.com>2013-10-16 11:52:43 -0400
committerBrad Payne (Vir Linden) <vir@lindenlab.com>2013-10-16 11:52:43 -0400
commit1f8b37e9ad65f8064b83adac295d9eb162976e4c (patch)
tree3ced849ad5750b7884d291e17e89fec419e03382 /indra/llprimitive
parent2331b9a93b12eb0a2f5fb6109f990d81b29d0584 (diff)
parentf7158bc5afcec1da8b9d2d5a4ed86921e62d4959 (diff)
merge
Diffstat (limited to 'indra/llprimitive')
-rwxr-xr-xindra/llprimitive/llmodel.cpp191
-rwxr-xr-xindra/llprimitive/llmodel.h4
-rwxr-xr-xindra/llprimitive/lltextureentry.cpp2
3 files changed, 181 insertions, 16 deletions
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 5ed05e2201..34e0483a83 100755
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -166,6 +166,7 @@ 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) || !pos_source )
{
+ llwarns << "Could not find dom sources for basic geo data; invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
@@ -186,27 +187,78 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
LLVolumeFace::VertexMapData::PointMap point_map;
- for (U32 i = 0; i < idx.getCount(); i += idx_stride)
+ U32 index_count = idx.getCount();
+ U32 vertex_count = pos_source ? v.getCount() : 0;
+ U32 tc_count = tc_source ? tc.getCount() : 0;
+ U32 norm_count = norm_source ? n.getCount() : 0;
+
+ for (U32 i = 0; i < index_count; i += idx_stride)
{
LLVolumeFace::VertexData cv;
if (pos_source)
{
+ // guard against model data specifiying out of range indices or verts
+ //
+ if (((i + pos_offset) > index_count)
+ || ((idx[i+pos_offset]*3+2) > vertex_count))
+ {
+ llwarns << "Out of range index data; invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
+
cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0],
v[idx[i+pos_offset]*3+1],
v[idx[i+pos_offset]*3+2]));
+
+ if (!cv.getPosition().isFinite3())
+ {
+ llwarns << "Nan positional data, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
}
if (tc_source)
{
+ // guard against model data specifiying out of range indices or tcs
+ //
+
+ if (((i + tc_offset) > index_count)
+ || ((idx[i+tc_offset]*2+1) > tc_count))
+ {
+ llwarns << "Out of range TC indices." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
+
cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],
tc[idx[i+tc_offset]*2+1]);
+
+ if (!cv.mTexCoord.isFinite())
+ {
+ llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
}
if (norm_source)
{
+ // guard against model data specifiying out of range indices or norms
+ //
+ if (((i + norm_offset) > index_count)
+ || ((idx[i+norm_offset]*3+2) > norm_count))
+ {
+ llwarns << "Found out of range norm indices, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
+
cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],
n[idx[i+norm_offset]*3+1],
n[idx[i+norm_offset]*3+2]));
+
+ if (!cv.getNormal().isFinite3())
+ {
+ llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
}
BOOL found = FALSE;
@@ -261,13 +313,13 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
- ll_aligned_free_16(new_face.mNormals);
+ //ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
- ll_aligned_free_16(new_face.mTexCoords);
+ //ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
@@ -292,13 +344,13 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
- ll_aligned_free_16(new_face.mNormals);
+ //ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
- ll_aligned_free_16(new_face.mTexCoords);
+ //ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
@@ -333,6 +385,7 @@ 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))
{
+ llwarns << "Could not get DOM sources for basic geo data, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
@@ -364,6 +417,11 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
LLVolumeFace::VertexMapData::PointMap point_map;
+ U32 index_count = idx.getCount();
+ U32 vertex_count = pos_source ? v.getCount() : 0;
+ U32 tc_count = tc_source ? tc.getCount() : 0;
+ U32 norm_count = norm_source ? n.getCount() : 0;
+
U32 cur_idx = 0;
for (U32 i = 0; i < vcount.getCount(); ++i)
{ //for each polygon
@@ -376,22 +434,68 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (pos_source)
{
+ // guard against model data specifiying out of range indices or verts
+ //
+ if (((cur_idx + pos_offset) > index_count)
+ || ((idx[cur_idx+pos_offset]*3+2) > vertex_count))
+ {
+ llwarns << "Out of range position indices, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
+
cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0],
v[idx[cur_idx+pos_offset]*3+1],
v[idx[cur_idx+pos_offset]*3+2]);
+
+ if (!cv.getPosition().isFinite3())
+ {
+ llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
+
}
if (tc_source)
{
+ // guard against model data specifiying out of range indices or tcs
+ //
+ if (((cur_idx + tc_offset) > index_count)
+ || ((idx[cur_idx+tc_offset]*2+1) > tc_count))
+ {
+ llwarns << "Out of range TC indices, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
+
cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
tc[idx[cur_idx+tc_offset]*2+1]);
+
+ if (!cv.mTexCoord.isFinite())
+ {
+ llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
}
if (norm_source)
{
+ // guard against model data specifiying out of range indices or norms
+ //
+ if (((cur_idx + norm_offset) > index_count)
+ || ((idx[cur_idx+norm_offset]*3+2) > norm_count))
+ {
+ llwarns << "Out of range norm indices, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
+
cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],
n[idx[cur_idx+norm_offset]*3+1],
n[idx[cur_idx+norm_offset]*3+2]);
+
+ if (!cv.getNormal().isFinite3())
+ {
+ llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
}
cur_idx += idx_stride;
@@ -480,13 +584,13 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
- ll_aligned_free_16(new_face.mNormals);
+ //ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
- ll_aligned_free_16(new_face.mTexCoords);
+ //ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
@@ -514,13 +618,13 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
- ll_aligned_free_16(new_face.mNormals);
+ //ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
- ll_aligned_free_16(new_face.mTexCoords);
+ //ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
@@ -558,6 +662,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
domVertices* vertices = (domVertices*) elem.cast();
if (!vertices)
{
+ llwarns << "Could not find vertex source, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
domInputLocal_Array& v_inp = vertices->getInput_array();
@@ -571,6 +676,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
domSource* src = (domSource*) elem.cast();
if (!src)
{
+ llwarns << "Could not find DOM source, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
v = &(src->getFloat_array()->getValue());
@@ -586,6 +692,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
domSource* src = (domSource*) elem.cast();
if (!src)
{
+ llwarns << "Could not find DOM source, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
n = &(src->getFloat_array()->getValue());
@@ -598,6 +705,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
domSource* src = (domSource*) elem.cast();
if (!src)
{
+ llwarns << "Could not find DOM source, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
t = &(src->getFloat_array()->getValue());
@@ -632,6 +740,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
vert.getPosition().set(v->get(v_idx),
v->get(v_idx+1),
v->get(v_idx+2));
+
+ if (!vert.getPosition().isFinite3())
+ {
+ llwarns << "Found NaN while loading position data from DAE-Model, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
}
//bounds check n and t lookups because some FBX to DAE converters
@@ -644,6 +758,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
vert.getNormal().set(n->get(n_idx),
n->get(n_idx+1),
n->get(n_idx+2));
+
+ if (!vert.getNormal().isFinite3())
+ {
+ llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
}
else
{
@@ -657,6 +777,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount());
vert.mTexCoord.setVec(t->get(t_idx),
t->get(t_idx+1));
+
+ if (!vert.mTexCoord.isFinite())
+ {
+ llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
+ return LLModel::BAD_ELEMENT;
+ }
}
else
{
@@ -730,13 +856,13 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
LLVolumeFace& new_face = *face_list.rbegin();
if (!n)
{
- ll_aligned_free_16(new_face.mNormals);
+ //ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!t)
{
- ll_aligned_free_16(new_face.mTexCoords);
+ //ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
@@ -1010,6 +1136,43 @@ void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& tra
translation_out = mNormalizedTranslation;
}
+LLVector3 LLModel::getTransformedCenter(const LLMatrix4& mat)
+{
+ LLVector3 ret;
+
+ if (!mVolumeFaces.empty())
+ {
+ LLMatrix4a m;
+ m.loadu(mat);
+
+ LLVector4a minv,maxv;
+
+ LLVector4a t;
+ m.affineTransform(mVolumeFaces[0].mPositions[0], t);
+ minv = maxv = t;
+
+ for (S32 i = 0; i < mVolumeFaces.size(); ++i)
+ {
+ LLVolumeFace& face = mVolumeFaces[i];
+
+ for (U32 j = 0; j < face.mNumVertices; ++j)
+ {
+ m.affineTransform(face.mPositions[j],t);
+ update_min_max(minv, maxv, t);
+ }
+ }
+
+ minv.add(maxv);
+ minv.mul(0.5f);
+
+ ret.set(minv.getF32ptr());
+ }
+
+ return ret;
+}
+
+
+
void LLModel::setNumVolumeFaces(S32 count)
{
mVolumeFaces.resize(count);
@@ -1036,7 +1199,7 @@ void LLModel::setVolumeFaceData(
}
else
{
- ll_aligned_free_16(face.mNormals);
+ //ll_aligned_free_16(face.mNormals);
face.mNormals = NULL;
}
@@ -1047,7 +1210,7 @@ void LLModel::setVolumeFaceData(
}
else
{
- ll_aligned_free_16(face.mTexCoords);
+ //ll_aligned_free_16(face.mTexCoords);
face.mTexCoords = NULL;
}
@@ -1246,7 +1409,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
}
else
{
- ll_aligned_free_16(new_face.mTexCoords);
+ //ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 1cf528fd9f..aaafc55258 100755
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -173,13 +173,15 @@ public:
void optimizeVolumeFaces();
void offsetMesh( const LLVector3& pivotPoint );
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
-
+ LLVector3 getTransformedCenter(const LLMatrix4& mat);
+
//reorder face list based on mMaterialList in this and reference so
//order matches that of reference (material ordering touchup)
bool matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
bool isMaterialListSubset( LLModel* ref );
bool needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
+
std::vector<std::string> mMaterialList;
//data used for skin weights
diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp
index 597f078490..0db75a0e82 100755
--- a/indra/llprimitive/lltextureentry.cpp
+++ b/indra/llprimitive/lltextureentry.cpp
@@ -545,7 +545,7 @@ S32 LLTextureEntry::setMaterialID(const LLMaterialID& pMaterialID)
{
mMaterialUpdatePending = true;
mMaterialID = pMaterialID;
- return TEM_CHANGE_NONE;
+ return TEM_CHANGE_TEXTURE;
}
mMaterialUpdatePending = false;