summaryrefslogtreecommitdiff
path: root/indra/llmath
diff options
context:
space:
mode:
authorMatthew Breindel (Falcon) <falcon@lindenlab.com>2010-09-22 13:04:53 -0700
committerMatthew Breindel (Falcon) <falcon@lindenlab.com>2010-09-22 13:04:53 -0700
commit569f3f4b06fc2f5a0fa658a49d519428983403f9 (patch)
tree3fdafee487d0b922793ff864970ce73f223cd861 /indra/llmath
parent05c2f451dcbb7fdfb6d45d8b65ec71ba6b799af4 (diff)
parent6d8e9cd8bde57bd033beeb9610f7094c19655ed1 (diff)
Merge
Diffstat (limited to 'indra/llmath')
-rw-r--r--indra/llmath/lloctree.h127
-rw-r--r--indra/llmath/llvolume.cpp263
-rw-r--r--indra/llmath/llvolume.h12
-rw-r--r--indra/llmath/llvolumeoctree.cpp61
-rw-r--r--indra/llmath/llvolumeoctree.h6
5 files changed, 266 insertions, 203 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..1f15d5465c 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -94,6 +94,17 @@ const F32 SKEW_MAX = 0.95f;
const F32 SCULPT_MIN_AREA = 0.002f;
const S32 SCULPT_MIN_AREA_DETAIL = 1;
+extern BOOL gDebugGL;
+
+void assert_aligned(void* ptr, U32 alignment)
+{
+ U32 t = (U32) ptr;
+ if (t%alignment != 0)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+}
+
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 +319,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 +350,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 +379,6 @@ public:
}
};
-
//-------------------------------------------------------------------
// statics
//-------------------------------------------------------------------
@@ -1991,7 +1999,7 @@ void LLVolumeFace::VertexData::init()
{
if (!mData)
{
- mData = (LLVector4a*) ll_aligned_malloc_16(32);
+ mData = (LLVector4a*) malloc(sizeof(LLVector4a)*2);
}
}
@@ -2012,7 +2020,7 @@ const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolu
if (this != &rhs)
{
init();
- LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 8*sizeof(F32));
+ LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 2*sizeof(LLVector4a));
mTexCoord = rhs.mTexCoord;
}
return *this;
@@ -2020,7 +2028,8 @@ const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolu
LLVolumeFace::VertexData::~VertexData()
{
- ll_aligned_free_16(mData);
+ free(mData);
+ mData = NULL;
}
LLVector4a& LLVolumeFace::VertexData::getPosition()
@@ -2258,12 +2267,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,24 +2579,21 @@ 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
U8 sculpt_type = (mParams.getSculptType() & LL_SCULPT_TYPE_MASK);
if (sculpt_type == LL_SCULPT_TYPE_MESH)
{
return LL_SCULPT_MESH_MAX_FACES;
}
-#endif
return (S32)mProfilep->mFaces.size();
}
@@ -4168,12 +4174,10 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
normals.clear();
segments.clear();
-#if LL_MESH_ENABLED
if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
{
return;
}
-#endif
S32 cur_index = 0;
//for each face
@@ -5232,7 +5236,7 @@ LLVolumeFace::LLVolumeFace() :
mWeights(NULL),
mOctree(NULL)
{
- mExtents = (LLVector4a*) ll_aligned_malloc_16(48);
+ mExtents = (LLVector4a*) malloc(sizeof(LLVector4a)*3);
mCenter = mExtents+2;
}
@@ -5253,7 +5257,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
mWeights(NULL),
mOctree(NULL)
{
- mExtents = (LLVector4a*) ll_aligned_malloc_16(48);
+ mExtents = (LLVector4a*) malloc(sizeof(LLVector4a)*3);
mCenter = mExtents+2;
*this = src;
}
@@ -5281,15 +5285,15 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
freeData();
- LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 12*sizeof(F32));
+ LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 3*sizeof(LLVector4a));
resizeVertices(src.mNumVertices);
resizeIndices(src.mNumIndices);
if (mNumVertices)
{
- S32 vert_size = mNumVertices*4*sizeof(F32);
- S32 tc_size = (mNumVertices*8+0xF) & ~0xF;
+ S32 vert_size = mNumVertices*sizeof(LLVector4a);
+ S32 tc_size = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF;
LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size);
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
@@ -5303,7 +5307,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
}
else
{
- ll_aligned_free_16(mBinormals);
+ free(mBinormals);
mBinormals = NULL;
}
@@ -5314,14 +5318,14 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
}
else
{
- ll_aligned_free_16(mWeights);
+ free(mWeights);
mWeights = NULL;
}
}
if (mNumIndices)
{
- S32 idx_size = (mNumIndices*2+0xF) & ~0xF;
+ S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF;
LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size);
}
@@ -5332,7 +5336,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
LLVolumeFace::~LLVolumeFace()
{
- ll_aligned_free_16(mExtents);
+ free(mExtents);
mExtents = NULL;
freeData();
@@ -5340,17 +5344,17 @@ LLVolumeFace::~LLVolumeFace()
void LLVolumeFace::freeData()
{
- ll_aligned_free_16(mPositions);
+ free(mPositions);
mPositions = NULL;
- ll_aligned_free_16(mNormals);
+ free( mNormals);
mNormals = NULL;
- ll_aligned_free_16(mTexCoords);
+ free(mTexCoords);
mTexCoords = NULL;
- ll_aligned_free_16(mIndices);
+ free(mIndices);
mIndices = NULL;
- ll_aligned_free_16(mBinormals);
+ free(mBinormals);
mBinormals = NULL;
- ll_aligned_free_16(mWeights);
+ free(mWeights);
mWeights = NULL;
delete mOctree;
@@ -5404,13 +5408,14 @@ bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a
return a.mV[1] < b.mV[1];
}
- return a.mV[2] < b.mV[2];
+ return a.mV[2] < b.mV[2];
}
void LLVolumeFace::optimize(F32 angle_cutoff)
{
LLVolumeFace new_face;
+ //map of points to vector of vertices at that point
VertexMapData::PointMap point_map;
//remove redundant vertices
@@ -5463,56 +5468,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 +6168,24 @@ 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);
+ free(mPositions);
+ free(mNormals);
+ free(mBinormals);
+ free(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 = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts);
+ assert_aligned(mPositions, 16);
+ mNormals = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts);
+ assert_aligned(mNormals, 16);
//pad texture coordinate block end to allow for QWORD reads
- S32 size = ((num_verts*8) + 0xF) & ~0xF;
- mTexCoords = (LLVector2*) ll_aligned_malloc_16(size);
+ S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
+ mTexCoords = (LLVector2*) malloc(size);
+ assert_aligned(mTexCoords, 16);
}
else
{
@@ -6181,43 +6206,21 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
{
S32 new_verts = mNumVertices+1;
S32 new_size = new_verts*16;
- S32 old_size = mNumVertices*16;
+// S32 old_size = mNumVertices*16;
//positions
- LLVector4a* dst = (LLVector4a*) ll_aligned_malloc_16(new_size);
- if (mPositions)
- {
- LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mPositions, old_size);
- ll_aligned_free_16(mPositions);
- }
- mPositions = dst;
-
+ mPositions = (LLVector4a*) realloc(mPositions, new_size);
+
//normals
- dst = (LLVector4a*) ll_aligned_malloc_16(new_size);
- if (mNormals)
- {
- LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mNormals, old_size);
- ll_aligned_free_16(mNormals);
- }
- mNormals = dst;
-
+ mNormals = (LLVector4a*) realloc(mNormals, new_size);
+
//tex coords
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);
- if (mTexCoords)
- {
- LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mTexCoords, old_size);
- ll_aligned_free_16(mTexCoords);
- }
- }
- mTexCoords = (LLVector2*) dst;
+ mTexCoords = (LLVector2*) realloc(mTexCoords, new_size);
+
//just clear binormals
- ll_aligned_free_16(mBinormals);
+ free(mBinormals);
mBinormals = NULL;
mPositions[mNumVertices] = pos;
@@ -6229,26 +6232,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);
+ free(mBinormals);
+ mBinormals = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts);
}
void LLVolumeFace::allocateWeights(S32 num_verts)
{
- ll_aligned_free_16(mWeights);
- mWeights = (LLVector4a*) ll_aligned_malloc_16(num_verts*16);
+ free(mWeights);
+ mWeights = (LLVector4a*) malloc(sizeof(LLVector4a)*num_verts);
}
void LLVolumeFace::resizeIndices(S32 num_indices)
{
- ll_aligned_free_16(mIndices);
-
+ free(mIndices);
+
if (num_indices)
{
//pad index block end to allow for QWORD reads
- S32 size = ((num_indices*2) + 0xF) & ~0xF;
+ S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF;
- mIndices = (U16*) ll_aligned_malloc_16(size);
+ mIndices = (U16*) malloc(size);
}
else
{
@@ -6266,13 +6269,7 @@ 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);
- if (mIndices)
- {
- LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mIndices, old_size);
- ll_aligned_free_16(mIndices);
- }
- mIndices = dst;
+ mIndices = (U16*) realloc(mIndices, new_size);
}
mIndices[mNumIndices++] = idx;
@@ -6313,28 +6310,13 @@ 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);
+ mPositions = (LLVector4a*) realloc(mPositions, new_count*sizeof(LLVector4a));
+ assert_aligned(mPositions, 16);
+ mNormals = (LLVector4a*) realloc(mNormals, new_count*sizeof(LLVector4a));
+ assert_aligned(mNormals, 16);
+ mTexCoords = (LLVector2*) realloc(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF);
+ assert_aligned(mTexCoords, 16);
-
- if (mNumVertices > 0)
- { //copy old buffers
- LLVector4a::memcpyNonAliased16((F32*) new_pos, (F32*) mPositions, mNumVertices*4*sizeof(F32));
- LLVector4a::memcpyNonAliased16((F32*) new_norm, (F32*) mNormals, mNumVertices*4*sizeof(F32));
- LLVector4a::memcpyNonAliased16((F32*) new_tc, (F32*) mTexCoords, mNumVertices*2*sizeof(F32));
- }
-
- //free old buffer space
- ll_aligned_free_16(mPositions);
- ll_aligned_free_16(mNormals);
- ll_aligned_free_16(mTexCoords);
-
- //point to new buffers
- mPositions = new_pos;
- mNormals = new_norm;
- mTexCoords = new_tc;
-
mNumVertices = new_count;
//get destination address of appended face
@@ -6379,19 +6361,8 @@ 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);
- if (mNumIndices > 0)
- { //copy old index buffer
- S32 old_size = (mNumIndices*2+0xF) & ~0xF;
- LLVector4a::memcpyNonAliased16((F32*) new_indices, (F32*) mIndices, old_size);
- }
-
- //free old index buffer
- ll_aligned_free_16(mIndices);
-
- //point to new index buffer
- mIndices = new_indices;
-
+ mIndices = (U16*) realloc(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF);
+
//get destination address into new index buffer
U16* dst_idx = mIndices+mNumIndices;
mNumIndices = new_count;
@@ -6433,14 +6404,10 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
resizeVertices(num_vertices);
resizeIndices(num_indices);
-#if LL_MESH_ENABLED
if ((volume->getParams().getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH)
{
mEdge.resize(num_indices);
}
-#else
- mEdge.resize(num_indices);
-#endif
}
LLVector4a* pos = (LLVector4a*) mPositions;
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index af28337f57..b4b59fd402 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -41,8 +41,6 @@ class LLVolumeParams;
class LLProfile;
class LLPath;
-#define LL_MESH_ENABLED 1
-
template <class T> class LLOctreeNode;
class LLVector4a;
@@ -192,15 +190,9 @@ const U8 LL_SCULPT_TYPE_SPHERE = 1;
const U8 LL_SCULPT_TYPE_TORUS = 2;
const U8 LL_SCULPT_TYPE_PLANE = 3;
const U8 LL_SCULPT_TYPE_CYLINDER = 4;
-#if LL_MESH_ENABLED
const U8 LL_SCULPT_TYPE_MESH = 5;
-
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |
LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH;
-#else
-const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |
- LL_SCULPT_TYPE_CYLINDER;
-#endif
const U8 LL_SCULPT_FLAG_INVERT = 64;
const U8 LL_SCULPT_FLAG_MIRROR = 128;
@@ -882,7 +874,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 +1036,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