SH-1732 Add streaming cost calculation for mesh objects.

master
Dave Parks 2011-06-02 22:58:57 -05:00
parent faef58a9b9
commit de5f93ca52
3 changed files with 297 additions and 4 deletions

View File

@ -416,6 +416,70 @@ LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BO
return face;
}
//static
S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split)
{ // this is basically LLProfile::genNGon stripped down to only the operations that influence the number of points
LLMemType m1(LLMemType::MTYPE_VOLUME);
S32 np = 0;
// Generate an n-sided "circular" path.
// 0 is (1,0), and we go counter-clockwise along a circular path from there.
F32 t, t_step, t_first, t_fraction;
F32 begin = params.getBegin();
F32 end = params.getEnd();
t_step = 1.0f / sides;
t_first = floor(begin * sides) / (F32)sides;
// pt1 is the first point on the fractional face.
// Starting t and ang values for the first face
t = t_first;
// Increment to the next point.
// pt2 is the end point on the fractional face
t += t_step;
t_fraction = (begin - t_first)*sides;
// Only use if it's not almost exactly on an edge.
if (t_fraction < 0.9999f)
{
np++;
}
// There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02
while (t < end)
{
// Iterate through all the integer steps of t.
np++;
t += t_step;
}
t_fraction = (end - (t - t_step))*sides;
// Find the fraction that we need to add to the end point.
t_fraction = (end - (t - t_step))*sides;
if (t_fraction > 0.0001f)
{
np++;
}
// If we're sliced, the profile is open.
if ((end - begin)*ang_scale < 0.99f)
{
if (params.getHollow() <= 0)
{
// put center point if not hollow.
np++;
}
}
return np;
}
// What is the bevel parameter used for? - DJS 04/05/02
// Bevel parameter is currently unused but presumedly would support
// filleted and chamfered corners
@ -672,6 +736,122 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3
return face;
}
//static
S32 LLProfile::getNumPoints(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
BOOL is_sculpted, S32 sculpt_size)
{ // this is basically LLProfile::generate stripped down to only operations that influence the number of points
LLMemType m1(LLMemType::MTYPE_VOLUME);
if (detail < MIN_LOD)
{
detail = MIN_LOD;
}
// Generate the face data
S32 i;
F32 begin = params.getBegin();
F32 end = params.getEnd();
F32 hollow = params.getHollow();
S32 face_num = 0;
S32 np = 0;
switch (params.getCurveType() & LL_PCODE_PROFILE_MASK)
{
case LL_PCODE_PROFILE_SQUARE:
{
np = getNumNGonPoints(params, 4,-0.375, 0, 1, split);
if (hollow)
{
np *= 2;
}
}
break;
case LL_PCODE_PROFILE_ISOTRI:
case LL_PCODE_PROFILE_RIGHTTRI:
case LL_PCODE_PROFILE_EQUALTRI:
{
np = getNumNGonPoints(params, 3,0, 0, 1, split);
if (hollow)
{
np *= 2;
}
}
break;
case LL_PCODE_PROFILE_CIRCLE:
{
// If this has a square hollow, we should adjust the
// number of faces a bit so that the geometry lines up.
U8 hole_type=0;
F32 circle_detail = MIN_DETAIL_FACES * detail;
if (hollow)
{
hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
if (hole_type == LL_PCODE_HOLE_SQUARE)
{
// Snap to the next multiple of four sides,
// so that corners line up.
circle_detail = llceil(circle_detail / 4.0f) * 4.0f;
}
}
S32 sides = (S32)circle_detail;
if (is_sculpted)
sides = sculpt_size;
np = getNumNGonPoints(params, sides);
if (hollow)
{
np *= 2;
}
}
break;
case LL_PCODE_PROFILE_CIRCLE_HALF:
{
// If this has a square hollow, we should adjust the
// number of faces a bit so that the geometry lines up.
U8 hole_type=0;
// Number of faces is cut in half because it's only a half-circle.
F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f;
if (hollow)
{
hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
if (hole_type == LL_PCODE_HOLE_SQUARE)
{
// Snap to the next multiple of four sides (div 2),
// so that corners line up.
circle_detail = llceil(circle_detail / 2.0f) * 2.0f;
}
}
np = getNumNGonPoints(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f);
if (hollow)
{
np *= 2;
}
// Special case for openness of sphere
if ((params.getEnd() - params.getBegin()) < 1.f)
{
}
else if (!hollow)
{
np++;
}
}
break;
default:
break;
};
return np;
}
BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
@ -1133,6 +1313,32 @@ LLPath::~LLPath()
{
}
S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
{ //this is basically LLPath::genNGon stripped down to only operations that influence the number of points added
S32 ret = 0;
F32 step= 1.0f / sides;
F32 t = params.getBegin();
ret = 1;
t+=step;
// Snap to a quantized parameter, so that cut does not
// affect most sample points.
t = ((S32)(t * sides)) / (F32)sides;
// Run through the non-cut dependent points.
while (t < params.getEnd())
{
ret++;
t+=step;
}
ret++;
return ret;
}
void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
{
// Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane.
@ -1310,6 +1516,56 @@ const LLVector2 LLPathParams::getEndScale() const
return end_scale;
}
S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail)
{ // this is basically LLPath::generate stripped down to only the operations that influence the number of points
LLMemType m1(LLMemType::MTYPE_VOLUME);
if (detail < MIN_LOD)
{
detail = MIN_LOD;
}
S32 np = 2; // hardcode for line
// Is this 0xf0 mask really necessary? DK 03/02/05
switch (params.getCurveType() & 0xf0)
{
default:
case LL_PCODE_PATH_LINE:
{
// Take the begin/end twist into account for detail.
np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2;
}
break;
case LL_PCODE_PATH_CIRCLE:
{
// Increase the detail as the revolutions and twist increase.
F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist());
S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions());
np = sides;
}
break;
case LL_PCODE_PATH_CIRCLE2:
{
//genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f);
np = getNumNGonPoints(params, llfloor(MIN_DETAIL_FACES * detail));
}
break;
case LL_PCODE_PATH_TEST:
np = 5;
break;
};
return np;
}
BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
BOOL is_sculpted, S32 sculpt_size)
{
@ -4065,6 +4321,23 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const
return index;
}
void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)
{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the
//supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost
F32 detail[] = {1.f, 1.5f, 2.5f, 4.f};
for (S32 i = 0; i < 4; i++)
{
S32 count = 0;
S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]);
S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]);
count = (profile_points-1)*2*(path_points-1);
count += profile_points*2;
counts[i] = count;
}
}
S32 LLVolume::getNumTriangleIndices() const
{
BOOL profile_open = getProfile().isOpen();

View File

@ -690,6 +690,9 @@ public:
BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); }
BOOL isOpen() const { return mOpen; }
void setDirty() { mDirty = TRUE; }
static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL isConcave() const { return mConcave; }
@ -714,6 +717,7 @@ public:
protected:
void genNormals(const LLProfileParams& params);
static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
@ -756,6 +760,9 @@ public:
virtual ~LLPath();
static S32 getNumPoints(const LLPathParams& params, F32 detail);
static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
@ -981,6 +988,7 @@ public:
// returns number of triangle indeces required for path/profile mesh
S32 getNumTriangleIndices() const;
static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
S32 getNumTriangles() const;

View File

@ -3096,16 +3096,28 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
{
F32 radius = getScale().length();
if (isMesh())
{
LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
F32 radius = getScale().length();
return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD);
}
return 0.f;
else
{
LLVolume* volume = getVolume();
S32 counts[4];
LLVolume::getLoDTriangleCounts(volume->getParams(), counts);
LLSD header;
header["lowest_lod"]["size"] = counts[0] * 10;
header["low_lod"]["size"] = counts[1] * 10;
header["medium_lod"]["size"] = counts[2] * 10;
header["high_lod"]["size"] = counts[3] * 10;
return LLMeshRepository::getStreamingCost(header, radius);
}
}
U32 LLVOVolume::getTriangleCount()