summaryrefslogtreecommitdiff
path: root/indra/llmath
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmath')
-rw-r--r--indra/llmath/llvolume.cpp124
-rw-r--r--indra/llmath/llvolume.h9
2 files changed, 103 insertions, 30 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 8b73f0ae8e..648f9a8d93 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2367,9 +2367,10 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
//input stream is now pointing at a zlib compressed block of LLSD
//decompress block
LLSD mdl;
- if (!unzip_llsd(mdl, is, size))
+ U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, is, size);
+ if (uzip_result != LLUZipHelper::ZR_OK)
{
- LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD, will probably fetch from sim again." << LL_ENDL;
+ LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL;
return false;
}
@@ -2676,11 +2677,17 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
}
}
}
+
+ if (!cacheOptimize())
+ {
+ // Out of memory?
+ LL_WARNS() << "Failed to optimize!" << LL_ENDL;
+ mVolumeFaces.clear();
+ return false;
+ }
mSculptLevel = 0; // success!
- cacheOptimize();
-
return true;
}
@@ -2712,12 +2719,16 @@ void LLVolume::copyVolumeFaces(const LLVolume* volume)
mSculptLevel = 0;
}
-void LLVolume::cacheOptimize()
+bool LLVolume::cacheOptimize()
{
for (S32 i = 0; i < mVolumeFaces.size(); ++i)
{
- mVolumeFaces[i].cacheOptimize();
+ if (!mVolumeFaces[i].cacheOptimize())
+ {
+ return false;
+ }
}
+ return true;
}
@@ -2910,15 +2921,41 @@ F32 LLVolume::sculptGetSurfaceArea()
return area;
}
-// create placeholder shape
-void LLVolume::sculptGeneratePlaceholder()
+// create empty placeholder shape
+void LLVolume::sculptGenerateEmptyPlaceholder()
{
S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size();
-
+
+ S32 line = 0;
+
+ for (S32 s = 0; s < sizeS; s++)
+ {
+ for (S32 t = 0; t < sizeT; t++)
+ {
+ S32 i = t + line;
+ LLVector4a& pt = mMesh[i];
+
+ F32* p = pt.getF32ptr();
+
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+
+ llassert(pt.isFinite3());
+ }
+ line += sizeT;
+ }
+}
+
+// create sphere placeholder shape
+void LLVolume::sculptGenerateSpherePlaceholder()
+{
+ S32 sizeS = mPathp->mPath.size();
+ S32 sizeT = mProfilep->mProfile.size();
+
S32 line = 0;
- // for now, this is a sphere.
for (S32 s = 0; s < sizeS; s++)
{
for (S32 t = 0; t < sizeT; t++)
@@ -2926,12 +2963,12 @@ void LLVolume::sculptGeneratePlaceholder()
S32 i = t + line;
LLVector4a& pt = mMesh[i];
-
- F32 u = (F32)s/(sizeS-1);
- F32 v = (F32)t/(sizeT-1);
+
+ F32 u = (F32)s / (sizeS - 1);
+ F32 v = (F32)t / (sizeT - 1);
const F32 RADIUS = (F32) 0.3;
-
+
F32* p = pt.getF32ptr();
p[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS);
@@ -2939,7 +2976,6 @@ void LLVolume::sculptGeneratePlaceholder()
p[2] = (F32)(cos(F_PI * v) * RADIUS);
llassert(pt.isFinite3());
-
}
line += sizeT;
}
@@ -3102,9 +3138,9 @@ void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32
}
// sculpt replaces generate() for sculpted surfaces
-void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level)
+void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder)
{
- U8 sculpt_type = mParams.getSculptType();
+ U8 sculpt_type = mParams.getSculptType();
BOOL data_is_empty = FALSE;
@@ -3152,13 +3188,22 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
{
data_is_empty = TRUE;
+ visible_placeholder = true;
}
}
}
if (data_is_empty)
{
- sculptGeneratePlaceholder();
+ if (visible_placeholder)
+ {
+ // Object should be visible since there will be nothing else to display
+ sculptGenerateSpherePlaceholder();
+ }
+ else
+ {
+ sculptGenerateEmptyPlaceholder();
+ }
}
@@ -5173,7 +5218,7 @@ public:
};
-void LLVolumeFace::cacheOptimize()
+bool LLVolumeFace::cacheOptimize()
{ //optimize for vertex cache according to Forsyth method:
// http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
@@ -5184,7 +5229,7 @@ void LLVolumeFace::cacheOptimize()
if (mNumVertices < 3)
{ //nothing to do
- return;
+ return true;
}
//mapping of vertices to triangles and indices
@@ -5193,8 +5238,16 @@ void LLVolumeFace::cacheOptimize()
//mapping of triangles do vertices
std::vector<LLVCacheTriangleData> triangle_data;
- triangle_data.resize(mNumIndices/3);
- vertex_data.resize(mNumVertices);
+ try
+ {
+ triangle_data.resize(mNumIndices / 3);
+ vertex_data.resize(mNumVertices);
+ }
+ catch (std::bad_alloc)
+ {
+ LL_WARNS("LLVOLUME") << "Resize failed" << LL_ENDL;
+ return false;
+ }
for (U32 i = 0; i < mNumIndices; i++)
{ //populate vertex data and triangle data arrays
@@ -5306,7 +5359,8 @@ void LLVolumeFace::cacheOptimize()
LLVector4a* pos = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+size);
if (pos == NULL)
{
- LL_ERRS("LLVOLUME") << "Allocation of positions vector[" << sizeof(LLVector4a) * 2 * num_verts + size << "] failed. " << LL_ENDL;
+ LL_WARNS("LLVOLUME") << "Allocation of positions vector[" << sizeof(LLVector4a) * 2 * num_verts + size << "] failed. " << LL_ENDL;
+ return false;
}
LLVector4a* norm = pos + num_verts;
LLVector2* tc = (LLVector2*) (norm + num_verts);
@@ -5317,7 +5371,9 @@ void LLVolumeFace::cacheOptimize()
wght = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
if (wght == NULL)
{
- LL_ERRS("LLVOLUME") << "Allocation of weights[" << sizeof(LLVector4a) * num_verts << "] failed" << LL_ENDL;
+ ll_aligned_free<64>(pos);
+ LL_WARNS("LLVOLUME") << "Allocation of weights[" << sizeof(LLVector4a) * num_verts << "] failed" << LL_ENDL;
+ return false;
}
}
@@ -5327,13 +5383,28 @@ void LLVolumeFace::cacheOptimize()
binorm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
if (binorm == NULL)
{
- LL_ERRS("LLVOLUME") << "Allocation of binormals[" << sizeof(LLVector4a)*num_verts << "] failed" << LL_ENDL;
+ ll_aligned_free<64>(pos);
+ ll_aligned_free_16(wght);
+ LL_WARNS("LLVOLUME") << "Allocation of binormals[" << sizeof(LLVector4a)*num_verts << "] failed" << LL_ENDL;
+ return false;
}
}
//allocate mapping of old indices to new indices
std::vector<S32> new_idx;
- new_idx.resize(mNumVertices, -1);
+
+ try
+ {
+ new_idx.resize(mNumVertices, -1);
+ }
+ catch (std::bad_alloc)
+ {
+ ll_aligned_free<64>(pos);
+ ll_aligned_free_16(wght);
+ ll_aligned_free_16(binorm);
+ LL_WARNS("LLVOLUME") << "Resize failed: " << mNumVertices << LL_ENDL;
+ return false;
+ }
S32 cur_idx = 0;
for (U32 i = 0; i < mNumIndices; ++i)
@@ -5379,6 +5450,7 @@ void LLVolumeFace::cacheOptimize()
//std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
//LL_INFOS() << result << LL_ENDL;
+ return true;
}
void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size)
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index bba691d243..4357b69b90 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -903,7 +903,7 @@ public:
};
void optimize(F32 angle_cutoff = 2.f);
- void cacheOptimize();
+ bool cacheOptimize();
void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
@@ -1059,16 +1059,17 @@ public:
U32 mFaceMask; // bit array of which faces exist in this volume
LLVector3 mLODScaleBias; // vector for biasing LOD based on scale
- void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level);
+ void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder);
void copyVolumeFaces(const LLVolume* volume);
void copyFacesTo(std::vector<LLVolumeFace> &faces) const;
void copyFacesFrom(const std::vector<LLVolumeFace> &faces);
- void cacheOptimize();
+ bool cacheOptimize();
private:
void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
F32 sculptGetSurfaceArea();
- void sculptGeneratePlaceholder();
+ void sculptGenerateEmptyPlaceholder();
+ void sculptGenerateSpherePlaceholder();
void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t);