diff options
Diffstat (limited to 'indra/llmath')
| -rw-r--r-- | indra/llmath/lloctree.h | 127 | ||||
| -rw-r--r-- | indra/llmath/llvolume.cpp | 180 | ||||
| -rw-r--r-- | indra/llmath/llvolume.h | 4 | ||||
| -rw-r--r-- | indra/llmath/llvolumeoctree.cpp | 61 | ||||
| -rw-r--r-- | indra/llmath/llvolumeoctree.h | 6 | 
5 files changed, 248 insertions, 130 deletions
| diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 73910ef98d..63adfa85b2 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -95,22 +95,30 @@ public:  	typedef LLOctreeNode<T>		oct_node;  	typedef LLOctreeListener<T>	oct_listener; +	/*void* operator new(size_t size) +	{ +		return ll_aligned_malloc_16(size); +	} + +	void operator delete(void* ptr) +	{ +		ll_aligned_free_16(ptr); +	}*/ +  	LLOctreeNode(	const LLVector4a& center,   					const LLVector4a& size,   					BaseType* parent,  -					S32 octant = -1) +					U8 octant = 255)  	:	mParent((oct_node*)parent),   		mOctant(octant)   	{  -		mD = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*4); - -		mD[CENTER] = center; -		mD[SIZE] = size; +		mCenter = center; +		mSize = size;  		updateMinMax(); -		if ((mOctant == -1) && mParent) +		if ((mOctant == 255) && mParent)  		{ -			mOctant = ((oct_node*) mParent)->getOctant(mD[CENTER]); +			mOctant = ((oct_node*) mParent)->getOctant(mCenter);  		}  		clearChildren(); @@ -124,30 +132,27 @@ public:  		{  			delete getChild(i);  		}  - -		ll_aligned_free_16(mD);  	}  	inline const BaseType* getParent()	const			{ return mParent; }  	inline void setParent(BaseType* parent)				{ mParent = (oct_node*) parent; } -	inline const LLVector4a& getCenter() const			{ return mD[CENTER]; } -	inline const LLVector4a& getSize() const			{ return mD[SIZE]; } -	inline void setCenter(const LLVector4a& center)		{ mD[CENTER] = center; } -	inline void setSize(const LLVector4a& size)			{ mD[SIZE] = size; } +	inline const LLVector4a& getCenter() const			{ return mCenter; } +	inline const LLVector4a& getSize() const			{ return mSize; } +	inline void setCenter(const LLVector4a& center)		{ mCenter = center; } +	inline void setSize(const LLVector4a& size)			{ mSize = size; }      inline oct_node* getNodeAt(T* data)					{ return getNodeAt(data->getPositionGroup(), data->getBinRadius()); } -	inline S32 getOctant() const						{ return mOctant; } -	inline void setOctant(S32 octant)					{ mOctant = octant; } +	inline U8 getOctant() const							{ return mOctant; }  	inline const oct_node*	getOctParent() const		{ return (const oct_node*) getParent(); }  	inline oct_node* getOctParent() 					{ return (oct_node*) getParent(); } -	S32 getOctant(const LLVector4a& pos) const			//get the octant pos is in +	U8 getOctant(const LLVector4a& pos) const			//get the octant pos is in  	{ -		return pos.greaterThan(mD[CENTER]).getGatheredBits() & 0x7; +		return (U8) (pos.greaterThan(mCenter).getGatheredBits() & 0x7);  	}  	inline bool isInside(const LLVector4a& pos, const F32& rad) const  	{ -		return rad <= mD[SIZE][0]*2.f && isInside(pos);  +		return rad <= mSize[0]*2.f && isInside(pos);   	}  	inline bool isInside(T* data) const			 @@ -157,13 +162,13 @@ public:  	bool isInside(const LLVector4a& pos) const  	{ -		S32 gt = pos.greaterThan(mD[MAX]).getGatheredBits() & 0x7; +		S32 gt = pos.greaterThan(mMax).getGatheredBits() & 0x7;  		if (gt)  		{  			return false;  		} -		S32 lt = pos.lessEqual(mD[MIN]).getGatheredBits() & 0x7; +		S32 lt = pos.lessEqual(mMin).getGatheredBits() & 0x7;  		if (lt)  		{  			return false; @@ -174,8 +179,8 @@ public:  	void updateMinMax()  	{ -		mD[MAX].setAdd(mD[CENTER], mD[SIZE]); -		mD[MIN].setSub(mD[CENTER], mD[SIZE]); +		mMax.setAdd(mCenter, mSize); +		mMin.setSub(mCenter, mSize);  	}  	inline oct_listener* getOctListener(U32 index)  @@ -195,7 +200,7 @@ public:  			return false;  		} -		F32 size = mD[SIZE][0]; +		F32 size = mSize[0];  		F32 p_size = size * 2.f;  		return (radius <= 0.001f && size <= 0.001f) || @@ -234,6 +239,29 @@ public:  	void accept(tree_traveler* visitor) const		{ visitor->visit(this); }  	void accept(oct_traveler* visitor) const		{ visitor->visit(this); } +	void validateChildMap() +	{ +		for (U32 i = 0; i < 8; i++) +		{ +			U8 idx = mChildMap[i]; +			if (idx != 255) +			{ +				LLOctreeNode<T>* child = mChild[idx]; + +				if (child->getOctant() != i) +				{ +					llerrs << "Invalid child map, bad octant data." << llendl; +				} + +				if (getOctant(child->getCenter()) != child->getOctant()) +				{ +					llerrs << "Invalid child octant compared to position data." << llendl; +				} +			} +		} +	} + +  	oct_node* getNodeAt(const LLVector4a& pos, const F32& rad)  	{   		LLOctreeNode<T>* node = this; @@ -241,25 +269,19 @@ public:  		if (node->isInside(pos, rad))  		{		  			//do a quick search by octant -			S32 octant = node->getOctant(pos); -			BOOL keep_going = TRUE; - +			U8 octant = node->getOctant(pos); +			  			//traverse the tree until we find a node that has no node  			//at the appropriate octant or is smaller than the object.    			//by definition, that node is the smallest node that contains   			// the data -			while (keep_going && node->getSize()[0] >= rad) +			U8 next_node = node->mChildMap[octant]; +			 +			while (next_node != 255 && node->getSize()[0] >= rad)  			{	 -				keep_going = FALSE; -				for (U32 i = 0; i < node->getChildCount() && !keep_going; i++) -				{ -					if (node->getChild(i)->getOctant() == octant) -					{ -						node = node->getChild(i); -						octant = node->getOctant(pos); -						keep_going = TRUE; -					} -				} +				node = node->getChild(next_node); +				octant = node->getOctant(pos); +				next_node = node->mChildMap[octant];  			}  		}  		else if (!node->contains(rad) && node->getParent()) @@ -439,6 +461,9 @@ public:  	void clearChildren()  	{  		mChild.clear(); + +		U32* foo = (U32*) mChildMap; +		foo[0] = foo[1] = 0xFFFFFFFF;  	}  	void validate() @@ -496,6 +521,8 @@ public:  		}  #endif +		mChildMap[child->getOctant()] = (U8) mChild.size(); +  		mChild.push_back(child);  		child->setParent(this); @@ -517,6 +544,8 @@ public:  			listener->handleChildRemoval(this, getChild(index));  		} +		 +  		if (destroy)  		{  			mChild[index]->destroy(); @@ -524,6 +553,15 @@ public:  		}  		mChild.erase(mChild.begin() + index); +		//rebuild child map +		U32* foo = (U32*) mChildMap; +		foo[0] = foo[1] = 0xFFFFFFFF; + +		for (U32 i = 0; i < mChild.size(); ++i) +		{ +			mChildMap[mChild[i]->getOctant()] = i; +		} +  		checkAlive();  	} @@ -562,15 +600,20 @@ protected:  		MIN = 3  	} eDName; -	LLVector4a* mD; +	LLVector4a mCenter; +	LLVector4a mSize; +	LLVector4a mMax; +	LLVector4a mMin;  	oct_node* mParent; -	S32 mOctant; +	U8 mOctant;  	child_list mChild; +	U8 mChildMap[8]; +  	element_list mData; -}; +};   //just like a regular node, except it might expand on insert and compress on balance  template <class T> @@ -613,6 +656,8 @@ public:  			//destroy child  			child->clearChildren();  			delete child; + +			return false;  		}  		return true; @@ -639,7 +684,7 @@ public:  		const LLVector4a& v = data->getPositionGroup();  		LLVector4a val; -		val.setSub(v, BaseType::mD[BaseType::CENTER]); +		val.setSub(v, BaseType::mCenter);  		val.setAbs(val);  		S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index ab9f8c4c24..24528a8ce9 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -94,6 +94,8 @@ const F32 SKEW_MAX	=  0.95f;  const F32 SCULPT_MIN_AREA = 0.002f;  const S32 SCULPT_MIN_AREA_DETAIL = 1; +extern BOOL gDebugGL; +  BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm)  {      	LLVector3 test = (pt2-pt1)%(pt3-pt2); @@ -308,22 +310,26 @@ public:  	}  	virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch) -	{ +	{ //this is a depth first traversal, so it's safe to assum all children have complete +		//bounding data +  		LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0);  		LLVector4a& min = node->mExtents[0];  		LLVector4a& max = node->mExtents[1]; -		if (branch->getElementCount() != 0) -		{ +		if (!branch->getData().empty()) +		{ //node has data, find AABB that binds data set  			const LLVolumeTriangle* tri = *(branch->getData().begin()); -						 +			 +			//initialize min/max to first available vertex  			min = *(tri->mV[0]);  			max = *(tri->mV[0]);  			for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter =   				branch->getData().begin(); iter != branch->getData().end(); ++iter) -			{ +			{ //for each triangle in node +  				//stretch by triangles in node  				tri = *iter; @@ -335,33 +341,27 @@ public:  				max.setMax(max, *tri->mV[1]);  				max.setMax(max, *tri->mV[2]);  			} - -			for (S32 i = 0; i < branch->getChildCount(); ++i) -			{  //stretch by child extents -				LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); -				min.setMin(min, child->mExtents[0]); -				max.setMax(min, child->mExtents[1]); -			}  		} -		else if (branch->getChildCount() != 0) -		{ +		else if (!branch->getChildren().empty()) +		{ //no data, but child nodes exist  			LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0); +			//initialize min/max to extents of first child  			min = child->mExtents[0];  			max = child->mExtents[1]; - -			for (S32 i = 1; i < branch->getChildCount(); ++i) -			{  //stretch by child extents -				child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); -				min.setMin(min, child->mExtents[0]); -				max.setMax(max, child->mExtents[1]); -			}  		}  		else  		{  			llerrs << "WTF? Empty leaf" << llendl;  		} -		 + +		for (S32 i = 0; i < branch->getChildCount(); ++i) +		{  //stretch by child extents +			LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); +			min.setMin(min, child->mExtents[0]); +			max.setMax(max, child->mExtents[1]); +		} +  		node->mBounds[0].setAdd(min, max);  		node->mBounds[0].mul(0.5f); @@ -370,7 +370,6 @@ public:  	}  }; -  //-------------------------------------------------------------------  // statics  //------------------------------------------------------------------- @@ -1991,7 +1990,7 @@ void LLVolumeFace::VertexData::init()  {  	if (!mData)  	{ -		mData = (LLVector4a*) ll_aligned_malloc_16(32); +		mData = new LLVector4a[2];  	}  } @@ -2020,7 +2019,7 @@ const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolu  LLVolumeFace::VertexData::~VertexData()  { -	ll_aligned_free_16(mData); +	delete [] mData;  }  LLVector4a& LLVolumeFace::VertexData::getPosition() @@ -2258,12 +2257,12 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  					U32 cur_influence = 0;  					LLVector4 wght(0,0,0,0); -					while (joint != END_INFLUENCES) +					while (joint != END_INFLUENCES && idx < weights.size())  					{  						U16 influence = weights[idx++];  						influence |= ((U16) weights[idx++] << 8); -						F32 w = llmin((F32) influence / 65535.f, 0.99999f); +						F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f);  						wght.mV[cur_influence++] = (F32) joint + w;  						if (cur_influence >= 4) @@ -2570,14 +2569,13 @@ void LLVolume::makeTetrahedron()  	mIsTetrahedron = TRUE;  } -void LLVolume::copyVolumeFaces(LLVolume* volume) +void LLVolume::copyVolumeFaces(const LLVolume* volume)  {  	mVolumeFaces = volume->mVolumeFaces;  	mSculptLevel = 0;  	mIsTetrahedron = FALSE;  } -  S32	LLVolume::getNumFaces() const  {  #if LL_MESH_ENABLED @@ -5232,7 +5230,7 @@ LLVolumeFace::LLVolumeFace() :  	mWeights(NULL),  	mOctree(NULL)  { -	mExtents = (LLVector4a*) ll_aligned_malloc_16(48); +	mExtents = new LLVector4a[3];  	mCenter = mExtents+2;  } @@ -5253,7 +5251,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)  	mWeights(NULL),  	mOctree(NULL)  {  -	mExtents = (LLVector4a*) ll_aligned_malloc_16(48); +	mExtents = new LLVector4a[3];  	mCenter = mExtents+2;  	*this = src;  } @@ -5288,7 +5286,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  	if (mNumVertices)  	{ -		S32 vert_size = mNumVertices*4*sizeof(F32); +		S32 vert_size = mNumVertices*sizeof(LLVector4a);  		S32 tc_size = (mNumVertices*8+0xF) & ~0xF;  		LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); @@ -5303,7 +5301,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  		}  		else  		{ -			ll_aligned_free_16(mBinormals); +			delete [] mBinormals;  			mBinormals = NULL;  		} @@ -5314,7 +5312,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  		}  		else  		{ -			ll_aligned_free_16(mWeights); +			delete [] mWeights;  			mWeights = NULL;  		}  	} @@ -5332,7 +5330,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  LLVolumeFace::~LLVolumeFace()  { -	ll_aligned_free_16(mExtents); +	delete [] mExtents;  	mExtents = NULL;  	freeData(); @@ -5340,17 +5338,17 @@ LLVolumeFace::~LLVolumeFace()  void LLVolumeFace::freeData()  { -	ll_aligned_free_16(mPositions); +	delete [] mPositions;  	mPositions = NULL; -	ll_aligned_free_16(mNormals); +	delete []  mNormals;  	mNormals = NULL; -	ll_aligned_free_16(mTexCoords); +	delete [] mTexCoords;  	mTexCoords = NULL; -	ll_aligned_free_16(mIndices); +	delete [] mIndices;  	mIndices = NULL; -	ll_aligned_free_16(mBinormals); +	delete [] mBinormals;  	mBinormals = NULL; -	ll_aligned_free_16(mWeights); +	delete [] mWeights;  	mWeights = NULL;  	delete mOctree; @@ -5463,56 +5461,73 @@ void LLVolumeFace::optimize(F32 angle_cutoff)  } -void LLVolumeFace::createOctree() +void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size)  { -	LLVector4a center; -	LLVector4a size; -	center.splat(0.f); -	size.splat(1.f); +	if (mOctree) +	{ +		return; +	}  	mOctree = new LLOctreeRoot<LLVolumeTriangle>(center, size, NULL);  	new LLVolumeOctreeListener(mOctree);  	for (U32 i = 0; i < mNumIndices; i+= 3) -	{ +	{ //for each triangle  		LLPointer<LLVolumeTriangle> tri = new LLVolumeTriangle();  		const LLVector4a& v0 = mPositions[mIndices[i]];  		const LLVector4a& v1 = mPositions[mIndices[i+1]];  		const LLVector4a& v2 = mPositions[mIndices[i+2]]; +		//store pointers to vertex data  		tri->mV[0] = &v0;  		tri->mV[1] = &v1;  		tri->mV[2] = &v2; +		//store indices  		tri->mIndex[0] = mIndices[i];  		tri->mIndex[1] = mIndices[i+1];  		tri->mIndex[2] = mIndices[i+2]; +		//get minimum point  		LLVector4a min = v0;  		min.setMin(min, v1);  		min.setMin(min, v2); +		//get maximum point  		LLVector4a max = v0;  		max.setMax(max, v1);  		max.setMax(max, v2); +		//compute center  		LLVector4a center;  		center.setAdd(min, max);  		center.mul(0.5f);  		*tri->mPositionGroup = center; +		//compute "radius"  		LLVector4a size;  		size.setSub(max,min); -		tri->mRadius = size.getLength3().getF32() * 0.5f; +		tri->mRadius = size.getLength3().getF32() * scaler; +		//insert  		mOctree->insert(tri);  	} +	//remove unneeded octree layers +	while (!mOctree->balance())	{ } + +	//calculate AABB for each node  	LLVolumeOctreeRebound rebound(this);  	rebound.traverse(mOctree); + +	if (gDebugGL) +	{ +		LLVolumeOctreeValidate validate; +		validate.traverse(mOctree); +	}  } @@ -6146,21 +6161,21 @@ void LLVolumeFace::createBinormals()  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(mTexCoords); +	delete [] mPositions; +	delete [] mNormals; +	delete [] mBinormals; +	delete [] mTexCoords;  	mBinormals = NULL;  	if (num_verts)  	{ -		mPositions = (LLVector4a*) ll_aligned_malloc_16(num_verts*16); -		mNormals = (LLVector4a*) ll_aligned_malloc_16(num_verts*16); +		mPositions = new LLVector4a[num_verts];  +		mNormals = new LLVector4a[num_verts];   		//pad texture coordinate block end to allow for QWORD reads  		S32 size = ((num_verts*8) + 0xF) & ~0xF; -		mTexCoords = (LLVector2*) ll_aligned_malloc_16(size); +		mTexCoords = new LLVector2[size/8];  	}  	else  	{ @@ -6184,20 +6199,20 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con  	S32 old_size = mNumVertices*16;  	//positions -	LLVector4a* dst = (LLVector4a*) ll_aligned_malloc_16(new_size); +	LLVector4a* dst = new LLVector4a[new_verts];  	if (mPositions)  	{  		LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mPositions, old_size); -		ll_aligned_free_16(mPositions); +		delete [] mPositions;  	}  	mPositions = dst;  	//normals -	dst = (LLVector4a*) ll_aligned_malloc_16(new_size); +	dst = new LLVector4a[new_verts];   	if (mNormals)  	{  		LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mNormals, old_size); -		ll_aligned_free_16(mNormals); +		delete [] mNormals;  	}  	mNormals = dst; @@ -6205,19 +6220,18 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con  	new_size = ((new_verts*8)+0xF) & ~0xF;  	old_size = ((mNumVertices*8)+0xF) & ~0xF; -	dst = (LLVector4a*) ll_aligned_malloc_16(new_size);  	{ -		LLVector2* dst = (LLVector2*) ll_aligned_malloc_16(new_size); +		LLVector2* dst = new LLVector2[new_size/8];   		if (mTexCoords)  		{  			LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mTexCoords, old_size); -			ll_aligned_free_16(mTexCoords); +			delete [] mTexCoords;  		} +		mTexCoords = dst;  	} -	mTexCoords = (LLVector2*) dst;  	//just clear binormals -	ll_aligned_free_16(mBinormals); +	delete [] mBinormals;  	mBinormals = NULL;  	mPositions[mNumVertices] = pos; @@ -6229,26 +6243,26 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con  void LLVolumeFace::allocateBinormals(S32 num_verts)  { -	ll_aligned_free_16(mBinormals); -	mBinormals = (LLVector4a*) ll_aligned_malloc_16(num_verts*16); +	delete [] mBinormals; +	mBinormals = new LLVector4a[num_verts];   }  void LLVolumeFace::allocateWeights(S32 num_verts)  { -	ll_aligned_free_16(mWeights); -	mWeights = (LLVector4a*) ll_aligned_malloc_16(num_verts*16); +	delete [] mWeights;  +	mWeights = new LLVector4a[num_verts];   }  void LLVolumeFace::resizeIndices(S32 num_indices)  { -	ll_aligned_free_16(mIndices); - +	delete [] mIndices; +	  	if (num_indices)  	{  		//pad index block end to allow for QWORD reads  		S32 size = ((num_indices*2) + 0xF) & ~0xF; -		mIndices = (U16*) ll_aligned_malloc_16(size);	 +		mIndices = new U16[size/2];  	}  	else  	{ @@ -6266,11 +6280,11 @@ void LLVolumeFace::pushIndex(const U16& idx)  	S32 old_size = ((mNumIndices*2)+0xF) & ~0xF;  	if (new_size != old_size)  	{ -		U16* dst = (U16*) ll_aligned_malloc_16(new_size); +		U16* dst = new U16[new_size/2];  		if (mIndices)  		{  			LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mIndices, old_size); -			ll_aligned_free_16(mIndices); +			delete [] mIndices;  		}  		mIndices = dst;  	} @@ -6313,9 +6327,9 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat  	}  	//allocate new buffer space -	LLVector4a* new_pos = (LLVector4a*) ll_aligned_malloc_16(new_count*16); -	LLVector4a* new_norm = (LLVector4a*) ll_aligned_malloc_16(new_count*16); -	LLVector2* new_tc = (LLVector2*) ll_aligned_malloc_16((new_count*8+0xF) & ~0xF); +	LLVector4a* new_pos = new LLVector4a[new_count]; +	LLVector4a* new_norm = new LLVector4a[new_count]; +	LLVector2* new_tc = new LLVector2[((new_count*8+0xF) & ~0xF)/8];  	if (mNumVertices > 0) @@ -6326,10 +6340,10 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat  	}  	//free old buffer space -	ll_aligned_free_16(mPositions); -	ll_aligned_free_16(mNormals); -	ll_aligned_free_16(mTexCoords); - +	delete [] mPositions; +	delete [] mNormals; +	delete [] mTexCoords; +	  	//point to new buffers  	mPositions = new_pos;  	mNormals = new_norm; @@ -6379,7 +6393,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat  	new_count = mNumIndices + face.mNumIndices;  	//allocate new index buffer -	U16* new_indices = (U16*) ll_aligned_malloc_16((new_count*2+0xF) & ~0xF); +	U16* new_indices = new U16[((new_count*2+0xF) & ~0xF)/2];  	if (mNumIndices > 0)  	{ //copy old index buffer  		S32 old_size = (mNumIndices*2+0xF) & ~0xF; @@ -6387,8 +6401,8 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat  	}  	//free old index buffer -	ll_aligned_free_16(mIndices); - +	delete [] mIndices; +	  	//point to new index buffer  	mIndices = new_indices; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index af28337f57..32364bd4b8 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -882,7 +882,7 @@ public:  	};  	void optimize(F32 angle_cutoff = 2.f); -	void createOctree(); +	void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));  	enum  	{ @@ -1044,7 +1044,7 @@ public:  	LLVector3			mLODScaleBias;		// vector for biasing LOD based on scale  	void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level); -	void copyVolumeFaces(LLVolume* volume); +	void copyVolumeFaces(const LLVolume* volume);  private:  	void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp index 194b1faf81..cb6211f63c 100644 --- a/indra/llmath/llvolumeoctree.cpp +++ b/indra/llmath/llvolumeoctree.cpp @@ -126,8 +126,8 @@ void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle>  	const F32* center = vl->mBounds[0].getF32();  	const F32* size = vl->mBounds[1].getF32();*/ -	//if (LLLineSegmentBoxIntersect(mStart.getF32(), mEnd.getF32(), vl->mBounds[0].getF32(), vl->mBounds[1].getF32())) -	if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1])) +	//if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1])) +	if (LLLineSegmentBoxIntersect(mStart.getF32ptr(), mEnd.getF32ptr(), vl->mBounds[0].getF32ptr(), vl->mBounds[1].getF32ptr()))  	{  		node->accept(this);  		for (S32 i = 0; i < node->getChildCount(); ++i) @@ -206,3 +206,60 @@ const F32& LLVolumeTriangle::getBinRadius() const  } +//TEST CODE + +void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle>* branch) +{ +	LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); + +	//make sure bounds matches extents +	LLVector4a& min = node->mExtents[0]; +	LLVector4a& max = node->mExtents[1]; + +	LLVector4a& center = node->mBounds[0]; +	LLVector4a& size = node->mBounds[1]; + +	LLVector4a test_min, test_max; +	test_min.setSub(center, size); +	test_max.setAdd(center, size); + +	if (!test_min.equals3(min, 0.001f) || +		!test_max.equals3(max, 0.001f)) +	{ +		llerrs << "Bad bounding box data found." << llendl; +	} + +	test_min.sub(LLVector4a(0.001f)); +	test_max.add(LLVector4a(0.001f)); + +	for (U32 i = 0; i < branch->getChildCount(); ++i) +	{ +		LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); + +		//make sure all children fit inside this node +		if (child->mExtents[0].lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ) || +			child->mExtents[1].greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ)) +		{ +			llerrs << "Child protrudes from bounding box." << llendl; +		} +	} + +	//children fit, check data +	for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getData().begin();  +			iter != branch->getData().end(); ++iter) +	{ +		const LLVolumeTriangle* tri = *iter; + +		//validate triangle +		for (U32 i = 0; i < 3; i++) +		{ +			if (tri->mV[i]->greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ) || +				tri->mV[i]->lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ)) +			{ +				llerrs << "Triangle protrudes from node." << llendl; +			} +		} +	} +} + + diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index 0031626498..0a02a2c597 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -88,8 +88,6 @@ public:  	F32* mClosestT;  	bool mHitFace; -	LLOctreeTriangleRayIntersect() { }; -  	LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,   								   const LLVolumeFace* face, F32* closest_t,  								   LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal); @@ -134,5 +132,9 @@ public:  	virtual const F32& getBinRadius() const;  }; +class LLVolumeOctreeValidate : public LLOctreeTraveler<LLVolumeTriangle> +{ +	virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch); +};  #endif | 
