SH-1732 Add streaming cost calculation for mesh objects.
parent
faef58a9b9
commit
de5f93ca52
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue