diff options
Diffstat (limited to 'indra/llmath')
| -rwxr-xr-x | indra/llmath/llvector4a.inl | 20 | ||||
| -rwxr-xr-x | indra/llmath/llvolume.cpp | 219 | 
2 files changed, 201 insertions, 38 deletions
| diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl index 7c52ffef21..558fe09323 100755 --- a/indra/llmath/llvector4a.inl +++ b/indra/llmath/llvector4a.inl @@ -409,6 +409,26 @@ inline void LLVector4a::normalize3fast()  	mQ = _mm_mul_ps( mQ, approxRsqrt );  } +inline void LLVector4a::normalize3fast_checked(LLVector4a* d) +{ +	if (!isFinite3()) +	{ +		*this = d ? *d : LLVector4a(0,1,0,1); +		return; +	} + +	LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + +	if (lenSqrd.getF32ptr()[0] <= FLT_EPSILON) +	{ +		*this = d ? *d : LLVector4a(0,1,0,1); +		return; +	} + +	const LLQuad approxRsqrt = _mm_rsqrt_ps(lenSqrd.mQ); +	mQ = _mm_mul_ps( mQ, approxRsqrt ); +} +  // Return true if this vector is normalized with respect to x,y,z up to tolerance  inline LLBool32 LLVector4a::isNormalized3( F32 tolerance ) const  { diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 640e916b4b..426a434e07 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -135,6 +135,82 @@ BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* cent  	return true;  } +// Finds tangent vec based on three vertices with texture coordinates. +// Fills in dummy values if the triangle has degenerate texture coordinates. +void calc_tangent_from_triangle( +	LLVector4a&			normal, +	LLVector4a&			tangent_out, +	const LLVector4a& v1, +	const LLVector2&  w1, +	const LLVector4a& v2, +	const LLVector2&  w2, +	const LLVector4a& v3, +	const LLVector2&  w3) +{ +	const F32* v1ptr = v1.getF32ptr(); +	const F32* v2ptr = v2.getF32ptr(); +	const F32* v3ptr = v3.getF32ptr(); + +	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); + +	LLVector4a	n = normal; +	LLVector4a	t = sdir; + +	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_checked(); + +		// Calculate handedness +		F32 handedness = ncrosst.dot3(tdir).getF32() < 0.f ? -1.f : 1.f; + +		tsubn.getF32ptr()[3] = handedness; + +		tangent_out = tsubn; +	} +	else +	{ +		// degenerate, make up a value +		// +		tangent_out.set(0,0,1,1); +	} + +}  // intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. @@ -5907,10 +5983,10 @@ void LLVolumeFace::cacheOptimize()  		wght = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);  	} -	LLVector4a* binorm = NULL; +	LLVector4a* tangent = NULL;  	if (mTangents)  	{ -		binorm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); +		tangent = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);  	}  	//allocate mapping of old indices to new indices @@ -5935,7 +6011,7 @@ void LLVolumeFace::cacheOptimize()  			}  			if (mTangents)  			{ -				binorm[cur_idx] = mTangents[idx]; +				tangent[cur_idx] = mTangents[idx];  			}  			cur_idx++; @@ -5957,7 +6033,7 @@ void LLVolumeFace::cacheOptimize()  	mNormals = norm;  	mTexCoords = tc;  	mWeights = wght; -	mTangents = binorm; +	mTangents = tangent;  	//std::string result = llformat("ACMR pre/post: %.3f/%.3f  --  %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);  	//LL_INFOS() << result << LL_ENDL; @@ -6305,6 +6381,43 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	cuv = (min_uv + max_uv)*0.5f; + +	LLVector4a tangent; +	calc_tangent_from_triangle( +			*norm, +			tangent, +			*mCenter, cuv, +			pos[0], tc[0], +			pos[1], tc[1]); + +	if (tangent.getLength3() < 0.01) +	{ +		tangent.set(1,0,0,1); +	} +	else +	{ +		LLVector4a default_tangent; +		default_tangent.set(1,0,0,1); +		tangent.normalize3fast_checked(&default_tangent); +	} + +	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_checked(); +  	VertexData vd;  	vd.setPosition(*mCenter);  	vd.mTexCoord = cuv; @@ -6317,6 +6430,14 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  		num_vertices++;  	} +	allocateTangents(num_vertices);		 + +	for (S32 i = 0; i < num_vertices; i++) +	{ +		mTangents[i].load4a(tangent.getF32ptr()); +		norm[i].load4a(normal.getF32ptr()); +	}	 +  	if (partial_build)  	{  		return TRUE; @@ -6551,36 +6672,6 @@ 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;  } @@ -6610,11 +6701,13 @@ void LLVolumeFace::createTangents()  		CalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices/3, mIndices, mTangents);  		//normalize tangents +		LLVector4a default_norm; +		default_norm.set(0,1,0,1);  		for (U32 i = 0; i < mNumVertices; i++)   		{ -			//binorm[i].normalize3fast(); +			//tangent[i].normalize3fast();  			//bump map/planar projection code requires normals to be normalized -			mNormals[i].normalize3fast(); +			mNormals[i].normalize3fast_checked();  		}  	}  } @@ -6799,7 +6892,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat  		//transform appended face normal and store  		norm_mat.rotate(src_norm[i], dst_norm[i]); -		dst_norm[i].normalize3fast(); +		dst_norm[i].normalize3fast_checked();  		//copy appended face texture coordinate  		dst_tc[i] = src_tc[i]; @@ -7208,11 +7301,61 @@ 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); +		 +	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); + +	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 ); +	} +} +  //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; | 
