Crash fixes in model upload

This commit is contained in:
Drake Arconis
2014-03-01 18:53:51 -05:00
parent 64d4a9e240
commit f5bdb56a7c
3 changed files with 232 additions and 51 deletions

View File

@@ -168,6 +168,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;
}
@@ -188,27 +189,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;
@@ -263,7 +315,7 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
//l_aligned_free_16(new_face.mNormals);
//ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
@@ -335,6 +387,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;
}
@@ -366,6 +419,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
@@ -378,22 +436,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;
@@ -560,6 +664,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();
@@ -573,6 +678,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());
@@ -588,6 +694,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());
@@ -600,6 +707,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());
@@ -634,6 +742,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
@@ -646,6 +760,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
{
@@ -659,6 +779,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
{
@@ -1591,6 +1717,7 @@ LLSD LLModel::writeModel(
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0"] = tc;
}
mdl[model_names[idx]][i]["TriangleList"] = indices;
if (skinning)

View File

@@ -241,6 +241,22 @@ bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a
bool validate_face(const LLVolumeFace& face)
{
for (S32 v = 0; v < face.mNumVertices; v++)
{
if(face.mPositions && !face.mPositions[v].isFinite3())
{
llwarns << "NaN position data in face found!" << llendl;
return false;
}
if(face.mNormals && !face.mNormals[v].isFinite3())
{
llwarns << "NaN normal data in face found!" << llendl;
return false;
}
}
for (S32 i = 0; i < face.mNumIndices; ++i)
{
if (face.mIndices[i] >= face.mNumVertices)
@@ -3807,15 +3823,30 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
U32 triangle_count = 0;
for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter)
U32 instanced_triangle_count = 0;
//get the triangle count for the whole scene
for (LLModelLoader::scene::iterator iter = mBaseScene.begin(), endIter = mBaseScene.end(); iter != endIter; ++iter)
{
LLModel* mdl = *iter;
for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
{
triangle_count += mdl->getVolumeFace(i).mNumIndices/3;
LLModel* mdl = instance->mModel;
if (mdl)
{
instanced_triangle_count += mdl->getNumTriangles();
}
}
}
//get the triangle count for the non-instanced set of models
for (U32 i = 0; i < mBaseModel.size(); ++i)
{
triangle_count += mBaseModel[i]->getNumTriangles();
}
//get ratio of uninstanced triangles to instanced triangles
F32 triangle_ratio = (F32) triangle_count / (F32) instanced_triangle_count;
U32 base_triangle_count = triangle_count;
U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
@@ -3849,6 +3880,8 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
if (which_lod > -1 && which_lod < NUM_LOD)
{
limit = mFMP->childGetValue("lod_triangle_limit_" + lod_name[which_lod]).asInteger();
//convert from "scene wide" to "non-instanced" triangle limit
limit = (S32) ( (F32) limit*triangle_ratio );
}
}
else
@@ -3953,7 +3986,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
U32 actual_verts = 0;
U32 submeshes = 0;
mRequestedTriangleCount[lod] = triangle_count;
mRequestedTriangleCount[lod] = (S32) ( (F32) triangle_count / triangle_ratio );
mRequestedErrorThreshold[lod] = lod_error_threshold;
glodGroupParameteri(mGroup, GLOD_ADAPT_MODE, lod_mode);
@@ -4135,28 +4168,36 @@ void LLModelPreview::updateStatusMessages()
//initialize total for this lod to 0
total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0;
for (U32 i = 0; i < mModel[lod].size(); ++i)
{ //for each model in the lod
S32 cur_tris = 0;
S32 cur_verts = 0;
S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();
for (LLModelLoader::scene::iterator iter = mScene[lod].begin(), endIter = mScene[lod].end(); iter != endIter; ++iter)
{
for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
{
LLModel* model = instance->mModel;
if (model)
{
//for each model in the lod
S32 cur_tris = 0;
S32 cur_verts = 0;
S32 cur_submeshes = model->getNumVolumeFaces();
for (S32 j = 0; j < cur_submeshes; ++j)
{ //for each submesh (face), add triangles and vertices to current total
const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
cur_tris += face.mNumIndices/3;
cur_verts += face.mNumVertices;
for (S32 j = 0; j < cur_submeshes; ++j)
{ //for each submesh (face), add triangles and vertices to current total
const LLVolumeFace& face = model->getVolumeFace(j);
cur_tris += face.mNumIndices/3;
cur_verts += face.mNumVertices;
}
//add this model to the lod total
total_tris[lod] += cur_tris;
total_verts[lod] += cur_verts;
total_submeshes[lod] += cur_submeshes;
//store this model's counts to asset data
tris[lod].push_back(cur_tris);
verts[lod].push_back(cur_verts);
submeshes[lod].push_back(cur_submeshes);
}
}
//add this model to the lod total
total_tris[lod] += cur_tris;
total_verts[lod] += cur_verts;
total_submeshes[lod] += cur_submeshes;
//store this model's counts to asset data
tris[lod].push_back(cur_tris);
verts[lod].push_back(cur_verts);
submeshes[lod].push_back(cur_submeshes);
}
}
@@ -4334,34 +4375,38 @@ void LLModelPreview::updateStatusMessages()
}
//add up physics triangles etc
S32 start = 0;
S32 end = mModel[LLModel::LOD_PHYSICS].size();
S32 phys_tris = 0;
S32 phys_hulls = 0;
S32 phys_points = 0;
for (S32 i = start; i < end; ++i)
{ //add up hulls and points and triangles for selected mesh(es)
LLModel* model = mModel[LLModel::LOD_PHYSICS][i];
S32 cur_submeshes = model->getNumVolumeFaces();
LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull;
if (!decomp.empty())
//get the triangle count for the whole scene
for (LLModelLoader::scene::iterator iter = mScene[LLModel::LOD_PHYSICS].begin(), endIter = mScene[LLModel::LOD_PHYSICS].end(); iter != endIter; ++iter)
{
for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
{
phys_hulls += decomp.size();
for (U32 i = 0; i < decomp.size(); ++i)
LLModel* model = instance->mModel;
if (model)
{
phys_points += decomp[i].size();
}
}
else
{ //choose physics shape OR decomposition, can't use both
for (S32 j = 0; j < cur_submeshes; ++j)
{ //for each submesh (face), add triangles and vertices to current total
const LLVolumeFace& face = model->getVolumeFace(j);
phys_tris += face.mNumIndices/3;
S32 cur_submeshes = model->getNumVolumeFaces();
LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull;
if (!decomp.empty())
{
phys_hulls += decomp.size();
for (U32 i = 0; i < decomp.size(); ++i)
{
phys_points += decomp[i].size();
}
}
else
{ //choose physics shape OR decomposition, can't use both
for (S32 j = 0; j < cur_submeshes; ++j)
{ //for each submesh (face), add triangles and vertices to current total
const LLVolumeFace& face = model->getVolumeFace(j);
phys_tris += face.mNumIndices/3;
}
}
}
}
}
@@ -4523,7 +4568,7 @@ void LLModelPreview::updateLodControls(S32 lod)
if (!lod_combo) return;
S32 lod_mode = lod_combo->getCurrentIndex();
if (lod_mode == 0) // LoD from file
if (lod_mode == LOD_FROM_FILE) // LoD from file
{
fmp->mLODMode[lod] = 0;
for (U32 i = 0; i < num_file_controls; ++i)
@@ -4536,7 +4581,7 @@ void LLModelPreview::updateLodControls(S32 lod)
mFMP->childHide(lod_controls[i] + lod_name[lod]);
}
}
else if (lod_mode == 2) // use LoD above
else if (lod_mode == USE_LOD_ABOVE) // use LoD above
{
fmp->mLODMode[lod] = 2;
for (U32 i = 0; i < num_file_controls; ++i)

View File

@@ -298,6 +298,15 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
typedef boost::signals2::signal<void (void)> model_loaded_signal_t;
typedef boost::signals2::signal<void (bool)> model_updated_signal_t;
public:
typedef enum
{
LOD_FROM_FILE = 0,
GENERATE,
USE_LOD_ABOVE,
} eLoDMode;
public:
LLModelPreview(S32 width, S32 height, LLFloater* fmp);
virtual ~LLModelPreview();