diff options
Diffstat (limited to 'indra/llmath')
93 files changed, 362 insertions, 311 deletions
| diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 5865ae030c..0614fd92ef 100644..100755 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -7,6 +7,7 @@ include(LLCommon)  include_directories(      ${LLCOMMON_INCLUDE_DIRS} +    ${LLCOMMON_SYSTEM_INCLUDE_DIRS}      )  set(llmath_SOURCE_FILES @@ -99,6 +100,10 @@ list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES})  add_library (llmath ${llmath_SOURCE_FILES}) +target_link_libraries(llmath +    ${LLCOMMON_LIBRARIES} +    ) +  # Add tests  if (LL_TESTS)    include(LLAddBuildTest) diff --git a/indra/llmath/camera.h b/indra/llmath/camera.h index 26f3c3d19f..26f3c3d19f 100644..100755 --- a/indra/llmath/camera.h +++ b/indra/llmath/camera.h diff --git a/indra/llmath/coordframe.h b/indra/llmath/coordframe.h index 271bcb433c..271bcb433c 100644..100755 --- a/indra/llmath/coordframe.h +++ b/indra/llmath/coordframe.h diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp index 3e2c05a6e6..3e2c05a6e6 100644..100755 --- a/indra/llmath/llbbox.cpp +++ b/indra/llmath/llbbox.cpp diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h index 28e69b75e1..28e69b75e1 100644..100755 --- a/indra/llmath/llbbox.h +++ b/indra/llmath/llbbox.h diff --git a/indra/llmath/llbboxlocal.cpp b/indra/llmath/llbboxlocal.cpp index bf0c1a7b93..bf0c1a7b93 100644..100755 --- a/indra/llmath/llbboxlocal.cpp +++ b/indra/llmath/llbboxlocal.cpp diff --git a/indra/llmath/llbboxlocal.h b/indra/llmath/llbboxlocal.h index defb899248..defb899248 100644..100755 --- a/indra/llmath/llbboxlocal.h +++ b/indra/llmath/llbboxlocal.h diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp index 1b2d609b67..1b2d609b67 100644..100755 --- a/indra/llmath/llcalc.cpp +++ b/indra/llmath/llcalc.cpp diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h index ceb9dce585..ceb9dce585 100644..100755 --- a/indra/llmath/llcalc.h +++ b/indra/llmath/llcalc.h diff --git a/indra/llmath/llcalcparser.cpp b/indra/llmath/llcalcparser.cpp index b4ca320659..b4ca320659 100644..100755 --- a/indra/llmath/llcalcparser.cpp +++ b/indra/llmath/llcalcparser.cpp diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h index e0ad270266..e0ad270266 100644..100755 --- a/indra/llmath/llcalcparser.h +++ b/indra/llmath/llcalcparser.h diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index 22ba26f99b..33cf185196 100644..100755 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -42,6 +42,11 @@ LLCamera::LLCamera() :  	mPlaneCount(6),  	mFrustumCornerDist(0.f)  { +	for (U32 i = 0; i < PLANE_MASK_NUM; i++) +	{ +		mPlaneMask[i] = PLANE_MASK_NONE; +	} +  	calculateFrustumPlanes();  }  @@ -52,6 +57,11 @@ LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_p  	mPlaneCount(6),  	mFrustumCornerDist(0.f)  { +	for (U32 i = 0; i < PLANE_MASK_NUM; i++) +	{ +		mPlaneMask[i] = PLANE_MASK_NONE; +	} +  	mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);  	mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE);  	if(far_plane < 0) far_plane = DEFAULT_FAR_PLANE; @@ -87,14 +97,14 @@ F32 LLCamera::getMaxView() const  void LLCamera::setUserClipPlane(LLPlane& plane)  { -	mPlaneCount = 7; -	mAgentPlanes[6] = plane; -	mPlaneMask[6] = plane.calcPlaneMask(); +	mPlaneCount = AGENT_PLANE_USER_CLIP_NUM; +	mAgentPlanes[AGENT_PLANE_USER_CLIP] = plane; +	mPlaneMask[AGENT_PLANE_USER_CLIP] = plane.calcPlaneMask();  }  void LLCamera::disableUserClipPlane()  { -	mPlaneCount = 6; +	mPlaneCount = AGENT_PLANE_NO_USER_CLIP_NUM;  }  void LLCamera::setView(F32 vertical_fov_rads)  @@ -161,31 +171,33 @@ size_t LLCamera::readFrustumFromBuffer(const char *buffer)  // ---------------- test methods  ----------------  -S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius)  +static	const LLVector4a sFrustumScaler[] =   { -	static const LLVector4a scaler[] = { -		LLVector4a(-1,-1,-1), -		LLVector4a( 1,-1,-1), -		LLVector4a(-1, 1,-1), -		LLVector4a( 1, 1,-1), -		LLVector4a(-1,-1, 1), -		LLVector4a( 1,-1, 1), -		LLVector4a(-1, 1, 1), -		LLVector4a( 1, 1, 1) -	}; +	LLVector4a(-1,-1,-1), +	LLVector4a( 1,-1,-1), +	LLVector4a(-1, 1,-1), +	LLVector4a( 1, 1,-1), +	LLVector4a(-1,-1, 1), +	LLVector4a( 1,-1, 1), +	LLVector4a(-1, 1, 1), +	LLVector4a( 1, 1, 1)		// 8 entries +}; +S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius)  +{  	U8 mask = 0;  	bool result = false;  	LLVector4a rscale, maxp, minp;  	LLSimdScalar d; -	for (U32 i = 0; i < mPlaneCount; i++) +	U32 max_planes = llmin(mPlaneCount, (U32) AGENT_PLANE_USER_CLIP_NUM);		// mAgentPlanes[] size is 7 +	for (U32 i = 0; i < max_planes; i++)  	{  		mask = mPlaneMask[i]; -		if (mask != 0xff) +		if (mask < PLANE_MASK_NUM)  		{  			const LLPlane& p(mAgentPlanes[i]);  			p.getAt<3>(d); -			rscale.setMul(radius, scaler[mask]); +			rscale.setMul(radius, sFrustumScaler[mask]);  			minp.setSub(center, rscale);  			d = -d;  			if (p.dot3(minp).getF32() > d)  @@ -207,29 +219,19 @@ S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius)  S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius)   { -	static const LLVector4a scaler[] = { -		LLVector4a(-1,-1,-1), -		LLVector4a( 1,-1,-1), -		LLVector4a(-1, 1,-1), -		LLVector4a( 1, 1,-1), -		LLVector4a(-1,-1, 1), -		LLVector4a( 1,-1, 1), -		LLVector4a(-1, 1, 1), -		LLVector4a( 1, 1, 1) -	}; -  	U8 mask = 0;  	bool result = false;  	LLVector4a rscale, maxp, minp;  	LLSimdScalar d; -	for (U32 i = 0; i < mPlaneCount; i++) +	U32 max_planes = llmin(mPlaneCount, (U32) AGENT_PLANE_USER_CLIP_NUM);		// mAgentPlanes[] size is 7 +	for (U32 i = 0; i < max_planes; i++)  	{  		mask = mPlaneMask[i]; -		if ((i != 5) && (mask != 0xff)) +		if ((i != 5) && (mask < PLANE_MASK_NUM))  		{  			const LLPlane& p(mAgentPlanes[i]);  			p.getAt<3>(d); -			rscale.setMul(radius, scaler[mask]); +			rscale.setMul(radius, sFrustumScaler[mask]);  			minp.setSub(center, rscale);  			d = -d;  			if (p.dot3(minp).getF32() > d)  @@ -369,7 +371,7 @@ int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius)  	bool res = false;  	for (int i = 0; i < 6; i++)  	{ -		if (mPlaneMask[i] != 0xff) +		if (mPlaneMask[i] != PLANE_MASK_NONE)  		{  			float d = mAgentPlanes[i].dist(sphere_center); @@ -541,14 +543,14 @@ void LLCamera::ignoreAgentFrustumPlane(S32 idx)  		return;  	} -	mPlaneMask[idx] = 0xff; +	mPlaneMask[idx] = PLANE_MASK_NONE;  	mAgentPlanes[idx].clear();  }  void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)  { -	for (int i = 0; i < 8; i++) +	for (int i = 0; i < AGENT_FRUSTRUM_NUM; i++)  	{  		mAgentFrustum[i] = frust[i];  	} @@ -560,22 +562,22 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)  	//order of planes is important, keep most likely to fail in the front of the list  	//near - frust[0], frust[1], frust[2] -	mAgentPlanes[2] = planeFromPoints(frust[0], frust[1], frust[2]); +	mAgentPlanes[AGENT_PLANE_NEAR] = planeFromPoints(frust[0], frust[1], frust[2]);  	//far   -	mAgentPlanes[5] = planeFromPoints(frust[5], frust[4], frust[6]); +	mAgentPlanes[AGENT_PLANE_FAR] = planeFromPoints(frust[5], frust[4], frust[6]);  	//left   -	mAgentPlanes[0] = planeFromPoints(frust[4], frust[0], frust[7]); +	mAgentPlanes[AGENT_PLANE_LEFT] = planeFromPoints(frust[4], frust[0], frust[7]);  	//right   -	mAgentPlanes[1] = planeFromPoints(frust[1], frust[5], frust[6]); +	mAgentPlanes[AGENT_PLANE_RIGHT] = planeFromPoints(frust[1], frust[5], frust[6]);  	//top   -	mAgentPlanes[4] = planeFromPoints(frust[3], frust[2], frust[6]); +	mAgentPlanes[AGENT_PLANE_TOP] = planeFromPoints(frust[3], frust[2], frust[6]);  	//bottom   -	mAgentPlanes[3] = planeFromPoints(frust[1], frust[0], frust[4]); +	mAgentPlanes[AGENT_PLANE_BOTTOM] = planeFromPoints(frust[1], frust[0], frust[4]);  	//cache plane octant facing mask for use in AABBInFrustum  	for (U32 i = 0; i < mPlaneCount; i++) @@ -635,7 +637,7 @@ void LLCamera::calculateWorldFrustumPlanes()  	LLVector3 center = mOrigin - mXAxis*mNearPlane;  	mWorldPlanePos = center;  	LLVector3 pnorm;	 -	for (int p=0; p<4; p++) +	for (int p = 0; p < PLANE_NUM; p++)  	{  		mLocalPlanes[p].getVector3(pnorm);  		LLVector3 norm = rotateToAbsolute(pnorm); diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index 0b591be622..1283cfb16b 100644..100755 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -76,26 +76,39 @@ public:  		PLANE_RIGHT = 1,  		PLANE_BOTTOM = 2,  		PLANE_TOP = 3, -		PLANE_NUM = 4 +		PLANE_NUM = 4, +		PLANE_MASK_NONE = 0xff		// Disable this plane  	};  	enum {  		PLANE_LEFT_MASK = (1<<PLANE_LEFT),  		PLANE_RIGHT_MASK = (1<<PLANE_RIGHT),  		PLANE_BOTTOM_MASK = (1<<PLANE_BOTTOM),  		PLANE_TOP_MASK = (1<<PLANE_TOP), -		PLANE_ALL_MASK = 0xf +		PLANE_ALL_MASK = 0xf,  	};  	enum -	{ +	{	// Indexes to mAgentPlanes[] and mPlaneMask[]  		AGENT_PLANE_LEFT = 0, -		AGENT_PLANE_RIGHT, -		AGENT_PLANE_NEAR, -		AGENT_PLANE_BOTTOM, -		AGENT_PLANE_TOP, -		AGENT_PLANE_FAR, +		AGENT_PLANE_RIGHT = 1, +		AGENT_PLANE_NEAR = 2, +		AGENT_PLANE_BOTTOM = 3, +		AGENT_PLANE_TOP = 4, +		AGENT_PLANE_FAR = 5, +		AGENT_PLANE_USER_CLIP = 6 +	}; +	enum +	{	// Sizes for mAgentPlanes[].  7th entry is special case for user clip +		AGENT_PLANE_NO_USER_CLIP_NUM = 6, +		AGENT_PLANE_USER_CLIP_NUM = 7, +		PLANE_MASK_NUM = 8			// 7 actually used, 8 is for alignment  	}; +	enum +	{ +		AGENT_FRUSTRUM_NUM = 8 +	}; +	  	enum {  		HORIZ_PLANE_LEFT = 0,  		HORIZ_PLANE_RIGHT = 1, @@ -108,15 +121,15 @@ public:  	};  private: -	LL_ALIGN_16(LLPlane mAgentPlanes[7]);  //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP -	U8 mPlaneMask[8];         // 8 for alignment	 +	LL_ALIGN_16(LLPlane mAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]);  //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP +	U8 mPlaneMask[PLANE_MASK_NUM];         // 8 for alignment	  	F32 mView;					// angle between top and bottom frustum planes in radians.  	F32 mAspect;				// width/height  	S32 mViewHeightInPixels;	// for ViewHeightInPixels() only  	F32 mNearPlane;  	F32 mFarPlane; -	LL_ALIGN_16(LLPlane mLocalPlanes[4]); +	LL_ALIGN_16(LLPlane mLocalPlanes[PLANE_NUM]);  	F32 mFixedDistance;			// Always return this distance, unless < 0  	LLVector3 mFrustCenter;		// center of frustum and radius squared for ultra-quick exclusion test  	F32 mFrustRadiusSquared; @@ -128,7 +141,7 @@ private:  	LLVector3 mWorldPlanePos;		// Position of World Planes (may be offset from camera)  public: -	LLVector3 mAgentFrustum[8];  //8 corners of 6-plane frustum +	LLVector3 mAgentFrustum[AGENT_FRUSTRUM_NUM];  //8 corners of 6-plane frustum  	F32	mFrustumCornerDist;		//distance to corner of frustum against far clip plane  	LLPlane& getAgentPlane(U32 idx) { return mAgentPlanes[idx]; } diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h index 9b76268afd..9b76268afd 100644..100755 --- a/indra/llmath/llcoord.h +++ b/indra/llmath/llcoord.h diff --git a/indra/llmath/llcoordframe.cpp b/indra/llmath/llcoordframe.cpp index 7dd8e43185..7dd8e43185 100644..100755 --- a/indra/llmath/llcoordframe.cpp +++ b/indra/llmath/llcoordframe.cpp diff --git a/indra/llmath/llcoordframe.h b/indra/llmath/llcoordframe.h index 909adf260c..909adf260c 100644..100755 --- a/indra/llmath/llcoordframe.h +++ b/indra/llmath/llcoordframe.h diff --git a/indra/llmath/llinterp.h b/indra/llmath/llinterp.h index 5187646179..5187646179 100644..100755 --- a/indra/llmath/llinterp.h +++ b/indra/llmath/llinterp.h diff --git a/indra/llmath/llline.cpp b/indra/llmath/llline.cpp index ef10d1e7fa..ef10d1e7fa 100644..100755 --- a/indra/llmath/llline.cpp +++ b/indra/llmath/llline.cpp diff --git a/indra/llmath/llline.h b/indra/llmath/llline.h index e1cbc1323e..e1cbc1323e 100644..100755 --- a/indra/llmath/llline.h +++ b/indra/llmath/llline.h diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index b93f89d674..b93f89d674 100644..100755 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h diff --git a/indra/llmath/llmatrix3a.cpp b/indra/llmath/llmatrix3a.cpp index ab077abcb0..ab077abcb0 100644..100755 --- a/indra/llmath/llmatrix3a.cpp +++ b/indra/llmath/llmatrix3a.cpp diff --git a/indra/llmath/llmatrix3a.h b/indra/llmath/llmatrix3a.h index 9916cfd2da..9916cfd2da 100644..100755 --- a/indra/llmath/llmatrix3a.h +++ b/indra/llmath/llmatrix3a.h diff --git a/indra/llmath/llmatrix3a.inl b/indra/llmath/llmatrix3a.inl index 37819fea3c..37819fea3c 100644..100755 --- a/indra/llmath/llmatrix3a.inl +++ b/indra/llmath/llmatrix3a.inl diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index c4cefdb4fa..c4cefdb4fa 100644..100755 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h diff --git a/indra/llmath/llmodularmath.cpp b/indra/llmath/llmodularmath.cpp index cdc20028bf..cdc20028bf 100644..100755 --- a/indra/llmath/llmodularmath.cpp +++ b/indra/llmath/llmodularmath.cpp diff --git a/indra/llmath/llmodularmath.h b/indra/llmath/llmodularmath.h index 0d4d28fadc..0d4d28fadc 100644..100755 --- a/indra/llmath/llmodularmath.h +++ b/indra/llmath/llmodularmath.h diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 7348904c61..7348904c61 100644..100755 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h diff --git a/indra/llmath/llperlin.cpp b/indra/llmath/llperlin.cpp index e1da2bf92b..e1da2bf92b 100644..100755 --- a/indra/llmath/llperlin.cpp +++ b/indra/llmath/llperlin.cpp diff --git a/indra/llmath/llperlin.h b/indra/llmath/llperlin.h index 40cf19d1ec..40cf19d1ec 100644..100755 --- a/indra/llmath/llperlin.h +++ b/indra/llmath/llperlin.h diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h index 3c32441b11..3c32441b11 100644..100755 --- a/indra/llmath/llplane.h +++ b/indra/llmath/llplane.h diff --git a/indra/llmath/llquantize.h b/indra/llmath/llquantize.h index 1595dbecf8..1595dbecf8 100644..100755 --- a/indra/llmath/llquantize.h +++ b/indra/llmath/llquantize.h diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp index 7381d5eb99..7381d5eb99 100644..100755 --- a/indra/llmath/llquaternion.cpp +++ b/indra/llmath/llquaternion.cpp diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h index ca0dfe206b..ca0dfe206b 100644..100755 --- a/indra/llmath/llquaternion.h +++ b/indra/llmath/llquaternion.h diff --git a/indra/llmath/llquaternion2.h b/indra/llmath/llquaternion2.h index fd9c0cf3ab..fd9c0cf3ab 100644..100755 --- a/indra/llmath/llquaternion2.h +++ b/indra/llmath/llquaternion2.h diff --git a/indra/llmath/llquaternion2.inl b/indra/llmath/llquaternion2.inl index 2a6987552d..2a6987552d 100644..100755 --- a/indra/llmath/llquaternion2.inl +++ b/indra/llmath/llquaternion2.inl diff --git a/indra/llmath/llrect.cpp b/indra/llmath/llrect.cpp index 4083c99768..4083c99768 100644..100755 --- a/indra/llmath/llrect.cpp +++ b/indra/llmath/llrect.cpp diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h index c51e0e0ae6..c51e0e0ae6 100644..100755 --- a/indra/llmath/llrect.h +++ b/indra/llmath/llrect.h diff --git a/indra/llmath/llsdutil_math.cpp b/indra/llmath/llsdutil_math.cpp index 591f7fde36..591f7fde36 100644..100755 --- a/indra/llmath/llsdutil_math.cpp +++ b/indra/llmath/llsdutil_math.cpp diff --git a/indra/llmath/llsdutil_math.h b/indra/llmath/llsdutil_math.h index 0ea78cd231..0ea78cd231 100644..100755 --- a/indra/llmath/llsdutil_math.h +++ b/indra/llmath/llsdutil_math.h diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h index 01458521ec..01458521ec 100644..100755 --- a/indra/llmath/llsimdmath.h +++ b/indra/llmath/llsimdmath.h diff --git a/indra/llmath/llsimdtypes.h b/indra/llmath/llsimdtypes.h index bd991d0e71..bd991d0e71 100644..100755 --- a/indra/llmath/llsimdtypes.h +++ b/indra/llmath/llsimdtypes.h diff --git a/indra/llmath/llsimdtypes.inl b/indra/llmath/llsimdtypes.inl index e905c84954..e905c84954 100644..100755 --- a/indra/llmath/llsimdtypes.inl +++ b/indra/llmath/llsimdtypes.inl diff --git a/indra/llmath/llsphere.cpp b/indra/llmath/llsphere.cpp index 740047b93a..740047b93a 100644..100755 --- a/indra/llmath/llsphere.cpp +++ b/indra/llmath/llsphere.cpp diff --git a/indra/llmath/llsphere.h b/indra/llmath/llsphere.h index 7c60a11406..7c60a11406 100644..100755 --- a/indra/llmath/llsphere.h +++ b/indra/llmath/llsphere.h diff --git a/indra/llmath/lltreenode.h b/indra/llmath/lltreenode.h index c66bc26176..c66bc26176 100644..100755 --- a/indra/llmath/lltreenode.h +++ b/indra/llmath/lltreenode.h diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp index 6edeb0fefe..6edeb0fefe 100644..100755 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 0526793d3a..79d0a44551 100644..100755 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -46,6 +46,7 @@ class LLRotation;  // of this writing, July 08, 2010) about getting it implemented before you resort to  // LLVector3/LLVector4.   ///////////////////////////////// +class LLVector4a;  LL_ALIGN_PREFIX(16)  class LLVector4a @@ -236,6 +237,11 @@ public:  	// Note that this does not consider zero length vectors!  	inline void normalize3fast(); +	// Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed +	// Same as above except substitutes default vector contents if the vector is non-finite or degenerate due to zero length. +	// +	inline void normalize3fast_checked(LLVector4a* d = 0); +  	// Return true if this vector is normalized with respect to x,y,z up to tolerance  	inline LLBool32 isNormalized3( F32 tolerance = 1e-3 ) const; diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl index 7c52ffef21..7c52ffef21 100644..100755 --- a/indra/llmath/llvector4a.inl +++ b/indra/llmath/llvector4a.inl diff --git a/indra/llmath/llvector4logical.h b/indra/llmath/llvector4logical.h index c5698f7cea..c5698f7cea 100644..100755 --- a/indra/llmath/llvector4logical.h +++ b/indra/llmath/llvector4logical.h diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 02c8d2b86f..14cebfe5aa 100644..100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1392,7 +1392,7 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en  	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t);  	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t);  	pt->mTexT  = t; -	 +  	// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02  	twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);  	// Rotate the point around the circle's center. @@ -1446,7 +1446,7 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en  	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t);  	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t);  	pt->mTexT  = t; -	 +  	// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02  	twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);  	// Rotate the point around the circle's center. @@ -1594,7 +1594,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  			S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions());  			if (is_sculpted) -				sides = sculpt_size; +				sides = llmax(sculpt_size, 1);  			genNGon(params, sides);  		} @@ -1644,6 +1644,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  			mPath[i].mScale.mV[0] = lerp(1,params.getScale().mV[0],t);  			mPath[i].mScale.mV[1] = lerp(1,params.getScale().mV[1],t);  			mPath[i].mTexT  = t; +  			mPath[i].mRot.setQuat(F_PI * params.getTwist() * t,1,0,0);  		} @@ -2079,9 +2080,9 @@ void LLVolume::regen()  	createVolumeFaces();  } -void LLVolume::genBinormals(S32 face) +void LLVolume::genTangents(S32 face)  { -	mVolumeFaces[face].createBinormals(); +	mVolumeFaces[face].createTangents();  }  LLVolume::~LLVolume() @@ -2442,6 +2443,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  			LLVector4a pos_range;  			pos_range.setSub(max_pos, min_pos);  			LLVector2 tc_range2 = max_tc - min_tc; +  			LLVector4a tc_range;  			tc_range.set(tc_range2[0], tc_range2[1], tc_range2[0], tc_range2[1]);  			LLVector4a min_tc4(min_tc[0], min_tc[1], min_tc[0], min_tc[1]); @@ -4392,7 +4394,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,  				segments.push_back(vertices.size());  #if DEBUG_SILHOUETTE_BINORMALS  				vertices.push_back(face.mVertices[j].getPosition()); -				vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].mBinormal*0.1f); +				vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].mTangent*0.1f);  				normals.push_back(LLVector3(0,0,1));  				normals.push_back(LLVector3(0,0,1));  				segments.push_back(vertices.size()); @@ -4508,22 +4510,9 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,  	}  } -S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,  -								   S32 face, -								   LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) -{ -	LLVector4a starta, enda; -	starta.load3(start.mV); -	enda.load3(end.mV); - -	return lineSegmentIntersect(starta, enda, face, intersection, tex_coord, normal, bi_normal); - -} - -  S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,   								   S32 face, -								   LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) +								   LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent_out)  {  	S32 hit_face = -1; @@ -4561,9 +4550,9 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en          if (LLLineSegmentBoxIntersect(start, end, box_center, box_size))  		{ -			if (bi_normal != NULL) // if the caller wants binormals, we may need to generate them +			if (tangent_out != NULL) // if the caller wants tangents, we may need to generate them  			{ -				genBinormals(i); +				genTangents(i);  			}  			if (isUnique()) @@ -4597,7 +4586,7 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en  								LLVector4a intersect = dir;  								intersect.mul(closest_t);  								intersect.add(start); -								intersection->set(intersect.getF32ptr()); +								*intersection = intersect;  							} @@ -4612,19 +4601,42 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en  							if (normal!= NULL)  							{ -								LLVector4* norm = (LLVector4*) face.mNormals; - -								*normal		= ((1.f - a - b)  * LLVector3(norm[idx0]) +  -									a              * LLVector3(norm[idx1]) + -									b              * LLVector3(norm[idx2])); +								LLVector4a* norm = face.mNormals; +								 +								LLVector4a n1,n2,n3; +								n1 = norm[idx0]; +								n1.mul(1.f-a-b); +								 +								n2 = norm[idx1]; +								n2.mul(a); +								 +								n3 = norm[idx2]; +								n3.mul(b); + +								n1.add(n2); +								n1.add(n3); +								 +								*normal		= n1;   							} -							if (bi_normal != NULL) +							if (tangent_out != NULL)  							{ -								LLVector4* binormal = (LLVector4*) face.mBinormals; -								*bi_normal = ((1.f - a - b)  * LLVector3(binormal[idx0]) +  -										a              * LLVector3(binormal[idx1]) + -										b              * LLVector3(binormal[idx2])); +								LLVector4a* tangents = face.mTangents; +								 +								LLVector4a t1,t2,t3; +								t1 = tangents[idx0]; +								t1.mul(1.f-a-b); +								 +								t2 = tangents[idx1]; +								t2.mul(a); +								 +								t3 = tangents[idx2]; +								t3.mul(b); + +								t1.add(t2); +								t1.add(t3); +								 +								*tangent_out = t1;   							}  						}  					} @@ -4637,7 +4649,7 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en  					face.createOctree();  				} -				LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal); +				LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out);  				intersect.traverse(face.mOctree);  				if (intersect.mHitFace)  				{ @@ -5183,7 +5195,7 @@ LLVolumeFace::LLVolumeFace() :  	mNumIndices(0),  	mPositions(NULL),  	mNormals(NULL), -	mBinormals(NULL), +	mTangents(NULL),  	mTexCoords(NULL),  	mIndices(NULL),  	mWeights(NULL), @@ -5206,7 +5218,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)  	mNumIndices(0),  	mPositions(NULL),  	mNormals(NULL), -	mBinormals(NULL), +	mTangents(NULL),  	mTexCoords(NULL),  	mIndices(NULL),  	mWeights(NULL), @@ -5264,15 +5276,15 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  		} -		if (src.mBinormals) +		if (src.mTangents)  		{ -			allocateBinormals(src.mNumVertices); -			LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) src.mBinormals, vert_size); +			allocateTangents(src.mNumVertices); +			LLVector4a::memcpyNonAliased16((F32*) mTangents, (F32*) src.mTangents, vert_size);  		}  		else  		{ -			ll_aligned_free_16(mBinormals); -			mBinormals = NULL; +			ll_aligned_free_16(mTangents); +			mTangents = NULL;  		}  		if (src.mWeights) @@ -5316,8 +5328,8 @@ void LLVolumeFace::freeData()  	mTexCoords = NULL;  	ll_aligned_free_16(mIndices);  	mIndices = NULL; -	ll_aligned_free_16(mBinormals); -	mBinormals = NULL; +	ll_aligned_free_16(mTangents); +	mTangents = NULL;  	ll_aligned_free_16(mWeights);  	mWeights = NULL; @@ -5897,7 +5909,7 @@ void LLVolumeFace::cacheOptimize()  	}  	LLVector4a* binorm = NULL; -	if (mBinormals) +	if (mTangents)  	{  		binorm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);  	} @@ -5922,9 +5934,9 @@ void LLVolumeFace::cacheOptimize()  			{  				wght[cur_idx] = mWeights[idx];  			} -			if (mBinormals) +			if (mTangents)  			{ -				binorm[cur_idx] = mBinormals[idx]; +				binorm[cur_idx] = mTangents[idx];  			}  			cur_idx++; @@ -5940,13 +5952,13 @@ void LLVolumeFace::cacheOptimize()  	ll_aligned_free_16(mNormals);  	ll_aligned_free_16(mTexCoords);  	ll_aligned_free_16(mWeights); -	ll_aligned_free_16(mBinormals); +	ll_aligned_free_16(mTangents);  	mPositions = pos;  	mNormals = norm;  	mTexCoords = tc;  	mWeights = wght; -	mBinormals = binorm; +	mTangents = binorm;  	//std::string result = llformat("ACMR pre/post: %.3f/%.3f  --  %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);  	//llinfos << result << llendl; @@ -6027,7 +6039,7 @@ void LLVolumeFace::swapData(LLVolumeFace& rhs)  {  	llswap(rhs.mPositions, mPositions);  	llswap(rhs.mNormals, mNormals); -	llswap(rhs.mBinormals, mBinormals); +	llswap(rhs.mTangents, mTangents);  	llswap(rhs.mTexCoords, mTexCoords);  	llswap(rhs.mIndices,mIndices);  	llswap(rhs.mNumVertices, mNumVertices); @@ -6066,12 +6078,7 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  	S32 max_t = volume->getPath().mPath.size();  	// S32 i; -	S32 num_vertices = 0, num_indices = 0;  	S32	grid_size = (profile.size()-1)/4; -	S32	quad_count = (grid_size * grid_size); - -	num_vertices = (grid_size+1)*(grid_size+1); -	num_indices = quad_count * 4;  	LLVector4a& min = mExtents[0];  	LLVector4a& max = mExtents[1]; @@ -6121,22 +6128,11 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  			corners[2].mTexCoord=swap;  		} -		LLVector4a binormal; -		 -		calc_binormal_from_triangle( binormal, -			corners[0].getPosition(), corners[0].mTexCoord, -			corners[1].getPosition(), corners[1].mTexCoord, -			corners[2].getPosition(), corners[2].mTexCoord); -		 -		binormal.normalize3fast(); -  		S32 size = (grid_size+1)*(grid_size+1);  		resizeVertices(size); -		allocateBinormals(size); - +		  		LLVector4a* pos = (LLVector4a*) mPositions;  		LLVector4a* norm = (LLVector4a*) mNormals; -		LLVector4a* binorm = (LLVector4a*) mBinormals;  		LLVector2* tc = (LLVector2*) mTexCoords;  		for(int gx = 0;gx<grid_size+1;gx++) @@ -6155,8 +6151,7 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  				*pos++ = newVert.getPosition();  				*norm++ = baseVert.getNormal();  				*tc++ = newVert.mTexCoord; -				*binorm++ = binormal; - +				  				if (gx == 0 && gy == 0)  				{  					min = newVert.getPosition(); @@ -6232,8 +6227,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK))  	{  		resizeVertices(num_vertices+1); -		allocateBinormals(num_vertices+1);	 - +		  		if (!partial_build)  		{  			resizeIndices(num_indices+3); @@ -6242,8 +6236,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	else  	{  		resizeVertices(num_vertices); -		allocateBinormals(num_vertices); - +		  		if (!partial_build)  		{  			resizeIndices(num_indices); @@ -6277,8 +6270,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	LLVector2* tc = (LLVector2*) mTexCoords;  	LLVector4a* pos = (LLVector4a*) mPositions;  	LLVector4a* norm = (LLVector4a*) mNormals; -	LLVector4a* binorm = (LLVector4a*) mBinormals; - +	  	// Copy the vertices into the array  	for (S32 i = 0; i < num_vertices; i++)  	{ @@ -6314,31 +6306,6 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	cuv = (min_uv + max_uv)*0.5f; -	LLVector4a binormal; -	calc_binormal_from_triangle(binormal, -		*mCenter, cuv, -		pos[0], tc[0], -		pos[1], tc[1]); -	binormal.normalize3fast(); - -	LLVector4a normal; -	LLVector4a d0, d1; -	 - -	d0.setSub(*mCenter, pos[0]); -	d1.setSub(*mCenter, pos[1]); - -	if (mTypeMask & TOP_MASK) -	{ -		normal.setCross3(d0, d1); -	} -	else -	{ -		normal.setCross3(d1, d0); -	} - -	normal.normalize3fast(); -  	VertexData vd;  	vd.setPosition(*mCenter);  	vd.mTexCoord = cuv; @@ -6347,15 +6314,10 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	{  		pos[num_vertices] = *mCenter;  		tc[num_vertices] = cuv; +  		num_vertices++;  	} -	for (S32 i = 0; i < num_vertices; i++) -	{ -		binorm[i].load4a(binormal.getF32ptr()); -		norm[i].load4a(normal.getF32ptr()); -	} -  	if (partial_build)  	{  		return TRUE; @@ -6590,63 +6552,68 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	} -		 + +	LLVector4a d0,d1; + +	d0.setSub(mPositions[mIndices[1]], mPositions[mIndices[0]]); +	d1.setSub(mPositions[mIndices[2]], mPositions[mIndices[0]]); + +	LLVector4a normal; +	normal.setCross3(d0,d1); + +	if (normal.dot3(normal).getF32() > F_APPROXIMATELY_ZERO) +	{ +		normal.normalize3fast(); +	} +	else +	{ //degenerate, make up a value +		normal.set(0,0,1); +	} + +	llassert(llfinite(normal.getF32ptr()[0])); +	llassert(llfinite(normal.getF32ptr()[1])); +	llassert(llfinite(normal.getF32ptr()[2])); + +	llassert(!llisnan(normal.getF32ptr()[0])); +	llassert(!llisnan(normal.getF32ptr()[1])); +	llassert(!llisnan(normal.getF32ptr()[2])); +	 +	for (S32 i = 0; i < num_vertices; i++) +	{ +		norm[i].load4a(normal.getF32ptr()); +	} +  	return TRUE;  } -void LLVolumeFace::createBinormals() +void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, +        const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent); + +void LLVolumeFace::createTangents()  { -	if (!mBinormals) +	if (!mTangents)  	{ -		allocateBinormals(mNumVertices); +		allocateTangents(mNumVertices); -		//generate binormals -		LLVector4a* pos = mPositions; -		LLVector2* tc = (LLVector2*) mTexCoords; -		LLVector4a* binorm = (LLVector4a*) mBinormals; +		//generate tangents +		//LLVector4a* pos = mPositions; +		//LLVector2* tc = (LLVector2*) mTexCoords; +		LLVector4a* binorm = (LLVector4a*) mTangents; -		LLVector4a* end = mBinormals+mNumVertices; +		LLVector4a* end = mTangents+mNumVertices;  		while (binorm < end)  		{  			(*binorm++).clear();  		} -		binorm = mBinormals; - -		for (U32 i = 0; i < mNumIndices/3; i++)  -		{	//for each triangle -			const U16& i0 = mIndices[i*3+0]; -			const U16& i1 = mIndices[i*3+1]; -			const U16& i2 = mIndices[i*3+2]; -						 -			//calculate binormal -			LLVector4a binormal; -			calc_binormal_from_triangle(binormal, -										pos[i0], tc[i0], -										pos[i1], tc[i1], -										pos[i2], tc[i2]); - - -			//add triangle normal to vertices -			binorm[i0].add(binormal); -			binorm[i1].add(binormal); -			binorm[i2].add(binormal); +		binorm = mTangents; -			//even out quad contributions -			if (i % 2 == 0)  -			{ -				binorm[i2].add(binormal); -			} -			else  -			{ -				binorm[i1].add(binormal); -			} -		} +		CalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices/3, mIndices, mTangents); -		//normalize binormals +		//normalize tangents  		for (U32 i = 0; i < mNumVertices; i++)   		{ -			binorm[i].normalize3fast(); +			//binorm[i].normalize3fast();  			//bump map/planar projection code requires normals to be normalized  			mNormals[i].normalize3fast();  		} @@ -6657,10 +6624,10 @@ void LLVolumeFace::resizeVertices(S32 num_verts)  {  	ll_aligned_free_16(mPositions);  	ll_aligned_free_16(mNormals); -	ll_aligned_free_16(mBinormals); +	ll_aligned_free_16(mTangents);  	ll_aligned_free_16(mTexCoords); -	mBinormals = NULL; +	mTangents = NULL;  	if (num_verts)  	{ @@ -6710,9 +6677,9 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con  	ll_assert_aligned(mTexCoords,16); -	//just clear binormals -	ll_aligned_free_16(mBinormals); -	mBinormals = NULL; +	//just clear tangents +	ll_aligned_free_16(mTangents); +	mTangents = NULL;  	mPositions[mNumVertices] = pos;  	mNormals[mNumVertices] = norm; @@ -6721,10 +6688,10 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con  	mNumVertices++;	  } -void LLVolumeFace::allocateBinormals(S32 num_verts) +void LLVolumeFace::allocateTangents(S32 num_verts)  { -	ll_aligned_free_16(mBinormals); -	mBinormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); +	ll_aligned_free_16(mTangents); +	mTangents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);  }  void LLVolumeFace::allocateWeights(S32 num_verts) @@ -6961,7 +6928,6 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  			if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2 && s > 0)  			{ -  				pos[cur_vertex].load3(mesh[i].mPos.mV);  				tc[cur_vertex] = LLVector2(ss,tt); @@ -6992,7 +6958,6 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  		}  	} -  	//get bounding box for this side  	LLVector4a& face_min = mExtents[0];  	LLVector4a& face_max = mExtents[1]; @@ -7098,6 +7063,14 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  		n[1]->add(c);  		n[2]->add(c); +		llassert(llfinite(c.getF32ptr()[0])); +		llassert(llfinite(c.getF32ptr()[1])); +		llassert(llfinite(c.getF32ptr()[2])); + +		llassert(!llisnan(c.getF32ptr()[0])); +		llassert(!llisnan(c.getF32ptr()[1])); +		llassert(!llisnan(c.getF32ptr()[2])); +  		//even out quad contributions  		n[i%2+1]->add(c);  	} @@ -7236,53 +7209,101 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  	return TRUE;  } -// Finds binormal based on three vertices with texture coordinates. -// Fills in dummy values if the triangle has degenerate texture coordinates. -void calc_binormal_from_triangle(LLVector4a& binormal, - -	const LLVector4a& pos0, -	const LLVector2& tex0, -	const LLVector4a& pos1, -	const LLVector2& tex1, -	const LLVector4a& pos2, -	const LLVector2& tex2) -{ -	LLVector4a rx0( pos0[VX], tex0.mV[VX], tex0.mV[VY] ); -	LLVector4a rx1( pos1[VX], tex1.mV[VX], tex1.mV[VY] ); -	LLVector4a rx2( pos2[VX], tex2.mV[VX], tex2.mV[VY] ); -	 -	LLVector4a ry0( pos0[VY], tex0.mV[VX], tex0.mV[VY] ); -	LLVector4a ry1( pos1[VY], tex1.mV[VX], tex1.mV[VY] ); -	LLVector4a ry2( pos2[VY], tex2.mV[VX], tex2.mV[VY] ); - -	LLVector4a rz0( pos0[VZ], tex0.mV[VX], tex0.mV[VY] ); -	LLVector4a rz1( pos1[VZ], tex1.mV[VX], tex1.mV[VY] ); -	LLVector4a rz2( pos2[VZ], tex2.mV[VX], tex2.mV[VY] ); -	 -	LLVector4a lhs, rhs; - -	LLVector4a r0;  -	lhs.setSub(rx0, rx1); rhs.setSub(rx0, rx2); -	r0.setCross3(lhs, rhs); +//adapted from Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html +void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, +        const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent) +{ +    //LLVector4a *tan1 = new LLVector4a[vertexCount * 2]; +	LLVector4a* tan1 = (LLVector4a*) ll_aligned_malloc_16(vertexCount*2*sizeof(LLVector4a)); + +    LLVector4a* tan2 = tan1 + vertexCount; + +	memset(tan1, 0, vertexCount*2*sizeof(LLVector4a)); +         +    for (U32 a = 0; a < triangleCount; a++) +    { +        U32 i1 = *index_array++; +        U32 i2 = *index_array++; +        U32 i3 = *index_array++; +         +        const LLVector4a& v1 = vertex[i1]; +        const LLVector4a& v2 = vertex[i2]; +        const LLVector4a& v3 = vertex[i3]; +         +        const LLVector2& w1 = texcoord[i1]; +        const LLVector2& w2 = texcoord[i2]; +        const LLVector2& w3 = texcoord[i3]; +         +		const F32* v1ptr = v1.getF32ptr(); +		const F32* v2ptr = v2.getF32ptr(); +		const F32* v3ptr = v3.getF32ptr(); -	LLVector4a r1; -	lhs.setSub(ry0, ry1); rhs.setSub(ry0, ry2); -	r1.setCross3(lhs, rhs); - -	LLVector4a r2; -	lhs.setSub(rz0, rz1); rhs.setSub(rz0, rz2); -	r2.setCross3(lhs, rhs); +        float x1 = v2ptr[0] - v1ptr[0]; +        float x2 = v3ptr[0] - v1ptr[0]; +        float y1 = v2ptr[1] - v1ptr[1]; +        float y2 = v3ptr[1] - v1ptr[1]; +        float z1 = v2ptr[2] - v1ptr[2]; +        float z2 = v3ptr[2] - v1ptr[2]; +         +        float s1 = w2.mV[0] - w1.mV[0]; +        float s2 = w3.mV[0] - w1.mV[0]; +        float t1 = w2.mV[1] - w1.mV[1]; +        float t2 = w3.mV[1] - w1.mV[1]; +         +		F32 rd = s1*t2-s2*t1; + +		float r = ((rd*rd) > FLT_EPSILON) ? 1.0F / rd : 1024.f; //some made up large ratio for division by zero + +		llassert(llfinite(r)); +		llassert(!llisnan(r)); + +		LLVector4a sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, +				(t2 * z1 - t1 * z2) * r); +		LLVector4a tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, +				(s1 * z2 - s2 * z1) * r); +         +		tan1[i1].add(sdir); +		tan1[i2].add(sdir); +		tan1[i3].add(sdir); +         +		tan2[i1].add(tdir); +		tan2[i2].add(tdir); +		tan2[i3].add(tdir); +    } +     +    for (U32 a = 0; a < vertexCount; a++) +    { +        LLVector4a n = normal[a]; + +		const LLVector4a& t = tan1[a]; + +		LLVector4a ncrosst; +		ncrosst.setCross3(n,t); + +        // Gram-Schmidt orthogonalize +        n.mul(n.dot3(t).getF32()); + +		LLVector4a tsubn; +		tsubn.setSub(t,n); + +		if (tsubn.dot3(tsubn).getF32() > F_APPROXIMATELY_ZERO) +		{ +			tsubn.normalize3fast(); +		 +			// Calculate handedness +			F32 handedness = ncrosst.dot3(tan2[a]).getF32() < 0.f ? -1.f : 1.f; +		 +			tsubn.getF32ptr()[3] = handedness; -	if( r0[VX] && r1[VX] && r2[VX] ) -	{ -		binormal.set( -				-r0[VZ] / r0[VX], -				-r1[VZ] / r1[VX], -				-r2[VZ] / r2[VX]); -		// binormal.normVec(); -	} -	else -	{ -		binormal.set( 0, 1 , 0 ); -	} +			tangent[a] = tsubn; +		} +		else +		{ //degenerate, make up a value +			tangent[a].set(0,0,1,1); +		} +    } +     +	ll_aligned_free_16(tan1);  } + + diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c845556557..164b8d6652 100644..100755 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -844,12 +844,12 @@ private:  public:  	BOOL create(LLVolume* volume, BOOL partial_build = FALSE); -	void createBinormals(); +	void createTangents();  	void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform);  	void resizeVertices(S32 num_verts); -	void allocateBinormals(S32 num_verts); +	void allocateTangents(S32 num_verts);  	void allocateWeights(S32 num_verts);  	void resizeIndices(S32 num_indices);  	void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx); @@ -916,7 +916,7 @@ public:  	LLVector4a* mPositions;  	LLVector4a* mNormals; -	LLVector4a* mBinormals; +	LLVector4a* mTangents;  	LLVector2*  mTexCoords;  	U16* mIndices; @@ -980,7 +980,7 @@ public:  	void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); }  	void regen(); -	void genBinormals(S32 face); +	void genTangents(S32 face);  	BOOL isConvex() const;  	BOOL isCap(S32 face); @@ -1008,21 +1008,14 @@ public:  	//get the face index of the face that intersects with the given line segment at the point   	//closest to start.  Moves end to the point of intersection.  Returns -1 if no intersection.  	//Line segment must be in volume space. -	S32 lineSegmentIntersect(const LLVector3& start, const LLVector3& end, +	S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,  							 S32 face = -1,                          // which face to check, -1 = ALL_SIDES -							 LLVector3* intersection = NULL,         // return the intersection point +							 LLVector4a* intersection = NULL,         // return the intersection point  							 LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point -							 LLVector3* normal = NULL,               // return the surface normal at the intersection point -							 LLVector3* bi_normal = NULL             // return the surface bi-normal at the intersection point +							 LLVector4a* normal = NULL,               // return the surface normal at the intersection point +							 LLVector4a* tangent = NULL             // return the surface tangent at the intersection point  		); -	S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,  -								   S32 face = 1, -								   LLVector3* intersection = NULL, -								   LLVector2* tex_coord = NULL, -								   LLVector3* normal = NULL, -								   LLVector3* bi_normal = NULL); -	  	LLFaceID generateFaceMask();  	BOOL isFaceMaskValid(LLFaceID face_mask); @@ -1081,21 +1074,12 @@ public:  std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); -void calc_binormal_from_triangle( -		LLVector4a& binormal, -		const LLVector4a& pos0, -		const LLVector2& tex0, -		const LLVector4a& pos1, -		const LLVector2& tex1, -		const LLVector4a& pos2, -		const LLVector2& tex2); -  BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size);  BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);  BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size); -BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, -							F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided); +//BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, +//							F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided);  BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir,  							F32& intersection_a, F32& intersection_b, F32& intersection_t); diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 9083273ee5..9083273ee5 100644..100755 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h index c75906f675..c75906f675 100644..100755 --- a/indra/llmath/llvolumemgr.h +++ b/indra/llmath/llvolumemgr.h diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp index cc83cb7235..0728b49c1f 100644..100755 --- a/indra/llmath/llvolumeoctree.cpp +++ b/indra/llmath/llvolumeoctree.cpp @@ -94,14 +94,14 @@ void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode<LLVolumeTria  LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,   							   const LLVolumeFace* face, F32* closest_t, -							   LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) +							   LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)     : mFace(face),       mStart(start),  	 mDir(dir),  	 mIntersection(intersection),  	 mTexCoord(tex_coord),  	 mNormal(normal), -	 mBinormal(bi_normal), +	 mTangent(tangent),  	 mClosestT(closest_t),  	 mHitFace(false)  { @@ -112,13 +112,7 @@ void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle>  {  	LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) node->getListener(0); -	/*const F32* start = mStart.getF32(); -	const F32* end = mEnd.getF32(); -	const F32* center = vl->mBounds[0].getF32(); -	const F32* size = vl->mBounds[1].getF32();*/ - -	//if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1])) -	if (LLLineSegmentBoxIntersect(mStart.getF32ptr(), mEnd.getF32ptr(), vl->mBounds[0].getF32ptr(), vl->mBounds[1].getF32ptr())) +	if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1]))  	{  		node->accept(this);  		for (S32 i = 0; i < node->getChildCount(); ++i) @@ -152,34 +146,60 @@ void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle>* n  					LLVector4a intersect = mDir;  					intersect.mul(*mClosestT);  					intersect.add(mStart); -					mIntersection->set(intersect.getF32ptr()); +					*mIntersection = intersect;  				} +				U32 idx0 = tri->mIndex[0]; +				U32 idx1 = tri->mIndex[1]; +				U32 idx2 = tri->mIndex[2];  				if (mTexCoord != NULL)  				{  					LLVector2* tc = (LLVector2*) mFace->mTexCoords; -					*mTexCoord = ((1.f - a - b)  * tc[tri->mIndex[0]] + -						a              * tc[tri->mIndex[1]] + -						b              * tc[tri->mIndex[2]]); +					*mTexCoord = ((1.f - a - b)  * tc[idx0] + +						a              * tc[idx1] + +						b              * tc[idx2]);  				}  				if (mNormal != NULL)  				{ -					LLVector4* norm = (LLVector4*) mFace->mNormals; - -					*mNormal    = ((1.f - a - b)  * LLVector3(norm[tri->mIndex[0]]) +  -						a              * LLVector3(norm[tri->mIndex[1]]) + -						b              * LLVector3(norm[tri->mIndex[2]])); +					LLVector4a* norm = mFace->mNormals; +								 +					LLVector4a n1,n2,n3; +					n1 = norm[idx0]; +					n1.mul(1.f-a-b); +								 +					n2 = norm[idx1]; +					n2.mul(a); +								 +					n3 = norm[idx2]; +					n3.mul(b); + +					n1.add(n2); +					n1.add(n3); +								 +					*mNormal		= n1;   				} -				if (mBinormal != NULL) +				if (mTangent != NULL)  				{ -					LLVector4* binormal = (LLVector4*) mFace->mBinormals; -					*mBinormal = ((1.f - a - b)  * LLVector3(binormal[tri->mIndex[0]]) +  -							a              * LLVector3(binormal[tri->mIndex[1]]) + -							b              * LLVector3(binormal[tri->mIndex[2]])); +					LLVector4a* tangents = mFace->mTangents; +								 +					LLVector4a t1,t2,t3; +					t1 = tangents[idx0]; +					t1.mul(1.f-a-b); +								 +					t2 = tangents[idx1]; +					t2.mul(a); +								 +					t3 = tangents[idx2]; +					t3.mul(b); + +					t1.add(t2); +					t1.add(t3); +								 +					*mTangent = t1;   				}  			}  		} diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index 9ae34a0c4e..80d6ced36d 100644..100755 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -137,16 +137,16 @@ public:  	LLVector4a mStart;  	LLVector4a mDir;  	LLVector4a mEnd; -	LLVector3* mIntersection; +	LLVector4a* mIntersection;  	LLVector2* mTexCoord; -	LLVector3* mNormal; -	LLVector3* mBinormal; +	LLVector4a* mNormal; +	LLVector4a* mTangent;  	F32* mClosestT;  	bool mHitFace;  	LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,   								   const LLVolumeFace* face, F32* closest_t, -								   LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal); +								   LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent);  	void traverse(const LLOctreeNode<LLVolumeTriangle>* node); diff --git a/indra/llmath/m3math.cpp b/indra/llmath/m3math.cpp index 802ddb9e57..802ddb9e57 100644..100755 --- a/indra/llmath/m3math.cpp +++ b/indra/llmath/m3math.cpp diff --git a/indra/llmath/m3math.h b/indra/llmath/m3math.h index 2be5452f8d..2be5452f8d 100644..100755 --- a/indra/llmath/m3math.h +++ b/indra/llmath/m3math.h diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index 6a1b4143cf..6a1b4143cf 100644..100755 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index a7dce10397..a7dce10397 100644..100755 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h diff --git a/indra/llmath/raytrace.cpp b/indra/llmath/raytrace.cpp index f38fe49bcb..f38fe49bcb 100644..100755 --- a/indra/llmath/raytrace.cpp +++ b/indra/llmath/raytrace.cpp diff --git a/indra/llmath/raytrace.h b/indra/llmath/raytrace.h index 2d32af0c86..2d32af0c86 100644..100755 --- a/indra/llmath/raytrace.h +++ b/indra/llmath/raytrace.h diff --git a/indra/llmath/tests/alignment_test.cpp b/indra/llmath/tests/alignment_test.cpp index 5ee3c45502..5ee3c45502 100644..100755 --- a/indra/llmath/tests/alignment_test.cpp +++ b/indra/llmath/tests/alignment_test.cpp diff --git a/indra/llmath/tests/llbbox_test.cpp b/indra/llmath/tests/llbbox_test.cpp index fd0dbb58fc..fd0dbb58fc 100644..100755 --- a/indra/llmath/tests/llbbox_test.cpp +++ b/indra/llmath/tests/llbbox_test.cpp diff --git a/indra/llmath/tests/llbboxlocal_test.cpp b/indra/llmath/tests/llbboxlocal_test.cpp index f31e4126c4..f31e4126c4 100644..100755 --- a/indra/llmath/tests/llbboxlocal_test.cpp +++ b/indra/llmath/tests/llbboxlocal_test.cpp diff --git a/indra/llmath/tests/llmodularmath_test.cpp b/indra/llmath/tests/llmodularmath_test.cpp index 063d3ef79f..063d3ef79f 100644..100755 --- a/indra/llmath/tests/llmodularmath_test.cpp +++ b/indra/llmath/tests/llmodularmath_test.cpp diff --git a/indra/llmath/tests/llquaternion_test.cpp b/indra/llmath/tests/llquaternion_test.cpp index e69010b2d6..e69010b2d6 100644..100755 --- a/indra/llmath/tests/llquaternion_test.cpp +++ b/indra/llmath/tests/llquaternion_test.cpp diff --git a/indra/llmath/tests/llrect_test.cpp b/indra/llmath/tests/llrect_test.cpp index d740173e69..d740173e69 100644..100755 --- a/indra/llmath/tests/llrect_test.cpp +++ b/indra/llmath/tests/llrect_test.cpp diff --git a/indra/llmath/tests/m3math_test.cpp b/indra/llmath/tests/m3math_test.cpp index 1ca2b005d9..1ca2b005d9 100644..100755 --- a/indra/llmath/tests/m3math_test.cpp +++ b/indra/llmath/tests/m3math_test.cpp diff --git a/indra/llmath/tests/mathmisc_test.cpp b/indra/llmath/tests/mathmisc_test.cpp index 91a2e6c009..91a2e6c009 100644..100755 --- a/indra/llmath/tests/mathmisc_test.cpp +++ b/indra/llmath/tests/mathmisc_test.cpp diff --git a/indra/llmath/tests/v2math_test.cpp b/indra/llmath/tests/v2math_test.cpp index 4d6a2eca93..4d6a2eca93 100644..100755 --- a/indra/llmath/tests/v2math_test.cpp +++ b/indra/llmath/tests/v2math_test.cpp diff --git a/indra/llmath/tests/v3color_test.cpp b/indra/llmath/tests/v3color_test.cpp index 29d1c483ab..29d1c483ab 100644..100755 --- a/indra/llmath/tests/v3color_test.cpp +++ b/indra/llmath/tests/v3color_test.cpp diff --git a/indra/llmath/tests/v3dmath_test.cpp b/indra/llmath/tests/v3dmath_test.cpp index 20b26faa12..20b26faa12 100644..100755 --- a/indra/llmath/tests/v3dmath_test.cpp +++ b/indra/llmath/tests/v3dmath_test.cpp diff --git a/indra/llmath/tests/v3math_test.cpp b/indra/llmath/tests/v3math_test.cpp index e4ae1c10ef..e4ae1c10ef 100644..100755 --- a/indra/llmath/tests/v3math_test.cpp +++ b/indra/llmath/tests/v3math_test.cpp diff --git a/indra/llmath/tests/v4color_test.cpp b/indra/llmath/tests/v4color_test.cpp index d7eec3c87f..d7eec3c87f 100644..100755 --- a/indra/llmath/tests/v4color_test.cpp +++ b/indra/llmath/tests/v4color_test.cpp diff --git a/indra/llmath/tests/v4coloru_test.cpp b/indra/llmath/tests/v4coloru_test.cpp index 128f6f3564..128f6f3564 100644..100755 --- a/indra/llmath/tests/v4coloru_test.cpp +++ b/indra/llmath/tests/v4coloru_test.cpp diff --git a/indra/llmath/tests/v4math_test.cpp b/indra/llmath/tests/v4math_test.cpp index 191ac864df..191ac864df 100644..100755 --- a/indra/llmath/tests/v4math_test.cpp +++ b/indra/llmath/tests/v4math_test.cpp diff --git a/indra/llmath/tests/xform_test.cpp b/indra/llmath/tests/xform_test.cpp index 49870eef3c..49870eef3c 100644..100755 --- a/indra/llmath/tests/xform_test.cpp +++ b/indra/llmath/tests/xform_test.cpp diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index a0cd642853..a0cd642853 100644..100755 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index 8d5db96f5e..8d5db96f5e 100644..100755 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h diff --git a/indra/llmath/v3color.cpp b/indra/llmath/v3color.cpp index d38f48b11e..d38f48b11e 100644..100755 --- a/indra/llmath/v3color.cpp +++ b/indra/llmath/v3color.cpp diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h index daf3a6857b..daf3a6857b 100644..100755 --- a/indra/llmath/v3color.h +++ b/indra/llmath/v3color.h diff --git a/indra/llmath/v3dmath.cpp b/indra/llmath/v3dmath.cpp index a50cb3c6ca..a50cb3c6ca 100644..100755 --- a/indra/llmath/v3dmath.cpp +++ b/indra/llmath/v3dmath.cpp diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h index 578dcdc8ea..578dcdc8ea 100644..100755 --- a/indra/llmath/v3dmath.h +++ b/indra/llmath/v3dmath.h diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp index e7107dee16..e7107dee16 100644..100755 --- a/indra/llmath/v3math.cpp +++ b/indra/llmath/v3math.cpp diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 0432aeba4c..0432aeba4c 100644..100755 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp index 81ac62be56..81ac62be56 100644..100755 --- a/indra/llmath/v4color.cpp +++ b/indra/llmath/v4color.cpp diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index b047f86e6e..8c8c315808 100644..100755 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -50,7 +50,7 @@ class LLColor4  		LLColor4(F32 r, F32 g, F32 b);		// Initializes LLColor4 to (r, g, b, 1)  		LLColor4(F32 r, F32 g, F32 b, F32 a);		// Initializes LLColor4 to (r. g, b, a)  		LLColor4(U32 clr);							// Initializes LLColor4 to (r=clr>>24, etc)) -		LLColor4(const F32 *vec);			// Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1) +		LLColor4(const F32 *vec);			// Initializes LLColor4 to (vec[0]. vec[1], vec[2], vec[3])  		LLColor4(const LLColor3 &vec, F32 a = 1.f);	// Initializes LLColor4 to (vec, a)  		explicit LLColor4(const LLSD& sd);  		explicit LLColor4(const LLColor4U& color4u);  // "explicit" to avoid automatic conversion diff --git a/indra/llmath/v4coloru.cpp b/indra/llmath/v4coloru.cpp index f1a2518cf3..f1a2518cf3 100644..100755 --- a/indra/llmath/v4coloru.cpp +++ b/indra/llmath/v4coloru.cpp diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h index 12da7e2dd7..12da7e2dd7 100644..100755 --- a/indra/llmath/v4coloru.h +++ b/indra/llmath/v4coloru.h diff --git a/indra/llmath/v4math.cpp b/indra/llmath/v4math.cpp index 2782cf2966..2782cf2966 100644..100755 --- a/indra/llmath/v4math.cpp +++ b/indra/llmath/v4math.cpp diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index 623c8b2003..623c8b2003 100644..100755 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h diff --git a/indra/llmath/xform.cpp b/indra/llmath/xform.cpp index b75aec6a27..b75aec6a27 100644..100755 --- a/indra/llmath/xform.cpp +++ b/indra/llmath/xform.cpp diff --git a/indra/llmath/xform.h b/indra/llmath/xform.h index 1b50749b3e..1b50749b3e 100644..100755 --- a/indra/llmath/xform.h +++ b/indra/llmath/xform.h | 
