From cd17687f01420952712a500107e0f93e7ab8d5f8 Mon Sep 17 00:00:00 2001
From: Jacek Antonelli
Date: Fri, 15 Aug 2008 23:45:34 -0500
Subject: Second Life viewer sources 1.19.1.0
---
linden/indra/llmath/llcamera.cpp | 127 +++--
linden/indra/llmath/llcamera.h | 22 +-
linden/indra/llmath/llcoordframe.cpp | 6 +-
linden/indra/llmath/llmath.h | 16 +
linden/indra/llmath/llmath_vc8.vcproj | 944 ++++++++++++++++-----------------
linden/indra/llmath/llmath_vc9.vcproj | 946 +++++++++++++++++-----------------
linden/indra/llmath/lloctree.h | 382 +++++++-------
linden/indra/llmath/llrect.h | 32 +-
linden/indra/llmath/lltreenode.h | 89 +---
linden/indra/llmath/llvolume.cpp | 546 ++++++++++++--------
linden/indra/llmath/llvolume.h | 18 +-
linden/indra/llmath/llvolumemgr.cpp | 23 +
linden/indra/llmath/llvolumemgr.h | 1 +
linden/indra/llmath/v3color.cpp | 8 +
linden/indra/llmath/v3color.h | 10 +-
linden/indra/llmath/v4color.cpp | 10 +-
linden/indra/llmath/v4color.h | 4 +-
linden/indra/llmath/v4math.h | 3 +-
18 files changed, 1701 insertions(+), 1486 deletions(-)
(limited to 'linden/indra/llmath')
diff --git a/linden/indra/llmath/llcamera.cpp b/linden/indra/llmath/llcamera.cpp
index 82c401f..7a9d576 100644
--- a/linden/indra/llmath/llcamera.cpp
+++ b/linden/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 ¢er, const LLVector3& radius)
+S32 LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius)
{
static const LLVector3 scaler[] = {
LLVector3(-1,-1,-1),
@@ -166,10 +180,56 @@ int LLCamera::AABBInFrustum(const LLVector3 ¢er, 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 ¢er, 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/linden/indra/llmath/llcamera.h b/linden/indra/llmath/llcamera.h
index 0e20798..7066b9f 100644
--- a/linden/indra/llmath/llcamera.h
+++ b/linden/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 ¢er, const F32 radius) const { return sphereInFrustum(center, radius); }
S32 AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius);
+ S32 AABBInFrustumNoFarClip(const LLVector3 ¢er, const LLVector3& radius);
+
//does a quick 'n dirty sphere-sphere check
S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius);
diff --git a/linden/indra/llmath/llcoordframe.cpp b/linden/indra/llmath/llcoordframe.cpp
index 6d18c8b..0196424 100644
--- a/linden/indra/llmath/llcoordframe.cpp
+++ b/linden/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/linden/indra/llmath/llmath.h b/linden/indra/llmath/llmath.h
index affdbf1..d3c0d86 100644
--- a/linden/indra/llmath/llmath.h
+++ b/linden/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/linden/indra/llmath/llmath_vc8.vcproj b/linden/indra/llmath/llmath_vc8.vcproj
index ed4193d..e85a852 100644
--- a/linden/indra/llmath/llmath_vc8.vcproj
+++ b/linden/indra/llmath/llmath_vc8.vcproj
@@ -1,472 +1,472 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linden/indra/llmath/llmath_vc9.vcproj b/linden/indra/llmath/llmath_vc9.vcproj
index 1f6d05b..6d60d1e 100644
--- a/linden/indra/llmath/llmath_vc9.vcproj
+++ b/linden/indra/llmath/llmath_vc9.vcproj
@@ -1,473 +1,473 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linden/indra/llmath/lloctree.h b/linden/indra/llmath/lloctree.h
index 6eee9fb..203cb41 100644
--- a/linden/indra/llmath/lloctree.h
+++ b/linden/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 LLOctreeState;
template class LLOctreeNode;
template
@@ -64,15 +63,27 @@ public:
virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0;
};
+template
+class LLOctreeTraveler : public LLTreeTraveler
+{
+public:
+ virtual void traverse(const LLTreeNode* node);
+ virtual void visit(const LLTreeNode* state) { }
+ virtual void visit(const LLOctreeNode* branch) = 0;
+};
template
class LLOctreeNode : public LLTreeNode
{
public:
-
+ typedef LLOctreeTraveler oct_traveler;
+ typedef LLTreeTraveler tree_traveler;
+ typedef typename std::set > element_list;
+ typedef typename std::set >::iterator element_iter;
+ typedef typename std::set >::const_iterator const_element_iter;
+ typedef typename std::vector*>::iterator tree_listener_iter;
+ typedef typename std::vector* > child_list;
typedef LLTreeNode BaseType;
- typedef LLTreeState tree_state;
- typedef LLOctreeState oct_state;
typedef LLOctreeNode oct_node;
typedef LLOctreeListener 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 ¢er, LLVector3d &size, T* data)
+ static void pushCenter(LLVector3d ¢er, 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 LLOctreeTraveler : public LLTreeTraveler
-{
-public:
- virtual void traverse(const LLTreeNode* node);
- virtual void visit(const LLTreeState* state) { }
- virtual void visit(const LLOctreeState* branch) = 0;
-};
-
-//will pass requests to a child, might make a new child
-template
-class LLOctreeState : public LLTreeState
-{
-public:
- typedef LLTreeState BaseType;
- typedef LLOctreeTraveler oct_traveler;
- typedef LLOctreeNode oct_node;
- typedef LLOctreeListener oct_listener;
- typedef LLTreeTraveler tree_traveler;
- typedef typename std::set > element_list;
- typedef typename std::set >::iterator element_iter;
- typedef typename std::set >::const_iterator const_element_iter;
- typedef typename std::vector*>::iterator tree_listener_iter;
- typedef typename std::vector* > 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* node = getOctNode();
+ LLOctreeNode* 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* node = getOctNode();
- LLOctreeNode* parent = node->getOctParent();
+ LLOctreeNode* 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::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* newstate = new LLOctreeState();
- child = new LLOctreeNode(center, size, newstate, node);
+ child = new LLOctreeNode(center, size, this);
addChild(child);
-
+
child->insert(data);
}
}
else
{
//it's not in here, give it to the root
- LLOctreeNode* 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* 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 LLOctreeRoot : public LLOctreeState
+class LLOctreeRoot : public LLOctreeNode
{
public:
- typedef LLOctreeState BaseType;
+ typedef LLOctreeNode BaseType;
typedef LLOctreeNode 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* 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::insert(data);
+ oct_node* node = getNodeAt(data);
+ if (node == this)
+ {
+ LLOctreeNode::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::pushCenter(center, size, data);
- node->setCenter(center);
- node->setSize(size*2);
- node->updateMinMax();
+ this->setCenter(center);
+ this->setSize(size*2);
+ this->updateMinMax();
}
- LLOctreeState::insert(data);
+ LLOctreeNode::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::pushCenter(newcenter, size, data);
- node->setCenter(newcenter);
- node->setSize(size*2);
- node->updateMinMax();
-
- //copy our children to a new branch
- LLOctreeState* newstate = new LLOctreeState();
- LLOctreeNode* newnode = new LLOctreeNode(center, size, newstate, node);
-
- for (U32 i = 0; i < this->getChildCount(); i++)
+ while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())))
{
- LLOctreeNode* 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::pushCenter(newcenter, size, data);
+ this->setCenter(newcenter);
+ this->setSize(size*2);
+ this->updateMinMax();
+
+ //copy our children to a new branch
+ LLOctreeNode* newnode = new LLOctreeNode(center, size, this);
+
+ for (U32 i = 0; i < this->getChildCount(); i++)
+ {
+ LLOctreeNode* 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
-void LLOctreeTraveler::traverse(const LLTreeNode* node)
+void LLOctreeTraveler::traverse(const LLTreeNode* tree_node)
{
- const LLOctreeState* state = (const LLOctreeState*) node->getState();
- state->accept(this);
- for (U32 i = 0; i < state->getChildCount(); i++)
+ const LLOctreeNode* node = (const LLOctreeNode*) tree_node;
+ node->accept(this);
+ for (U32 i = 0; i < node->getChildCount(); i++)
{
- traverse(state->getChild(i));
+ traverse(node->getChild(i));
}
}
diff --git a/linden/indra/llmath/llrect.h b/linden/indra/llmath/llrect.h
index 76b5a27..9aadf9f 100644
--- a/linden/indra/llmath/llrect.h
+++ b/linden/indra/llmath/llrect.h
@@ -152,68 +152,74 @@ public:
mBottom <= rect->mTop && rect->mBottom <= mTop ;
}
- void set(Type left, Type top, Type right, Type bottom)
+ LLRectBase& set(Type left, Type top, Type right, Type bottom)
{
mLeft = left;
mTop = top;
mRight = right;
mBottom = bottom;
+ return *this;
}
// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
- void setOriginAndSize( Type left, Type bottom, Type width, Type height)
+ LLRectBase& setOriginAndSize( Type left, Type bottom, Type width, Type height)
{
mLeft = left;
mTop = bottom + height;
mRight = left + width;
mBottom = bottom;
+ return *this;
}
// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
- void setLeftTopAndSize( Type left, Type top, Type width, Type height)
+ LLRectBase& setLeftTopAndSize( Type left, Type top, Type width, Type height)
{
mLeft = left;
mTop = top;
mRight = left + width;
mBottom = top - height;
+ return *this;
}
- void setCenterAndSize(Type x, Type y, Type width, Type height)
+ LLRectBase& setCenterAndSize(Type x, Type y, Type width, Type height)
{
mLeft = x - width/2;
mTop = y + height/2;
mRight = x + width/2;
mBottom = y - height/2;
+ return *this;
}
- void translate(Type horiz, Type vertical)
+ LLRectBase& translate(Type horiz, Type vertical)
{
mLeft += horiz;
mRight += horiz;
mTop += vertical;
mBottom += vertical;
+ return *this;
}
- void stretch( Type dx, Type dy)
+ LLRectBase& stretch( Type dx, Type dy)
{
mLeft -= dx;
mRight += dx;
mTop += dy;
mBottom -= dy;
- makeValid();
+ return makeValid();
}
- void stretch( Type delta )
+ LLRectBase& stretch( Type delta )
{
stretch(delta, delta);
-
+ return *this;
}
- void makeValid()
+ LLRectBase& makeValid()
{
mLeft = llmin(mLeft, mRight);
mBottom = llmin(mBottom, mTop);
+ return *this;
}
bool isNull() const
@@ -221,15 +227,16 @@ public:
return mLeft == mRight || mBottom == mTop;
}
- void unionWith(const LLRectBase &other)
+ LLRectBase& unionWith(const LLRectBase &other)
{
mLeft = llmin(mLeft, other.mLeft);
mRight = llmax(mRight, other.mRight);
mBottom = llmin(mBottom, other.mBottom);
mTop = llmax(mTop, other.mTop);
+ return *this;
}
- void intersectWith(const LLRectBase &other)
+ LLRectBase& intersectWith(const LLRectBase &other)
{
mLeft = llmax(mLeft, other.mLeft);
mRight = llmin(mRight, other.mRight);
@@ -243,6 +250,7 @@ public:
{
mBottom = mTop;
}
+ return *this;
}
friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect)
diff --git a/linden/indra/llmath/lltreenode.h b/linden/indra/llmath/lltreenode.h
index 160a5bd..64beed8 100644
--- a/linden/indra/llmath/lltreenode.h
+++ b/linden/indra/llmath/lltreenode.h
@@ -40,23 +40,6 @@ template class LLTreeTraveler;
template class LLTreeListener;
template
-class LLTreeState
-{
-public:
- LLTreeState(LLTreeNode* node) { setNode(node); }
- virtual ~LLTreeState() { };
- virtual bool insert(T* data) = 0;
- virtual bool remove(T* data) = 0;
- virtual void setNode(LLTreeNode* node);
- virtual const LLTreeNode* getNode() const { return mNode; }
- virtual LLTreeNode* getNode() { return mNode; }
- virtual void accept(LLTreeTraveler* traveler) const = 0;
- virtual LLTreeListener* getListener(U32 index) const;
-private:
- LLTreeNode* mNode;
-};
-
-template
class LLTreeListener: public LLRefCount
{
public:
@@ -70,19 +53,14 @@ template
class LLTreeNode
{
public:
- LLTreeNode(LLTreeState* state) { setState(state); }
virtual ~LLTreeNode();
- LLTreeState* getState() { return mState; }
- const LLTreeState* getState() const { return mState; }
-
- void setState(LLTreeState* state);
- void insert(T* data);
- bool remove(T* data);
- void notifyRemoval(T* data);
- inline U32 getListenerCount() { return mListeners.size(); }
- inline LLTreeListener* getListener(U32 index) const { return mListeners[index]; }
- inline void addListener(LLTreeListener* 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* getListener(U32 index) const { return mListeners[index]; }
+ virtual void addListener(LLTreeListener* listener) { mListeners.push_back(listener); }
protected:
void destroyListeners()
@@ -94,7 +72,6 @@ protected:
mListeners.clear();
}
- LLTreeState* mState;
public:
std::vector > > mListeners;
};
@@ -105,7 +82,7 @@ class LLTreeTraveler
public:
virtual ~LLTreeTraveler() { };
virtual void traverse(const LLTreeNode* node) = 0;
- virtual void visit(const LLTreeState* state) = 0;
+ virtual void visit(const LLTreeNode* node) = 0;
};
template
@@ -115,25 +92,19 @@ LLTreeNode::~LLTreeNode()
};
template
-void LLTreeNode::insert(T* data)
+bool LLTreeNode::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
bool LLTreeNode::remove(T* data)
{
- if (mState->remove(data))
- {
- return true;
- }
- return false;
+ return true;
};
template
@@ -145,38 +116,4 @@ void LLTreeNode::notifyRemoval(T* data)
}
}
-template
-void LLTreeNode::setState(LLTreeState* 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
-void LLTreeState::setNode(LLTreeNode* node)
-{
- mNode = node;
- if (node && node->getState() != this)
- {
- node->setState(this);
- }
-};
-
-template
-LLTreeListener* LLTreeState::getListener(U32 index) const
-{
- return mNode->getListener(index);
-}
-
#endif
diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp
index 3316168..266ec08 100644
--- a/linden/indra/llmath/llvolume.cpp
+++ b/linden/indra/llmath/llvolume.cpp
@@ -1639,12 +1639,27 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, 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);
}
}
}
@@ -1840,55 +1854,70 @@ inline LLVector3 sculpt_rgb_to_vector(U8 r, U8 g, U8 b)
return value;
}
+inline U32 sculpt_xy_to_index(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components)
+{
+ U32 index = (x + y * sculpt_width) * sculpt_components;
-// sculpt replaces generate() for sculpted surfaces
-void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level)
+ // attempt to resolve DEV-11158 - remove assert later.
+ llassert(index < sculpt_width * sculpt_height * sculpt_components);
+
+ return index;
+}
+
+
+inline U32 sculpt_st_to_index(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components)
{
- U8 sculpt_type = mParams.getSculptType();
+ U32 x = (U32) ((F32)s/(size_s) * (F32) sculpt_width);
+ U32 y = (U32) ((F32)t/(size_t) * (F32) sculpt_height);
- BOOL data_is_empty = FALSE;
+ return sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components);
+}
- if (sculpt_width == 0 || sculpt_height == 0 || sculpt_data == NULL)
- {
- sculpt_level = -1;
- data_is_empty = TRUE;
- }
- mPathp->generate(mDetail, 0, TRUE);
- mProfilep->generate(mPathp->isOpen(), mDetail, 0, TRUE);
-
+inline LLVector3 sculpt_index_to_vector(U32 index, const U8* sculpt_data)
+{
+ LLVector3 v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]);
+
+ return v;
+}
+
+inline LLVector3 sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)
+{
+ U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components);
+
+ return sculpt_index_to_vector(index, sculpt_data);
+}
+
+inline LLVector3 sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)
+{
+ U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components);
+
+ return sculpt_index_to_vector(index, sculpt_data);
+}
+
+
+F32 LLVolume::sculptGetSurfaceArea(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)
+{
+ // test to see if image has enough variation to create non-degenerate geometry
+
S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size();
- sNumMeshPoints -= mMesh.size();
- mMesh.resize(sizeS * sizeT);
- sNumMeshPoints += mMesh.size();
-
F32 area = 0;
- // first test to see if image has enough variation to create non-degenerate geometry
- if (!data_is_empty)
+
+ if ((sculpt_width != 0) &&
+ (sculpt_height != 0) &&
+ (sculpt_components != 0) &&
+ (sculpt_data != NULL))
{
for (S32 s = 0; s < sizeS - 1; s++)
{
for (S32 t = 0; t < sizeT - 1; t++)
{
- // first coordinate
- U32 x = (U32) ((F32)s/(sizeS) * (F32) sculpt_width);
- U32 y = (U32) ((F32)t/(sizeT) * (F32) sculpt_height);
-
- // coordinate offset by 1
- U32 x2 = (U32) ((F32)(s+1)/(sizeS) * (F32) sculpt_width);
- U32 y2 = (U32) ((F32)(t+1)/(sizeT) * (F32) sculpt_height);
-
- // three points on a triagle - find the image indices first
- U32 p1_index = (x + y * sculpt_width) * sculpt_components;
- U32 p2_index = (x2 + y * sculpt_width) * sculpt_components;
- U32 p3_index = (x + y2 * sculpt_width) * sculpt_components;
-
// convert image data to vectors
- LLVector3 p1 = sculpt_rgb_to_vector(sculpt_data[p1_index], sculpt_data[p1_index+1], sculpt_data[p1_index+2]);
- LLVector3 p2 = sculpt_rgb_to_vector(sculpt_data[p2_index], sculpt_data[p2_index+1], sculpt_data[p2_index+2]);
- LLVector3 p3 = sculpt_rgb_to_vector(sculpt_data[p3_index], sculpt_data[p3_index+1], sculpt_data[p3_index+2]);
+ LLVector3 p1 = sculpt_st_to_vector(s, t, sizeS, sizeT, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
+ LLVector3 p2 = sculpt_st_to_vector(s+1, t, sizeS, sizeT, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
+ LLVector3 p3 = sculpt_st_to_vector(s, t+1, sizeS, sizeT, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
// compute the area of the parallelogram by taking the length of the cross product:
// (parallegram is an approximation of two triangles)
@@ -1896,99 +1925,151 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
area += cross.magVec();
}
}
- if (area < SCULPT_MIN_AREA)
- data_is_empty = TRUE;
}
- //generate vertex positions
- if (data_is_empty) // if empty, make a sphere
- {
- S32 line = 0;
+ return area;
+}
+
+// create placeholder shape
+void LLVolume::sculptGeneratePlaceholder()
+{
+ S32 sizeS = mPathp->mPath.size();
+ S32 sizeT = mProfilep->mProfile.size();
+
+ S32 line = 0;
- for (S32 s = 0; s < sizeS; s++)
+ // for now, this is a sphere.
+ for (S32 s = 0; s < sizeS; s++)
+ {
+ for (S32 t = 0; t < sizeT; t++)
{
- for (S32 t = 0; t < sizeT; t++)
- {
- S32 i = t + line;
- Point& pt = mMesh[i];
+ S32 i = t + line;
+ Point& pt = mMesh[i];
- F32 u = (F32)s/(sizeS-1);
- F32 v = (F32)t/(sizeT-1);
+ F32 u = (F32)s/(sizeS-1);
+ F32 v = (F32)t/(sizeT-1);
- const F32 RADIUS = (F32) 0.3;
+ const F32 RADIUS = (F32) 0.3;
- pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS);
- pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS);
- pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS);
+ pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS);
+ pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS);
+ pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS);
- }
- line += sizeT;
}
- }
- else
+ line += sizeT;
+ }
+}
+
+// create the vertices from the map
+void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type)
+{
+ S32 sizeS = mPathp->mPath.size();
+ S32 sizeT = mProfilep->mProfile.size();
+
+ S32 line = 0;
+ for (S32 s = 0; s < sizeS; s++)
{
- S32 line = 0;
- for (S32 s = 0; s < sizeS; s++)
+ // Run along the profile.
+ for (S32 t = 0; t < sizeT; t++)
{
- // Run along the profile.
- for (S32 t = 0; t < sizeT; t++)
- {
- S32 i = t + line;
- Point& pt = mMesh[i];
+ S32 i = t + line;
+ Point& pt = mMesh[i];
- U32 x = (U32) ((F32)t/(sizeT-1) * (F32) sculpt_width);
- U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height);
+ U32 x = (U32) ((F32)t/(sizeT-1) * (F32) sculpt_width);
+ U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height);
- if (y == 0) // top row stitching
+ if (y == 0) // top row stitching
+ {
+ // pinch?
+ if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
{
- // pinch?
- if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
- {
- x = sculpt_width / 2;
- }
+ x = sculpt_width / 2;
}
+ }
- if (y == sculpt_height) // bottom row stitching
+ if (y == sculpt_height) // bottom row stitching
+ {
+ // wrap?
+ if (sculpt_type == LL_SCULPT_TYPE_TORUS)
{
- // wrap?
- if (sculpt_type == LL_SCULPT_TYPE_TORUS)
- {
- y = 0;
- }
- else
- {
- y = sculpt_height - 1;
- }
+ y = 0;
+ }
+ else
+ {
+ y = sculpt_height - 1;
+ }
- // pinch?
- if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
- {
- x = sculpt_width / 2;
- }
+ // pinch?
+ if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
+ {
+ x = sculpt_width / 2;
}
+ }
- if (x == sculpt_width) // side stitching
+ if (x == sculpt_width) // side stitching
+ {
+ // wrap?
+ if ((sculpt_type == LL_SCULPT_TYPE_SPHERE) ||
+ (sculpt_type == LL_SCULPT_TYPE_TORUS) ||
+ (sculpt_type == LL_SCULPT_TYPE_CYLINDER))
{
- // wrap?
- if ((sculpt_type == LL_SCULPT_TYPE_SPHERE) ||
- (sculpt_type == LL_SCULPT_TYPE_TORUS) ||
- (sculpt_type == LL_SCULPT_TYPE_CYLINDER))
- {
- x = 0;
- }
+ x = 0;
+ }
- else
- {
- x = sculpt_width - 1;
- }
+ else
+ {
+ x = sculpt_width - 1;
}
-
- U32 index = (x + y * sculpt_width) * sculpt_components;
- pt.mPos = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]);
}
- line += sizeT;
+
+ pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
}
+ line += sizeT;
+ }
+}
+
+
+// sculpt replaces generate() for sculpted surfaces
+void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level)
+{
+ U8 sculpt_type = mParams.getSculptType();
+
+ BOOL data_is_empty = FALSE;
+
+ if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components == 0 || sculpt_data == NULL)
+ {
+ sculpt_level = -1;
+ data_is_empty = TRUE;
+ }
+
+ mPathp->generate(mDetail, 0, TRUE);
+ mProfilep->generate(mPathp->isOpen(), mDetail, 0, TRUE);
+
+ S32 sizeS = mPathp->mPath.size();
+ S32 sizeT = mProfilep->mProfile.size();
+
+ // weird crash bug - DEV-11158 - trying to collect more data:
+ if ((sizeS == 0) || (sizeT == 0))
+ {
+ llwarns << "sculpt bad mesh size " << sizeS << " " << sizeT << llendl;
+ }
+
+ sNumMeshPoints -= mMesh.size();
+ mMesh.resize(sizeS * sizeT);
+ sNumMeshPoints += mMesh.size();
+
+ if (sculptGetSurfaceArea(sculpt_width, sculpt_height, sculpt_components, sculpt_data) < SCULPT_MIN_AREA)
+ data_is_empty = TRUE;
+
+ //generate vertex positions
+ if (data_is_empty) // if empty, make a placeholder mesh
+ {
+ sculptGeneratePlaceholder();
+ }
+ else
+ {
+ sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type);
}
for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++)
@@ -3967,18 +4048,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 +4082,7 @@ void LerpPlanarVertex(LLVolumeFace::VertexData& v0,
vout.mBinormal = v0.mBinormal;
}
-BOOL LLVolumeFace::createUnCutCubeCap()
+BOOL LLVolumeFace::createUnCutCubeCap(BOOL partial_build)
{
const std::vector& mesh = mVolumep->getMesh();
const std::vector& profile = mVolumep->getProfile().mProfile;
@@ -4055,6 +4137,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=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=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 +4197,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 +4209,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 +4299,10 @@ BOOL LLVolumeFace::createCap()
{
mVertices.push_back(vd);
num_vertices++;
- vector_append(mIndices, 3);
+ if (!partial_build)
+ {
+ vector_append(mIndices, 3);
+ }
}
@@ -4213,6 +4312,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 +4586,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 +4645,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 +4763,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 +4830,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 +4971,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/linden/indra/llmath/llvolume.h b/linden/indra/llmath/llvolume.h
index 7b384f2..5ec7997 100644
--- a/linden/indra/llmath/llvolume.h
+++ b/linden/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 mVertices;
- std::vector mIndices;
+ std::vector mIndices;
std::vector mEdge;
LLVolume *mVolumep; // Deliberately NOT reference counted - djs 11/20/03 - otherwise would make an annoying circular reference
@@ -811,9 +813,9 @@ public:
LLStrider &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& 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);
@@ -899,6 +903,10 @@ 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);
+private:
+ F32 sculptGetSurfaceArea(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data);
+ void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
+ void sculptGeneratePlaceholder();
protected:
BOOL generate();
diff --git a/linden/indra/llmath/llvolumemgr.cpp b/linden/indra/llmath/llvolumemgr.cpp
index 17bafcd..4bf7ca6 100644
--- a/linden/indra/llmath/llvolumemgr.cpp
+++ b/linden/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/linden/indra/llmath/llvolumemgr.h b/linden/indra/llmath/llvolumemgr.h
index 0688163..0d6aa56 100644
--- a/linden/indra/llmath/llvolumemgr.h
+++ b/linden/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/linden/indra/llmath/v3color.cpp b/linden/indra/llmath/v3color.cpp
index cc4f874..9bdcd27 100644
--- a/linden/indra/llmath/v3color.cpp
+++ b/linden/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/linden/indra/llmath/v3color.h b/linden/indra/llmath/v3color.h
index 782ccd7..a3bf385 100644
--- a/linden/indra/llmath/v3color.h
+++ b/linden/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/linden/indra/llmath/v4color.cpp b/linden/indra/llmath/v4color.cpp
index b1884b7..8e6907e 100644
--- a/linden/indra/llmath/v4color.cpp
+++ b/linden/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/linden/indra/llmath/v4color.h b/linden/indra/llmath/v4color.h
index 9ba2690..a2c0fb6 100644
--- a/linden/indra/llmath/v4color.h
+++ b/linden/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/linden/indra/llmath/v4math.h b/linden/indra/llmath/v4math.h
index f9d0c43..60e30e3 100644
--- a/linden/indra/llmath/v4math.h
+++ b/linden/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)
--
cgit v1.1