summaryrefslogtreecommitdiff
path: root/indra/llmath
diff options
context:
space:
mode:
authorBrad Kittenbrink <brad@lindenlab.com>2008-02-27 18:58:14 +0000
committerBrad Kittenbrink <brad@lindenlab.com>2008-02-27 18:58:14 +0000
commit6d52efe452aa8469e0343da1c7d108f3f52ab651 (patch)
treea87be48e9840d7fc1f7ee514d7c7f994e71fdb3c /indra/llmath
parent6027ad2630b8650cabcf00628ee9b0d25bedd67f (diff)
Merge of windlight into release (QAR-286). This includes all changes in
windlight14 which have passed QA (up through r79932). svn merge -r 80831:80833 svn+ssh://svn.lindenlab.com/svn/linden/branches/merge_windlight14_r80620
Diffstat (limited to 'indra/llmath')
-rw-r--r--indra/llmath/llcamera.cpp127
-rw-r--r--indra/llmath/llcamera.h22
-rw-r--r--indra/llmath/llcoordframe.cpp6
-rw-r--r--indra/llmath/llmath.h16
-rw-r--r--indra/llmath/lloctree.h382
-rw-r--r--indra/llmath/lltreenode.h89
-rw-r--r--indra/llmath/llvolume.cpp277
-rw-r--r--indra/llmath/llvolume.h14
-rw-r--r--indra/llmath/llvolumemgr.cpp23
-rw-r--r--indra/llmath/llvolumemgr.h1
-rw-r--r--indra/llmath/v3color.cpp8
-rw-r--r--indra/llmath/v3color.h10
-rw-r--r--indra/llmath/v4color.cpp10
-rw-r--r--indra/llmath/v4color.h4
-rw-r--r--indra/llmath/v4math.h3
15 files changed, 564 insertions, 428 deletions
diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index 2ec9ba8503..3b9ba9d0f7 100644
--- a/indra/llmath/llcamera.cpp
+++ b/indra/llmath/llcamera.cpp
@@ -43,7 +43,8 @@ LLCamera::LLCamera() :
mViewHeightInPixels( -1 ), // invalid height
mNearPlane(DEFAULT_NEAR_PLANE),
mFarPlane(DEFAULT_FAR_PLANE),
- mFixedDistance(-1.f)
+ mFixedDistance(-1.f),
+ mPlaneCount(6)
{
calculateFrustumPlanes();
}
@@ -56,7 +57,8 @@ LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pix
mViewHeightInPixels(view_height_in_pixels),
mNearPlane(near_plane),
mFarPlane(far_plane),
- mFixedDistance(-1.f)
+ mFixedDistance(-1.f),
+ mPlaneCount(6)
{
if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; }
else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; }
@@ -78,6 +80,18 @@ LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pix
// ---------------- LLCamera::setFoo() member functions ----------------
+void LLCamera::setUserClipPlane(LLPlane plane)
+{
+ mPlaneCount = 7;
+ mAgentPlanes[6].p = plane;
+ mAgentPlanes[6].mask = calcPlaneMask(plane);
+}
+
+void LLCamera::disableUserClipPlane()
+{
+ mPlaneCount = 6;
+}
+
void LLCamera::setView(F32 field_of_view)
{
mView = field_of_view;
@@ -150,7 +164,7 @@ size_t LLCamera::readFrustumFromBuffer(const char *buffer)
// ---------------- test methods ----------------
-int LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
+S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
{
static const LLVector3 scaler[] = {
LLVector3(-1,-1,-1),
@@ -166,10 +180,56 @@ int LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
U8 mask = 0;
S32 result = 2;
- for (int i = 0; i < 6; i++)
+ for (U32 i = 0; i < mPlaneCount; i++)
+ {
+ mask = mAgentPlanes[i].mask;
+ LLPlane p = mAgentPlanes[i].p;
+ LLVector3 n = LLVector3(p);
+ float d = p.mV[3];
+ LLVector3 rscale = radius.scaledVec(scaler[mask]);
+
+ LLVector3 minp = center - rscale;
+ LLVector3 maxp = center + rscale;
+
+ if (n * minp > -d)
+ {
+ return 0;
+ }
+
+ if (n * maxp > -d)
+ {
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& radius)
+{
+ static const LLVector3 scaler[] = {
+ LLVector3(-1,-1,-1),
+ LLVector3( 1,-1,-1),
+ LLVector3(-1, 1,-1),
+ LLVector3( 1, 1,-1),
+ LLVector3(-1,-1, 1),
+ LLVector3( 1,-1, 1),
+ LLVector3(-1, 1, 1),
+ LLVector3( 1, 1, 1)
+ };
+
+ U8 mask = 0;
+ S32 result = 2;
+
+ for (U32 i = 0; i < mPlaneCount; i++)
{
- mask = mAgentPlaneMask[i];
- LLPlane p = mAgentPlanes[i];
+ if (i == 5)
+ {
+ continue;
+ }
+
+ mask = mAgentPlanes[i].mask;
+ LLPlane p = mAgentPlanes[i].p;
LLVector3 n = LLVector3(p);
float d = p.mV[3];
LLVector3 rscale = radius.scaledVec(scaler[mask]);
@@ -312,7 +372,7 @@ int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius)
int res = 2;
for (int i = 0; i < 6; i++)
{
- float d = mAgentPlanes[i].dist(sphere_center);
+ float d = mAgentPlanes[i].p.dist(sphere_center);
if (d > radius)
{
@@ -477,6 +537,25 @@ LLPlane planeFromPoints(LLVector3 p1, LLVector3 p2, LLVector3 p3)
return LLPlane(p1, n);
}
+U8 LLCamera::calcPlaneMask(const LLPlane& plane)
+{
+ U8 mask = 0;
+
+ if (plane.mV[0] >= 0)
+ {
+ mask |= 1;
+ }
+ if (plane.mV[1] >= 0)
+ {
+ mask |= 2;
+ }
+ if (plane.mV[2] >= 0)
+ {
+ mask |= 4;
+ }
+
+ return mask;
+}
void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
{
@@ -486,48 +565,34 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
mAgentFrustum[i] = frust[i];
}
+ mFrustumCornerDist = (frust[5] - getOrigin()).magVec();
+
//frust contains the 8 points of the frustum, calculate 6 planes
//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[2].p = planeFromPoints(frust[0], frust[1], frust[2]);
//far
- mAgentPlanes[5] = planeFromPoints(frust[5], frust[4], frust[6]);
+ mAgentPlanes[5].p = planeFromPoints(frust[5], frust[4], frust[6]);
//left
- mAgentPlanes[0] = planeFromPoints(frust[4], frust[0], frust[7]);
+ mAgentPlanes[0].p = planeFromPoints(frust[4], frust[0], frust[7]);
//right
- mAgentPlanes[1] = planeFromPoints(frust[1], frust[5], frust[6]);
+ mAgentPlanes[1].p = planeFromPoints(frust[1], frust[5], frust[6]);
//top
- mAgentPlanes[4] = planeFromPoints(frust[3], frust[2], frust[6]);
+ mAgentPlanes[4].p = planeFromPoints(frust[3], frust[2], frust[6]);
//bottom
- mAgentPlanes[3] = planeFromPoints(frust[1], frust[0], frust[4]);
+ mAgentPlanes[3].p = planeFromPoints(frust[1], frust[0], frust[4]);
//cache plane octant facing mask for use in AABBInFrustum
- for (int i = 0; i < 6; i++)
+ for (U32 i = 0; i < mPlaneCount; i++)
{
- U8 mask = 0;
- LLPlane p = mAgentPlanes[i];
- LLVector3 n = LLVector3(p);
-
- if (n.mV[0] >= 0)
- {
- mask |= 1;
- }
- if (n.mV[1] >= 0)
- {
- mask |= 2;
- }
- if (n.mV[2] >= 0)
- {
- mask |= 4;
- }
- mAgentPlaneMask[i] = mask;
+ mAgentPlanes[i].mask = calcPlaneMask(mAgentPlanes[i].p);
}
}
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index 67ffb2e450..bd894753f8 100644
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -46,7 +46,7 @@ const F32 MAX_FIELD_OF_VIEW = F_PI;
const F32 MAX_ASPECT_RATIO = 50.0f;
const F32 MAX_NEAR_PLANE = 10.f;
const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though.
-const F32 MAX_FAR_CLIP = 1024.0f;
+const F32 MAX_FAR_CLIP = 512.0f;
const F32 MIN_FIELD_OF_VIEW = 0.1f;
const F32 MIN_ASPECT_RATIO = 0.02f;
@@ -114,16 +114,28 @@ protected:
LLPlane mWorldPlanes[PLANE_NUM];
LLPlane mHorizPlanes[HORIZ_PLANE_NUM];
- LLPlane mAgentPlanes[6]; //frustum in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
- U8 mAgentPlaneMask[6];
+
+ typedef struct
+ {
+ LLPlane p;
+ U8 mask;
+ } frustum_plane;
+ frustum_plane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
+
+ U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in
+
LLVector3 mWorldPlanePos; // Position of World Planes (may be offset from camera)
public:
- LLVector3 mAgentFrustum[8];
+ LLVector3 mAgentFrustum[8]; //8 corners of 6-plane frustum
+ F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane
public:
LLCamera();
LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
+ void setUserClipPlane(LLPlane plane);
+ void disableUserClipPlane();
+ U8 calcPlaneMask(const LLPlane& plane);
void setView(F32 new_view);
void setViewHeightInPixels(S32 height);
void setAspect(F32 new_aspect);
@@ -164,6 +176,8 @@ public:
S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); }
S32 sphereInFrustumFull(const LLVector3 &center, const F32 radius) const { return sphereInFrustum(center, radius); }
S32 AABBInFrustum(const LLVector3 &center, const LLVector3& radius);
+ S32 AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& radius);
+
//does a quick 'n dirty sphere-sphere check
S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius);
diff --git a/indra/llmath/llcoordframe.cpp b/indra/llmath/llcoordframe.cpp
index 70d4646264..f108454731 100644
--- a/indra/llmath/llcoordframe.cpp
+++ b/indra/llmath/llcoordframe.cpp
@@ -730,7 +730,11 @@ void LLCoordFrame::lookDir(const LLVector3 &at, const LLVector3 &up_direction)
left.normVec();
LLVector3 up = at % left;
- setAxes(at, left, up);
+
+ if (at.isFinite() && left.isFinite() && up.isFinite())
+ {
+ setAxes(at, left, up);
+ }
}
void LLCoordFrame::lookDir(const LLVector3 &xuv)
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index f1b223f559..6df241d3ab 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -440,4 +440,20 @@ inline F32 llsimple_angle(F32 angle)
return angle;
}
+//calculate the nearesr power of two number for val, bounded by max_power_two
+inline U32 get_nearest_power_two(U32 val, U32 max_power_two)
+{
+ if(!max_power_two)
+ {
+ max_power_two = 1 << 31 ;
+ }
+ if(max_power_two & (max_power_two - 1))
+ {
+ return 0 ;
+ }
+
+ for(; val < max_power_two ; max_power_two >>= 1) ;
+
+ return max_power_two ;
+}
#endif
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index def6cb415a..fab8070259 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -47,10 +47,9 @@
#if LL_DARWIN
#define LL_OCTREE_MAX_CAPACITY 32
#else
-#define LL_OCTREE_MAX_CAPACITY 256
+#define LL_OCTREE_MAX_CAPACITY 128
#endif
-template <class T> class LLOctreeState;
template <class T> class LLOctreeNode;
template <class T>
@@ -64,15 +63,27 @@ public:
virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0;
};
+template <class T>
+class LLOctreeTraveler : public LLTreeTraveler<T>
+{
+public:
+ virtual void traverse(const LLTreeNode<T>* node);
+ virtual void visit(const LLTreeNode<T>* state) { }
+ virtual void visit(const LLOctreeNode<T>* branch) = 0;
+};
template <class T>
class LLOctreeNode : public LLTreeNode<T>
{
public:
-
+ typedef LLOctreeTraveler<T> oct_traveler;
+ typedef LLTreeTraveler<T> tree_traveler;
+ typedef typename std::set<LLPointer<T> > element_list;
+ typedef typename std::set<LLPointer<T> >::iterator element_iter;
+ typedef typename std::set<LLPointer<T> >::const_iterator const_element_iter;
+ typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter;
+ typedef typename std::vector<LLOctreeNode<T>* > child_list;
typedef LLTreeNode<T> BaseType;
- typedef LLTreeState<T> tree_state;
- typedef LLOctreeState<T> oct_state;
typedef LLOctreeNode<T> oct_node;
typedef LLOctreeListener<T> oct_listener;
@@ -82,11 +93,9 @@ public:
LLOctreeNode( LLVector3d center,
LLVector3d size,
- tree_state* state,
BaseType* parent,
U8 octant = 255)
- : BaseType(state),
- mParent((oct_node*)parent),
+ : mParent((oct_node*)parent),
mCenter(center),
mSize(size),
mOctant(octant)
@@ -96,9 +105,19 @@ public:
{
mOctant = ((oct_node*) mParent)->getOctant(mCenter.mdV);
}
+
+ clearChildren();
}
- ~LLOctreeNode() { BaseType::destroyListeners(); delete this->mState; }
+ virtual ~LLOctreeNode()
+ {
+ BaseType::destroyListeners();
+
+ for (U32 i = 0; i < getChildCount(); i++)
+ {
+ delete getChild(i);
+ }
+ }
inline const BaseType* getParent() const { return mParent; }
inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; }
@@ -106,25 +125,12 @@ public:
inline const LLVector3d& getSize() const { return mSize; }
inline void setCenter(LLVector3d center) { mCenter = center; }
inline void setSize(LLVector3d size) { mSize = size; }
- inline bool balance() { return getOctState()->balance(); }
- inline void validate() { getOctState()->validate(); }
- inline U32 getChildCount() const { return getOctState()->getChildCount(); }
- inline oct_node* getChild(U32 index) { return getOctState()->getChild(index); }
- inline const oct_node* getChild(U32 index) const { return getOctState()->getChild(index); }
- inline U32 getElementCount() const { return getOctState()->getElementCount(); }
- inline void removeByAddress(T* data) { getOctState()->removeByAddress(data); }
- inline bool hasLeafState() const { return getOctState()->isLeaf(); }
- inline void destroy() { getOctState()->destroy(); }
- inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
- inline oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) { return getOctState()->getNodeAt(pos, rad); }
+ inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
inline U8 getOctant() const { return mOctant; }
inline void setOctant(U8 octant) { mOctant = octant; }
- inline const oct_state* getOctState() const { return (const oct_state*) BaseType::mState; }
- inline oct_state* getOctState() { return (oct_state*) BaseType::mState; }
inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); }
inline oct_node* getOctParent() { return (oct_node*) getParent(); }
- inline void deleteChild(oct_node* child) { getOctState()->deleteChild(child); }
-
+
U8 getOctant(const F64 pos[]) const //get the octant pos is in
{
U8 ret = 0;
@@ -205,9 +211,9 @@ public:
(radius <= p_size && radius > size);
}
- static void pushCenter(LLVector3d &center, LLVector3d &size, T* data)
+ static void pushCenter(LLVector3d &center, const LLVector3d &size, const T* data)
{
- LLVector3d pos(data->getPositionGroup());
+ const LLVector3d& pos = data->getPositionGroup();
for (U32 i = 0; i < 3; i++)
{
if (pos.mdV[i] > center.mdV[i])
@@ -221,76 +227,25 @@ public:
}
}
-protected:
- oct_node* mParent;
- LLVector3d mCenter;
- LLVector3d mSize;
- LLVector3d mMax;
- LLVector3d mMin;
- U8 mOctant;
-};
-
-template <class T>
-class LLOctreeTraveler : public LLTreeTraveler<T>
-{
-public:
- virtual void traverse(const LLTreeNode<T>* node);
- virtual void visit(const LLTreeState<T>* state) { }
- virtual void visit(const LLOctreeState<T>* branch) = 0;
-};
-
-//will pass requests to a child, might make a new child
-template <class T>
-class LLOctreeState : public LLTreeState<T>
-{
-public:
- typedef LLTreeState<T> BaseType;
- typedef LLOctreeTraveler<T> oct_traveler;
- typedef LLOctreeNode<T> oct_node;
- typedef LLOctreeListener<T> oct_listener;
- typedef LLTreeTraveler<T> tree_traveler;
- typedef typename std::set<LLPointer<T> > element_list;
- typedef typename std::set<LLPointer<T> >::iterator element_iter;
- typedef typename std::set<LLPointer<T> >::const_iterator const_element_iter;
- typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter;
- typedef typename std::vector<LLOctreeNode<T>* > child_list;
+ void accept(oct_traveler* visitor) { visitor->visit(this); }
+ virtual bool isLeaf() const { return mChild.empty(); }
- LLOctreeState(oct_node* node = NULL): BaseType(node) { this->clearChildren(); }
- virtual ~LLOctreeState()
- {
- for (U32 i = 0; i < getChildCount(); i++)
- {
- delete getChild(i);
- }
- }
-
+ U32 getElementCount() const { return mData.size(); }
+ element_list& getData() { return mData; }
+ const element_list& getData() const { return mData; }
- virtual void accept(oct_traveler* visitor) { visitor->visit(this); }
- virtual bool isLeaf() const { return mChild.empty(); }
+ U32 getChildCount() const { return mChild.size(); }
+ oct_node* getChild(U32 index) { return mChild[index]; }
+ const oct_node* getChild(U32 index) const { return mChild[index]; }
+ child_list& getChildren() { return mChild; }
+ const child_list& getChildren() const { return mChild; }
- virtual U32 getElementCount() const { return mData.size(); }
- virtual element_list& getData() { return mData; }
- virtual const element_list& getData() const { return mData; }
+ void accept(tree_traveler* visitor) const { visitor->visit(this); }
+ void accept(oct_traveler* visitor) const { visitor->visit(this); }
- virtual U32 getChildCount() const { return mChild.size(); }
- virtual oct_node* getChild(U32 index) { return mChild[index]; }
- virtual const oct_node* getChild(U32 index) const { return mChild[index]; }
- virtual child_list& getChildren() { return mChild; }
- virtual const child_list& getChildren() const { return mChild; }
-
- virtual void accept(tree_traveler* visitor) const { visitor->visit(this); }
- virtual void accept(oct_traveler* visitor) const { visitor->visit(this); }
- const oct_node* getOctNode() const { return (const oct_node*) BaseType::getNode(); }
- oct_node* getOctNode() { return (oct_node*) BaseType::getNode(); }
-
- virtual oct_node* getNodeAt(T* data)
- {
- return getNodeAt(data->getPositionGroup(), data->getBinRadius());
- }
-
- virtual oct_node* getNodeAt(const LLVector3d& pos, const F64& rad)
+ oct_node* getNodeAt(const LLVector3d& pos, const F64& rad)
{
- LLOctreeNode<T>* node = getOctNode();
+ LLOctreeNode<T>* node = this;
if (node->isInside(pos, rad))
{
@@ -328,26 +283,19 @@ public:
{
if (data == NULL)
{
- OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl;
+ //OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl;
return false;
}
- LLOctreeNode<T>* node = getOctNode();
- LLOctreeNode<T>* parent = node->getOctParent();
+ LLOctreeNode<T>* parent = getOctParent();
//is it here?
- if (node->isInside(data->getPositionGroup()))
+ if (isInside(data->getPositionGroup()))
{
if (getElementCount() < LL_OCTREE_MAX_CAPACITY &&
- (node->contains(data->getBinRadius()) ||
- (data->getBinRadius() > node->getSize().mdV[0] &&
+ (contains(data->getBinRadius()) ||
+ (data->getBinRadius() > getSize().mdV[0] &&
parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
{ //it belongs here
- if (data == NULL)
- {
- OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE LEAF !!!" << llendl;
- return false;
- }
-
#if LL_OCTREE_PARANOIA_CHECK
//if this is a redundant insertion, error out (should never happen)
if (mData.find(data) != mData.end())
@@ -358,6 +306,7 @@ public:
#endif
mData.insert(data);
+ BaseType::insert(data);
return true;
}
else
@@ -375,8 +324,8 @@ public:
}
//it's here, but no kids are in the right place, make a new kid
- LLVector3d center(node->getCenter());
- LLVector3d size(node->getSize()*0.5);
+ LLVector3d center(getCenter());
+ LLVector3d size(getSize()*0.5);
//push center in direction of data
LLOctreeNode<T>::pushCenter(center, size, data);
@@ -386,7 +335,6 @@ public:
{
//this really isn't possible, something bad has happened
OCT_ERRS << "Octree detected floating point error and gave up." << llendl;
- //bool check = node->isInside(data);
return false;
}
@@ -396,25 +344,25 @@ public:
if (mChild[i]->getCenter() == center)
{
OCT_ERRS << "Octree detected duplicate child center and gave up." << llendl;
- //bool check = node->isInside(data);
- //check = getChild(i)->isInside(data);
return false;
}
}
#endif
//make the new kid
- LLOctreeState<T>* newstate = new LLOctreeState<T>();
- child = new LLOctreeNode<T>(center, size, newstate, node);
+ child = new LLOctreeNode<T>(center, size, this);
addChild(child);
-
+
child->insert(data);
}
}
else
{
//it's not in here, give it to the root
- LLOctreeNode<T>* parent = node->getOctParent();
+ //OCT_ERRS << "Octree insertion failed, starting over from root!" << llendl;
+
+ oct_node* node = this;
+
while (parent)
{
node = parent;
@@ -427,22 +375,20 @@ public:
return false;
}
- virtual bool remove(T* data)
+ bool remove(T* data)
{
- oct_node* node = getOctNode();
-
if (mData.find(data) != mData.end())
{ //we have data
mData.erase(data);
- node->notifyRemoval(data);
+ notifyRemoval(data);
checkAlive();
return true;
}
- else if (node->isInside(data))
+ else if (isInside(data))
{
oct_node* dest = getNodeAt(data);
- if (dest != node)
+ if (dest != this)
{
return dest->remove(data);
}
@@ -451,7 +397,9 @@ public:
//SHE'S GONE MISSING...
//none of the children have it, let's just brute force this bastard out
//starting with the root node (UGLY CODE COMETH!)
- oct_node* parent = node->getOctParent();
+ oct_node* parent = getOctParent();
+ oct_node* node = this;
+
while (parent != NULL)
{
node = parent;
@@ -464,12 +412,12 @@ public:
return true;
}
- virtual void removeByAddress(T* data)
+ void removeByAddress(T* data)
{
if (mData.find(data) != mData.end())
{
mData.erase(data);
- getOctNode()->notifyRemoval(data);
+ notifyRemoval(data);
llwarns << "FOUND!" << llendl;
checkAlive();
return;
@@ -482,20 +430,18 @@ public:
}
}
- virtual void clearChildren()
+ void clearChildren()
{
mChild.clear();
}
- virtual void validate()
+ void validate()
{
#if LL_OCTREE_PARANOIA_CHECK
- LLOctreeNode<T>* node = this->getOctNode();
-
for (U32 i = 0; i < getChildCount(); i++)
{
mChild[i]->validate();
- if (mChild[i]->getParent() != node)
+ if (mChild[i]->getParent() != this)
{
llerrs << "Octree child has invalid parent." << llendl;
}
@@ -508,7 +454,7 @@ public:
return false;
}
- virtual void destroy()
+ void destroy()
{
for (U32 i = 0; i < getChildCount(); i++)
{
@@ -517,7 +463,7 @@ public:
}
}
- virtual void addChild(oct_node* child, BOOL silent = FALSE)
+ void addChild(oct_node* child, BOOL silent = FALSE)
{
#if LL_OCTREE_PARANOIA_CHECK
for (U32 i = 0; i < getChildCount(); i++)
@@ -539,27 +485,24 @@ public:
#endif
mChild.push_back(child);
- child->setParent(getOctNode());
+ child->setParent(this);
if (!silent)
{
- oct_node* node = getOctNode();
-
- for (U32 i = 0; i < node->getListenerCount(); i++)
+ for (U32 i = 0; i < this->getListenerCount(); i++)
{
- oct_listener* listener = node->getOctListener(i);
- listener->handleChildAddition(node, child);
+ oct_listener* listener = getOctListener(i);
+ listener->handleChildAddition(this, child);
}
}
}
- virtual void removeChild(U8 index, BOOL destroy = FALSE)
+ void removeChild(U8 index, BOOL destroy = FALSE)
{
- oct_node* node = getOctNode();
- for (U32 i = 0; i < node->getListenerCount(); i++)
+ for (U32 i = 0; i < this->getListenerCount(); i++)
{
- oct_listener* listener = node->getOctListener(i);
- listener->handleChildRemoval(node, getChild(index));
+ oct_listener* listener = getOctListener(i);
+ listener->handleChildRemoval(this, getChild(index));
}
if (destroy)
@@ -572,20 +515,19 @@ public:
checkAlive();
}
- virtual void checkAlive()
+ void checkAlive()
{
if (getChildCount() == 0 && getElementCount() == 0)
{
- oct_node* node = getOctNode();
- oct_node* parent = node->getOctParent();
+ oct_node* parent = getOctParent();
if (parent)
{
- parent->deleteChild(node);
+ parent->deleteChild(this);
}
}
}
- virtual void deleteChild(oct_node* node)
+ void deleteChild(oct_node* node)
{
for (U32 i = 0; i < getChildCount(); i++)
{
@@ -596,55 +538,62 @@ public:
}
}
- OCT_ERRS << "Octree failed to delete requested child." << llendl;
+ //OCT_ERRS << "Octree failed to delete requested child." << llendl;
}
-protected:
+protected:
child_list mChild;
element_list mData;
+ oct_node* mParent;
+ LLVector3d mCenter;
+ LLVector3d mSize;
+ LLVector3d mMax;
+ LLVector3d mMin;
+ U8 mOctant;
};
-//just like a branch, except it might expand the node it points to
+//just like a regular node, except it might expand on insert and compress on balance
template <class T>
-class LLOctreeRoot : public LLOctreeState<T>
+class LLOctreeRoot : public LLOctreeNode<T>
{
public:
- typedef LLOctreeState<T> BaseType;
+ typedef LLOctreeNode<T> BaseType;
typedef LLOctreeNode<T> oct_node;
+
+ LLOctreeRoot( LLVector3d center,
+ LLVector3d size,
+ BaseType* parent)
+ : BaseType(center, size, parent)
+ {
+ }
- LLOctreeRoot(oct_node* node = NULL) : BaseType(node) { }
-
- oct_node* getOctNode() { return BaseType::getOctNode(); }
- virtual bool isLeaf() { return false; }
+ bool isLeaf() { return false; }
- virtual bool balance()
+ bool balance()
{
- //the cached node might be invalid, so don't reference it
if (this->getChildCount() == 1 &&
- !(this->mChild[0]->hasLeafState()) &&
+ !(this->mChild[0]->isLeaf()) &&
this->mChild[0]->getElementCount() == 0)
{ //if we have only one child and that child is an empty branch, make that child the root
- BaseType* state = this->mChild[0]->getOctState();
oct_node* child = this->mChild[0];
- oct_node* root = getOctNode();
-
+
//make the root node look like the child
- root->setCenter(this->mChild[0]->getCenter());
- root->setSize(this->mChild[0]->getSize());
- root->updateMinMax();
+ this->setCenter(this->mChild[0]->getCenter());
+ this->setSize(this->mChild[0]->getSize());
+ this->updateMinMax();
//reset root node child list
this->clearChildren();
//copy the child's children into the root node silently
//(don't notify listeners of addition)
- for (U32 i = 0; i < state->getChildCount(); i++)
+ for (U32 i = 0; i < child->getChildCount(); i++)
{
- addChild(state->getChild(i), TRUE);
+ addChild(child->getChild(i), TRUE);
}
//destroy child
- state->clearChildren();
+ child->clearChildren();
delete child;
}
@@ -652,69 +601,90 @@ public:
}
// LLOctreeRoot::insert
- virtual bool insert(T* data)
+ bool insert(T* data)
{
if (data == NULL)
{
- OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl;
+ //OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl;
return false;
}
if (data->getBinRadius() > 4096.0)
{
- OCT_ERRS << "!!! ELEMENT EXCEDES MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl;
+ //OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl;
+ return false;
}
- LLOctreeNode<T>* node = getOctNode();
- if (node->getSize().mdV[0] > data->getBinRadius() && node->isInside(data->getPositionGroup()))
+ const F64 MAX_MAG = 1024.0*1024.0;
+
+ const LLVector3d& v = data->getPositionGroup();
+ if (!(fabs(v.mdV[0]-this->mCenter.mdV[0]) < MAX_MAG &&
+ fabs(v.mdV[1]-this->mCenter.mdV[1]) < MAX_MAG &&
+ fabs(v.mdV[2]-this->mCenter.mdV[2]) < MAX_MAG))
+ {
+ //OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl;
+ return false;
+ }
+
+ if (this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup()))
{
//we got it, just act like a branch
- LLOctreeState<T>::insert(data);
+ oct_node* node = getNodeAt(data);
+ if (node == this)
+ {
+ LLOctreeNode<T>::insert(data);
+ }
+ else
+ {
+ node->insert(data);
+ }
}
else if (this->getChildCount() == 0)
{
//first object being added, just wrap it up
- while (!(node->getSize().mdV[0] > data->getBinRadius() && node->isInside(data->getPositionGroup())))
+ while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())))
{
LLVector3d center, size;
- center = node->getCenter();
- size = node->getSize();
+ center = this->getCenter();
+ size = this->getSize();
LLOctreeNode<T>::pushCenter(center, size, data);
- node->setCenter(center);
- node->setSize(size*2);
- node->updateMinMax();
+ this->setCenter(center);
+ this->setSize(size*2);
+ this->updateMinMax();
}
- LLOctreeState<T>::insert(data);
+ LLOctreeNode<T>::insert(data);
}
else
{
- //the data is outside the root node, we need to grow
- LLVector3d center(node->getCenter());
- LLVector3d size(node->getSize());
-
- //expand this node
- LLVector3d newcenter(center);
- LLOctreeNode<T>::pushCenter(newcenter, size, data);
- node->setCenter(newcenter);
- node->setSize(size*2);
- node->updateMinMax();
-
- //copy our children to a new branch
- LLOctreeState<T>* newstate = new LLOctreeState<T>();
- LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, newstate, node);
-
- for (U32 i = 0; i < this->getChildCount(); i++)
+ while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())))
{
- LLOctreeNode<T>* child = this->getChild(i);
- newstate->addChild(child);
- }
+ //the data is outside the root node, we need to grow
+ LLVector3d center(this->getCenter());
+ LLVector3d size(this->getSize());
+
+ //expand this node
+ LLVector3d newcenter(center);
+ LLOctreeNode<T>::pushCenter(newcenter, size, data);
+ this->setCenter(newcenter);
+ this->setSize(size*2);
+ this->updateMinMax();
+
+ //copy our children to a new branch
+ LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, this);
+
+ for (U32 i = 0; i < this->getChildCount(); i++)
+ {
+ LLOctreeNode<T>* child = this->getChild(i);
+ newnode->addChild(child);
+ }
- //clear our children and add the root copy
- this->clearChildren();
- addChild(newnode);
+ //clear our children and add the root copy
+ this->clearChildren();
+ addChild(newnode);
+ }
//insert the data
- node->insert(data);
+ insert(data);
}
return false;
@@ -726,13 +696,13 @@ public:
// LLOctreeTraveler
//========================
template <class T>
-void LLOctreeTraveler<T>::traverse(const LLTreeNode<T>* node)
+void LLOctreeTraveler<T>::traverse(const LLTreeNode<T>* tree_node)
{
- const LLOctreeState<T>* state = (const LLOctreeState<T>*) node->getState();
- state->accept(this);
- for (U32 i = 0; i < state->getChildCount(); i++)
+ const LLOctreeNode<T>* node = (const LLOctreeNode<T>*) tree_node;
+ node->accept(this);
+ for (U32 i = 0; i < node->getChildCount(); i++)
{
- traverse(state->getChild(i));
+ traverse(node->getChild(i));
}
}
diff --git a/indra/llmath/lltreenode.h b/indra/llmath/lltreenode.h
index 6cafee01d4..6685915bcf 100644
--- a/indra/llmath/lltreenode.h
+++ b/indra/llmath/lltreenode.h
@@ -40,23 +40,6 @@ template <class T> class LLTreeTraveler;
template <class T> class LLTreeListener;
template <class T>
-class LLTreeState
-{
-public:
- LLTreeState(LLTreeNode<T>* node) { setNode(node); }
- virtual ~LLTreeState() { };
- virtual bool insert(T* data) = 0;
- virtual bool remove(T* data) = 0;
- virtual void setNode(LLTreeNode<T>* node);
- virtual const LLTreeNode<T>* getNode() const { return mNode; }
- virtual LLTreeNode<T>* getNode() { return mNode; }
- virtual void accept(LLTreeTraveler<T>* traveler) const = 0;
- virtual LLTreeListener<T>* getListener(U32 index) const;
-private:
- LLTreeNode<T>* mNode;
-};
-
-template <class T>
class LLTreeListener: public LLRefCount
{
public:
@@ -70,19 +53,14 @@ template <class T>
class LLTreeNode
{
public:
- LLTreeNode(LLTreeState<T>* state) { setState(state); }
virtual ~LLTreeNode();
- LLTreeState<T>* getState() { return mState; }
- const LLTreeState<T>* getState() const { return mState; }
-
- void setState(LLTreeState<T>* state);
- void insert(T* data);
- bool remove(T* data);
- void notifyRemoval(T* data);
- inline U32 getListenerCount() { return mListeners.size(); }
- inline LLTreeListener<T>* getListener(U32 index) const { return mListeners[index]; }
- inline void addListener(LLTreeListener<T>* listener) { mListeners.push_back(listener); }
- inline void removeListener(U32 index) { mListeners.erase(mListeners.begin()+index); }
+
+ virtual bool insert(T* data);
+ virtual bool remove(T* data);
+ virtual void notifyRemoval(T* data);
+ virtual U32 getListenerCount() { return mListeners.size(); }
+ virtual LLTreeListener<T>* getListener(U32 index) const { return mListeners[index]; }
+ virtual void addListener(LLTreeListener<T>* listener) { mListeners.push_back(listener); }
protected:
void destroyListeners()
@@ -94,7 +72,6 @@ protected:
mListeners.clear();
}
- LLTreeState<T>* mState;
public:
std::vector<LLPointer<LLTreeListener<T> > > mListeners;
};
@@ -105,7 +82,7 @@ class LLTreeTraveler
public:
virtual ~LLTreeTraveler() { };
virtual void traverse(const LLTreeNode<T>* node) = 0;
- virtual void visit(const LLTreeState<T>* state) = 0;
+ virtual void visit(const LLTreeNode<T>* node) = 0;
};
template <class T>
@@ -115,25 +92,19 @@ LLTreeNode<T>::~LLTreeNode()
};
template <class T>
-void LLTreeNode<T>::insert(T* data)
+bool LLTreeNode<T>::insert(T* data)
{
- if (mState->insert(data))
+ for (U32 i = 0; i < mListeners.size(); i++)
{
- for (U32 i = 0; i < mListeners.size(); i++)
- {
- mListeners[i]->handleInsertion(this, data);
- }
+ mListeners[i]->handleInsertion(this, data);
}
+ return true;
};
template <class T>
bool LLTreeNode<T>::remove(T* data)
{
- if (mState->remove(data))
- {
- return true;
- }
- return false;
+ return true;
};
template <class T>
@@ -145,38 +116,4 @@ void LLTreeNode<T>::notifyRemoval(T* data)
}
}
-template <class T>
-void LLTreeNode<T>::setState(LLTreeState<T>* state)
-{
- mState = state;
- if (state)
- {
- if (state->getNode() != this)
- {
- state->setNode(this);
- }
-
- for (U32 i = 0; i < mListeners.size(); i++)
- {
- mListeners[i]->handleStateChange(this);
- }
- }
-};
-
-template <class T>
-void LLTreeState<T>::setNode(LLTreeNode<T>* node)
-{
- mNode = node;
- if (node && node->getState() != this)
- {
- node->setState(this);
- }
-};
-
-template <class T>
-LLTreeListener<T>* LLTreeState<T>::getListener(U32 index) const
-{
- return mNode->getListener(index);
-}
-
#endif
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 037357c92e..ab2eef0ee9 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -1639,12 +1639,27 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
}
}
+void LLVolume::resizePath(S32 length)
+{
+ mPathp->resizePath(length);
+ if (mVolumeFaces != NULL)
+ {
+ delete[] mVolumeFaces;
+ mVolumeFaces = NULL;
+ }
+}
+
void LLVolume::regen()
{
generate();
createVolumeFaces();
}
+void LLVolume::genBinormals(S32 face)
+{
+ mVolumeFaces[face].createBinormals();
+}
+
LLVolume::~LLVolume()
{
sNumMeshPoints -= mMesh.size();
@@ -1746,12 +1761,6 @@ void LLVolume::createVolumeFaces()
{
S32 i;
- if (mVolumeFaces != NULL)
- {
- delete[] mVolumeFaces;
- mVolumeFaces = NULL;
- }
-
if (mGenerateSingleFace)
{
mNumVolumeFaces = 0;
@@ -1760,7 +1769,12 @@ void LLVolume::createVolumeFaces()
{
S32 num_faces = getNumFaces();
mNumVolumeFaces = num_faces;
- mVolumeFaces = new LLVolumeFace[num_faces];
+ BOOL partial_build = TRUE;
+ if (!mVolumeFaces)
+ {
+ partial_build = FALSE;
+ mVolumeFaces = new LLVolumeFace[num_faces];
+ }
// Initialize volume faces with parameter data
for (i = 0; i < num_faces; i++)
{
@@ -1823,7 +1837,7 @@ void LLVolume::createVolumeFaces()
for (i = 0; i < mNumVolumeFaces; i++)
{
- mVolumeFaces[i].create();
+ mVolumeFaces[i].create(partial_build);
}
}
}
@@ -3967,18 +3981,19 @@ LLVolumeFace::LLVolumeFace()
mBeginT = 0;
mNumS = 0;
mNumT = 0;
+ mHasBinormals = FALSE;
}
-BOOL LLVolumeFace::create()
+BOOL LLVolumeFace::create(BOOL partial_build)
{
if (mTypeMask & CAP_MASK)
{
- return createCap();
+ return createCap(partial_build);
}
else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK))
{
- return createSide();
+ return createSide(partial_build);
}
else
{
@@ -4000,7 +4015,7 @@ void LerpPlanarVertex(LLVolumeFace::VertexData& v0,
vout.mBinormal = v0.mBinormal;
}
-BOOL LLVolumeFace::createUnCutCubeCap()
+BOOL LLVolumeFace::createUnCutCubeCap(BOOL partial_build)
{
const std::vector<LLVolume::Point>& mesh = mVolumep->getMesh();
const std::vector<LLVector3>& profile = mVolumep->getProfile().mProfile;
@@ -4055,6 +4070,12 @@ BOOL LLVolumeFace::createUnCutCubeCap()
corners[t].mBinormal = baseVert.mBinormal;
corners[t].mNormal = baseVert.mNormal;
}
+ mHasBinormals = TRUE;
+
+ if (partial_build)
+ {
+ mVertices.clear();
+ }
S32 vtop = mVertices.size();
for(int gx = 0;gx<grid_size+1;gx++){
@@ -4082,22 +4103,25 @@ BOOL LLVolumeFace::createUnCutCubeCap()
mCenter = (min + max) * 0.5f;
- int idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
- for(int gx = 0;gx<grid_size;gx++){
- for(int gy = 0;gy<grid_size;gy++){
- if (mTypeMask & TOP_MASK){
- for(int i=5;i>=0;i--)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
- }else{
- for(int i=0;i<6;i++)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
+ if (!partial_build)
+ {
+ int idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
+ for(int gx = 0;gx<grid_size;gx++){
+ for(int gy = 0;gy<grid_size;gy++){
+ if (mTypeMask & TOP_MASK){
+ for(int i=5;i>=0;i--)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
+ }else{
+ for(int i=0;i<6;i++)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
+ }
}
}
}
-
+
return TRUE;
}
-BOOL LLVolumeFace::createCap()
+BOOL LLVolumeFace::createCap(BOOL partial_build)
{
if (!(mTypeMask & HOLLOW_MASK) &&
!(mTypeMask & OPEN_MASK) &&
@@ -4106,7 +4130,7 @@ BOOL LLVolumeFace::createCap()
(mVolumep->getProfile().mParams.getCurveType()==LL_PCODE_PROFILE_SQUARE &&
mVolumep->getPath().mParams.getCurveType()==LL_PCODE_PATH_LINE)
){
- return createUnCutCubeCap();
+ return createUnCutCubeCap(partial_build);
}
S32 i;
@@ -4118,8 +4142,13 @@ BOOL LLVolumeFace::createCap()
// All types of caps have the same number of vertices and indices
num_vertices = profile.size();
num_indices = (profile.size() - 2)*3;
- vector_append(mVertices,num_vertices);
- vector_append(mIndices,num_indices);
+
+ mVertices.resize(num_vertices);
+
+ if (!partial_build)
+ {
+ mIndices.resize(num_indices);
+ }
S32 max_s = mVolumep->getProfile().getTotal();
S32 max_t = mVolumep->getPath().mPath.size();
@@ -4203,7 +4232,10 @@ BOOL LLVolumeFace::createCap()
{
mVertices.push_back(vd);
num_vertices++;
- vector_append(mIndices, 3);
+ if (!partial_build)
+ {
+ vector_append(mIndices, 3);
+ }
}
@@ -4213,6 +4245,13 @@ BOOL LLVolumeFace::createCap()
mVertices[i].mNormal = normal;
}
+ mHasBinormals = TRUE;
+
+ if (partial_build)
+ {
+ return TRUE;
+ }
+
if (mTypeMask & HOLLOW_MASK)
{
if (mTypeMask & TOP_MASK)
@@ -4480,7 +4519,50 @@ BOOL LLVolumeFace::createCap()
return TRUE;
}
-BOOL LLVolumeFace::createSide()
+void LLVolumeFace::createBinormals()
+{
+ if (!mHasBinormals)
+ {
+ //generate binormals
+ for (U32 i = 0; i < mIndices.size()/3; i++)
+ { //for each triangle
+ const VertexData& v0 = mVertices[mIndices[i*3+0]];
+ const VertexData& v1 = mVertices[mIndices[i*3+1]];
+ const VertexData& v2 = mVertices[mIndices[i*3+2]];
+
+ //calculate binormal
+ LLVector3 binorm = calc_binormal_from_triangle(v0.mPosition, v0.mTexCoord,
+ v1.mPosition, v1.mTexCoord,
+ v2.mPosition, v2.mTexCoord);
+
+ for (U32 j = 0; j < 3; j++)
+ { //add triangle normal to vertices
+ mVertices[mIndices[i*3+j]].mBinormal += binorm; // * (weight_sum - d[j])/weight_sum;
+ }
+
+ //even out quad contributions
+ if (i % 2 == 0)
+ {
+ mVertices[mIndices[i*3+2]].mBinormal += binorm;
+ }
+ else
+ {
+ mVertices[mIndices[i*3+1]].mBinormal += binorm;
+ }
+ }
+
+ //normalize binormals
+ for (U32 i = 0; i < mVertices.size(); i++)
+ {
+ mVertices[i].mBinormal.normVec();
+ mVertices[i].mNormal.normVec();
+ }
+
+ mHasBinormals = TRUE;
+ }
+}
+
+BOOL LLVolumeFace::createSide(BOOL partial_build)
{
BOOL flat = mTypeMask & FLAT_MASK;
S32 num_vertices, num_indices;
@@ -4496,9 +4578,14 @@ BOOL LLVolumeFace::createSide()
num_vertices = mNumS*mNumT;
num_indices = (mNumS-1)*(mNumT-1)*6;
- vector_append(mVertices,num_vertices);
- vector_append(mIndices,num_indices);
- vector_append(mEdge, num_indices);
+
+ mVertices.resize(num_vertices);
+
+ if (!partial_build)
+ {
+ mIndices.resize(num_indices);
+ mEdge.resize(num_indices);
+ }
LLVector3& face_min = mExtents[0];
LLVector3& face_max = mExtents[1];
@@ -4609,61 +4696,63 @@ BOOL LLVolumeFace::createSide()
S32 cur_edge = 0;
BOOL flat_face = mTypeMask & FLAT_MASK;
- // Now we generate the indices.
- for (t = 0; t < (mNumT-1); t++)
- {
- for (s = 0; s < (mNumS-1); s++)
- {
- mIndices[cur_index++] = s + mNumS*t; //bottom left
- mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right
- mIndices[cur_index++] = s + mNumS*(t+1); //top left
- mIndices[cur_index++] = s + mNumS*t; //bottom left
- mIndices[cur_index++] = s+1 + mNumS*t; //bottom right
- mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right
-
- mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face
- if (t < mNumT-2) { //top right/top left neighbor face
- mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1;
- }
- else if (mNumT <= 3 || mVolumep->getPath().isOpen() == TRUE) { //no neighbor
- mEdge[cur_edge++] = -1;
- }
- else { //wrap on T
- mEdge[cur_edge++] = s*2+1;
- }
- if (s > 0) { //top left/bottom left neighbor face
- mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1;
- }
- else if (flat_face || mVolumep->getProfile().isOpen() == TRUE) { //no neighbor
- mEdge[cur_edge++] = -1;
- }
- else { //wrap on S
- mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1;
- }
-
- if (t > 0) { //bottom left/bottom right neighbor face
- mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2;
- }
- else if (mNumT <= 3 || mVolumep->getPath().isOpen() == TRUE) { //no neighbor
- mEdge[cur_edge++] = -1;
- }
- else { //wrap on T
- mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2;
- }
- if (s < mNumS-2) { //bottom right/top right neighbor face
- mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2;
- }
- else if (flat_face || mVolumep->getProfile().isOpen() == TRUE) { //no neighbor
- mEdge[cur_edge++] = -1;
- }
- else { //wrap on S
- mEdge[cur_edge++] = (mNumS-1)*2*t;
+ if (!partial_build)
+ {
+ // Now we generate the indices.
+ for (t = 0; t < (mNumT-1); t++)
+ {
+ for (s = 0; s < (mNumS-1); s++)
+ {
+ mIndices[cur_index++] = s + mNumS*t; //bottom left
+ mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right
+ mIndices[cur_index++] = s + mNumS*(t+1); //top left
+ mIndices[cur_index++] = s + mNumS*t; //bottom left
+ mIndices[cur_index++] = s+1 + mNumS*t; //bottom right
+ mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right
+
+ mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face
+ if (t < mNumT-2) { //top right/top left neighbor face
+ mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1;
+ }
+ else if (mNumT <= 3 || mVolumep->getPath().isOpen() == TRUE) { //no neighbor
+ mEdge[cur_edge++] = -1;
+ }
+ else { //wrap on T
+ mEdge[cur_edge++] = s*2+1;
+ }
+ if (s > 0) { //top left/bottom left neighbor face
+ mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1;
+ }
+ else if (flat_face || mVolumep->getProfile().isOpen() == TRUE) { //no neighbor
+ mEdge[cur_edge++] = -1;
+ }
+ else { //wrap on S
+ mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1;
+ }
+
+ if (t > 0) { //bottom left/bottom right neighbor face
+ mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2;
+ }
+ else if (mNumT <= 3 || mVolumep->getPath().isOpen() == TRUE) { //no neighbor
+ mEdge[cur_edge++] = -1;
+ }
+ else { //wrap on T
+ mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2;
+ }
+ if (s < mNumS-2) { //bottom right/top right neighbor face
+ mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2;
+ }
+ else if (flat_face || mVolumep->getProfile().isOpen() == TRUE) { //no neighbor
+ mEdge[cur_edge++] = -1;
+ }
+ else { //wrap on S
+ mEdge[cur_edge++] = (mNumS-1)*2*t;
+ }
+ mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face
}
- mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face
}
}
-
//generate normals
for (U32 i = 0; i < mIndices.size()/3; i++) { //for each triangle
const VertexData& v0 = mVertices[mIndices[i*3+0]];
@@ -4674,27 +4763,22 @@ BOOL LLVolumeFace::createSide()
LLVector3 norm = (v0.mPosition-v1.mPosition)%
(v0.mPosition-v2.mPosition);
- //calculate binormal
- LLVector3 binorm = calc_binormal_from_triangle(v0.mPosition, v0.mTexCoord,
- v1.mPosition, v1.mTexCoord,
- v2.mPosition, v2.mTexCoord);
-
- for (U32 j = 0; j < 3; j++) { //add triangle normal to vertices
+ for (U32 j = 0; j < 3; j++)
+ { //add triangle normal to vertices
mVertices[mIndices[i*3+j]].mNormal += norm; // * (weight_sum - d[j])/weight_sum;
- mVertices[mIndices[i*3+j]].mBinormal += binorm; // * (weight_sum - d[j])/weight_sum;
}
//even out quad contributions
- if (i % 2 == 0) {
+ if (i % 2 == 0)
+ {
mVertices[mIndices[i*3+2]].mNormal += norm;
- mVertices[mIndices[i*3+2]].mBinormal += binorm;
}
- else {
+ else
+ {
mVertices[mIndices[i*3+1]].mNormal += norm;
- mVertices[mIndices[i*3+1]].mBinormal += binorm;
}
}
-
+
// adjust normals based on wrapping and stitching
BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f);
@@ -4820,15 +4904,6 @@ BOOL LLVolumeFace::createSide()
}
-
- //normalize normals and binormals here so the meshes that reference
- //this volume data don't have to
- for (U32 i = 0; i < mVertices.size(); i++)
- {
- mVertices[i].mNormal.normVec();
- mVertices[i].mBinormal.normVec();
- }
-
return TRUE;
}
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 3dadc56261..3e61947947 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -762,7 +762,8 @@ class LLVolumeFace
{
public:
LLVolumeFace();
- BOOL create();
+ BOOL create(BOOL partial_build = FALSE);
+ void createBinormals();
class VertexData
{
@@ -792,6 +793,7 @@ public:
S32 mID;
U32 mTypeMask;
LLVector3 mCenter;
+ BOOL mHasBinormals;
// Only used for INNER/OUTER faces
S32 mBeginS;
@@ -802,7 +804,7 @@ public:
LLVector3 mExtents[2]; //minimum and maximum point of face
std::vector<VertexData> mVertices;
- std::vector<S32> mIndices;
+ std::vector<U16> mIndices;
std::vector<S32> mEdge;
LLVolume *mVolumep; // Deliberately NOT reference counted - djs 11/20/03 - otherwise would make an annoying circular reference
@@ -811,9 +813,9 @@ public:
LLStrider<LLColor4U> &new_colors, const S32 num_new, const LLVolumeFace &new_face);
protected:
- BOOL createUnCutCubeCap();
- BOOL createCap();
- BOOL createSide();
+ BOOL createUnCutCubeCap(BOOL partial_build = FALSE);
+ BOOL createCap(BOOL partial_build = FALSE);
+ BOOL createSide(BOOL partial_build = FALSE);
};
class LLVolume : public LLRefCount
@@ -850,12 +852,14 @@ public:
LLVolumeParams getCopyOfParams() const { return mParams; }
const LLProfile& getProfile() const { return *mProfilep; }
LLPath& getPath() const { return *mPathp; }
+ void resizePath(S32 length);
const std::vector<Point>& getMesh() const { return mMesh; }
const LLVector3& getMeshPt(const U32 i) const { return mMesh[i].mPos; }
void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); }
void regen();
+ void genBinormals(S32 face);
BOOL isConvex() const;
BOOL isCap(S32 face);
diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp
index eae6ab7f4a..945d74f7c1 100644
--- a/indra/llmath/llvolumemgr.cpp
+++ b/indra/llmath/llvolumemgr.cpp
@@ -283,6 +283,29 @@ S32 LLVolumeLODGroup::getDetailFromTan(const F32 tan_angle)
return NUM_LODS - 1;
}
+void LLVolumeLODGroup::getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher)
+{
+ S32 detail = getDetailFromTan(tan_angle);
+
+ if (detail > 0)
+ {
+ to_lower = tan_angle - mDetailThresholds[detail];
+ }
+ else
+ {
+ to_lower = 1024.f*1024.f;
+ }
+
+ if (detail < NUM_LODS-1)
+ {
+ to_higher = mDetailThresholds[detail+1] - tan_angle;
+ }
+ else
+ {
+ to_higher = 1024.f*1024.f;
+ }
+}
+
F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
{
return mDetailScales[detail];
diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h
index 7aa0a3f3bf..3d7b663670 100644
--- a/indra/llmath/llvolumemgr.h
+++ b/indra/llmath/llvolumemgr.h
@@ -56,6 +56,7 @@ public:
BOOL derefLOD(LLVolume *volumep);
static S32 getDetailFromTan(const F32 tan_angle);
+ static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher);
static F32 getVolumeScaleFromDetail(const S32 detail);
LLVolume *getLOD(const S32 detail);
diff --git a/indra/llmath/v3color.cpp b/indra/llmath/v3color.cpp
index 462075c763..8a49be5615 100644
--- a/indra/llmath/v3color.cpp
+++ b/indra/llmath/v3color.cpp
@@ -33,6 +33,7 @@
#include "v3color.h"
#include "v4color.h"
+#include "v4math.h"
LLColor3 LLColor3::white(1.0f, 1.0f, 1.0f);
LLColor3 LLColor3::black(0.0f, 0.0f, 0.0f);
@@ -45,6 +46,13 @@ LLColor3::LLColor3(const LLColor4 &a)
mV[2] = a.mV[2];
}
+LLColor3::LLColor3(const LLVector4 &a)
+{
+ mV[0] = a.mV[0];
+ mV[1] = a.mV[1];
+ mV[2] = a.mV[2];
+}
+
LLColor3::LLColor3(const LLSD &sd)
{
mV[0] = (F32) sd[0].asReal();
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index d09af7a8c4..56820148d5 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -33,6 +33,7 @@
#define LL_V3COLOR_H
class LLColor4;
+class LLVector4;
#include "llerror.h"
#include "llmath.h"
@@ -57,6 +58,7 @@ public:
LLColor3(const F32 *vec); // Initializes LLColor3 to (vec[0]. vec[1], vec[2])
LLColor3(char *color_string); // html format color ie "#FFDDEE"
explicit LLColor3(const LLColor4& color4); // "explicit" to avoid automatic conversion
+ explicit LLColor3(const LLVector4& vector4); // "explicit" to avoid automatic conversion
LLColor3(const LLSD& sd);
@@ -87,6 +89,7 @@ public:
F32 magVec() const; // Returns magnitude of LLColor3
F32 magVecSquared() const; // Returns magnitude squared of LLColor3
F32 normVec(); // Normalizes and returns the magnitude of LLColor3
+ F32 brightness() const; // Returns brightness of LLColor3
const LLColor3& operator=(const LLColor4 &a);
@@ -98,7 +101,7 @@ public:
friend const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b); // Return vector a minus b
friend const LLColor3& operator*=(LLColor3 &a, const LLColor3 &b);
- friend LLColor3 operator*(const LLColor3 &a, const LLColor3 &b); // Return a dot b
+ friend LLColor3 operator*(const LLColor3 &a, const LLColor3 &b); // Return component wise a * b
friend LLColor3 operator*(const LLColor3 &a, F32 k); // Return a times scaler k
friend LLColor3 operator*(F32 k, const LLColor3 &a); // Return a times scaler k
@@ -231,6 +234,11 @@ inline const LLColor3& LLColor3::setVec(const F32 *vec)
return (*this);
}
+inline F32 LLColor3::brightness(void) const
+{
+ return (mV[0] + mV[1] + mV[2]) / 3.0f;
+}
+
inline F32 LLColor3::magVec(void) const
{
return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp
index 4ce8e10527..21166472e4 100644
--- a/indra/llmath/v4color.cpp
+++ b/indra/llmath/v4color.cpp
@@ -36,7 +36,7 @@
#include "v4color.h"
#include "v4coloru.h"
#include "v3color.h"
-//#include "vmath.h"
+#include "v4math.h"
#include "llmath.h"
// LLColor4
@@ -153,6 +153,14 @@ LLColor4::LLColor4(const LLColor4U& color4u)
mV[VW] = color4u.mV[VW] * SCALE;
}
+LLColor4::LLColor4(const LLVector4& vector4)
+{
+ mV[VX] = vector4.mV[VX];
+ mV[VY] = vector4.mV[VY];
+ mV[VZ] = vector4.mV[VZ];
+ mV[VW] = vector4.mV[VW];
+}
+
const LLColor4& LLColor4::setVec(const LLColor4U& color4u)
{
const F32 SCALE = 1.f/255.f;
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index 0514870ef6..bd990444b5 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -39,6 +39,7 @@
class LLColor3;
class LLColor4U;
+class LLVector4;
// LLColor4 = |x y z w|
@@ -58,6 +59,7 @@ class LLColor4
LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a)
LLColor4(const LLSD& sd);
explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion
+ explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion
LLSD getValue() const
{
@@ -107,7 +109,7 @@ class LLColor4
friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a
friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b
friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b
- friend LLColor4 operator*(const LLColor4 &a, const LLColor4 &b); // Return a * b
+ friend LLColor4 operator*(const LLColor4 &a, const LLColor4 &b); // Return component wise a * b
friend LLColor4 operator*(const LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change)
friend LLColor4 operator*(F32 k, const LLColor4 &a); // Return rgb times scaler k (no alpha change)
friend LLColor4 operator%(const LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change)
diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h
index 57dcad35fe..34b5f9e33c 100644
--- a/indra/llmath/v4math.h
+++ b/indra/llmath/v4math.h
@@ -312,7 +312,8 @@ inline bool operator!=(const LLVector4 &a, const LLVector4 &b)
{
return ( (a.mV[VX] != b.mV[VX])
||(a.mV[VY] != b.mV[VY])
- ||(a.mV[VZ] != b.mV[VZ]));
+ ||(a.mV[VZ] != b.mV[VZ])
+ ||(a.mV[VW] != b.mV[VW]) );
}
inline const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b)