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