diff options
Diffstat (limited to 'indra/llmath/llvolume.cpp')
-rw-r--r-- | indra/llmath/llvolume.cpp | 123 |
1 files changed, 94 insertions, 29 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 762c0f74f3..40f7b1e9fb 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -371,7 +371,7 @@ BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, cons } } -class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle> +class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle, LLVolumeTriangle*> { public: const LLVolumeFace* mFace; @@ -381,7 +381,7 @@ public: mFace = face; } - virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch) + virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch) { //this is a depth first traversal, so it's safe to assum all children have complete //bounding data LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME @@ -399,8 +399,7 @@ public: min = *(tri->mV[0]); max = *(tri->mV[0]); - for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = - branch->getDataBegin(); iter != branch->getDataEnd(); ++iter) + for (LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = branch->getDataBegin(); iter != branch->getDataEnd(); ++iter) { //for each triangle in node //stretch by triangles in node @@ -2387,7 +2386,25 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; return false; } - + return unpackVolumeFacesInternal(mdl); +} + +bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size) +{ + //input data is now pointing at a zlib compressed block of LLSD + //decompress block + LLSD mdl; + U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size); + if (uzip_result != LLUZipHelper::ZR_OK) + { + LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; + return false; + } + return unpackVolumeFacesInternal(mdl); +} + +bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) +{ { U32 face_count = mdl.size(); @@ -2399,7 +2416,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) mVolumeFaces.resize(face_count); - for (U32 i = 0; i < face_count; ++i) + for (size_t i = 0; i < face_count; ++i) { LLVolumeFace& face = mVolumeFaces[i]; @@ -2423,6 +2440,13 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) //copy out indices S32 num_indices = idx.size() / 2; + const S32 indices_to_discard = num_indices % 3; + if (indices_to_discard > 0) + { + // Invalid number of triangle indices + LL_WARNS() << "Incomplete triangle discarded from face! Indices count " << num_indices << " was not divisible by 3. face index: " << i << " Total: " << face_count << LL_ENDL; + num_indices -= indices_to_discard; + } face.resizeIndices(num_indices); if (num_indices > 2 && !face.mIndices) @@ -2438,8 +2462,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) } U16* indices = (U16*) &(idx[0]); - U32 count = idx.size()/2; - for (U32 j = 0; j < count; ++j) + for (U32 j = 0; j < num_indices; ++j) { face.mIndices[j] = indices[j]; } @@ -3831,8 +3854,8 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, #if DEBUG_SILHOUETTE_EDGE_MAP //for each triangle - U32 count = face.mNumIndices; - for (U32 j = 0; j < count/3; j++) { + U32 tri_count = face.mNumIndices / 3; + for (U32 j = 0; j < tri_count; j++) { //get vertices S32 v1 = face.mIndices[j*3+0]; S32 v2 = face.mIndices[j*3+1]; @@ -3850,7 +3873,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, continue; } - if (nIndex >= (S32) count/3) { + if (nIndex >= (S32)tri_count) { continue; } //get neighbor vertices @@ -4142,13 +4165,13 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en } else { - if (!face.mOctree) + if (!face.getOctree()) { face.createOctree(); } LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out); - intersect.traverse(face.mOctree); + intersect.traverse(face.getOctree()); if (intersect.mHitFace) { hit_face = i; @@ -4703,6 +4726,7 @@ LLVolumeFace::LLVolumeFace() : #endif mWeightsScrubbed(FALSE), mOctree(NULL), + mOctreeTriangles(NULL), mOptimized(FALSE) { mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); @@ -4732,8 +4756,9 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) mJointIndices(NULL), #endif mWeightsScrubbed(FALSE), - mOctree(NULL) -{ + mOctree(NULL), + mOctreeTriangles(NULL) +{ mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); mCenter = mExtents+2; *this = src; @@ -4873,8 +4898,7 @@ void LLVolumeFace::freeData() mJustWeights = NULL; #endif - delete mOctree; - mOctree = NULL; + destroyOctree(); } BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) @@ -4882,8 +4906,7 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME //tree for this face is no longer valid - delete mOctree; - mOctree = NULL; + destroyOctree(); LL_CHECK_MEMORY BOOL ret = FALSE ; @@ -5008,6 +5031,17 @@ void LLVolumeFace::optimize(F32 angle_cutoff) { U16 index = mIndices[i]; + if (index >= mNumVertices) + { + // invalid index + // replace with a valid index to avoid crashes + index = mNumVertices - 1; + mIndices[i] = index; + + // Needs better logging + LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL; + } + LLVolumeFace::VertexData cv; getVertexData(index, cv); @@ -5380,6 +5414,17 @@ bool LLVolumeFace::cacheOptimize() U16 idx = mIndices[i]; U32 tri_idx = i / 3; + if (idx >= mNumVertices) + { + // invalid index + // replace with a valid index to avoid crashes + idx = mNumVertices - 1; + mIndices[i] = idx; + + // Needs better logging + LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL; + } + vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx])); vertex_data[idx].mIdx = idx; triangle_data[tri_idx].mVertex[i % 3] = &(vertex_data[idx]); @@ -5596,21 +5641,27 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - if (mOctree) + if (getOctree()) { return; } - mOctree = new LLOctreeRoot<LLVolumeTriangle>(center, size, NULL); + llassert(mNumIndices % 3 == 0); + + mOctree = new LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>(center, size, NULL); new LLVolumeOctreeListener(mOctree); + const U32 num_triangles = mNumIndices / 3; + // Initialize all the triangles we need + mOctreeTriangles = new LLVolumeTriangle[num_triangles]; - for (U32 i = 0; i < mNumIndices; i+= 3) + for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) { //for each triangle - LLPointer<LLVolumeTriangle> tri = new LLVolumeTriangle(); + const U32 index = triangle_index * 3; + LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - const LLVector4a& v0 = mPositions[mIndices[i]]; - const LLVector4a& v1 = mPositions[mIndices[i+1]]; - const LLVector4a& v2 = mPositions[mIndices[i+2]]; + const LLVector4a& v0 = mPositions[mIndices[index]]; + const LLVector4a& v1 = mPositions[mIndices[index + 1]]; + const LLVector4a& v2 = mPositions[mIndices[index + 2]]; //store pointers to vertex data tri->mV[0] = &v0; @@ -5618,9 +5669,9 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe tri->mV[2] = &v2; //store indices - tri->mIndex[0] = mIndices[i]; - tri->mIndex[1] = mIndices[i+1]; - tri->mIndex[2] = mIndices[i+2]; + tri->mIndex[0] = mIndices[index]; + tri->mIndex[1] = mIndices[index + 1]; + tri->mIndex[2] = mIndices[index + 2]; //get minimum point LLVector4a min = v0; @@ -5663,6 +5714,19 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe } } +void LLVolumeFace::destroyOctree() +{ + delete mOctree; + mOctree = NULL; + delete[] mOctreeTriangles; + mOctreeTriangles = NULL; +} + +const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* LLVolumeFace::getOctree() const +{ + return mOctree; +} + void LLVolumeFace::swapData(LLVolumeFace& rhs) { @@ -6534,6 +6598,7 @@ void LLVolumeFace::allocateJointIndices(S32 num_verts) void LLVolumeFace::resizeIndices(S32 num_indices) { ll_aligned_free_16(mIndices); + llassert(num_indices % 3 == 0); if (num_indices) { |