diff options
| -rw-r--r-- | indra/llmath/llvolume.cpp | 273 | ||||
| -rw-r--r-- | indra/llmath/llvolume.h | 8 | ||||
| -rw-r--r-- | indra/newview/llvovolume.cpp | 20 | 
3 files changed, 297 insertions, 4 deletions
| diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index fbda824179..fa94a7934e 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -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(); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 01bfbd858b..f67f8f644d 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -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; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index c917a5fd9d..39e555f781 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -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() | 
