summaryrefslogtreecommitdiff
path: root/indra/llmath
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmath')
-rw-r--r--indra/llmath/llvolume.cpp269
-rw-r--r--indra/llmath/llvolume.h4
2 files changed, 172 insertions, 101 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index ab2eef0ee9..44fef9daf6 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -1854,55 +1854,70 @@ inline LLVector3 sculpt_rgb_to_vector(U8 r, U8 g, U8 b)
return value;
}
+inline U32 sculpt_xy_to_index(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components)
+{
+ U32 index = (x + y * sculpt_width) * sculpt_components;
-// 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)
+ // attempt to resolve DEV-11158 - remove assert later.
+ llassert(index < sculpt_width * sculpt_height * sculpt_components);
+
+ return index;
+}
+
+
+inline U32 sculpt_st_to_index(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components)
{
- U8 sculpt_type = mParams.getSculptType();
+ U32 x = (U32) ((F32)s/(size_s) * (F32) sculpt_width);
+ U32 y = (U32) ((F32)t/(size_t) * (F32) sculpt_height);
- BOOL data_is_empty = FALSE;
+ return sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components);
+}
- if (sculpt_width == 0 || sculpt_height == 0 || sculpt_data == NULL)
- {
- sculpt_level = -1;
- data_is_empty = TRUE;
- }
- mPathp->generate(mDetail, 0, TRUE);
- mProfilep->generate(mPathp->isOpen(), mDetail, 0, TRUE);
-
+inline LLVector3 sculpt_index_to_vector(U32 index, const U8* sculpt_data)
+{
+ LLVector3 v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]);
+
+ return v;
+}
+
+inline LLVector3 sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)
+{
+ U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components);
+
+ return sculpt_index_to_vector(index, sculpt_data);
+}
+
+inline LLVector3 sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)
+{
+ U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components);
+
+ return sculpt_index_to_vector(index, sculpt_data);
+}
+
+
+F32 LLVolume::sculptGetSurfaceArea(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)
+{
+ // test to see if image has enough variation to create non-degenerate geometry
+
S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size();
- sNumMeshPoints -= mMesh.size();
- mMesh.resize(sizeS * sizeT);
- sNumMeshPoints += mMesh.size();
-
F32 area = 0;
- // first test to see if image has enough variation to create non-degenerate geometry
- if (!data_is_empty)
+
+ if ((sculpt_width != 0) &&
+ (sculpt_height != 0) &&
+ (sculpt_components != 0) &&
+ (sculpt_data != NULL))
{
for (S32 s = 0; s < sizeS - 1; s++)
{
for (S32 t = 0; t < sizeT - 1; t++)
{
- // first coordinate
- U32 x = (U32) ((F32)s/(sizeS) * (F32) sculpt_width);
- U32 y = (U32) ((F32)t/(sizeT) * (F32) sculpt_height);
-
- // coordinate offset by 1
- U32 x2 = (U32) ((F32)(s+1)/(sizeS) * (F32) sculpt_width);
- U32 y2 = (U32) ((F32)(t+1)/(sizeT) * (F32) sculpt_height);
-
- // three points on a triagle - find the image indices first
- U32 p1_index = (x + y * sculpt_width) * sculpt_components;
- U32 p2_index = (x2 + y * sculpt_width) * sculpt_components;
- U32 p3_index = (x + y2 * sculpt_width) * sculpt_components;
-
// convert image data to vectors
- LLVector3 p1 = sculpt_rgb_to_vector(sculpt_data[p1_index], sculpt_data[p1_index+1], sculpt_data[p1_index+2]);
- LLVector3 p2 = sculpt_rgb_to_vector(sculpt_data[p2_index], sculpt_data[p2_index+1], sculpt_data[p2_index+2]);
- LLVector3 p3 = sculpt_rgb_to_vector(sculpt_data[p3_index], sculpt_data[p3_index+1], sculpt_data[p3_index+2]);
+ LLVector3 p1 = sculpt_st_to_vector(s, t, sizeS, sizeT, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
+ LLVector3 p2 = sculpt_st_to_vector(s+1, t, sizeS, sizeT, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
+ LLVector3 p3 = sculpt_st_to_vector(s, t+1, sizeS, sizeT, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
// compute the area of the parallelogram by taking the length of the cross product:
// (parallegram is an approximation of two triangles)
@@ -1910,99 +1925,151 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
area += cross.magVec();
}
}
- if (area < SCULPT_MIN_AREA)
- data_is_empty = TRUE;
}
- //generate vertex positions
- if (data_is_empty) // if empty, make a sphere
- {
- S32 line = 0;
+ return area;
+}
+
+// create placeholder shape
+void LLVolume::sculptGeneratePlaceholder()
+{
+ S32 sizeS = mPathp->mPath.size();
+ S32 sizeT = mProfilep->mProfile.size();
+
+ S32 line = 0;
- for (S32 s = 0; s < sizeS; s++)
+ // for now, this is a sphere.
+ for (S32 s = 0; s < sizeS; s++)
+ {
+ for (S32 t = 0; t < sizeT; t++)
{
- for (S32 t = 0; t < sizeT; t++)
- {
- S32 i = t + line;
- Point& pt = mMesh[i];
+ S32 i = t + line;
+ Point& 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;
+ const F32 RADIUS = (F32) 0.3;
- pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS);
- pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS);
- pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS);
+ pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS);
+ pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS);
+ pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS);
- }
- line += sizeT;
}
- }
- else
+ line += sizeT;
+ }
+}
+
+// create the vertices from the map
+void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type)
+{
+ S32 sizeS = mPathp->mPath.size();
+ S32 sizeT = mProfilep->mProfile.size();
+
+ S32 line = 0;
+ for (S32 s = 0; s < sizeS; s++)
{
- S32 line = 0;
- for (S32 s = 0; s < sizeS; s++)
+ // Run along the profile.
+ for (S32 t = 0; t < sizeT; t++)
{
- // Run along the profile.
- for (S32 t = 0; t < sizeT; t++)
- {
- S32 i = t + line;
- Point& pt = mMesh[i];
+ S32 i = t + line;
+ Point& pt = mMesh[i];
- U32 x = (U32) ((F32)t/(sizeT-1) * (F32) sculpt_width);
- U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height);
+ U32 x = (U32) ((F32)t/(sizeT-1) * (F32) sculpt_width);
+ U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height);
- if (y == 0) // top row stitching
+ if (y == 0) // top row stitching
+ {
+ // pinch?
+ if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
{
- // pinch?
- if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
- {
- x = sculpt_width / 2;
- }
+ x = sculpt_width / 2;
}
+ }
- if (y == sculpt_height) // bottom row stitching
+ if (y == sculpt_height) // bottom row stitching
+ {
+ // wrap?
+ if (sculpt_type == LL_SCULPT_TYPE_TORUS)
{
- // wrap?
- if (sculpt_type == LL_SCULPT_TYPE_TORUS)
- {
- y = 0;
- }
- else
- {
- y = sculpt_height - 1;
- }
+ y = 0;
+ }
+ else
+ {
+ y = sculpt_height - 1;
+ }
- // pinch?
- if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
- {
- x = sculpt_width / 2;
- }
+ // pinch?
+ if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
+ {
+ x = sculpt_width / 2;
}
+ }
- if (x == sculpt_width) // side stitching
+ if (x == sculpt_width) // side stitching
+ {
+ // wrap?
+ if ((sculpt_type == LL_SCULPT_TYPE_SPHERE) ||
+ (sculpt_type == LL_SCULPT_TYPE_TORUS) ||
+ (sculpt_type == LL_SCULPT_TYPE_CYLINDER))
{
- // wrap?
- if ((sculpt_type == LL_SCULPT_TYPE_SPHERE) ||
- (sculpt_type == LL_SCULPT_TYPE_TORUS) ||
- (sculpt_type == LL_SCULPT_TYPE_CYLINDER))
- {
- x = 0;
- }
+ x = 0;
+ }
- else
- {
- x = sculpt_width - 1;
- }
+ else
+ {
+ x = sculpt_width - 1;
}
-
- U32 index = (x + y * sculpt_width) * sculpt_components;
- pt.mPos = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]);
}
- line += sizeT;
+
+ pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
}
+ line += sizeT;
+ }
+}
+
+
+// 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)
+{
+ U8 sculpt_type = mParams.getSculptType();
+
+ BOOL data_is_empty = FALSE;
+
+ if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components == 0 || sculpt_data == NULL)
+ {
+ sculpt_level = -1;
+ data_is_empty = TRUE;
+ }
+
+ mPathp->generate(mDetail, 0, TRUE);
+ mProfilep->generate(mPathp->isOpen(), mDetail, 0, TRUE);
+
+ S32 sizeS = mPathp->mPath.size();
+ S32 sizeT = mProfilep->mProfile.size();
+
+ // weird crash bug - DEV-11158 - trying to collect more data:
+ if ((sizeS == 0) || (sizeT == 0))
+ {
+ llwarns << "sculpt bad mesh size " << sizeS << " " << sizeT << llendl;
+ }
+
+ sNumMeshPoints -= mMesh.size();
+ mMesh.resize(sizeS * sizeT);
+ sNumMeshPoints += mMesh.size();
+
+ if (sculptGetSurfaceArea(sculpt_width, sculpt_height, sculpt_components, sculpt_data) < SCULPT_MIN_AREA)
+ data_is_empty = TRUE;
+
+ //generate vertex positions
+ if (data_is_empty) // if empty, make a placeholder mesh
+ {
+ sculptGeneratePlaceholder();
+ }
+ else
+ {
+ sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type);
}
for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++)
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 3e61947947..9af02d2629 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -903,6 +903,10 @@ public:
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);
+private:
+ F32 sculptGetSurfaceArea(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data);
+ void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
+ void sculptGeneratePlaceholder();
protected:
BOOL generate();