Merge of windlight into release (QAR-286). This includes all changes in

windlight14 which have passed QA (up through r79932).

svn merge -r 80831:80833 svn+ssh://svn.lindenlab.com/svn/linden/branches/merge_windlight14_r80620
master
Brad Kittenbrink 2008-02-27 18:58:14 +00:00
parent 6027ad2630
commit 6d52efe452
399 changed files with 33059 additions and 13135 deletions

View File

@ -8,6 +8,9 @@ Able Whitman
VWR-650
VWR-1460
VWR-1691
Aimee Trescothick
VWR-3903
VWR-4803
Alejandro Rosenthal
VWR-1184
Alissa Sabre
@ -44,9 +47,12 @@ Balp Allen
Benja Kepler
VWR-746
Blakar Ogre
VWR-418
VWR-881
VWR-983
VWR-1612
VWR-1613
VWR-2164
blino Nakamura
VWR-17
Boroondas Gupte
@ -172,6 +178,7 @@ McCabe Maxsted
Michelle2 Zenovka
VWR-2652
VWR-2834
VWR-3749
Mm Alder
VWR-3777
Mr Greggan

View File

@ -2030,64 +2030,6 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
}
}
//-----------------------------------------------------------------------------
// writeCAL3D()
//-----------------------------------------------------------------------------
void LLKeyframeMotion::writeCAL3D(apr_file_t* fp)
{
// <ANIMATION VERSION="1000" DURATION="1.03333" NUMTRACKS="58">
// <TRACK BONEID="0" NUMKEYFRAMES="31">
// <KEYFRAME TIME="0">
// <TRANSLATION>0 0 48.8332</TRANSLATION>
// <ROTATION>0.0512905 0.05657 0.66973 0.738668</ROTATION>
// </KEYFRAME>
// </TRACK>
// </ANIMATION>
apr_file_printf(fp, "<ANIMATION VERSION=\"1000\" DURATION=\"%.5f\" NUMTRACKS=\"%d\">\n", getDuration(), mJointMotionList->getNumJointMotions());
for (U32 joint_index = 0; joint_index < mJointMotionList->getNumJointMotions(); joint_index++)
{
JointMotion* joint_motionp = mJointMotionList->getJointMotion(joint_index);
LLJoint* animated_joint = mCharacter->getJoint(joint_motionp->mJointName);
S32 joint_num = animated_joint->mJointNum + 1;
apr_file_printf(fp, " <TRACK BONEID=\"%d\" NUMKEYFRAMES=\"%d\">\n", joint_num, joint_motionp->mRotationCurve.mNumKeys );
PositionKey* pos_keyp = joint_motionp->mPositionCurve.mKeys.getFirstData();
for (RotationKey* rot_keyp = joint_motionp->mRotationCurve.mKeys.getFirstData();
rot_keyp;
rot_keyp = joint_motionp->mRotationCurve.mKeys.getNextData())
{
apr_file_printf(fp, " <KEYFRAME TIME=\"%0.3f\">\n", rot_keyp->mTime);
LLVector3 nominal_pos = animated_joint->getPosition();
if (animated_joint->getParent())
{
nominal_pos.scaleVec(animated_joint->getParent()->getScale());
}
nominal_pos = nominal_pos * 100.f;
if (joint_motionp->mUsage & LLJointState::POS && pos_keyp)
{
LLVector3 pos_val = pos_keyp->mPosition;
pos_val = pos_val * 100.f;
pos_val += nominal_pos;
apr_file_printf(fp, " <TRANSLATION>%0.4f %0.4f %0.4f</TRANSLATION>\n", pos_val.mV[VX], pos_val.mV[VY], pos_val.mV[VZ]);
pos_keyp = joint_motionp->mPositionCurve.mKeys.getNextData();
}
else
{
apr_file_printf(fp, " <TRANSLATION>%0.4f %0.4f %0.4f</TRANSLATION>\n", nominal_pos.mV[VX], nominal_pos.mV[VY], nominal_pos.mV[VZ]);
}
LLQuaternion rot_val = ~rot_keyp->mRotation;
apr_file_printf(fp, " <ROTATION>%0.4f %0.4f %0.4f %0.4f</ROTATION>\n", rot_val.mQ[VX], rot_val.mQ[VY], rot_val.mQ[VZ], rot_val.mQ[VW]);
apr_file_printf(fp, " </KEYFRAME>\n");
}
apr_file_printf(fp, " </TRACK>\n");
}
apr_file_printf(fp, "</ANIMATION>\n");
}
//--------------------------------------------------------------------
// LLKeyframeDataCache::dumpDiagInfo()
//--------------------------------------------------------------------

View File

@ -158,7 +158,6 @@ public:
U32 getFileSize();
BOOL serialize(LLDataPacker& dp) const;
BOOL deserialize(LLDataPacker& dp);
void writeCAL3D(apr_file_t* fp);
BOOL isLoaded() { return mJointMotionList != NULL; }

View File

@ -746,7 +746,7 @@ void LLMotionController::updateMotion()
// is calculating a new keyframe pose, make sure the last one gets applied
mPoseBlender.interpolate(1.f);
mPoseBlender.clearBlenders();
clearBlenders();
mTimeStepCount = quantum_count;
mLastTime = mTime;
@ -824,6 +824,13 @@ void LLMotionController::updateMotion()
//-----------------------------------------------------------------------------
BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time)
{
// It's not clear why the getWeight() line seems to be crashing this, but
// hopefully this fixes it.
if (motion == NULL || motion->getPose() == NULL)
{
return FALSE;
}
if (mLoadingMotions.find(motion) != mLoadingMotions.end())
{
// we want to start this motion, but we can't yet, so flag it as started

View File

@ -157,6 +157,8 @@ public:
// deactivates terminated motions`
void updateMotion();
void clearBlenders() { mPoseBlender.clearBlenders(); }
// flush motions
// releases all motion instances
void flushAllMotions();

View File

@ -379,15 +379,20 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
}
}
// apply blended transforms
target_joint->setPosition(blended_pos);
target_joint->setScale(blended_scale);
target_joint->setRotation(blended_rot);
if (!added_scale.isFinite())
{
added_scale.clearVec();
}
// apply additive transforms
target_joint->setPosition(target_joint->getPosition() + added_pos);
target_joint->setScale(target_joint->getScale() + added_scale);
target_joint->setRotation(added_rot * target_joint->getRotation());
if (!blended_scale.isFinite())
{
blended_scale.setVec(1,1,1);
}
// apply transforms
target_joint->setPosition(blended_pos + added_pos);
target_joint->setScale(blended_scale + added_scale);
target_joint->setRotation(added_rot * blended_rot);
if (apply_now)
{

View File

@ -62,6 +62,7 @@ public:
FTM_SIMULATE_PARTICLES,
FTM_UPDATE_SKY,
FTM_UPDATE_TEXTURES,
FTM_UPDATE_WLPARAM,
FTM_UPDATE_WATER,
FTM_UPDATE_CLOUDS,
FTM_UPDATE_GRASS,
@ -86,8 +87,12 @@ public:
FTM_RENDER_HUD,
FTM_RENDER_PARTICLES,
FTM_RENDER_WATER,
FTM_RENDER_WL_SKY,
FTM_RENDER_FAKE_VBO_UPDATE,
FTM_RENDER_TIMER,
FTM_RENDER_UI,
FTM_RENDER_BLOOM,
FTM_RENDER_BLOOM_FBO,
FTM_RENDER_FONTS,
// newview specific
@ -124,6 +129,7 @@ public:
FTM_GEO_RESERVE,
FTM_GEO_LIGHT,
FTM_GEO_SHADOW,
FTM_GEO_SKY,
FTM_GEN_VOLUME,
FTM_GEN_TRIANGLES,
FTM_GEN_FLEX,
@ -150,7 +156,6 @@ public:
FTM_PIPELINE,
FTM_VFILE_WAIT,
FTM_FLEXIBLE_UPDATE,
FTM_OCCLUSION,
FTM_OCCLUSION_READBACK,
FTM_HUD_EFFECTS,
FTM_HUD_UPDATE,

View File

@ -286,6 +286,7 @@ llofstream::llofstream(const char *_Filename,
llofstream::~llofstream()
{ // destroy the object
close();
delete _Filebuffer;
}

View File

@ -192,10 +192,7 @@ public:
{
noteAction(id);
typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
if (curr.count < m.countLimit)
{
curr.count = m.countLimit;
}
curr.count = llmax(m.countLimit, curr.count);
curr.blocked = TRUE;
}

View File

@ -43,7 +43,8 @@ LLCamera::LLCamera() :
mViewHeightInPixels( -1 ), // invalid height
mNearPlane(DEFAULT_NEAR_PLANE),
mFarPlane(DEFAULT_FAR_PLANE),
mFixedDistance(-1.f)
mFixedDistance(-1.f),
mPlaneCount(6)
{
calculateFrustumPlanes();
}
@ -56,7 +57,8 @@ LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pix
mViewHeightInPixels(view_height_in_pixels),
mNearPlane(near_plane),
mFarPlane(far_plane),
mFixedDistance(-1.f)
mFixedDistance(-1.f),
mPlaneCount(6)
{
if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; }
else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; }
@ -78,6 +80,18 @@ LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pix
// ---------------- LLCamera::setFoo() member functions ----------------
void LLCamera::setUserClipPlane(LLPlane plane)
{
mPlaneCount = 7;
mAgentPlanes[6].p = plane;
mAgentPlanes[6].mask = calcPlaneMask(plane);
}
void LLCamera::disableUserClipPlane()
{
mPlaneCount = 6;
}
void LLCamera::setView(F32 field_of_view)
{
mView = field_of_view;
@ -150,7 +164,7 @@ size_t LLCamera::readFrustumFromBuffer(const char *buffer)
// ---------------- test methods ----------------
int LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
{
static const LLVector3 scaler[] = {
LLVector3(-1,-1,-1),
@ -166,10 +180,56 @@ int LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
U8 mask = 0;
S32 result = 2;
for (int i = 0; i < 6; i++)
for (U32 i = 0; i < mPlaneCount; i++)
{
mask = mAgentPlaneMask[i];
LLPlane p = mAgentPlanes[i];
mask = mAgentPlanes[i].mask;
LLPlane p = mAgentPlanes[i].p;
LLVector3 n = LLVector3(p);
float d = p.mV[3];
LLVector3 rscale = radius.scaledVec(scaler[mask]);
LLVector3 minp = center - rscale;
LLVector3 maxp = center + rscale;
if (n * minp > -d)
{
return 0;
}
if (n * maxp > -d)
{
result = 1;
}
}
return result;
}
S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& radius)
{
static const LLVector3 scaler[] = {
LLVector3(-1,-1,-1),
LLVector3( 1,-1,-1),
LLVector3(-1, 1,-1),
LLVector3( 1, 1,-1),
LLVector3(-1,-1, 1),
LLVector3( 1,-1, 1),
LLVector3(-1, 1, 1),
LLVector3( 1, 1, 1)
};
U8 mask = 0;
S32 result = 2;
for (U32 i = 0; i < mPlaneCount; i++)
{
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);
}
}

View File

@ -46,7 +46,7 @@ const F32 MAX_FIELD_OF_VIEW = F_PI;
const F32 MAX_ASPECT_RATIO = 50.0f;
const F32 MAX_NEAR_PLANE = 10.f;
const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though.
const F32 MAX_FAR_CLIP = 1024.0f;
const F32 MAX_FAR_CLIP = 512.0f;
const F32 MIN_FIELD_OF_VIEW = 0.1f;
const F32 MIN_ASPECT_RATIO = 0.02f;
@ -114,16 +114,28 @@ protected:
LLPlane mWorldPlanes[PLANE_NUM];
LLPlane mHorizPlanes[HORIZ_PLANE_NUM];
LLPlane mAgentPlanes[6]; //frustum in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
U8 mAgentPlaneMask[6];
typedef struct
{
LLPlane p;
U8 mask;
} frustum_plane;
frustum_plane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in
LLVector3 mWorldPlanePos; // Position of World Planes (may be offset from camera)
public:
LLVector3 mAgentFrustum[8];
LLVector3 mAgentFrustum[8]; //8 corners of 6-plane frustum
F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane
public:
LLCamera();
LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
void setUserClipPlane(LLPlane plane);
void disableUserClipPlane();
U8 calcPlaneMask(const LLPlane& plane);
void setView(F32 new_view);
void setViewHeightInPixels(S32 height);
void setAspect(F32 new_aspect);
@ -164,6 +176,8 @@ public:
S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); }
S32 sphereInFrustumFull(const LLVector3 &center, const F32 radius) const { return sphereInFrustum(center, radius); }
S32 AABBInFrustum(const LLVector3 &center, const LLVector3& radius);
S32 AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& radius);
//does a quick 'n dirty sphere-sphere check
S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius);

View File

@ -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)

View File

@ -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

View File

@ -47,10 +47,9 @@
#if LL_DARWIN
#define LL_OCTREE_MAX_CAPACITY 32
#else
#define LL_OCTREE_MAX_CAPACITY 256
#define LL_OCTREE_MAX_CAPACITY 128
#endif
template <class T> class LLOctreeState;
template <class T> class LLOctreeNode;
template <class T>
@ -64,15 +63,27 @@ public:
virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0;
};
template <class T>
class LLOctreeTraveler : public LLTreeTraveler<T>
{
public:
virtual void traverse(const LLTreeNode<T>* node);
virtual void visit(const LLTreeNode<T>* state) { }
virtual void visit(const LLOctreeNode<T>* branch) = 0;
};
template <class T>
class LLOctreeNode : public LLTreeNode<T>
{
public:
typedef LLOctreeTraveler<T> oct_traveler;
typedef LLTreeTraveler<T> tree_traveler;
typedef typename std::set<LLPointer<T> > element_list;
typedef typename std::set<LLPointer<T> >::iterator element_iter;
typedef typename std::set<LLPointer<T> >::const_iterator const_element_iter;
typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter;
typedef typename std::vector<LLOctreeNode<T>* > child_list;
typedef LLTreeNode<T> BaseType;
typedef LLTreeState<T> tree_state;
typedef LLOctreeState<T> oct_state;
typedef LLOctreeNode<T> oct_node;
typedef LLOctreeListener<T> oct_listener;
@ -82,11 +93,9 @@ public:
LLOctreeNode( LLVector3d center,
LLVector3d size,
tree_state* state,
BaseType* parent,
U8 octant = 255)
: BaseType(state),
mParent((oct_node*)parent),
: mParent((oct_node*)parent),
mCenter(center),
mSize(size),
mOctant(octant)
@ -96,9 +105,19 @@ public:
{
mOctant = ((oct_node*) mParent)->getOctant(mCenter.mdV);
}
clearChildren();
}
~LLOctreeNode() { BaseType::destroyListeners(); delete this->mState; }
virtual ~LLOctreeNode()
{
BaseType::destroyListeners();
for (U32 i = 0; i < getChildCount(); i++)
{
delete getChild(i);
}
}
inline const BaseType* getParent() const { return mParent; }
inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; }
@ -106,25 +125,12 @@ public:
inline const LLVector3d& getSize() const { return mSize; }
inline void setCenter(LLVector3d center) { mCenter = center; }
inline void setSize(LLVector3d size) { mSize = size; }
inline bool balance() { return getOctState()->balance(); }
inline void validate() { getOctState()->validate(); }
inline U32 getChildCount() const { return getOctState()->getChildCount(); }
inline oct_node* getChild(U32 index) { return getOctState()->getChild(index); }
inline const oct_node* getChild(U32 index) const { return getOctState()->getChild(index); }
inline U32 getElementCount() const { return getOctState()->getElementCount(); }
inline void removeByAddress(T* data) { getOctState()->removeByAddress(data); }
inline bool hasLeafState() const { return getOctState()->isLeaf(); }
inline void destroy() { getOctState()->destroy(); }
inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
inline oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) { return getOctState()->getNodeAt(pos, rad); }
inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
inline U8 getOctant() const { return mOctant; }
inline void setOctant(U8 octant) { mOctant = octant; }
inline const oct_state* getOctState() const { return (const oct_state*) BaseType::mState; }
inline oct_state* getOctState() { return (oct_state*) BaseType::mState; }
inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); }
inline oct_node* getOctParent() { return (oct_node*) getParent(); }
inline void deleteChild(oct_node* child) { getOctState()->deleteChild(child); }
U8 getOctant(const F64 pos[]) const //get the octant pos is in
{
U8 ret = 0;
@ -205,9 +211,9 @@ public:
(radius <= p_size && radius > size);
}
static void pushCenter(LLVector3d &center, LLVector3d &size, T* data)
static void pushCenter(LLVector3d &center, const LLVector3d &size, const T* data)
{
LLVector3d pos(data->getPositionGroup());
const LLVector3d& pos = data->getPositionGroup();
for (U32 i = 0; i < 3; i++)
{
if (pos.mdV[i] > center.mdV[i])
@ -221,76 +227,25 @@ public:
}
}
protected:
oct_node* mParent;
LLVector3d mCenter;
LLVector3d mSize;
LLVector3d mMax;
LLVector3d mMin;
U8 mOctant;
};
template <class T>
class LLOctreeTraveler : public LLTreeTraveler<T>
{
public:
virtual void traverse(const LLTreeNode<T>* node);
virtual void visit(const LLTreeState<T>* state) { }
virtual void visit(const LLOctreeState<T>* branch) = 0;
};
//will pass requests to a child, might make a new child
template <class T>
class LLOctreeState : public LLTreeState<T>
{
public:
typedef LLTreeState<T> BaseType;
typedef LLOctreeTraveler<T> oct_traveler;
typedef LLOctreeNode<T> oct_node;
typedef LLOctreeListener<T> oct_listener;
typedef LLTreeTraveler<T> tree_traveler;
typedef typename std::set<LLPointer<T> > element_list;
typedef typename std::set<LLPointer<T> >::iterator element_iter;
typedef typename std::set<LLPointer<T> >::const_iterator const_element_iter;
typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter;
typedef typename std::vector<LLOctreeNode<T>* > child_list;
void accept(oct_traveler* visitor) { visitor->visit(this); }
virtual bool isLeaf() const { return mChild.empty(); }
LLOctreeState(oct_node* node = NULL): BaseType(node) { this->clearChildren(); }
virtual ~LLOctreeState()
{
for (U32 i = 0; i < getChildCount(); i++)
{
delete getChild(i);
}
}
U32 getElementCount() const { return mData.size(); }
element_list& getData() { return mData; }
const element_list& getData() const { return mData; }
virtual void accept(oct_traveler* visitor) { visitor->visit(this); }
virtual bool isLeaf() const { return mChild.empty(); }
U32 getChildCount() const { return mChild.size(); }
oct_node* getChild(U32 index) { return mChild[index]; }
const oct_node* getChild(U32 index) const { return mChild[index]; }
child_list& getChildren() { return mChild; }
const child_list& getChildren() const { return mChild; }
virtual U32 getElementCount() const { return mData.size(); }
virtual element_list& getData() { return mData; }
virtual const element_list& getData() const { return mData; }
void accept(tree_traveler* visitor) const { visitor->visit(this); }
void accept(oct_traveler* visitor) const { visitor->visit(this); }
virtual U32 getChildCount() const { return mChild.size(); }
virtual oct_node* getChild(U32 index) { return mChild[index]; }
virtual const oct_node* getChild(U32 index) const { return mChild[index]; }
virtual child_list& getChildren() { return mChild; }
virtual const child_list& getChildren() const { return mChild; }
virtual void accept(tree_traveler* visitor) const { visitor->visit(this); }
virtual void accept(oct_traveler* visitor) const { visitor->visit(this); }
const oct_node* getOctNode() const { return (const oct_node*) BaseType::getNode(); }
oct_node* getOctNode() { return (oct_node*) BaseType::getNode(); }
virtual oct_node* getNodeAt(T* data)
{
return getNodeAt(data->getPositionGroup(), data->getBinRadius());
}
virtual oct_node* getNodeAt(const LLVector3d& pos, const F64& rad)
oct_node* getNodeAt(const LLVector3d& pos, const F64& rad)
{
LLOctreeNode<T>* node = getOctNode();
LLOctreeNode<T>* node = this;
if (node->isInside(pos, rad))
{
@ -328,26 +283,19 @@ public:
{
if (data == NULL)
{
OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl;
//OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl;
return false;
}
LLOctreeNode<T>* node = getOctNode();
LLOctreeNode<T>* parent = node->getOctParent();
LLOctreeNode<T>* parent = getOctParent();
//is it here?
if (node->isInside(data->getPositionGroup()))
if (isInside(data->getPositionGroup()))
{
if (getElementCount() < LL_OCTREE_MAX_CAPACITY &&
(node->contains(data->getBinRadius()) ||
(data->getBinRadius() > node->getSize().mdV[0] &&
(contains(data->getBinRadius()) ||
(data->getBinRadius() > getSize().mdV[0] &&
parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
{ //it belongs here
if (data == NULL)
{
OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE LEAF !!!" << llendl;
return false;
}
#if LL_OCTREE_PARANOIA_CHECK
//if this is a redundant insertion, error out (should never happen)
if (mData.find(data) != mData.end())
@ -358,6 +306,7 @@ public:
#endif
mData.insert(data);
BaseType::insert(data);
return true;
}
else
@ -375,8 +324,8 @@ public:
}
//it's here, but no kids are in the right place, make a new kid
LLVector3d center(node->getCenter());
LLVector3d size(node->getSize()*0.5);
LLVector3d center(getCenter());
LLVector3d size(getSize()*0.5);
//push center in direction of data
LLOctreeNode<T>::pushCenter(center, size, data);
@ -386,7 +335,6 @@ public:
{
//this really isn't possible, something bad has happened
OCT_ERRS << "Octree detected floating point error and gave up." << llendl;
//bool check = node->isInside(data);
return false;
}
@ -396,25 +344,25 @@ public:
if (mChild[i]->getCenter() == center)
{
OCT_ERRS << "Octree detected duplicate child center and gave up." << llendl;
//bool check = node->isInside(data);
//check = getChild(i)->isInside(data);
return false;
}
}
#endif
//make the new kid
LLOctreeState<T>* newstate = new LLOctreeState<T>();
child = new LLOctreeNode<T>(center, size, newstate, node);
child = new LLOctreeNode<T>(center, size, this);
addChild(child);
child->insert(data);
}
}
else
{
//it's not in here, give it to the root
LLOctreeNode<T>* parent = node->getOctParent();
//OCT_ERRS << "Octree insertion failed, starting over from root!" << llendl;
oct_node* node = this;
while (parent)
{
node = parent;
@ -427,22 +375,20 @@ public:
return false;
}
virtual bool remove(T* data)
bool remove(T* data)
{
oct_node* node = getOctNode();
if (mData.find(data) != mData.end())
{ //we have data
mData.erase(data);
node->notifyRemoval(data);
notifyRemoval(data);
checkAlive();
return true;
}
else if (node->isInside(data))
else if (isInside(data))
{
oct_node* dest = getNodeAt(data);
if (dest != node)
if (dest != this)
{
return dest->remove(data);
}
@ -451,7 +397,9 @@ public:
//SHE'S GONE MISSING...
//none of the children have it, let's just brute force this bastard out
//starting with the root node (UGLY CODE COMETH!)
oct_node* parent = node->getOctParent();
oct_node* parent = getOctParent();
oct_node* node = this;
while (parent != NULL)
{
node = parent;
@ -464,12 +412,12 @@ public:
return true;
}
virtual void removeByAddress(T* data)
void removeByAddress(T* data)
{
if (mData.find(data) != mData.end())
{
mData.erase(data);
getOctNode()->notifyRemoval(data);
notifyRemoval(data);
llwarns << "FOUND!" << llendl;
checkAlive();
return;
@ -482,20 +430,18 @@ public:
}
}
virtual void clearChildren()
void clearChildren()
{
mChild.clear();
}
virtual void validate()
void validate()
{
#if LL_OCTREE_PARANOIA_CHECK
LLOctreeNode<T>* node = this->getOctNode();
for (U32 i = 0; i < getChildCount(); i++)
{
mChild[i]->validate();
if (mChild[i]->getParent() != node)
if (mChild[i]->getParent() != this)
{
llerrs << "Octree child has invalid parent." << llendl;
}
@ -508,7 +454,7 @@ public:
return false;
}
virtual void destroy()
void destroy()
{
for (U32 i = 0; i < getChildCount(); i++)
{
@ -517,7 +463,7 @@ public:
}
}
virtual void addChild(oct_node* child, BOOL silent = FALSE)
void addChild(oct_node* child, BOOL silent = FALSE)
{
#if LL_OCTREE_PARANOIA_CHECK
for (U32 i = 0; i < getChildCount(); i++)
@ -539,27 +485,24 @@ public:
#endif
mChild.push_back(child);
child->setParent(getOctNode());
child->setParent(this);
if (!silent)
{
oct_node* node = getOctNode();
for (U32 i = 0; i < node->getListenerCount(); i++)
for (U32 i = 0; i < this->getListenerCount(); i++)
{
oct_listener* listener = node->getOctListener(i);
listener->handleChildAddition(node, child);
oct_listener* listener = getOctListener(i);
listener->handleChildAddition(this, child);
}
}
}
virtual void removeChild(U8 index, BOOL destroy = FALSE)
void removeChild(U8 index, BOOL destroy = FALSE)
{
oct_node* node = getOctNode();
for (U32 i = 0; i < node->getListenerCount(); i++)
for (U32 i = 0; i < this->getListenerCount(); i++)
{
oct_listener* listener = node->getOctListener(i);
listener->handleChildRemoval(node, getChild(index));
oct_listener* listener = getOctListener(i);
listener->handleChildRemoval(this, getChild(index));
}
if (destroy)
@ -572,20 +515,19 @@ public:
checkAlive();
}
virtual void checkAlive()
void checkAlive()
{
if (getChildCount() == 0 && getElementCount() == 0)
{
oct_node* node = getOctNode();
oct_node* parent = node->getOctParent();
oct_node* parent = getOctParent();
if (parent)
{
parent->deleteChild(node);
parent->deleteChild(this);
}
}
}
virtual void deleteChild(oct_node* node)
void deleteChild(oct_node* node)
{
for (U32 i = 0; i < getChildCount(); i++)
{
@ -596,55 +538,62 @@ public:
}
}
OCT_ERRS << "Octree failed to delete requested child." << llendl;
//OCT_ERRS << "Octree failed to delete requested child." << llendl;
}
protected:
protected:
child_list mChild;
element_list mData;
oct_node* mParent;
LLVector3d mCenter;
LLVector3d mSize;
LLVector3d mMax;
LLVector3d mMin;
U8 mOctant;
};
//just like a branch, except it might expand the node it points to
//just like a regular node, except it might expand on insert and compress on balance
template <class T>
class LLOctreeRoot : public LLOctreeState<T>
class LLOctreeRoot : public LLOctreeNode<T>
{
public:
typedef LLOctreeState<T> BaseType;
typedef LLOctreeNode<T> BaseType;
typedef LLOctreeNode<T> oct_node;
LLOctreeRoot(oct_node* node = NULL) : BaseType(node) { }
oct_node* getOctNode() { return BaseType::getOctNode(); }
virtual bool isLeaf() { return false; }
virtual bool balance()
LLOctreeRoot( LLVector3d center,
LLVector3d size,
BaseType* parent)
: BaseType(center, size, parent)
{
}
bool isLeaf() { return false; }
bool balance()
{
//the cached node might be invalid, so don't reference it
if (this->getChildCount() == 1 &&
!(this->mChild[0]->hasLeafState()) &&
!(this->mChild[0]->isLeaf()) &&
this->mChild[0]->getElementCount() == 0)
{ //if we have only one child and that child is an empty branch, make that child the root
BaseType* state = this->mChild[0]->getOctState();
oct_node* child = this->mChild[0];
oct_node* root = getOctNode();
//make the root node look like the child
root->setCenter(this->mChild[0]->getCenter());
root->setSize(this->mChild[0]->getSize());
root->updateMinMax();
this->setCenter(this->mChild[0]->getCenter());
this->setSize(this->mChild[0]->getSize());
this->updateMinMax();
//reset root node child list
this->clearChildren();
//copy the child's children into the root node silently
//(don't notify listeners of addition)
for (U32 i = 0; i < state->getChildCount(); i++)
for (U32 i = 0; i < child->getChildCount(); i++)
{
addChild(state->getChild(i), TRUE);
addChild(child->getChild(i), TRUE);
}
//destroy child
state->clearChildren();
child->clearChildren();
delete child;
}
@ -652,69 +601,90 @@ public:
}
// LLOctreeRoot::insert
virtual bool insert(T* data)
bool insert(T* data)
{
if (data == NULL)
{
OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl;
//OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl;
return false;
}
if (data->getBinRadius() > 4096.0)
{
OCT_ERRS << "!!! ELEMENT EXCEDES MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl;
//OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl;
return false;
}
LLOctreeNode<T>* node = getOctNode();
if (node->getSize().mdV[0] > data->getBinRadius() && node->isInside(data->getPositionGroup()))
const F64 MAX_MAG = 1024.0*1024.0;
const LLVector3d& v = data->getPositionGroup();
if (!(fabs(v.mdV[0]-this->mCenter.mdV[0]) < MAX_MAG &&
fabs(v.mdV[1]-this->mCenter.mdV[1]) < MAX_MAG &&
fabs(v.mdV[2]-this->mCenter.mdV[2]) < MAX_MAG))
{
//OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl;
return false;
}
if (this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup()))
{
//we got it, just act like a branch
LLOctreeState<T>::insert(data);
oct_node* node = getNodeAt(data);
if (node == this)
{
LLOctreeNode<T>::insert(data);
}
else
{
node->insert(data);
}
}
else if (this->getChildCount() == 0)
{
//first object being added, just wrap it up
while (!(node->getSize().mdV[0] > data->getBinRadius() && node->isInside(data->getPositionGroup())))
while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())))
{
LLVector3d center, size;
center = node->getCenter();
size = node->getSize();
center = this->getCenter();
size = this->getSize();
LLOctreeNode<T>::pushCenter(center, size, data);
node->setCenter(center);
node->setSize(size*2);
node->updateMinMax();
this->setCenter(center);
this->setSize(size*2);
this->updateMinMax();
}
LLOctreeState<T>::insert(data);
LLOctreeNode<T>::insert(data);
}
else
{
//the data is outside the root node, we need to grow
LLVector3d center(node->getCenter());
LLVector3d size(node->getSize());
//expand this node
LLVector3d newcenter(center);
LLOctreeNode<T>::pushCenter(newcenter, size, data);
node->setCenter(newcenter);
node->setSize(size*2);
node->updateMinMax();
//copy our children to a new branch
LLOctreeState<T>* newstate = new LLOctreeState<T>();
LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, newstate, node);
for (U32 i = 0; i < this->getChildCount(); i++)
while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())))
{
LLOctreeNode<T>* child = this->getChild(i);
newstate->addChild(child);
//the data is outside the root node, we need to grow
LLVector3d center(this->getCenter());
LLVector3d size(this->getSize());
//expand this node
LLVector3d newcenter(center);
LLOctreeNode<T>::pushCenter(newcenter, size, data);
this->setCenter(newcenter);
this->setSize(size*2);
this->updateMinMax();
//copy our children to a new branch
LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, this);
for (U32 i = 0; i < this->getChildCount(); i++)
{
LLOctreeNode<T>* child = this->getChild(i);
newnode->addChild(child);
}
//clear our children and add the root copy
this->clearChildren();
addChild(newnode);
}
//clear our children and add the root copy
this->clearChildren();
addChild(newnode);
//insert the data
node->insert(data);
insert(data);
}
return false;
@ -726,13 +696,13 @@ public:
// LLOctreeTraveler
//========================
template <class T>
void LLOctreeTraveler<T>::traverse(const LLTreeNode<T>* node)
void LLOctreeTraveler<T>::traverse(const LLTreeNode<T>* tree_node)
{
const LLOctreeState<T>* state = (const LLOctreeState<T>*) node->getState();
state->accept(this);
for (U32 i = 0; i < state->getChildCount(); i++)
const LLOctreeNode<T>* node = (const LLOctreeNode<T>*) tree_node;
node->accept(this);
for (U32 i = 0; i < node->getChildCount(); i++)
{
traverse(state->getChild(i));
traverse(node->getChild(i));
}
}

View File

@ -39,23 +39,6 @@ template <class T> class LLTreeNode;
template <class T> class LLTreeTraveler;
template <class T> class LLTreeListener;
template <class T>
class LLTreeState
{
public:
LLTreeState(LLTreeNode<T>* node) { setNode(node); }
virtual ~LLTreeState() { };
virtual bool insert(T* data) = 0;
virtual bool remove(T* data) = 0;
virtual void setNode(LLTreeNode<T>* node);
virtual const LLTreeNode<T>* getNode() const { return mNode; }
virtual LLTreeNode<T>* getNode() { return mNode; }
virtual void accept(LLTreeTraveler<T>* traveler) const = 0;
virtual LLTreeListener<T>* getListener(U32 index) const;
private:
LLTreeNode<T>* mNode;
};
template <class T>
class LLTreeListener: public LLRefCount
{
@ -70,19 +53,14 @@ template <class T>
class LLTreeNode
{
public:
LLTreeNode(LLTreeState<T>* state) { setState(state); }
virtual ~LLTreeNode();
LLTreeState<T>* getState() { return mState; }
const LLTreeState<T>* getState() const { return mState; }
void setState(LLTreeState<T>* state);
void insert(T* data);
bool remove(T* data);
void notifyRemoval(T* data);
inline U32 getListenerCount() { return mListeners.size(); }
inline LLTreeListener<T>* getListener(U32 index) const { return mListeners[index]; }
inline void addListener(LLTreeListener<T>* listener) { mListeners.push_back(listener); }
inline void removeListener(U32 index) { mListeners.erase(mListeners.begin()+index); }
virtual bool insert(T* data);
virtual bool remove(T* data);
virtual void notifyRemoval(T* data);
virtual U32 getListenerCount() { return mListeners.size(); }
virtual LLTreeListener<T>* getListener(U32 index) const { return mListeners[index]; }
virtual void addListener(LLTreeListener<T>* listener) { mListeners.push_back(listener); }
protected:
void destroyListeners()
@ -94,7 +72,6 @@ protected:
mListeners.clear();
}
LLTreeState<T>* mState;
public:
std::vector<LLPointer<LLTreeListener<T> > > mListeners;
};
@ -105,7 +82,7 @@ class LLTreeTraveler
public:
virtual ~LLTreeTraveler() { };
virtual void traverse(const LLTreeNode<T>* node) = 0;
virtual void visit(const LLTreeState<T>* state) = 0;
virtual void visit(const LLTreeNode<T>* node) = 0;
};
template <class T>
@ -115,25 +92,19 @@ LLTreeNode<T>::~LLTreeNode()
};
template <class T>
void LLTreeNode<T>::insert(T* data)
bool LLTreeNode<T>::insert(T* data)
{
if (mState->insert(data))
for (U32 i = 0; i < mListeners.size(); i++)
{
for (U32 i = 0; i < mListeners.size(); i++)
{
mListeners[i]->handleInsertion(this, data);
}
mListeners[i]->handleInsertion(this, data);
}
return true;
};
template <class T>
bool LLTreeNode<T>::remove(T* data)
{
if (mState->remove(data))
{
return true;
}
return false;
return true;
};
template <class T>
@ -145,38 +116,4 @@ void LLTreeNode<T>::notifyRemoval(T* data)
}
}
template <class T>
void LLTreeNode<T>::setState(LLTreeState<T>* state)
{
mState = state;
if (state)
{
if (state->getNode() != this)
{
state->setNode(this);
}
for (U32 i = 0; i < mListeners.size(); i++)
{
mListeners[i]->handleStateChange(this);
}
}
};
template <class T>
void LLTreeState<T>::setNode(LLTreeNode<T>* node)
{
mNode = node;
if (node && node->getState() != this)
{
node->setState(this);
}
};
template <class T>
LLTreeListener<T>* LLTreeState<T>::getListener(U32 index) const
{
return mNode->getListener(index);
}
#endif

View File

@ -1639,12 +1639,27 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
}
}
void LLVolume::resizePath(S32 length)
{
mPathp->resizePath(length);
if (mVolumeFaces != NULL)
{
delete[] mVolumeFaces;
mVolumeFaces = NULL;
}
}
void LLVolume::regen()
{
generate();
createVolumeFaces();
}
void LLVolume::genBinormals(S32 face)
{
mVolumeFaces[face].createBinormals();
}
LLVolume::~LLVolume()
{
sNumMeshPoints -= mMesh.size();
@ -1746,12 +1761,6 @@ void LLVolume::createVolumeFaces()
{
S32 i;
if (mVolumeFaces != NULL)
{
delete[] mVolumeFaces;
mVolumeFaces = NULL;
}
if (mGenerateSingleFace)
{
mNumVolumeFaces = 0;
@ -1760,7 +1769,12 @@ void LLVolume::createVolumeFaces()
{
S32 num_faces = getNumFaces();
mNumVolumeFaces = num_faces;
mVolumeFaces = new LLVolumeFace[num_faces];
BOOL partial_build = TRUE;
if (!mVolumeFaces)
{
partial_build = FALSE;
mVolumeFaces = new LLVolumeFace[num_faces];
}
// Initialize volume faces with parameter data
for (i = 0; i < num_faces; i++)
{
@ -1823,7 +1837,7 @@ void LLVolume::createVolumeFaces()
for (i = 0; i < mNumVolumeFaces; i++)
{
mVolumeFaces[i].create();
mVolumeFaces[i].create(partial_build);
}
}
}
@ -3967,18 +3981,19 @@ LLVolumeFace::LLVolumeFace()
mBeginT = 0;
mNumS = 0;
mNumT = 0;
mHasBinormals = FALSE;
}
BOOL LLVolumeFace::create()
BOOL LLVolumeFace::create(BOOL partial_build)
{
if (mTypeMask & CAP_MASK)
{
return createCap();
return createCap(partial_build);
}
else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK))
{
return createSide();
return createSide(partial_build);
}
else
{
@ -4000,7 +4015,7 @@ void LerpPlanarVertex(LLVolumeFace::VertexData& v0,
vout.mBinormal = v0.mBinormal;
}
BOOL LLVolumeFace::createUnCutCubeCap()
BOOL LLVolumeFace::createUnCutCubeCap(BOOL partial_build)
{
const std::vector<LLVolume::Point>& mesh = mVolumep->getMesh();
const std::vector<LLVector3>& profile = mVolumep->getProfile().mProfile;
@ -4055,6 +4070,12 @@ BOOL LLVolumeFace::createUnCutCubeCap()
corners[t].mBinormal = baseVert.mBinormal;
corners[t].mNormal = baseVert.mNormal;
}
mHasBinormals = TRUE;
if (partial_build)
{
mVertices.clear();
}
S32 vtop = mVertices.size();
for(int gx = 0;gx<grid_size+1;gx++){
@ -4082,22 +4103,25 @@ BOOL LLVolumeFace::createUnCutCubeCap()
mCenter = (min + max) * 0.5f;
int idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
for(int gx = 0;gx<grid_size;gx++){
for(int gy = 0;gy<grid_size;gy++){
if (mTypeMask & TOP_MASK){
for(int i=5;i>=0;i--)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
}else{
for(int i=0;i<6;i++)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
if (!partial_build)
{
int idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
for(int gx = 0;gx<grid_size;gx++){
for(int gy = 0;gy<grid_size;gy++){
if (mTypeMask & TOP_MASK){
for(int i=5;i>=0;i--)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
}else{
for(int i=0;i<6;i++)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
}
}
}
}
return TRUE;
}
BOOL LLVolumeFace::createCap()
BOOL LLVolumeFace::createCap(BOOL partial_build)
{
if (!(mTypeMask & HOLLOW_MASK) &&
!(mTypeMask & OPEN_MASK) &&
@ -4106,7 +4130,7 @@ BOOL LLVolumeFace::createCap()
(mVolumep->getProfile().mParams.getCurveType()==LL_PCODE_PROFILE_SQUARE &&
mVolumep->getPath().mParams.getCurveType()==LL_PCODE_PATH_LINE)
){
return createUnCutCubeCap();
return createUnCutCubeCap(partial_build);
}
S32 i;
@ -4118,8 +4142,13 @@ BOOL LLVolumeFace::createCap()
// All types of caps have the same number of vertices and indices
num_vertices = profile.size();
num_indices = (profile.size() - 2)*3;
vector_append(mVertices,num_vertices);
vector_append(mIndices,num_indices);
mVertices.resize(num_vertices);
if (!partial_build)
{
mIndices.resize(num_indices);
}
S32 max_s = mVolumep->getProfile().getTotal();
S32 max_t = mVolumep->getPath().mPath.size();
@ -4203,7 +4232,10 @@ BOOL LLVolumeFace::createCap()
{
mVertices.push_back(vd);
num_vertices++;
vector_append(mIndices, 3);
if (!partial_build)
{
vector_append(mIndices, 3);
}
}
@ -4213,6 +4245,13 @@ BOOL LLVolumeFace::createCap()
mVertices[i].mNormal = normal;
}
mHasBinormals = TRUE;
if (partial_build)
{
return TRUE;
}
if (mTypeMask & HOLLOW_MASK)
{
if (mTypeMask & TOP_MASK)
@ -4480,7 +4519,50 @@ BOOL LLVolumeFace::createCap()
return TRUE;
}
BOOL LLVolumeFace::createSide()
void LLVolumeFace::createBinormals()
{
if (!mHasBinormals)
{
//generate binormals
for (U32 i = 0; i < mIndices.size()/3; i++)
{ //for each triangle
const VertexData& v0 = mVertices[mIndices[i*3+0]];
const VertexData& v1 = mVertices[mIndices[i*3+1]];
const VertexData& v2 = mVertices[mIndices[i*3+2]];
//calculate binormal
LLVector3 binorm = calc_binormal_from_triangle(v0.mPosition, v0.mTexCoord,
v1.mPosition, v1.mTexCoord,
v2.mPosition, v2.mTexCoord);
for (U32 j = 0; j < 3; j++)
{ //add triangle normal to vertices
mVertices[mIndices[i*3+j]].mBinormal += binorm; // * (weight_sum - d[j])/weight_sum;
}
//even out quad contributions
if (i % 2 == 0)
{
mVertices[mIndices[i*3+2]].mBinormal += binorm;
}
else
{
mVertices[mIndices[i*3+1]].mBinormal += binorm;
}
}
//normalize binormals
for (U32 i = 0; i < mVertices.size(); i++)
{
mVertices[i].mBinormal.normVec();
mVertices[i].mNormal.normVec();
}
mHasBinormals = TRUE;
}
}
BOOL LLVolumeFace::createSide(BOOL partial_build)
{
BOOL flat = mTypeMask & FLAT_MASK;
S32 num_vertices, num_indices;
@ -4496,9 +4578,14 @@ BOOL LLVolumeFace::createSide()
num_vertices = mNumS*mNumT;
num_indices = (mNumS-1)*(mNumT-1)*6;
vector_append(mVertices,num_vertices);
vector_append(mIndices,num_indices);
vector_append(mEdge, num_indices);
mVertices.resize(num_vertices);
if (!partial_build)
{
mIndices.resize(num_indices);
mEdge.resize(num_indices);
}
LLVector3& face_min = mExtents[0];
LLVector3& face_max = mExtents[1];
@ -4609,61 +4696,63 @@ BOOL LLVolumeFace::createSide()
S32 cur_edge = 0;
BOOL flat_face = mTypeMask & FLAT_MASK;
// Now we generate the indices.
for (t = 0; t < (mNumT-1); t++)
if (!partial_build)
{
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
// 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;
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
}
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
}
}
//generate normals
for (U32 i = 0; i < mIndices.size()/3; i++) { //for each triangle
const VertexData& v0 = mVertices[mIndices[i*3+0]];
@ -4674,27 +4763,22 @@ BOOL LLVolumeFace::createSide()
LLVector3 norm = (v0.mPosition-v1.mPosition)%
(v0.mPosition-v2.mPosition);
//calculate binormal
LLVector3 binorm = calc_binormal_from_triangle(v0.mPosition, v0.mTexCoord,
v1.mPosition, v1.mTexCoord,
v2.mPosition, v2.mTexCoord);
for (U32 j = 0; j < 3; j++) { //add triangle normal to vertices
for (U32 j = 0; j < 3; j++)
{ //add triangle normal to vertices
mVertices[mIndices[i*3+j]].mNormal += norm; // * (weight_sum - d[j])/weight_sum;
mVertices[mIndices[i*3+j]].mBinormal += binorm; // * (weight_sum - d[j])/weight_sum;
}
//even out quad contributions
if (i % 2 == 0) {
if (i % 2 == 0)
{
mVertices[mIndices[i*3+2]].mNormal += norm;
mVertices[mIndices[i*3+2]].mBinormal += binorm;
}
else {
else
{
mVertices[mIndices[i*3+1]].mNormal += norm;
mVertices[mIndices[i*3+1]].mBinormal += binorm;
}
}
// adjust normals based on wrapping and stitching
BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f);
@ -4820,15 +4904,6 @@ BOOL LLVolumeFace::createSide()
}
//normalize normals and binormals here so the meshes that reference
//this volume data don't have to
for (U32 i = 0; i < mVertices.size(); i++)
{
mVertices[i].mNormal.normVec();
mVertices[i].mBinormal.normVec();
}
return TRUE;
}

View File

@ -762,7 +762,8 @@ class LLVolumeFace
{
public:
LLVolumeFace();
BOOL create();
BOOL create(BOOL partial_build = FALSE);
void createBinormals();
class VertexData
{
@ -792,6 +793,7 @@ public:
S32 mID;
U32 mTypeMask;
LLVector3 mCenter;
BOOL mHasBinormals;
// Only used for INNER/OUTER faces
S32 mBeginS;
@ -802,7 +804,7 @@ public:
LLVector3 mExtents[2]; //minimum and maximum point of face
std::vector<VertexData> mVertices;
std::vector<S32> mIndices;
std::vector<U16> mIndices;
std::vector<S32> mEdge;
LLVolume *mVolumep; // Deliberately NOT reference counted - djs 11/20/03 - otherwise would make an annoying circular reference
@ -811,9 +813,9 @@ public:
LLStrider<LLColor4U> &new_colors, const S32 num_new, const LLVolumeFace &new_face);
protected:
BOOL createUnCutCubeCap();
BOOL createCap();
BOOL createSide();
BOOL createUnCutCubeCap(BOOL partial_build = FALSE);
BOOL createCap(BOOL partial_build = FALSE);
BOOL createSide(BOOL partial_build = FALSE);
};
class LLVolume : public LLRefCount
@ -850,12 +852,14 @@ public:
LLVolumeParams getCopyOfParams() const { return mParams; }
const LLProfile& getProfile() const { return *mProfilep; }
LLPath& getPath() const { return *mPathp; }
void resizePath(S32 length);
const std::vector<Point>& getMesh() const { return mMesh; }
const LLVector3& getMeshPt(const U32 i) const { return mMesh[i].mPos; }
void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); }
void regen();
void genBinormals(S32 face);
BOOL isConvex() const;
BOOL isCap(S32 face);

View File

@ -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];

View File

@ -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);

View File

@ -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();

View File

@ -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]);

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -389,4 +389,3 @@ S32 LLTextureEntry::setGlow(F32 glow)
}
return 0;
}

View File

@ -36,6 +36,7 @@
#include "llfont.h"
#include "llfontgl.h"
#include "llgl.h"
#include "llglimmediate.h"
#include "v4color.h"
#include "llstl.h"
@ -556,8 +557,8 @@ S32 LLFontGL::render(const LLWString &wstr,
BOOL use_embedded,
BOOL use_ellipses) const
{
LLGLEnable texture_2d(GL_TEXTURE_2D);
LLGLEnable tex(GL_TEXTURE_2D);
if (wstr.empty())
{
return 0;
@ -593,9 +594,9 @@ S32 LLFontGL::render(const LLWString &wstr,
}
}
glPushMatrix();
gGL.pushMatrix();
glLoadIdentity();
glTranslatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
//glScalef(sScaleX, sScaleY, 1.0f);
// avoid half pixels
@ -604,20 +605,20 @@ S32 LLFontGL::render(const LLWString &wstr,
//F32 half_pixel_distance = llabs(fmodf(sCurOrigin.mX * sScaleX, 1.f) - 0.5f);
//if (half_pixel_distance < PIXEL_BORDER_THRESHOLD)
//{
glTranslatef(PIXEL_CORRECTION_DISTANCE*sScaleX, 0.f, 0.f);
gGL.translatef(PIXEL_CORRECTION_DISTANCE*sScaleX, 0.f, 0.f);
//}
// this code would just snap to pixel grid, although it seems to introduce more jitter
//F32 pixel_offset_x = llround(sCurOrigin.mX * sScaleX) - (sCurOrigin.mX * sScaleX);
//F32 pixel_offset_y = llround(sCurOrigin.mY * sScaleY) - (sCurOrigin.mY * sScaleY);
//glTranslatef(-pixel_offset_x, -pixel_offset_y, 0.f);
//gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f);
// scale back to native pixel size
//glScalef(1.f / sScaleX, 1.f / sScaleY, 1.f);
//glScaled(1.0 / (F64) sScaleX, 1.0 / (F64) sScaleY, 1.0f);
LLFastTimer t(LLFastTimer::FTM_RENDER_FONTS);
glColor4fv( color.mV );
gGL.color4fv( color.mV );
S32 chars_drawn = 0;
S32 i;
@ -638,7 +639,7 @@ S32 LLFontGL::render(const LLWString &wstr,
mImageGLp->bind(0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Not guaranteed to be set correctly
gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Not guaranteed to be set correctly
cur_x = ((F32)x * sScaleX);
cur_y = ((F32)y * sScaleY);
@ -743,9 +744,9 @@ S32 LLFontGL::render(const LLWString &wstr,
if (!label.empty())
{
glPushMatrix();
gGL.pushMatrix();
//glLoadIdentity();
//glTranslatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
//gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
//glScalef(sScaleX, sScaleY, 1.f);
gExtCharFont->render(label, 0,
/*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX),
@ -753,10 +754,10 @@ S32 LLFontGL::render(const LLWString &wstr,
color,
halign, BASELINE, NORMAL, S32_MAX, S32_MAX, NULL,
TRUE );
glPopMatrix();
gGL.popMatrix();
}
glColor4fv(color.mV);
gGL.color4fv(color.mV);
chars_drawn++;
cur_x += ext_advance;
@ -836,10 +837,10 @@ S32 LLFontGL::render(const LLWString &wstr,
if (style & UNDERLINE)
{
LLGLSNoTexture no_texture;
glBegin(GL_LINES);
glVertex2f(start_x, cur_y - (mDescender));
glVertex2f(cur_x, cur_y - (mDescender));
glEnd();
gGL.begin(GL_LINES);
gGL.vertex2f(start_x, cur_y - (mDescender));
gGL.vertex2f(cur_x, cur_y - (mDescender));
gGL.end();
}
// *FIX: get this working in all alignment cases, etc.
@ -847,9 +848,9 @@ S32 LLFontGL::render(const LLWString &wstr,
{
// recursively render ellipses at end of string
// we've already reserved enough room
glPushMatrix();
gGL.pushMatrix();
//glLoadIdentity();
//glTranslatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
//gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
//glScalef(sScaleX, sScaleY, 1.f);
renderUTF8("...",
0,
@ -860,10 +861,10 @@ S32 LLFontGL::render(const LLWString &wstr,
S32_MAX, max_pixels,
right_x,
FALSE);
glPopMatrix();
gGL.popMatrix();
}
glPopMatrix();
gGL.popMatrix();
return chars_drawn;
}
@ -1309,20 +1310,20 @@ void LLFontGL::removeEmbeddedChar( llwchar wc )
void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const
{
glTexCoord2f(uv_rect.mRight, uv_rect.mTop);
glVertex2f(llfont_round_x(screen_rect.mRight),
gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
gGL.vertex2f(llfont_round_x(screen_rect.mRight),
llfont_round_y(screen_rect.mTop));
glTexCoord2f(uv_rect.mLeft, uv_rect.mTop);
glVertex2f(llfont_round_x(screen_rect.mLeft),
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
gGL.vertex2f(llfont_round_x(screen_rect.mLeft),
llfont_round_y(screen_rect.mTop));
glTexCoord2f(uv_rect.mLeft, uv_rect.mBottom);
glVertex2f(llfont_round_x(screen_rect.mLeft + slant_amt),
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
gGL.vertex2f(llfont_round_x(screen_rect.mLeft + slant_amt),
llfont_round_y(screen_rect.mBottom));
glTexCoord2f(uv_rect.mRight, uv_rect.mBottom);
glVertex2f(llfont_round_x(screen_rect.mRight + slant_amt),
gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
gGL.vertex2f(llfont_round_x(screen_rect.mRight + slant_amt),
llfont_round_y(screen_rect.mBottom));
}
@ -1331,13 +1332,13 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con
F32 slant_offset;
slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f);
glBegin(GL_QUADS);
gGL.begin(GL_QUADS);
{
//FIXME: bold and drop shadow are mutually exclusive only for convenience
//Allow both when we need them.
if (style & BOLD)
{
glColor4fv(color.mV);
gGL.color4fv(color.mV);
for (S32 pass = 0; pass < 2; pass++)
{
LLRectf screen_rect_offset = screen_rect;
@ -1350,7 +1351,7 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con
{
LLColor4 shadow_color = LLFontGL::sShadowColor;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH;
glColor4fv(shadow_color.mV);
gGL.color4fv(shadow_color.mV);
for (S32 pass = 0; pass < 5; pass++)
{
LLRectf screen_rect_offset = screen_rect;
@ -1376,28 +1377,28 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con
renderQuad(screen_rect_offset, uv_rect, slant_offset);
}
glColor4fv(color.mV);
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
else if (style & DROP_SHADOW)
{
LLColor4 shadow_color = LLFontGL::sShadowColor;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
glColor4fv(shadow_color.mV);
gGL.color4fv(shadow_color.mV);
LLRectf screen_rect_shadow = screen_rect;
screen_rect_shadow.translate(1.f, -1.f);
renderQuad(screen_rect_shadow, uv_rect, slant_offset);
glColor4fv(color.mV);
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
else // normal rendering
{
glColor4fv(color.mV);
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
}
glEnd();
gGL.end();
}
// static

View File

@ -41,6 +41,8 @@
#include "llmath.h"
#include "llgl.h"
#include "llglimmediate.h"
//----------------------------------------------------------------------------
@ -49,6 +51,8 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f;
//statics
LLGLuint LLImageGL::sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS] = { 0 };
U32 LLImageGL::sUniqueCount = 0;
U32 LLImageGL::sBindCount = 0;
S32 LLImageGL::sGlobalTextureMemory = 0;
S32 LLImageGL::sBoundTextureMemory = 0;
S32 LLImageGL::sCurBoundTextureMemory = 0;
@ -123,6 +127,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
// static
void LLImageGL::bindExternalTexture(LLGLuint gl_name, S32 stage, LLGLenum bind_target )
{
gGL.flush();
glActiveTextureARB(GL_TEXTURE0_ARB + stage);
glClientActiveTextureARB(GL_TEXTURE0_ARB + stage);
glBindTexture(bind_target, gl_name);
@ -135,6 +140,7 @@ void LLImageGL::unbindTexture(S32 stage, LLGLenum bind_target)
// LLGLSLShader can return -1
if (stage >= 0)
{
gGL.flush();
glActiveTextureARB(GL_TEXTURE0_ARB + stage);
glClientActiveTextureARB(GL_TEXTURE0_ARB + stage);
glBindTexture(bind_target, 0);
@ -148,6 +154,7 @@ void LLImageGL::unbindTexture(S32 stage)
// LLGLSLShader can return -1
if (stage >= 0)
{
gGL.flush();
glActiveTextureARB(GL_TEXTURE0_ARB + stage);
glClientActiveTextureARB(GL_TEXTURE0_ARB + stage);
glBindTexture(GL_TEXTURE_2D, 0);
@ -411,6 +418,7 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
llwarns << "Trying to bind a texture while GL is disabled!" << llendl;
}
glActiveTextureARB(GL_TEXTURE0_ARB + stage);
if (sCurrentBoundTextures[stage] && sCurrentBoundTextures[stage] == mTexName)
@ -425,12 +433,15 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
mMissed = ! getIsResident(TRUE);
#endif
gGL.flush();
glBindTexture(mBindTarget, mTexName);
sCurrentBoundTextures[stage] = mTexName;
sBindCount++;
if (mLastBindTime != sLastFrameTime)
{
// we haven't accounted for this texture yet this frame
sUniqueCount++;
updateBoundTexMem(mTextureMemory);
mLastBindTime = sLastFrameTime;
}
@ -439,6 +450,7 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
}
else
{
gGL.flush();
glBindTexture(mBindTarget, 0);
sCurrentBoundTextures[stage] = 0;
return FALSE;
@ -665,7 +677,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
}
mHasMipMaps = FALSE;
}
glFlush();
stop_glerror();
}
@ -759,7 +770,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
stop_glerror();
}
glFlush();
return TRUE;
}
@ -1046,6 +1057,7 @@ void LLImageGL::destroyGLTexture()
{
unbindTexture(i, GL_TEXTURE_2D);
stop_glerror();
glActiveTextureARB(GL_TEXTURE0_ARB);
}
}

View File

@ -185,7 +185,8 @@ public:
static S32 sGlobalTextureMemory; // Tracks main memory texmem
static S32 sBoundTextureMemory; // Tracks bound texmem for last completed frame
static S32 sCurBoundTextureMemory; // Tracks bound texmem for current frame
static U32 sBindCount; // Tracks number of texture binds for current frame
static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
static BOOL sGlobalUseAnisotropic;
#if DEBUG_MISS

View File

@ -0,0 +1,185 @@
/**
* @file llrendertarget.cpp
* @brief LLRenderTarget implementation
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2007, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llrendertarget.h"
#include "llglimmediate.h"
BOOL LLRenderTarget::sUseFBO = FALSE;
LLRenderTarget::LLRenderTarget()
{
mResX = mResY = mTex = mFBO = mDepth = 0;
mUseDepth = FALSE;
mUsage = GL_TEXTURE_2D;
}
LLRenderTarget::~LLRenderTarget()
{
release();
}
void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage, BOOL force_fbo)
{
mResX = resx;
mResY = resy;
mUsage = usage;
mUseDepth = depth;
release();
glGenTextures(1, (GLuint *) &mTex);
glBindTexture(mUsage, mTex);
glTexImage2D(mUsage, 0, color_fmt, mResX, mResY, 0, color_fmt, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(mUsage, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(mUsage, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (mUsage != GL_TEXTURE_RECTANGLE_ARB)
{
glTexParameteri(mUsage, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(mUsage, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
}
else
{
// ATI doesn't support mirrored repeat for rectangular textures.
glTexParameteri(mUsage, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(mUsage, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
stop_glerror();
if (sUseFBO || force_fbo)
{
if (depth)
{
glGenRenderbuffersEXT(1, (GLuint *) &mDepth);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,mResX,mResY);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
}
glGenFramebuffersEXT(1, (GLuint *) &mFBO);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
if (mDepth)
{
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, mDepth);
}
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
mUsage, mTex, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
}
void LLRenderTarget::release()
{
if (mFBO)
{
glDeleteFramebuffersEXT(1, (GLuint *) &mFBO);
mFBO = 0;
}
if (mTex)
{
glDeleteTextures(1, (GLuint *) &mTex);
mTex = 0;
}
if (mDepth)
{
glDeleteRenderbuffersEXT(1, (GLuint *) &mDepth);
mDepth = 0;
}
}
void LLRenderTarget::bindTarget()
{
if (mFBO)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
}
glViewport(0, 0, mResX, mResY);
}
void LLRenderTarget::clear()
{
U32 mask = GL_COLOR_BUFFER_BIT;
if (mUseDepth)
{
mask |= GL_DEPTH_BUFFER_BIT;
}
if (mFBO)
{
glClear(mask);
}
else
{
LLGLEnable scissor(GL_SCISSOR_TEST);
glScissor(0, 0, mResX, mResY);
glClear(mask);
}
}
void LLRenderTarget::bindTexture()
{
glBindTexture(mUsage, mTex);
}
void LLRenderTarget::flush()
{
gGL.flush();
if (!mFBO)
{
bindTexture();
glCopyTexSubImage2D(mUsage, 0, 0, 0, 0, 0, mResX, mResY);
}
}
BOOL LLRenderTarget::isComplete() const
{
return (mTex || mDepth) ? TRUE : FALSE;
}
void LLRenderTarget::getViewport(S32* viewport)
{
viewport[0] = 0;
viewport[1] = 0;
viewport[2] = mResX;
viewport[3] = mResY;
}

View File

@ -0,0 +1,116 @@
/**
* @file llrendertarget.h
* @brief Off screen render target abstraction. Loose wrapper for GL_EXT_framebuffer_objects.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2007, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLRENDERTARGET_H
#define LL_LLRENDERTARGET_H
#include "llgl.h"
/*
SAMPLE USAGE:
LLFBOTarget target;
...
//allocate a 256x256 RGBA render target with depth buffer
target.allocate(256,256,GL_RGBA,TRUE);
//render to contents of offscreen buffer
target.bindTarget();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
... <issue drawing commands> ...
target.flush();
...
//use target as a texture
target.bindTexture();
... <issue drawing commands> ...
*/
class LLRenderTarget
{
public:
//whether or not to use FBO implementation
static BOOL sUseFBO;
LLRenderTarget();
~LLRenderTarget();
//allocate resources for rendering
//must be called before use
//multiple calls will release previously allocated resources
void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage = GL_TEXTURE_2D, BOOL force_fbo = FALSE);
//free any allocated resources
//safe to call redundantly
void release();
//bind target for rendering
//applies appropriate viewport
void bindTarget();
//clear render targer, clears depth buffer if present,
//uses scissor rect if in copy-to-texture mode
void clear();
//get applied viewport
void getViewport(S32* viewport);
//bind results of render for sampling
void bindTexture();
//flush rendering operations
//must be called when rendering is complete
//should be used 1:1 with bindTarget
// call bindTarget once, do all your rendering, call flush once
void flush();
//Returns TRUE if target is ready to be rendered into.
//That is, if the target has been allocated with at least
//one renderable attachment (i.e. color buffer, depth buffer).
BOOL isComplete() const;
private:
U32 mResX;
U32 mResY;
U32 mTex;
U32 mFBO;
U32 mDepth;
BOOL mUseDepth;
U32 mUsage;
};
#endif

View File

@ -31,6 +31,8 @@
#include "linden_common.h"
#include <boost/static_assert.hpp>
#include "llvertexbuffer.h"
// #include "llrender.h"
#include "llglheaders.h"
@ -40,8 +42,16 @@
//============================================================================
//static
LLVBOPool LLVertexBuffer::sStreamVBOPool;
LLVBOPool LLVertexBuffer::sDynamicVBOPool;
LLVBOPool LLVertexBuffer::sStreamIBOPool;
LLVBOPool LLVertexBuffer::sDynamicIBOPool;
U32 LLVertexBuffer::sBindCount = 0;
U32 LLVertexBuffer::sSetCount = 0;
S32 LLVertexBuffer::sCount = 0;
S32 LLVertexBuffer::sGLCount = 0;
S32 LLVertexBuffer::sMappedCount = 0;
BOOL LLVertexBuffer::sEnableVBOs = TRUE;
U32 LLVertexBuffer::sGLRenderBuffer = 0;
U32 LLVertexBuffer::sGLRenderIndices = 0;
@ -50,9 +60,9 @@ BOOL LLVertexBuffer::sVBOActive = FALSE;
BOOL LLVertexBuffer::sIBOActive = FALSE;
U32 LLVertexBuffer::sAllocatedBytes = 0;
BOOL LLVertexBuffer::sRenderActive = FALSE;
BOOL LLVertexBuffer::sMapped = FALSE;
std::vector<U32> LLVertexBuffer::sDeleteList;
LLVertexBuffer::buffer_list_t LLVertexBuffer::sLockedList;
S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
{
@ -70,6 +80,10 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
void LLVertexBuffer::initClass(bool use_vbo)
{
sEnableVBOs = use_vbo;
LLGLNamePool::registerPool(&sDynamicVBOPool);
LLGLNamePool::registerPool(&sDynamicIBOPool);
LLGLNamePool::registerPool(&sStreamVBOPool);
LLGLNamePool::registerPool(&sStreamIBOPool);
}
//static
@ -88,13 +102,13 @@ void LLVertexBuffer::unbind()
sGLRenderBuffer = 0;
sGLRenderIndices = 0;
sLastMask = 0;
}
//static
void LLVertexBuffer::cleanupClass()
{
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
sLockedList.clear();
startRender();
stopRender();
clientCopy(); // deletes GL buffers
@ -127,41 +141,8 @@ void LLVertexBuffer::clientCopy(F64 max_time)
{
if (!sDeleteList.empty())
{
size_t num = sDeleteList.size();
glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0]));
sDeleteList.clear();
sGLCount -= num;
}
if (sEnableVBOs)
{
LLTimer timer;
BOOL reset = TRUE;
buffer_list_t::iterator iter = sLockedList.begin();
while(iter != sLockedList.end())
{
LLVertexBuffer* buffer = *iter;
if (buffer->isLocked() && buffer->useVBOs())
{
buffer->setBuffer(0);
}
++iter;
if (reset)
{
reset = FALSE;
timer.reset(); //skip first copy (don't count pipeline stall)
}
else
{
if (timer.getElapsedTimeF64() > max_time)
{
break;
}
}
}
sLockedList.erase(sLockedList.begin(), iter);
}
}
@ -175,27 +156,40 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mFinal(FALSE),
mFilthy(FALSE),
mEmpty(TRUE),
mResized(FALSE)
mResized(FALSE),
mDynamicSize(FALSE)
{
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
if (!sEnableVBOs)
{
mUsage = GL_STREAM_DRAW_ARB;
mUsage = 0 ;
}
S32 stride = calcStride(typemask, mOffsets);
mTypeMask = typemask;
mStride = stride;
sCount++;
}
//static
S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets)
{
S32 stride = 0;
for (S32 i=0; i<TYPE_MAX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
{
mOffsets[i] = stride;
if (offsets)
{
offsets[i] = stride;
}
stride += sTypeOffsets[i];
}
}
mTypeMask = typemask;
mStride = stride;
sCount++;
return stride;
}
// protected, use unref()
@ -206,23 +200,80 @@ LLVertexBuffer::~LLVertexBuffer()
destroyGLBuffer();
destroyGLIndices();
sCount--;
if (mLocked)
{
//pull off of locked list
for (buffer_list_t::iterator i = sLockedList.begin(); i != sLockedList.end(); ++i)
{
if (*i == this)
{
sLockedList.erase(i);
break;
}
}
}
};
//----------------------------------------------------------------------------
void LLVertexBuffer::genBuffer()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
mGLBuffer = sStreamVBOPool.allocate();
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
mGLBuffer = sDynamicVBOPool.allocate();
}
else
{
BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
glGenBuffersARB(1, (GLuint*)&mGLBuffer);
}
sGLCount++;
}
void LLVertexBuffer::genIndices()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
mGLIndices = sStreamIBOPool.allocate();
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
mGLIndices = sDynamicIBOPool.allocate();
}
else
{
BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
glGenBuffersARB(1, (GLuint*)&mGLIndices);
}
sGLCount++;
}
void LLVertexBuffer::releaseBuffer()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
sStreamVBOPool.release(mGLBuffer);
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
sDynamicVBOPool.release(mGLBuffer);
}
else
{
sDeleteList.push_back(mGLBuffer);
}
sGLCount--;
}
void LLVertexBuffer::releaseIndices()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
sStreamIBOPool.release(mGLIndices);
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
sDynamicIBOPool.release(mGLIndices);
}
else
{
sDeleteList.push_back(mGLIndices);
}
sGLCount--;
}
void LLVertexBuffer::createGLBuffer()
{
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
@ -238,20 +289,20 @@ void LLVertexBuffer::createGLBuffer()
return;
}
mMappedData = new U8[size];
memset(mMappedData, 0, size);
mEmpty = TRUE;
if (useVBOs())
{
glGenBuffersARB(1, (GLuint*) &mGLBuffer);
mMappedData = NULL;
genBuffer();
mResized = TRUE;
sGLCount++;
}
else
{
static int gl_buffer_idx = 0;
mGLBuffer = ++gl_buffer_idx;
mMappedData = new U8[size];
memset(mMappedData, 0, size);
}
}
@ -270,18 +321,18 @@ void LLVertexBuffer::createGLIndices()
return;
}
mMappedIndexData = new U8[size];
memset(mMappedIndexData, 0, size);
mEmpty = TRUE;
if (useVBOs())
{
glGenBuffersARB(1, (GLuint*) &mGLIndices);
mMappedIndexData = NULL;
genIndices();
mResized = TRUE;
sGLCount++;
}
else
{
mMappedIndexData = new U8[size];
memset(mMappedIndexData, 0, size);
static int gl_buffer_idx = 0;
mGLIndices = ++gl_buffer_idx;
}
@ -294,12 +345,19 @@ void LLVertexBuffer::destroyGLBuffer()
{
if (useVBOs())
{
sDeleteList.push_back(mGLBuffer);
if (mMappedData || mMappedIndexData)
{
llerrs << "Vertex buffer destroyed while mapped!" << llendl;
}
releaseBuffer();
}
delete [] mMappedData;
mMappedData = NULL;
mEmpty = TRUE;
else
{
delete [] mMappedData;
mMappedData = NULL;
mEmpty = TRUE;
}
sAllocatedBytes -= getSize();
}
@ -313,12 +371,19 @@ void LLVertexBuffer::destroyGLIndices()
{
if (useVBOs())
{
sDeleteList.push_back(mGLIndices);
if (mMappedData || mMappedIndexData)
{
llerrs << "Vertex buffer destroyed while mapped." << llendl;
}
releaseIndices();
}
delete [] mMappedIndexData;
mMappedIndexData = NULL;
mEmpty = TRUE;
else
{
delete [] mMappedIndexData;
mMappedIndexData = NULL;
mEmpty = TRUE;
}
sAllocatedBytes -= getIndicesSize();
}
@ -328,6 +393,15 @@ void LLVertexBuffer::destroyGLIndices()
void LLVertexBuffer::updateNumVerts(S32 nverts)
{
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
if (nverts >= 65535)
{
llwarns << "Vertex buffer overflow!" << llendl;
nverts = 65535;
}
mRequestedNumVerts = nverts;
if (!mDynamicSize)
{
mNumVerts = nverts;
@ -336,18 +410,19 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
nverts > mNumVerts ||
nverts < mNumVerts/2)
{
if (mUsage != GL_STATIC_DRAW_ARB)
if (mUsage != GL_STATIC_DRAW_ARB && nverts + nverts/4 <= 65535)
{
nverts += nverts/4;
}
mNumVerts = nverts;
}
}
void LLVertexBuffer::updateNumIndices(S32 nindices)
{
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
mRequestedNumIndices = nindices;
if (!mDynamicSize)
{
mNumIndices = nindices;
@ -365,54 +440,6 @@ void LLVertexBuffer::updateNumIndices(S32 nindices)
}
}
void LLVertexBuffer::makeStatic()
{
if (!sEnableVBOs)
{
return;
}
if (sRenderActive)
{
llerrs << "Make static called during render." << llendl;
}
if (mUsage != GL_STATIC_DRAW_ARB)
{
if (useVBOs())
{
if (mGLBuffer)
{
sDeleteList.push_back(mGLBuffer);
}
if (mGLIndices)
{
sDeleteList.push_back(mGLIndices);
}
}
if (mGLBuffer)
{
sGLCount++;
glGenBuffersARB(1, (GLuint*) &mGLBuffer);
}
if (mGLIndices)
{
sGLCount++;
glGenBuffersARB(1, (GLuint*) &mGLIndices);
}
mUsage = GL_STATIC_DRAW_ARB;
mResized = TRUE;
if (!mLocked)
{
mLocked = TRUE;
sLockedList.push_back(this);
}
}
}
void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
{
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
@ -435,6 +462,9 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
{
mRequestedNumVerts = newnverts;
mRequestedNumIndices = newnindices;
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
mDynamicSize = TRUE;
if (mUsage == GL_STATIC_DRAW_ARB)
@ -469,22 +499,25 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
else
{
//delete old buffer, keep GL buffer for now
U8* old = mMappedData;
mMappedData = new U8[newsize];
if (old)
{
memcpy(mMappedData, old, llmin(newsize, oldsize));
if (newsize > oldsize)
{
memset(mMappedData+oldsize, 0, newsize-oldsize);
}
delete [] old;
}
else
if (!useVBOs())
{
memset(mMappedData, 0, newsize);
mEmpty = TRUE;
U8* old = mMappedData;
mMappedData = new U8[newsize];
if (old)
{
memcpy(mMappedData, old, llmin(newsize, oldsize));
if (newsize > oldsize)
{
memset(mMappedData+oldsize, 0, newsize-oldsize);
}
delete [] old;
}
else
{
memset(mMappedData, 0, newsize);
mEmpty = TRUE;
}
}
mResized = TRUE;
}
@ -502,22 +535,26 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
}
else
{
//delete old buffer, keep GL buffer for now
U8* old = mMappedIndexData;
mMappedIndexData = new U8[new_index_size];
if (old)
{
memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size));
if (new_index_size > old_index_size)
{
memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size);
}
delete [] old;
}
else
if (!useVBOs())
{
memset(mMappedIndexData, 0, new_index_size);
mEmpty = TRUE;
//delete old buffer, keep GL buffer for now
U8* old = mMappedIndexData;
mMappedIndexData = new U8[new_index_size];
if (old)
{
memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size));
if (new_index_size > old_index_size)
{
memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size);
}
delete [] old;
}
else
{
memset(mMappedIndexData, 0, new_index_size);
mEmpty = TRUE;
}
}
mResized = TRUE;
}
@ -527,18 +564,29 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
destroyGLIndices();
}
}
if (mResized && useVBOs())
{
setBuffer(0);
}
}
BOOL LLVertexBuffer::useVBOs() const
{
//it's generally ineffective to use VBO for things that are streaming
//when we already have a client buffer around
if (mUsage == GL_STREAM_DRAW_ARB)
//it's generally ineffective to use VBO for things that are streaming on apple
#if LL_DARWIN
if (!mUsage || mUsage == GL_STREAM_DRAW_ARB)
{
return FALSE;
}
return sEnableVBOs && (!sRenderActive || !mLocked);
#else
if (!mUsage)
{
return FALSE;
}
#endif
return sEnableVBOs; // && (!sRenderActive || !mLocked);
}
//----------------------------------------------------------------------------
@ -547,27 +595,27 @@ BOOL LLVertexBuffer::useVBOs() const
U8* LLVertexBuffer::mapBuffer(S32 access)
{
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
if (sRenderActive)
{
llwarns << "Buffer mapped during render frame!" << llendl;
}
if (!mGLBuffer && !mGLIndices)
{
llerrs << "LLVertexBuffer::mapBuffer() called before createGLBuffer" << llendl;
}
if (mFinal)
{
llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl;
}
if (!mMappedData && !mMappedIndexData)
if (!useVBOs() && !mMappedData && !mMappedIndexData)
{
llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl;
}
if (!mLocked && useVBOs())
{
setBuffer(0);
mLocked = TRUE;
sLockedList.push_back(this);
mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
/*if (sMapped)
{
llerrs << "Mapped two VBOs at the same time!" << llendl;
}
sMapped = TRUE;*/
sMappedCount++;
}
return mMappedData;
@ -580,64 +628,19 @@ void LLVertexBuffer::unmapBuffer()
{
if (useVBOs() && mLocked)
{
if (mGLBuffer)
{
if (mResized)
{
glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), mMappedData, mUsage);
}
else
{
if (mEmpty || mDirtyRegions.empty())
{
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
}
else
{
for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i)
{
DirtyRegion& region = *i;
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, region.mIndex*mStride, region.mCount*mStride, mMappedData + region.mIndex*mStride);
}
}
}
}
if (mGLIndices)
{
if (mResized)
{
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), mMappedIndexData, mUsage);
}
else
{
if (mEmpty || mDirtyRegions.empty())
{
glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
}
else
{
for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i)
{
DirtyRegion& region = *i;
glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, region.mIndicesIndex*sizeof(U32),
region.mIndicesCount*sizeof(U32), mMappedIndexData + region.mIndicesIndex*sizeof(U32));
}
}
}
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
mDirtyRegions.clear();
mFilthy = FALSE;
mResized = FALSE;
/*if (!sMapped)
{
llerrs << "Redundantly unmapped VBO!" << llendl;
}
sMapped = FALSE;*/
sMappedCount--;
if (mUsage == GL_STATIC_DRAW_ARB)
{ //static draw buffers can only be mapped a single time
//throw out client data (we won't be using it again)
delete [] mMappedData;
delete [] mMappedIndexData;
mMappedIndexData = NULL;
mMappedData = NULL;
mEmpty = TRUE;
mFinal = TRUE;
}
@ -645,10 +648,11 @@ void LLVertexBuffer::unmapBuffer()
{
mEmpty = FALSE;
}
mMappedIndexData = NULL;
mMappedData = NULL;
mLocked = FALSE;
glFlush();
}
}
}
@ -690,9 +694,9 @@ bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index)
{
return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index);
}
bool LLVertexBuffer::getIndexStrider(LLStrider<U32>& strider, S32 index)
bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index)
{
return VertexBufferStrider<U32,TYPE_INDEX>::get(*this, strider, index);
return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index);
}
bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index)
{
@ -755,16 +759,46 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
{
if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))
{
/*if (sMapped)
{
llerrs << "VBO bound while another VBO mapped!" << llendl;
}*/
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
sBindCount++;
sVBOActive = TRUE;
setup = TRUE; // ... or the bound buffer changed
}
if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))
{
/*if (sMapped)
{
llerrs << "VBO bound while another VBO mapped!" << llendl;
}*/
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
sBindCount++;
sIBOActive = TRUE;
}
if (mResized)
{
if (mGLBuffer)
{
glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), NULL, mUsage);
}
if (mGLIndices)
{
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), NULL, mUsage);
}
mEmpty = TRUE;
mResized = FALSE;
if (data_mask != 0)
{
llerrs << "Buffer set for rendering before being filled after resize." << llendl;
}
}
unmapBuffer();
}
else
@ -774,6 +808,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
if (sEnableVBOs && sVBOActive)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
sBindCount++;
sVBOActive = FALSE;
setup = TRUE; // ... or a VBO is deactivated
}
@ -784,7 +819,12 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
}
if (sEnableVBOs && mGLIndices && sIBOActive)
{
/*if (sMapped)
{
llerrs << "VBO unbound while potentially mapped!" << llendl;
}*/
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
sBindCount++;
sIBOActive = FALSE;
}
}
@ -803,9 +843,11 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
llwarns << "Vertex buffer set for rendering outside of render frame." << llendl;
}
setupVertexBuffer(data_mask); // subclass specific setup (virtual function)
sLastMask = data_mask;
sSetCount++;
}
}
sLastMask = data_mask;
}
// virtual (default)
@ -821,10 +863,6 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
}
if (data_mask & MAP_VERTEX)
{
glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0));
}
if (data_mask & MAP_NORMAL)
{
glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL]));
@ -855,49 +893,19 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
{
glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
}
if (data_mask & MAP_VERTEX)
{
glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0));
}
llglassertok();
}
void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count)
{
if (useVBOs() && !mFilthy)
// TODO: use GL_APPLE_flush_buffer_range here
/*if (useVBOs() && !mFilthy)
{
if (!mDirtyRegions.empty())
{
DirtyRegion& region = *(mDirtyRegions.rbegin());
if (region.mIndex+region.mCount > vert_index)
{
//this buffer has received multiple updates since the last copy, mark it filthy
mFilthy = TRUE;
mDirtyRegions.clear();
return;
}
if (region.mIndex + region.mCount == vert_index &&
region.mIndicesIndex + region.mIndicesCount == indices_index)
{
region.mCount += vert_count;
region.mIndicesCount += indices_count;
return;
}
}
mDirtyRegions.push_back(DirtyRegion(vert_index,vert_count,indices_index,indices_count));
}
}*/
}
void LLVertexBuffer::markClean()
{
if (!mResized && !mEmpty && !mFilthy)
{
buffer_list_t::reverse_iterator iter = sLockedList.rbegin();
if (*iter == this)
{
mLocked = FALSE;
sLockedList.pop_back();
}
}
}

View File

@ -50,12 +50,38 @@
// be called as soon as getVertexPointer(), etc is called (which MUST ONLY be
// called from the main (i.e OpenGL) thread)
//============================================================================
// gl name pools for dynamic and streaming buffers
class LLVBOPool : public LLGLNamePool
{
protected:
virtual GLuint allocateName()
{
GLuint name;
glGenBuffersARB(1, &name);
return name;
}
virtual void releaseName(GLuint name)
{
glDeleteBuffersARB(1, &name);
}
};
//============================================================================
// base class
class LLVertexBuffer : public LLRefCount
{
public:
static LLVBOPool sStreamVBOPool;
static LLVBOPool sDynamicVBOPool;
static LLVBOPool sStreamIBOPool;
static LLVBOPool sDynamicIBOPool;
static void initClass(bool use_vbo);
static void cleanupClass();
static void startRender(); //between start and stop render, no client copies will occur
@ -63,6 +89,12 @@ public:
static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
static void unbind(); //unbind any bound vertex buffer
//get the size of a vertex with the given typemask
//if offsets is not NULL, its contents will be filled
//with the offset of each vertex component in the buffer,
// indexed by the following enum
static S32 calcStride(const U32& typemask, S32* offsets = NULL);
enum {
TYPE_VERTEX,
TYPE_NORMAL,
@ -92,10 +124,16 @@ public:
};
protected:
friend class LLGLImmediate;
virtual ~LLVertexBuffer(); // use unref()
virtual void setupVertexBuffer(U32 data_mask) const; // pure virtual, called from mapBuffer()
void genBuffer();
void genIndices();
void releaseBuffer();
void releaseIndices();
void createGLBuffer();
void createGLIndices();
void destroyGLBuffer();
@ -104,7 +142,7 @@ protected:
void updateNumIndices(S32 nindices);
virtual BOOL useVBOs() const;
void unmapBuffer();
public:
LLVertexBuffer(U32 typemask, S32 usage);
@ -115,8 +153,7 @@ public:
// allocate buffer
void allocateBuffer(S32 nverts, S32 nindices, bool create);
virtual void resizeBuffer(S32 newnverts, S32 newnindices);
void makeStatic();
// Only call each getVertexPointer, etc, once before calling unmapBuffer()
// call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer()
// example:
@ -125,7 +162,7 @@ public:
// setVertsNorms(verts, norms);
// vb->unmapBuffer();
bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0);
bool getIndexStrider(LLStrider<U32>& strider, S32 index=0);
bool getIndexStrider(LLStrider<U16>& strider, S32 index=0);
bool getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index=0);
bool getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index=0);
bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
@ -138,13 +175,16 @@ public:
BOOL isLocked() const { return mLocked; }
S32 getNumVerts() const { return mNumVerts; }
S32 getNumIndices() const { return mNumIndices; }
S32 getRequestedVerts() const { return mRequestedNumVerts; }
S32 getRequestedIndices() const { return mRequestedNumIndices; }
U8* getIndicesPointer() const { return useVBOs() ? NULL : mMappedIndexData; }
U8* getVerticesPointer() const { return useVBOs() ? NULL : mMappedData; }
S32 getStride() const { return mStride; }
S32 getTypeMask() const { return mTypeMask; }
BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; }
S32 getSize() const { return mNumVerts*mStride; }
S32 getIndicesSize() const { return mNumIndices * sizeof(U32); }
S32 getIndicesSize() const { return mNumIndices * sizeof(U16); }
U8* getMappedData() const { return mMappedData; }
U8* getMappedIndices() const { return mMappedIndexData; }
S32 getOffset(S32 type) const { return mOffsets[type]; }
@ -153,11 +193,13 @@ public:
void setStride(S32 type, S32 new_stride);
void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count);
void markClean();
protected:
S32 mNumVerts; // Number of vertices
S32 mNumIndices; // Number of indices
S32 mNumVerts; // Number of vertices allocated
S32 mNumIndices; // Number of indices allocated
S32 mRequestedNumVerts; // Number of vertices requested
S32 mRequestedNumIndices; // Number of indices requested
S32 mStride;
U32 mTypeMask;
S32 mUsage; // GL usage
@ -192,10 +234,11 @@ public:
static BOOL sRenderActive;
static S32 sCount;
static S32 sGLCount;
static S32 sMappedCount;
static BOOL sMapped;
static std::vector<U32> sDeleteList;
typedef std::list<LLVertexBuffer*> buffer_list_t;
static buffer_list_t sLockedList;
static BOOL sEnableVBOs;
static S32 sTypeOffsets[TYPE_MAX];
static U32 sGLRenderBuffer;
@ -204,6 +247,8 @@ public:
static BOOL sIBOActive;
static U32 sLastMask;
static U32 sAllocatedBytes;
static U32 sBindCount;
static U32 sSetCount;
};

View File

@ -48,6 +48,7 @@
#include "llglheaders.h"
#include "llfocusmgr.h"
#include "llwindow.h"
#include "llglimmediate.h"
// globals loaded from settings.xml
S32 LLBUTTON_ORIG_H_PAD = 6; // Pre-zoomable UI
@ -601,9 +602,9 @@ void LLButton::draw()
mImagep->draw(0, 0, getEnabled() ? mImageColor : mDisabledImageColor );
if (mCurGlowStrength > 0.01f)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
mImagep->drawSolid(0, 0, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}
else
@ -612,9 +613,9 @@ void LLButton::draw()
mImagep->draw(0, 0, getRect().getWidth(), getRect().getHeight(), getEnabled() ? mImageColor : mDisabledImageColor );
if (mCurGlowStrength > 0.01f)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
mImagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}
else

View File

@ -89,7 +89,16 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLString& name, const LLRect& rect,
LLCHECKBOXCTRL_VPAD + 1, // padding to get better alignment
text_width + LLCHECKBOXCTRL_HPAD,
text_height );
mLabel = new LLTextBox( "CheckboxCtrl Label", label_rect, label.c_str(), mFont );
// *HACK Get rid of this with SL-55508...
// this allows blank check boxes and radio boxes for now
LLString local_label = label;
if(local_label.empty())
{
local_label = " ";
}
mLabel = new LLTextBox( "CheckboxCtrl Label", label_rect, local_label.c_str(), mFont );
mLabel->setFollowsLeft();
mLabel->setFollowsBottom();
addChild(mLabel);

View File

@ -2123,42 +2123,40 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
if( floater->isResizable() )
{
LLRect view_rect = floater->getRect();
S32 view_width = view_rect.getWidth();
S32 view_height = view_rect.getHeight();
S32 old_width = view_rect.getWidth();
S32 old_height = view_rect.getHeight();
S32 min_width;
S32 min_height;
floater->getResizeLimits( &min_width, &min_height );
// Make sure floater isn't already smaller than its min height/width?
S32 new_width = llmax( min_width, view_width );
S32 new_height = llmax( min_height, view_height );
S32 new_width = llmax( min_width, old_width );
S32 new_height = llmax( min_height, old_height);
if( !allow_partial_outside
&& ( (new_width > screen_width)
|| (new_height > screen_height) ) )
if((new_width > screen_width) || (new_height > screen_height))
{
// We have to force this window to be inside the screen.
// We have to make this window able to fit on screen
new_width = llmin(new_width, screen_width);
new_height = llmin(new_height, screen_height);
// Still respect minimum width/height
// ...while respecting minimum width/height
new_width = llmax(new_width, min_width);
new_height = llmax(new_height, min_height);
floater->reshape( new_width, new_height, TRUE );
// Make sure the damn thing is actually onscreen.
if (floater->translateIntoRect(snap_rect_local, FALSE))
if (floater->followsRight())
{
floater->clearSnapTarget();
floater->translate(old_width - new_width, 0);
}
if (floater->followsTop())
{
floater->translate(0, old_height - new_height);
}
}
else if (!floater->isMinimized())
{
floater->reshape(new_width, new_height, TRUE);
}
}
// move window fully onscreen
if (floater->translateIntoRect( snap_rect_local, allow_partial_outside ))
{
floater->clearSnapTarget();

View File

@ -47,6 +47,7 @@
#include "llmath.h"
#include "llgl.h"
#include "llglimmediate.h"
#include "llfocusmgr.h"
#include "llfont.h"
#include "llcoord.h"
@ -470,7 +471,7 @@ void LLMenuItemGL::draw( void )
// let disabled items be highlighted, just don't draw them as such
if( getEnabled() && getHighlight() && !mBriefItem)
{
glColor4fv( sHighlightBackground.mV );
gGL.color4fv( sHighlightBackground.mV );
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );
}
@ -580,7 +581,7 @@ LLMenuItemSeparatorGL::LLMenuItemSeparatorGL( const LLString &name ) :
void LLMenuItemSeparatorGL::draw( void )
{
glColor4fv( getDisabledColor().mV );
gGL.color4fv( getDisabledColor().mV );
const S32 y = getRect().getHeight() / 2;
const S32 PAD = 6;
gl_line_2d( PAD, y, getRect().getWidth() - PAD, y );
@ -701,17 +702,17 @@ void LLMenuItemTearOffGL::draw()
// disabled items can be highlighted, but shouldn't render as such
if( getEnabled() && getHighlight() && !isBriefItem())
{
glColor4fv( getHighlightBGColor().mV );
gGL.color4fv( getHighlightBGColor().mV );
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );
}
if (getEnabled())
{
glColor4fv( getEnabledColor().mV );
gGL.color4fv( getEnabledColor().mV );
}
else
{
glColor4fv( getDisabledColor().mV );
gGL.color4fv( getDisabledColor().mV );
}
const S32 y = getRect().getHeight() / 3;
const S32 PAD = 6;
@ -1638,7 +1639,7 @@ void LLMenuItemBranchDownGL::draw( void )
if( getHighlight() )
{
glColor4fv( getHighlightBGColor().mV );
gGL.color4fv( getHighlightBGColor().mV );
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );
}
@ -2949,7 +2950,7 @@ void LLMenuGL::draw( void )
void LLMenuGL::drawBackground(LLMenuItemGL* itemp, LLColor4& color)
{
glColor4fv( color.mV );
gGL.color4fv( color.mV );
LLRect item_rect = itemp->getRect();
gl_rect_2d( 0, item_rect.getHeight(), item_rect.getWidth(), 0);
}
@ -3476,9 +3477,9 @@ void LLPieMenu::draw()
F32 center_y = height/2;
S32 steps = 100;
glPushMatrix();
gGL.pushMatrix();
{
glTranslatef(center_x, center_y, 0.f);
gGL.translatef(center_x, center_y, 0.f);
F32 line_width = LLUI::sConfigGroup->getF32("PieMenuLineWidth");
LLColor4 line_color = LLUI::sColorsGroup->getColor("PieMenuLineColor");
@ -3517,16 +3518,16 @@ void LLPieMenu::draw()
gl_washer_spokes_2d( mCurRadius, (F32)PIE_CENTER_SIZE, 8, line_color, outer_color );
// inner circle
glColor4fv( line_color.mV );
gGL.color4fv( line_color.mV );
gl_circle_2d( 0, 0, (F32)PIE_CENTER_SIZE, steps, FALSE );
// outer circle
glColor4fv( outer_color.mV );
gGL.color4fv( outer_color.mV );
gl_circle_2d( 0, 0, mCurRadius, steps, FALSE );
LLUI::setLineWidth(1.0f);
}
glPopMatrix();
gGL.popMatrix();
mHoverThisFrame = FALSE;
@ -3541,10 +3542,10 @@ void LLPieMenu::drawBackground(LLMenuItemGL* itemp, LLColor4& color)
F32 center_y = height/2;
S32 steps = 100;
glColor4fv( color.mV );
glPushMatrix();
gGL.color4fv( color.mV );
gGL.pushMatrix();
{
glTranslatef(center_x - itemp->getRect().mLeft, center_y - itemp->getRect().mBottom, 0.f);
gGL.translatef(center_x - itemp->getRect().mLeft, center_y - itemp->getRect().mBottom, 0.f);
item_list_t::iterator item_iter;
S32 i = 0;
@ -3564,7 +3565,7 @@ void LLPieMenu::drawBackground(LLMenuItemGL* itemp, LLColor4& color)
i++;
}
}
glPopMatrix();
gGL.popMatrix();
}
// virtual

View File

@ -0,0 +1,677 @@
/**
* @file llmultisldr.cpp
* @brief LLMultiSlider base class
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2007, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmultislider.h"
#include "llui.h"
#include "llgl.h"
#include "llwindow.h"
#include "llfocusmgr.h"
#include "llkeyboard.h" // for the MASK constants
#include "llcontrol.h"
#include "llimagegl.h"
#include <sstream>
const S32 MULTI_THUMB_WIDTH = 8;
const S32 MULTI_TRACK_HEIGHT = 6;
const F32 FLOAT_THRESHOLD = 0.00001f;
const S32 EXTRA_TRIANGLE_WIDTH = 2;
const S32 EXTRA_TRIANGLE_HEIGHT = -2;
S32 LLMultiSlider::mNameCounter = 0;
LLMultiSlider::LLMultiSlider(
const LLString& name,
const LLRect& rect,
void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
void* callback_userdata,
F32 initial_value,
F32 min_value,
F32 max_value,
F32 increment,
S32 max_sliders,
BOOL allow_overlap,
BOOL draw_track,
BOOL use_triangle,
const LLString& control_name)
:
LLUICtrl( name, rect, TRUE, on_commit_callback, callback_userdata,
FOLLOWS_LEFT | FOLLOWS_TOP),
mInitialValue( initial_value ),
mMinValue( min_value ),
mMaxValue( max_value ),
mIncrement( increment ),
mMaxNumSliders(max_sliders),
mAllowOverlap(allow_overlap),
mDrawTrack(draw_track),
mUseTriangle(use_triangle),
mMouseOffset( 0 ),
mDragStartThumbRect( 0, getRect().getHeight(), MULTI_THUMB_WIDTH, 0 ),
mTrackColor( LLUI::sColorsGroup->getColor( "MultiSliderTrackColor" ) ),
mThumbOutlineColor( LLUI::sColorsGroup->getColor( "MultiSliderThumbOutlineColor" ) ),
mThumbCenterColor( LLUI::sColorsGroup->getColor( "MultiSliderThumbCenterColor" ) ),
mThumbCenterSelectedColor( LLUI::sColorsGroup->getColor( "MultiSliderThumbCenterSelectedColor" ) ),
mDisabledThumbColor(LLUI::sColorsGroup->getColor( "MultiSliderDisabledThumbColor" ) ),
mTriangleColor(LLUI::sColorsGroup->getColor( "MultiSliderTriangleColor" ) ),
mMouseDownCallback( NULL ),
mMouseUpCallback( NULL )
{
mValue.emptyMap();
mCurSlider = LLString::null;
// properly handle setting the starting thumb rect
// do it this way to handle both the operating-on-settings
// and standalone ways of using this
setControlName(control_name, NULL);
setValue(getValue());
}
EWidgetType LLMultiSlider::getWidgetType() const
{
return WIDGET_TYPE_MULTI_SLIDER_BAR;
}
LLString LLMultiSlider::getWidgetTag() const
{
return LL_MULTI_SLIDER_TAG;
}
void LLMultiSlider::setSliderValue(const LLString& name, F32 value, BOOL from_event)
{
// exit if not there
if(!mValue.has(name)) {
return;
}
value = llclamp( value, mMinValue, mMaxValue );
// Round to nearest increment (bias towards rounding down)
value -= mMinValue;
value += mIncrement/2.0001f;
value -= fmod(value, mIncrement);
F32 newValue = mMinValue + value;
// now, make sure no overlap
// if we want that
if(!mAllowOverlap) {
bool hit = false;
// look at the current spot
// and see if anything is there
LLSD::map_iterator mIt = mValue.beginMap();
for(;mIt != mValue.endMap(); mIt++) {
F32 testVal = (F32)mIt->second.asReal() - newValue;
if(testVal > -FLOAT_THRESHOLD && testVal < FLOAT_THRESHOLD &&
mIt->first != name) {
hit = true;
break;
}
}
// if none found, stop
if(hit) {
return;
}
}
// now set it in the map
mValue[name] = newValue;
// set the control if it's the current slider and not from an event
if (!from_event && name == mCurSlider)
{
setControlValue(mValue);
}
F32 t = (newValue - mMinValue) / (mMaxValue - mMinValue);
S32 left_edge = MULTI_THUMB_WIDTH/2;
S32 right_edge = getRect().getWidth() - (MULTI_THUMB_WIDTH/2);
S32 x = left_edge + S32( t * (right_edge - left_edge) );
mThumbRects[name].mLeft = x - (MULTI_THUMB_WIDTH/2);
mThumbRects[name].mRight = x + (MULTI_THUMB_WIDTH/2);
}
void LLMultiSlider::setValue(const LLSD& value)
{
// only do if it's a map
if(value.isMap()) {
// add each value... the first in the map becomes the current
LLSD::map_const_iterator mIt = value.beginMap();
mCurSlider = mIt->first;
for(; mIt != value.endMap(); mIt++) {
setSliderValue(mIt->first, (F32)mIt->second.asReal(), TRUE);
}
}
}
F32 LLMultiSlider::getSliderValue(const LLString& name) const
{
return (F32)mValue[name].asReal();
}
void LLMultiSlider::setCurSlider(const LLString& name)
{
if(mValue.has(name)) {
mCurSlider = name;
}
}
const LLString& LLMultiSlider::addSlider()
{
return addSlider(mInitialValue);
}
const LLString& LLMultiSlider::addSlider(F32 val)
{
std::stringstream newName;
F32 initVal = val;
if(mValue.size() >= mMaxNumSliders) {
return LLString::null;
}
// create a new name
newName << "sldr" << mNameCounter;
mNameCounter++;
bool foundOne = findUnusedValue(initVal);
if(!foundOne) {
return LLString::null;
}
// add a new thumb rect
mThumbRects[newName.str()] = LLRect( 0, getRect().getHeight(), MULTI_THUMB_WIDTH, 0 );
// add the value and set the current slider to this one
mValue.insert(newName.str(), initVal);
mCurSlider = newName.str();
// move the slider
setSliderValue(mCurSlider, initVal, TRUE);
return mCurSlider;
}
bool LLMultiSlider::findUnusedValue(F32& initVal)
{
bool firstTry = true;
// find the first open slot starting with
// the initial value
while(true) {
bool hit = false;
// look at the current spot
// and see if anything is there
LLSD::map_iterator mIt = mValue.beginMap();
for(;mIt != mValue.endMap(); mIt++) {
F32 testVal = (F32)mIt->second.asReal() - initVal;
if(testVal > -FLOAT_THRESHOLD && testVal < FLOAT_THRESHOLD) {
hit = true;
break;
}
}
// if we found one
if(!hit) {
break;
}
// increment and wrap if need be
initVal += mIncrement;
if(initVal > mMaxValue) {
initVal = mMinValue;
}
// stop if it's filled
if(initVal == mInitialValue && !firstTry) {
llwarns << "Whoa! Too many multi slider elements to add one to" << llendl;
return false;
}
firstTry = false;
continue;
}
return true;
}
void LLMultiSlider::deleteSlider(const LLString& name)
{
// can't delete last slider
if(mValue.size() <= 0) {
return;
}
// get rid of value from mValue and its thumb rect
mValue.erase(name);
mThumbRects.erase(name);
// set to the last created
if(mValue.size() > 0) {
std::map<LLString, LLRect>::iterator mIt = mThumbRects.end();
mIt--;
mCurSlider = mIt->first;
}
}
void LLMultiSlider::clear()
{
while(mThumbRects.size() > 0) {
deleteCurSlider();
}
LLUICtrl::clear();
}
BOOL LLMultiSlider::handleHover(S32 x, S32 y, MASK mask)
{
if( gFocusMgr.getMouseCapture() == this )
{
S32 left_edge = MULTI_THUMB_WIDTH/2;
S32 right_edge = getRect().getWidth() - (MULTI_THUMB_WIDTH/2);
x += mMouseOffset;
x = llclamp( x, left_edge, right_edge );
F32 t = F32(x - left_edge) / (right_edge - left_edge);
setCurSliderValue(t * (mMaxValue - mMinValue) + mMinValue );
onCommit();
getWindow()->setCursor(UI_CURSOR_ARROW);
lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
}
else
{
getWindow()->setCursor(UI_CURSOR_ARROW);
lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;
}
return TRUE;
}
BOOL LLMultiSlider::handleMouseUp(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
if( gFocusMgr.getMouseCapture() == this )
{
gFocusMgr.setMouseCapture( NULL );
if( mMouseUpCallback )
{
mMouseUpCallback( this, mCallbackUserData );
}
handled = TRUE;
make_ui_sound("UISndClickRelease");
}
else
{
handled = TRUE;
}
return handled;
}
BOOL LLMultiSlider::handleMouseDown(S32 x, S32 y, MASK mask)
{
// only do sticky-focus on non-chrome widgets
if (!getIsChrome())
{
setFocus(TRUE);
}
if( mMouseDownCallback )
{
mMouseDownCallback( this, mCallbackUserData );
}
if (MASK_CONTROL & mask) // if CTRL is modifying
{
setCurSliderValue(mInitialValue);
onCommit();
}
else
{
// scroll through thumbs to see if we have a new one selected and select that one
std::map<LLString, LLRect>::iterator mIt = mThumbRects.begin();
for(; mIt != mThumbRects.end(); mIt++) {
// check if inside. If so, set current slider and continue
if(mIt->second.pointInRect(x,y)) {
mCurSlider = mIt->first;
break;
}
}
// Find the offset of the actual mouse location from the center of the thumb.
if (mThumbRects[mCurSlider].pointInRect(x,y))
{
mMouseOffset = (mThumbRects[mCurSlider].mLeft + MULTI_THUMB_WIDTH/2) - x;
}
else
{
mMouseOffset = 0;
}
// Start dragging the thumb
// No handler needed for focus lost since this class has no state that depends on it.
gFocusMgr.setMouseCapture( this );
mDragStartThumbRect = mThumbRects[mCurSlider];
}
make_ui_sound("UISndClick");
return TRUE;
}
BOOL LLMultiSlider::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;
if( getVisible() && getEnabled() && !called_from_parent )
{
switch(key)
{
case KEY_UP:
case KEY_DOWN:
// eat up and down keys to be consistent
handled = TRUE;
break;
case KEY_LEFT:
setCurSliderValue(getCurSliderValue() - getIncrement());
onCommit();
handled = TRUE;
break;
case KEY_RIGHT:
setCurSliderValue(getCurSliderValue() + getIncrement());
onCommit();
handled = TRUE;
break;
default:
break;
}
}
return handled;
}
void LLMultiSlider::draw()
{
LLColor4 curThumbColor;
std::map<LLString, LLRect>::iterator mIt;
std::map<LLString, LLRect>::iterator curSldrIt;
if( getVisible() )
{
// Draw background and thumb.
// drawing solids requires texturing be disabled
LLGLSNoTexture no_texture;
LLRect rect(mDragStartThumbRect);
F32 opacity = getEnabled() ? 1.f : 0.3f;
// Track
LLUUID thumb_image_id;
thumb_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
LLPointer<LLImageGL> thumb_imagep(LLUI::sImageProvider->getUIImageByID(thumb_image_id)->getImage());
S32 height_offset = (getRect().getHeight() - MULTI_TRACK_HEIGHT) / 2;
LLRect track_rect(0, getRect().getHeight() - height_offset, getRect().getWidth(), height_offset );
if(mDrawTrack)
{
track_rect.stretch(-1);
gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 16, 16, track_rect.getWidth(), track_rect.getHeight(),
thumb_imagep, mTrackColor % opacity);
}
// if we're supposed to use a drawn triangle
// simple gl call for the triangle
if(mUseTriangle) {
for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) {
gl_triangle_2d(
mIt->second.mLeft - EXTRA_TRIANGLE_WIDTH,
mIt->second.mTop + EXTRA_TRIANGLE_HEIGHT,
mIt->second.mRight + EXTRA_TRIANGLE_WIDTH,
mIt->second.mTop + EXTRA_TRIANGLE_HEIGHT,
mIt->second.mLeft + mIt->second.getWidth() / 2,
mIt->second.mBottom - EXTRA_TRIANGLE_HEIGHT,
mTriangleColor, TRUE);
}
}
else if (!thumb_imagep)
{
// draw all the thumbs
curSldrIt = mThumbRects.end();
for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) {
// choose the color
curThumbColor = mThumbCenterColor;
if(mIt->first == mCurSlider) {
curSldrIt = mIt;
continue;
//curThumbColor = mThumbCenterSelectedColor;
}
// the draw command
gl_rect_2d(mIt->second, curThumbColor, TRUE);
}
// now draw the current slider
if(curSldrIt != mThumbRects.end()) {
gl_rect_2d(curSldrIt->second, mThumbCenterSelectedColor, TRUE);
}
// and draw the drag start
if (gFocusMgr.getMouseCapture() == this)
{
gl_rect_2d(mDragStartThumbRect, mThumbCenterColor % opacity, FALSE);
}
}
else if( gFocusMgr.getMouseCapture() == this )
{
// draw drag start
gl_draw_scaled_image_with_border(mDragStartThumbRect.mLeft,
mDragStartThumbRect.mBottom, 16, 16,
mDragStartThumbRect.getWidth(),
mDragStartThumbRect.getHeight(),
thumb_imagep, mThumbCenterColor % 0.3f, TRUE);
// draw the highlight
if (hasFocus())
{
F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
LLRect highlight_rect = mThumbRects[mCurSlider];
highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
gl_draw_scaled_image_with_border(highlight_rect.mLeft,
highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(),
highlight_rect.getHeight(),
thumb_imagep, gFocusMgr.getFocusColor());
}
// draw the thumbs
curSldrIt = mThumbRects.end();
for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) {
// choose the color
curThumbColor = mThumbCenterColor;
if(mIt->first == mCurSlider) {
// don't draw now, draw last
curSldrIt = mIt;
continue;
}
// the draw command
gl_draw_scaled_image_with_border(
mIt->second.mLeft,
mIt->second.mBottom, 16, 16,
mIt->second.getWidth(),
mIt->second.getHeight(), thumb_imagep,
curThumbColor, TRUE);
}
// draw cur slider last
if(curSldrIt != mThumbRects.end()) {
gl_draw_scaled_image_with_border(
curSldrIt->second.mLeft,
curSldrIt->second.mBottom, 16, 16,
curSldrIt->second.getWidth(),
curSldrIt->second.getHeight(), thumb_imagep,
mThumbCenterSelectedColor, TRUE);
}
}
else
{
// draw highlight
if (hasFocus())
{
F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
LLRect highlight_rect = mThumbRects[mCurSlider];
highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(),
thumb_imagep, gFocusMgr.getFocusColor());
}
// draw thumbs
curSldrIt = mThumbRects.end();
for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) {
// choose the color
curThumbColor = mThumbCenterColor;
if(mIt->first == mCurSlider) {
curSldrIt = mIt;
continue;
//curThumbColor = mThumbCenterSelectedColor;
}
// the draw command
gl_draw_scaled_image_with_border(
mIt->second.mLeft,
mIt->second.mBottom, 16, 16,
mIt->second.getWidth(),
mIt->second.getHeight(), thumb_imagep,
curThumbColor % opacity, TRUE);
}
if(curSldrIt != mThumbRects.end()) {
gl_draw_scaled_image_with_border(
curSldrIt->second.mLeft,
curSldrIt->second.mBottom, 16, 16,
curSldrIt->second.getWidth(),
curSldrIt->second.getHeight(), thumb_imagep,
mThumbCenterSelectedColor % opacity, TRUE);
}
}
LLUICtrl::draw();
}
}
// virtual
LLXMLNodePtr LLMultiSlider::getXML(bool save_children) const
{
LLXMLNodePtr node = LLUICtrl::getXML();
node->createChild("initial_val", TRUE)->setFloatValue(getInitialValue());
node->createChild("min_val", TRUE)->setFloatValue(getMinValue());
node->createChild("max_val", TRUE)->setFloatValue(getMaxValue());
node->createChild("increment", TRUE)->setFloatValue(getIncrement());
return node;
}
//static
LLView* LLMultiSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
LLString name("multi_slider_bar");
node->getAttributeString("name", name);
LLRect rect;
createRect(node, rect, parent, LLRect());
F32 initial_value = 0.f;
node->getAttributeF32("initial_val", initial_value);
F32 min_value = 0.f;
node->getAttributeF32("min_val", min_value);
F32 max_value = 1.f;
node->getAttributeF32("max_val", max_value);
F32 increment = 0.1f;
node->getAttributeF32("increment", increment);
S32 max_sliders = 1;
node->getAttributeS32("max_sliders", max_sliders);
BOOL allow_overlap = FALSE;
node->getAttributeBOOL("allow_overlap", allow_overlap);
BOOL draw_track = TRUE;
node->getAttributeBOOL("draw_track", draw_track);
BOOL use_triangle = FALSE;
node->getAttributeBOOL("use_triangle", use_triangle);
LLMultiSlider* multiSlider = new LLMultiSlider(name,
rect,
NULL,
NULL,
initial_value,
min_value,
max_value,
increment,
max_sliders,
allow_overlap,
draw_track,
use_triangle);
multiSlider->initFromXML(node, parent);
return multiSlider;
}

129
indra/llui/llmultislider.h Normal file
View File

@ -0,0 +1,129 @@
/**
* @file llmultislider.h
* @brief A simple multislider
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2007, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_MULTI_SLIDER_H
#define LL_MULTI_SLIDER_H
#include "lluictrl.h"
#include "v4color.h"
class LLUICtrlFactory;
class LLMultiSlider : public LLUICtrl
{
public:
LLMultiSlider(
const LLString& name,
const LLRect& rect,
void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
void* callback_userdata,
F32 initial_value,
F32 min_value,
F32 max_value,
F32 increment,
S32 max_sliders,
BOOL allow_overlap,
BOOL draw_track,
BOOL use_triangle,
const LLString& control_name = LLString::null );
virtual EWidgetType getWidgetType() const;
virtual LLString getWidgetTag() const;
virtual LLXMLNodePtr getXML(bool save_children = true) const;
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
void setSliderValue(const LLString& name, F32 value, BOOL from_event = FALSE);
F32 getSliderValue(const LLString& name) const;
const LLString& getCurSlider() const { return mCurSlider; }
F32 getCurSliderValue() const { return getSliderValue(mCurSlider); }
void setCurSlider(const LLString& name);
void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); }
virtual void setValue(const LLSD& value);
virtual LLSD getValue() const { return mValue; }
virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); }
virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); }
F32 getInitialValue() const { return mInitialValue; }
F32 getMinValue() const { return mMinValue; }
F32 getMaxValue() const { return mMaxValue; }
F32 getIncrement() const { return mIncrement; }
void setMinValue(F32 min_value) { mMinValue = min_value; }
void setMaxValue(F32 max_value) { mMaxValue = max_value; }
void setIncrement(F32 increment) { mIncrement = increment; }
void setMouseDownCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseDownCallback = cb; }
void setMouseUpCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseUpCallback = cb; }
bool findUnusedValue(F32& initVal);
const LLString& addSlider();
const LLString& addSlider(F32 val);
void deleteSlider(const LLString& name);
void deleteCurSlider() { deleteSlider(mCurSlider); }
void clear();
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
virtual void draw();
protected:
LLSD mValue;
F32 mInitialValue;
F32 mMinValue;
F32 mMaxValue;
F32 mIncrement;
LLString mCurSlider;
static S32 mNameCounter;
S32 mMaxNumSliders;
BOOL mAllowOverlap;
BOOL mDrawTrack;
BOOL mUseTriangle; /// hacked in toggle to use a triangle
S32 mMouseOffset;
LLRect mDragStartThumbRect;
std::map<LLString, LLRect> mThumbRects;
LLColor4 mTrackColor;
LLColor4 mThumbOutlineColor;
LLColor4 mThumbCenterColor;
LLColor4 mThumbCenterSelectedColor;
LLColor4 mDisabledThumbColor;
LLColor4 mTriangleColor;
void (*mMouseDownCallback)(LLUICtrl* ctrl, void* userdata);
void (*mMouseUpCallback)(LLUICtrl* ctrl, void* userdata);
};
#endif // LL_LLSLIDER_H

View File

@ -0,0 +1,634 @@
/**
* @file llmultisliderctrl.cpp
* @brief LLMultiSliderCtrl base class
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2007, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmultisliderctrl.h"
#include "audioengine.h"
#include "sound_ids.h"
#include "llmath.h"
#include "llfontgl.h"
#include "llgl.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "llmultislider.h"
#include "llstring.h"
#include "lltextbox.h"
#include "llui.h"
#include "lluiconstants.h"
#include "llcontrol.h"
#include "llfocusmgr.h"
#include "llresmgr.h"
const U32 MAX_STRING_LENGTH = 10;
LLMultiSliderCtrl::LLMultiSliderCtrl(const LLString& name, const LLRect& rect,
const LLString& label,
const LLFontGL* font,
S32 label_width,
S32 text_left,
BOOL show_text,
BOOL can_edit_text,
void (*commit_callback)(LLUICtrl*, void*),
void* callback_user_data,
F32 initial_value, F32 min_value, F32 max_value, F32 increment,
S32 max_sliders, BOOL allow_overlap,
BOOL draw_track,
BOOL use_triangle,
const LLString& control_which)
: LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data ),
mFont(font),
mShowText( show_text ),
mCanEditText( can_edit_text ),
mPrecision( 3 ),
mLabelBox( NULL ),
mLabelWidth( label_width ),
mEditor( NULL ),
mTextBox( NULL ),
mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
mSliderMouseUpCallback( NULL ),
mSliderMouseDownCallback( NULL )
{
S32 top = getRect().getHeight();
S32 bottom = 0;
S32 left = 0;
// Label
if( !label.empty() )
{
if (label_width == 0)
{
label_width = font->getWidth(label);
}
LLRect label_rect( left, top, label_width, bottom );
mLabelBox = new LLTextBox( "MultiSliderCtrl Label", label_rect, label.c_str(), font );
addChild(mLabelBox);
}
S32 slider_right = getRect().getWidth();
if( show_text )
{
slider_right = text_left - MULTI_SLIDERCTRL_SPACING;
}
S32 slider_left = label_width ? label_width + MULTI_SLIDERCTRL_SPACING : 0;
LLRect slider_rect( slider_left, top, slider_right, bottom );
mMultiSlider = new LLMultiSlider(
"multi_slider",
slider_rect,
LLMultiSliderCtrl::onSliderCommit, this,
initial_value, min_value, max_value, increment,
max_sliders, allow_overlap, draw_track,
use_triangle,
control_which );
addChild( mMultiSlider );
mCurValue = mMultiSlider->getCurSliderValue();
if( show_text )
{
LLRect text_rect( text_left, top, getRect().getWidth(), bottom );
if( can_edit_text )
{
mEditor = new LLLineEditor( "MultiSliderCtrl Editor", text_rect,
"", font,
MAX_STRING_LENGTH,
&LLMultiSliderCtrl::onEditorCommit, NULL, NULL, this,
&LLLineEditor::prevalidateFloat );
mEditor->setFollowsLeft();
mEditor->setFollowsBottom();
mEditor->setFocusReceivedCallback( &LLMultiSliderCtrl::onEditorGainFocus );
mEditor->setIgnoreTab(TRUE);
// don't do this, as selecting the entire text is single clicking in some cases
// and double clicking in others
//mEditor->setSelectAllonFocusReceived(TRUE);
addChild(mEditor);
}
else
{
mTextBox = new LLTextBox( "MultiSliderCtrl Text", text_rect, "", font);
mTextBox->setFollowsLeft();
mTextBox->setFollowsBottom();
addChild(mTextBox);
}
}
updateText();
}
LLMultiSliderCtrl::~LLMultiSliderCtrl()
{
// Children all cleaned up by default view destructor.
}
// static
void LLMultiSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
{
LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
llassert( caller == self->mEditor );
self->onFocusReceived();
}
void LLMultiSliderCtrl::setValue(const LLSD& value)
{
mMultiSlider->setValue(value);
mCurValue = mMultiSlider->getCurSliderValue();
updateText();
}
void LLMultiSliderCtrl::setSliderValue(const LLString& name, F32 v, BOOL from_event)
{
mMultiSlider->setSliderValue(name, v, from_event );
mCurValue = mMultiSlider->getCurSliderValue();
updateText();
}
void LLMultiSliderCtrl::setCurSlider(const LLString& name)
{
mMultiSlider->setCurSlider(name);
mCurValue = mMultiSlider->getCurSliderValue();
}
BOOL LLMultiSliderCtrl::setLabelArg( const LLString& key, const LLString& text )
{
BOOL res = FALSE;
if (mLabelBox)
{
res = mLabelBox->setTextArg(key, text);
if (res && mLabelWidth == 0)
{
S32 label_width = mFont->getWidth(mLabelBox->getText());
LLRect rect = mLabelBox->getRect();
S32 prev_right = rect.mRight;
rect.mRight = rect.mLeft + label_width;
mLabelBox->setRect(rect);
S32 delta = rect.mRight - prev_right;
rect = mMultiSlider->getRect();
S32 left = rect.mLeft + delta;
left = llclamp(left, 0, rect.mRight-MULTI_SLIDERCTRL_SPACING);
rect.mLeft = left;
mMultiSlider->setRect(rect);
}
}
return res;
}
const LLString& LLMultiSliderCtrl::addSlider()
{
const LLString& name = mMultiSlider->addSlider();
// if it returns null, pass it on
if(name == LLString::null) {
return LLString::null;
}
// otherwise, update stuff
mCurValue = mMultiSlider->getCurSliderValue();
updateText();
return name;
}
const LLString& LLMultiSliderCtrl::addSlider(F32 val)
{
const LLString& name = mMultiSlider->addSlider(val);
// if it returns null, pass it on
if(name == LLString::null) {
return LLString::null;
}
// otherwise, update stuff
mCurValue = mMultiSlider->getCurSliderValue();
updateText();
return name;
}
void LLMultiSliderCtrl::deleteSlider(const LLString& name)
{
mMultiSlider->deleteSlider(name);
mCurValue = mMultiSlider->getCurSliderValue();
updateText();
}
void LLMultiSliderCtrl::clear()
{
setCurSliderValue(0.0f);
if( mEditor )
{
mEditor->setText(LLString(""));
}
if( mTextBox )
{
mTextBox->setText(LLString(""));
}
// get rid of sliders
mMultiSlider->clear();
}
BOOL LLMultiSliderCtrl::isMouseHeldDown()
{
return gFocusMgr.getMouseCapture() == mMultiSlider;
}
void LLMultiSliderCtrl::updateText()
{
if( mEditor || mTextBox )
{
LLLocale locale(LLLocale::USER_LOCALE);
// Don't display very small negative values as -0.000
F32 displayed_value = (F32)(floor(getCurSliderValue() * pow(10.0, (F64)mPrecision) + 0.5) / pow(10.0, (F64)mPrecision));
LLString format = llformat("%%.%df", mPrecision);
LLString text = llformat(format.c_str(), displayed_value);
if( mEditor )
{
mEditor->setText( text );
}
else
{
mTextBox->setText( text );
}
}
}
// static
void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
{
LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
llassert( caller == self->mEditor );
BOOL success = FALSE;
F32 val = self->mCurValue;
F32 saved_val = self->mCurValue;
LLString text = self->mEditor->getText();
if( LLLineEditor::postvalidateFloat( text ) )
{
LLLocale locale(LLLocale::USER_LOCALE);
val = (F32) atof( text.c_str() );
if( self->mMultiSlider->getMinValue() <= val && val <= self->mMultiSlider->getMaxValue() )
{
if( self->mValidateCallback )
{
self->setCurSliderValue( val ); // set the value temporarily so that the callback can retrieve it.
if( self->mValidateCallback( self, self->mCallbackUserData ) )
{
success = TRUE;
}
}
else
{
self->setCurSliderValue( val );
success = TRUE;
}
}
}
if( success )
{
self->onCommit();
}
else
{
if( self->getCurSliderValue() != saved_val )
{
self->setCurSliderValue( saved_val );
}
self->reportInvalidData();
}
self->updateText();
}
// static
void LLMultiSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
{
LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
//llassert( caller == self->mSlider );
BOOL success = FALSE;
F32 saved_val = self->mCurValue;
F32 new_val = self->mMultiSlider->getCurSliderValue();
if( self->mValidateCallback )
{
self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it.
if( self->mValidateCallback( self, self->mCallbackUserData ) )
{
success = TRUE;
}
}
else
{
self->mCurValue = new_val;
success = TRUE;
}
if( success )
{
self->onCommit();
}
else
{
if( self->mCurValue != saved_val )
{
self->setCurSliderValue( saved_val );
}
self->reportInvalidData();
}
self->updateText();
}
void LLMultiSliderCtrl::setEnabled(BOOL b)
{
LLUICtrl::setEnabled( b );
if( mLabelBox )
{
mLabelBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
}
mMultiSlider->setEnabled( b );
if( mEditor )
{
mEditor->setEnabled( b );
}
if( mTextBox )
{
mTextBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
}
}
void LLMultiSliderCtrl::setTentative(BOOL b)
{
if( mEditor )
{
mEditor->setTentative(b);
}
LLUICtrl::setTentative(b);
}
void LLMultiSliderCtrl::onCommit()
{
setTentative(FALSE);
if( mEditor )
{
mEditor->setTentative(FALSE);
}
LLUICtrl::onCommit();
}
void LLMultiSliderCtrl::setPrecision(S32 precision)
{
if (precision < 0 || precision > 10)
{
llerrs << "LLMultiSliderCtrl::setPrecision - precision out of range" << llendl;
return;
}
mPrecision = precision;
updateText();
}
void LLMultiSliderCtrl::setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) )
{
mSliderMouseDownCallback = slider_mousedown_callback;
mMultiSlider->setMouseDownCallback( LLMultiSliderCtrl::onSliderMouseDown );
}
// static
void LLMultiSliderCtrl::onSliderMouseDown(LLUICtrl* caller, void* userdata)
{
LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
if( self->mSliderMouseDownCallback )
{
self->mSliderMouseDownCallback( self, self->mCallbackUserData );
}
}
void LLMultiSliderCtrl::setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) )
{
mSliderMouseUpCallback = slider_mouseup_callback;
mMultiSlider->setMouseUpCallback( LLMultiSliderCtrl::onSliderMouseUp );
}
// static
void LLMultiSliderCtrl::onSliderMouseUp(LLUICtrl* caller, void* userdata)
{
LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
if( self->mSliderMouseUpCallback )
{
self->mSliderMouseUpCallback( self, self->mCallbackUserData );
}
}
void LLMultiSliderCtrl::onTabInto()
{
if( mEditor )
{
mEditor->onTabInto();
}
}
void LLMultiSliderCtrl::reportInvalidData()
{
make_ui_sound("UISndBadKeystroke");
}
//virtual
LLString LLMultiSliderCtrl::getControlName() const
{
return mMultiSlider->getControlName();
}
// virtual
void LLMultiSliderCtrl::setControlName(const LLString& control_name, LLView* context)
{
mMultiSlider->setControlName(control_name, context);
}
// virtual
LLXMLNodePtr LLMultiSliderCtrl::getXML(bool save_children) const
{
LLXMLNodePtr node = LLUICtrl::getXML();
node->createChild("show_text", TRUE)->setBoolValue(mShowText);
node->createChild("can_edit_text", TRUE)->setBoolValue(mCanEditText);
node->createChild("decimal_digits", TRUE)->setIntValue(mPrecision);
if (mLabelBox)
{
node->createChild("label", TRUE)->setStringValue(mLabelBox->getText());
}
// TomY TODO: Do we really want to export the transient state of the slider?
node->createChild("value", TRUE)->setFloatValue(mCurValue);
if (mMultiSlider)
{
node->createChild("initial_val", TRUE)->setFloatValue(mMultiSlider->getInitialValue());
node->createChild("min_val", TRUE)->setFloatValue(mMultiSlider->getMinValue());
node->createChild("max_val", TRUE)->setFloatValue(mMultiSlider->getMaxValue());
node->createChild("increment", TRUE)->setFloatValue(mMultiSlider->getIncrement());
}
addColorXML(node, mTextEnabledColor, "text_enabled_color", "LabelTextColor");
addColorXML(node, mTextDisabledColor, "text_disabled_color", "LabelDisabledColor");
return node;
}
LLView* LLMultiSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
LLString name("multi_slider");
node->getAttributeString("name", name);
LLString label;
node->getAttributeString("label", label);
LLRect rect;
createRect(node, rect, parent, LLRect());
LLFontGL* font = LLView::selectFont(node);
// HACK: Font might not be specified.
if (!font)
{
font = LLFontGL::sSansSerifSmall;
}
S32 label_width = 0;
node->getAttributeS32("label_width", label_width);
BOOL show_text = TRUE;
node->getAttributeBOOL("show_text", show_text);
BOOL can_edit_text = FALSE;
node->getAttributeBOOL("can_edit_text", can_edit_text);
BOOL allow_overlap = FALSE;
node->getAttributeBOOL("allow_overlap", allow_overlap);
BOOL draw_track = TRUE;
node->getAttributeBOOL("draw_track", draw_track);
BOOL use_triangle = FALSE;
node->getAttributeBOOL("use_triangle", use_triangle);
F32 initial_value = 0.f;
node->getAttributeF32("initial_val", initial_value);
F32 min_value = 0.f;
node->getAttributeF32("min_val", min_value);
F32 max_value = 1.f;
node->getAttributeF32("max_val", max_value);
F32 increment = 0.1f;
node->getAttributeF32("increment", increment);
U32 precision = 3;
node->getAttributeU32("decimal_digits", precision);
S32 max_sliders = 1;
node->getAttributeS32("max_sliders", max_sliders);
S32 text_left = 0;
if (show_text)
{
// calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
if ( max_value )
text_left = font->getWidth("0") * ( static_cast < S32 > ( log10 ( max_value ) ) + precision + 1 );
if ( increment < 1.0f )
text_left += font->getWidth("."); // (mostly) take account of decimal point in value
if ( min_value < 0.0f || max_value < 0.0f )
text_left += font->getWidth("-"); // (mostly) take account of minus sign
// padding to make things look nicer
text_left += 8;
}
LLUICtrlCallback callback = NULL;
if (label.empty())
{
label.assign(node->getTextContents());
}
LLMultiSliderCtrl* slider = new LLMultiSliderCtrl(name,
rect,
label,
font,
label_width,
rect.getWidth() - text_left,
show_text,
can_edit_text,
callback,
NULL,
initial_value,
min_value,
max_value,
increment,
max_sliders,
allow_overlap,
draw_track,
use_triangle);
slider->setPrecision(precision);
slider->initFromXML(node, parent);
slider->updateText();
return slider;
}

View File

@ -0,0 +1,160 @@
/**
* @file llmultisliderctrl.h
* @brief LLMultiSliderCtrl base class
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2007, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_MULTI_SLIDERCTRL_H
#define LL_MULTI_SLIDERCTRL_H
#include "lluictrl.h"
#include "v4color.h"
#include "llmultislider.h"
#include "lltextbox.h"
#include "llrect.h"
//
// Constants
//
const S32 MULTI_SLIDERCTRL_SPACING = 4; // space between label, slider, and text
const S32 MULTI_SLIDERCTRL_HEIGHT = 16;
//
// Classes
//
class LLFontGL;
class LLLineEditor;
class LLSlider;
class LLMultiSliderCtrl : public LLUICtrl
{
public:
LLMultiSliderCtrl(const LLString& name,
const LLRect& rect,
const LLString& label,
const LLFontGL* font,
S32 slider_left,
S32 text_left,
BOOL show_text,
BOOL can_edit_text,
void (*commit_callback)(LLUICtrl*, void*),
void* callback_userdata,
F32 initial_value, F32 min_value, F32 max_value, F32 increment,
S32 max_sliders, BOOL allow_overlap, BOOL draw_track,
BOOL use_triangle,
const LLString& control_which = LLString::null );
virtual ~LLMultiSliderCtrl();
virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_MULTI_SLIDER; }
virtual LLString getWidgetTag() const { return LL_MULTI_SLIDER_CTRL_TAG; }
virtual LLXMLNodePtr getXML(bool save_children = true) const;
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
F32 getSliderValue(const LLString& name) const;
void setSliderValue(const LLString& name, F32 v, BOOL from_event = FALSE);
virtual void setValue(const LLSD& value );
virtual LLSD getValue() const { return mMultiSlider->getValue(); }
virtual BOOL setLabelArg( const LLString& key, const LLString& text );
const LLString& getCurSlider() const { return mMultiSlider->getCurSlider(); }
F32 getCurSliderValue() const { return mCurValue; }
void setCurSlider(const LLString& name);
void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mMultiSlider->getCurSlider(), val, from_event); }
virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); }
virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); }
BOOL isMouseHeldDown();
virtual void setEnabled( BOOL b );
virtual void clear();
virtual void setPrecision(S32 precision);
void setMinValue(F32 min_value) {mMultiSlider->setMinValue(min_value);}
void setMaxValue(F32 max_value) {mMultiSlider->setMaxValue(max_value);}
void setIncrement(F32 increment) {mMultiSlider->setIncrement(increment);}
/// for adding and deleting sliders
const LLString& addSlider();
const LLString& addSlider(F32 val);
void deleteSlider(const LLString& name);
void deleteCurSlider() { deleteSlider(mMultiSlider->getCurSlider()); }
F32 getMinValue() { return mMultiSlider->getMinValue(); }
F32 getMaxValue() { return mMultiSlider->getMaxValue(); }
void setLabel(const LLString& label) { if (mLabelBox) mLabelBox->setText(label); }
void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; }
void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; }
void setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) );
void setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) );
virtual void onTabInto();
virtual void setTentative(BOOL b); // marks value as tentative
virtual void onCommit(); // mark not tentative, then commit
virtual void setControlName(const LLString& control_name, LLView* context);
virtual LLString getControlName() const;
static void onSliderCommit(LLUICtrl* caller, void* userdata);
static void onSliderMouseDown(LLUICtrl* caller,void* userdata);
static void onSliderMouseUp(LLUICtrl* caller,void* userdata);
static void onEditorCommit(LLUICtrl* caller, void* userdata);
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
private:
void updateText();
void reportInvalidData();
private:
const LLFontGL* mFont;
BOOL mShowText;
BOOL mCanEditText;
S32 mPrecision;
LLTextBox* mLabelBox;
S32 mLabelWidth;
F32 mCurValue;
LLMultiSlider* mMultiSlider;
LLLineEditor* mEditor;
LLTextBox* mTextBox;
LLColor4 mTextEnabledColor;
LLColor4 mTextDisabledColor;
void (*mSliderMouseUpCallback)( LLUICtrl* ctrl, void* userdata );
void (*mSliderMouseDownCallback)( LLUICtrl* ctrl, void* userdata );
};
#endif // LL_MULTI_SLIDERCTRL_H

View File

@ -188,7 +188,7 @@ public:
BOOL childSetLabelArg(const LLString& id, const LLString& key, const LLStringExplicit& text);
BOOL childSetToolTipArg(const LLString& id, const LLString& key, const LLStringExplicit& text);
// LLSlider / LLSpinCtrl
// LLSlider / LLMultiSlider / LLSpinCtrl
void childSetMinValue(const LLString& id, LLSD min_value);
void childSetMaxValue(const LLString& id, LLSD max_value);

View File

@ -46,6 +46,7 @@
#include "llwindow.h"
#include "llglheaders.h"
#include "llcontrol.h"
#include "llglimmediate.h"
LLScrollbar::LLScrollbar(
const LLString& name, LLRect rect,
@ -538,10 +539,10 @@ void LLScrollbar::draw()
rounded_rect_imagep, mThumbColor );
if (mCurGlowStrength > 0.01f)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(),
rounded_rect_imagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}

View File

@ -33,6 +33,7 @@
#include "linden_common.h"
#include "llgl.h"
#include "llglimmediate.h"
#include "llscrollcontainer.h"
#include "llscrollbar.h"
@ -459,7 +460,7 @@ void LLScrollableContainerView::draw()
if( mIsOpaque )
{
LLGLSNoTexture no_texture;
glColor4fv( mBackgroundColor.mV );
gGL.color4fv( mBackgroundColor.mV );
gl_rect_2d( mInnerRect );
}

View File

@ -43,6 +43,7 @@
#include "llclipboard.h"
#include "llfocusmgr.h"
#include "llgl.h"
#include "llglimmediate.h"
#include "llglheaders.h"
#include "llresmgr.h"
#include "llscrollbar.h"
@ -280,7 +281,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
if (mHighlightCount > 0)
{
mRoundedRectImage->bind();
glColor4fv(highlight_color.mV);
gGL.color4fv(highlight_color.mV);
S32 left = 0;
switch(mFontAlignment)
{
@ -392,7 +393,7 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const
bg_rect.stretch(LIST_BORDER_PAD, 0);
{
LLGLSNoTexture no_texture;
glColor4fv(bg_color.mV);
gGL.color4fv(bg_color.mV);
gl_rect_2d( bg_rect );
}
@ -1711,7 +1712,7 @@ void LLScrollListCtrl::draw()
if (mBackgroundVisible)
{
LLGLSNoTexture no_texture;
glColor4fv( getEnabled() ? mBgWriteableColor.mV : mBgReadOnlyColor.mV );
gGL.color4fv( getEnabled() ? mBgWriteableColor.mV : mBgReadOnlyColor.mV );
gl_rect_2d(background);
}

View File

@ -70,8 +70,8 @@ public:
F32 getMinValue() const { return mMinValue; }
F32 getMaxValue() const { return mMaxValue; }
F32 getIncrement() const { return mIncrement; }
void setMinValue(F32 min_value) {mMinValue = min_value;}
void setMaxValue(F32 max_value) {mMaxValue = max_value;}
void setMinValue(F32 min_value) {mMinValue = min_value; updateThumbRect(); }
void setMaxValue(F32 max_value) {mMaxValue = max_value; updateThumbRect(); }
void setIncrement(F32 increment) {mIncrement = increment;}
void setMouseDownCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseDownCallback = cb; }
void setMouseUpCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseUpCallback = cb; }

View File

@ -83,9 +83,9 @@ public:
virtual void setEnabled( BOOL b );
virtual void clear();
virtual void setPrecision(S32 precision);
void setMinValue(F32 min_value) { mSlider->setMinValue(min_value); }
void setMaxValue(F32 max_value) { mSlider->setMaxValue(max_value); }
void setIncrement(F32 increment) { mSlider->setIncrement(increment); }
void setMinValue(F32 min_value) { mSlider->setMinValue(min_value); updateText(); }
void setMaxValue(F32 max_value) { mSlider->setMaxValue(max_value); updateText(); }
void setIncrement(F32 increment) { mSlider->setIncrement(increment);}
F32 getMinValue() { return mSlider->getMinValue(); }
F32 getMaxValue() { return mSlider->getMaxValue(); }
@ -102,7 +102,12 @@ public:
virtual void setTentative(BOOL b); // marks value as tentative
virtual void onCommit(); // mark not tentative, then commit
virtual void setControlName(const LLString& control_name, LLView* context) { mSlider->setControlName(control_name, context); }
virtual void setControlName(const LLString& control_name, LLView* context)
{
LLView::setControlName(control_name, context);
mSlider->setControlName(control_name, context);
}
virtual LLString getControlName() const { return mSlider->getControlName(); }
static void onSliderCommit(LLUICtrl* caller, void* userdata);

View File

@ -86,6 +86,8 @@ public:
virtual void setMinValue(F32 min) { mMinValue = min; }
virtual void setMaxValue(F32 max) { mMaxValue = max; }
virtual void setIncrement(F32 inc) { mIncrement = inc; }
virtual F32 getMinValue() { return mMinValue ; }
virtual F32 getMaxValue() { return mMaxValue ; }
void setLabel(const LLStringExplicit& label);
void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; }

View File

@ -40,6 +40,7 @@
#include "llcriticaldamp.h"
#include "lluictrlfactory.h"
#include "lltabcontainervertical.h"
#include "llglimmediate.h"
const F32 SCROLL_STEP_TIME = 0.4f;
@ -287,15 +288,15 @@ void LLTabContainer::draw()
if( mIsVertical && has_scroll_arrows )
{
// Redraw the arrows so that they appears on top.
glPushMatrix();
glTranslatef((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
gGL.pushMatrix();
gGL.translatef((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
mPrevArrowBtn->draw();
glPopMatrix();
gGL.popMatrix();
glPushMatrix();
glTranslatef((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
gGL.pushMatrix();
gGL.translatef((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
mNextArrowBtn->draw();
glPopMatrix();
gGL.popMatrix();
}
}

View File

@ -37,6 +37,7 @@
#include "llfontgl.h"
#include "llgl.h"
#include "llglimmediate.h"
#include "llui.h"
#include "lluictrlfactory.h"
#include "llrect.h"
@ -424,7 +425,7 @@ void LLTextEditor::updateLineStartList(S32 startpos)
else
{
const llwchar* str = mWText.c_str() + start_idx;
S32 drawn = mGLFont->maxDrawableChars(str, (F32)mTextRect.getWidth() - line_width,
S32 drawn = mGLFont->maxDrawableChars(str, (F32)abs(mTextRect.getWidth()) - line_width,
end_idx - start_idx, mWordWrap, mAllowEmbeddedItems );
if( 0 == drawn && line_width == 0)
{
@ -2601,7 +2602,7 @@ void LLTextEditor::drawSelectionBackground()
LLGLSNoTexture no_texture;
const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor;
F32 alpha = hasFocus() ? 1.f : 0.5f;
glColor4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha );
gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha );
if( selection_left_y == selection_right_y )
{
@ -2729,7 +2730,7 @@ void LLTextEditor::drawCursor()
LLGLSNoTexture no_texture;
glColor4fv( mCursorColor.mV );
gGL.color4fv( mCursorColor.mV );
gl_rect_2d(llfloor(cursor_left), llfloor(cursor_top),
llfloor(cursor_right), llfloor(cursor_bottom));
@ -2750,7 +2751,6 @@ void LLTextEditor::drawCursor()
{
text_color = mFgColor;
}
LLGLSTexture texture;
mGLFont->render(text, mCursorPos, next_char_left, cursor_bottom + line_height,
LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], 1.f),
LLFontGL::LEFT, LLFontGL::TOP,

File diff suppressed because it is too large Load Diff

View File

@ -224,6 +224,8 @@ typedef enum e_widget_type
WIDGET_TYPE_SLIDER, // actually LLSliderCtrl
WIDGET_TYPE_SLIDER_BAR, // actually LLSlider
WIDGET_TYPE_VOLUME_SLIDER,//actually LLVolumeSliderCtrl
WIDGET_TYPE_MULTI_SLIDER, // actually LLMultiSliderCtrl
WIDGET_TYPE_MULTI_SLIDER_BAR, // actually LLMultiSlider
WIDGET_TYPE_SPINNER,
WIDGET_TYPE_TEXT_EDITOR,
WIDGET_TYPE_TEXTURE_PICKER,

View File

@ -59,6 +59,8 @@
#include "llscrolllistctrl.h"
#include "llslider.h"
#include "llsliderctrl.h"
#include "llmultislider.h"
#include "llmultisliderctrl.h"
#include "llspinctrl.h"
#include "lltabcontainer.h"
#include "lltabcontainervertical.h"
@ -92,6 +94,8 @@ const LLString LLUICtrlFactory::sUICtrlNames[WIDGET_TYPE_COUNT] =
LLString("slider"), //WIDGET_TYPE_SLIDER, actually LLSliderCtrl
LLString("slider_bar"), //WIDGET_TYPE_SLIDER_BAR, actually LLSlider
LLString("volume_slider"), //WIDGET_TYPE_VOLUME_SLIDER, actually LLSlider + "volume" param
LLString("multi_slider"), //WIDGET_TYPE_MULTI_SLIDER, actually LLMultiSliderCtrl
LLString("multi_slider_bar"), //WIDGET_TYPE_MULTI_SLIDER_BAR, actually LLMultiSlider
LLString("spinner"), //WIDGET_TYPE_SPINNER, actually LLSpinCtrl
LLString("text_editor"), //WIDGET_TYPE_TEXT_EDITOR
LLString("texture_picker"),//WIDGET_TYPE_TEXTURE_PICKER
@ -206,6 +210,8 @@ LLUICtrlFactory::LLUICtrlFactory()
LLUICtrlCreator<LLSliderCtrl>::registerCreator(LL_SLIDER_CTRL_TAG, this);
LLUICtrlCreator<LLSlider>::registerCreator(LL_SLIDER_TAG, this);
LLUICtrlCreator<LLSlider>::registerCreator(LL_VOLUME_SLIDER_CTRL_TAG, this);
LLUICtrlCreator<LLMultiSliderCtrl>::registerCreator(LL_MULTI_SLIDER_CTRL_TAG, this);
LLUICtrlCreator<LLMultiSlider>::registerCreator(LL_MULTI_SLIDER_TAG, this);
LLUICtrlCreator<LLSpinCtrl>::registerCreator(LL_SPIN_CTRL_TAG, this);
LLUICtrlCreator<LLTextBox>::registerCreator(LL_TEXT_BOX_TAG, this);
LLUICtrlCreator<LLRadioGroup>::registerCreator(LL_RADIO_GROUP_TAG, this);
@ -729,6 +735,16 @@ LLScrollingPanelList* LLUICtrlFactory::getScrollingPanelList(const LLPanel* pane
return panelp->getChild<LLScrollingPanelList>(name);
}
LLMultiSliderCtrl* LLUICtrlFactory::getMultiSliderByName(const LLPanel* panelp, const LLString& name)
{
return panelp->getChild<LLMultiSliderCtrl>(name);
}
LLMultiSlider* LLUICtrlFactory::getMultiSliderBarByName(const LLPanel* panelp, const LLString& name)
{
return panelp->getChild<LLMultiSlider>(name);
}
LLCtrlListInterface* LLUICtrlFactory::getListInterfaceByName(const LLPanel* panelp, const LLString& name)
{

View File

@ -91,6 +91,8 @@ public:
static class LLPanel* getPanelByName( const LLPanel* panelp, const LLString& name);
static class LLMenuItemCallGL* getMenuItemCallByName( const LLPanel* panelp, const LLString& name);
static class LLScrollingPanelList* getScrollingPanelList( const LLPanel* panelp, const LLString& name);
static class LLMultiSliderCtrl* getMultiSliderByName( const LLPanel* panelp, const LLString& name);
static class LLMultiSlider* getMultiSliderBarByName(const LLPanel* panelp, const LLString& name);
// interface getters
static LLCtrlListInterface* getListInterfaceByName( const LLPanel* panelp, const LLString& name);

View File

@ -37,6 +37,7 @@
#include <cassert>
#include <boost/tokenizer.hpp>
#include "llglimmediate.h"
#include "llevent.h"
#include "llfontgl.h"
#include "llfocusmgr.h"
@ -1290,28 +1291,28 @@ void LLView::drawDebugRect()
border_color.mV[sDepth%3] = 1.f;
}
glColor4fv( border_color.mV );
gGL.color4fv( border_color.mV );
glBegin(GL_LINES);
glVertex2i(0, debug_rect.getHeight() - 1);
glVertex2i(0, 0);
gGL.begin(GL_LINES);
gGL.vertex2i(0, debug_rect.getHeight() - 1);
gGL.vertex2i(0, 0);
glVertex2i(0, 0);
glVertex2i(debug_rect.getWidth() - 1, 0);
gGL.vertex2i(0, 0);
gGL.vertex2i(debug_rect.getWidth() - 1, 0);
glVertex2i(debug_rect.getWidth() - 1, 0);
glVertex2i(debug_rect.getWidth() - 1, debug_rect.getHeight() - 1);
gGL.vertex2i(debug_rect.getWidth() - 1, 0);
gGL.vertex2i(debug_rect.getWidth() - 1, debug_rect.getHeight() - 1);
glVertex2i(debug_rect.getWidth() - 1, debug_rect.getHeight() - 1);
glVertex2i(0, debug_rect.getHeight() - 1);
glEnd();
gGL.vertex2i(debug_rect.getWidth() - 1, debug_rect.getHeight() - 1);
gGL.vertex2i(0, debug_rect.getHeight() - 1);
gGL.end();
// Draw the name if it's not a leaf node
if (mChildList.size() && !sEditingUI)
{
//char temp[256];
S32 x, y;
glColor4fv( border_color.mV );
gGL.color4fv( border_color.mV );
x = debug_rect.getWidth()/2;
y = debug_rect.getHeight()/2;
LLString debug_text = llformat("%s (%d x %d)", getName().c_str(),

View File

@ -30,6 +30,7 @@
#include "linden_common.h"
#include "llviewborder.h"
#include "llglimmediate.h"
#include "llfocusmgr.h"
LLViewBorder::LLViewBorder( const LLString& name, const LLRect& rect, EBevel bevel, EStyle style, S32 width )
@ -145,11 +146,11 @@ void LLViewBorder::drawOnePixelLines()
S32 right = getRect().getWidth();
S32 bottom = 0;
glColor4fv( top_color.mV );
gGL.color4fv( top_color.mV );
gl_line_2d(left, bottom, left, top);
gl_line_2d(left, top, right, top);
glColor4fv( bottom_color.mV );
gGL.color4fv( bottom_color.mV );
gl_line_2d(right, top, right, bottom);
gl_line_2d(left, bottom, right, bottom);
@ -205,19 +206,19 @@ void LLViewBorder::drawTwoPixelLines()
S32 bottom = 0;
// draw borders
glColor3fv( top_out_color );
gGL.color3fv( top_out_color );
gl_line_2d(left, bottom, left, top-1);
gl_line_2d(left, top-1, right, top-1);
glColor3fv( top_in_color );
gGL.color3fv( top_in_color );
gl_line_2d(left+1, bottom+1, left+1, top-2);
gl_line_2d(left+1, top-2, right-1, top-2);
glColor3fv( bottom_out_color );
gGL.color3fv( bottom_out_color );
gl_line_2d(right-1, top-1, right-1, bottom);
gl_line_2d(left, bottom, right, bottom);
glColor3fv( bottom_in_color );
gGL.color3fv( bottom_in_color );
gl_line_2d(right-2, top-2, right-2, bottom+1);
gl_line_2d(left+1, bottom+1, right-1, bottom+1);
}
@ -228,7 +229,7 @@ void LLViewBorder::drawTextures()
llassert( FALSE ); // TODO: finish implementing
glColor4fv(UI_VERTEX_COLOR.mV);
gGL.color4fv(UI_VERTEX_COLOR.mV);
mTexture->bind();
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
@ -243,12 +244,12 @@ void LLViewBorder::drawTextures()
void LLViewBorder::drawTextureTrapezoid( F32 degrees, S32 width, S32 length, F32 start_x, F32 start_y )
{
glPushMatrix();
gGL.pushMatrix();
{
glTranslatef(start_x, start_y, 0.f);
gGL.translatef(start_x, start_y, 0.f);
glRotatef( degrees, 0, 0, 1 );
glBegin(GL_QUADS);
gGL.begin(GL_QUADS);
{
// width, width /---------\ length-width, width //
// / \ //
@ -256,21 +257,21 @@ void LLViewBorder::drawTextureTrapezoid( F32 degrees, S32 width, S32 length, F32
// /---------------\ //
// 0,0 length, 0 //
glTexCoord2f( 0, 0 );
glVertex2i( 0, 0 );
gGL.texCoord2f( 0, 0 );
gGL.vertex2i( 0, 0 );
glTexCoord2f( (GLfloat)length, 0 );
glVertex2i( length, 0 );
gGL.texCoord2f( (GLfloat)length, 0 );
gGL.vertex2i( length, 0 );
glTexCoord2f( (GLfloat)(length - width), (GLfloat)width );
glVertex2i( length - width, width );
gGL.texCoord2f( (GLfloat)(length - width), (GLfloat)width );
gGL.vertex2i( length - width, width );
glTexCoord2f( (GLfloat)width, (GLfloat)width );
glVertex2i( width, width );
gGL.texCoord2f( (GLfloat)width, (GLfloat)width );
gGL.vertex2i( width, width );
}
glEnd();
gGL.end();
}
glPopMatrix();
gGL.popMatrix();
}
BOOL LLViewBorder::getBevelFromAttribute(LLXMLNodePtr node, LLViewBorder::EBevel& bevel_style)

View File

@ -64,6 +64,9 @@ public:
const LLColor4& highlight_light, const LLColor4& highlight_dark );
void setTexture( const class LLUUID &image_id );
LLColor4 getHighlightLight() {return mHighlightLight;}
LLColor4 getShadowDark() {return mHighlightDark;}
EStyle getStyle() const { return mStyle; }
void setKeyboardFocusHighlight( BOOL b ) { mHasKeyboardFocus = b; }

View File

@ -35,7 +35,9 @@
#include "linden_common.h"
#define INITGUID
#include <dxdiag.h>
#undef INITGUID
#include <boost/tokenizer.hpp>

View File

@ -247,7 +247,7 @@ LLWindow::LLWindow(BOOL fullscreen, U32 flags)
mFlags(flags),
mHighSurrogate(0)
{
for (U32 i = 0; i < 6; i++)
for (U32 i = 0; i < 8; i++)
{
mJoyAxis[i] = 0;
}
@ -275,7 +275,7 @@ void LLWindow::decBusyCount()
F32 LLWindow::getJoystickAxis(U32 axis)
{
if (axis < 6)
if (axis < 8)
{
return mJoyAxis[axis];
}

View File

@ -258,7 +258,7 @@ protected:
ESwapMethod mSwapMethod;
BOOL mHideCursorPermanent;
U32 mFlags;
F32 mJoyAxis[6];
F32 mJoyAxis[8];
U8 mJoyButtonState[16];
U16 mHighSurrogate;

View File

@ -42,6 +42,7 @@
#include "llgl.h"
#include "llstring.h"
#include "lldir.h"
#include "llviewercontrol.h"
#include "llglheaders.h"
@ -800,22 +801,24 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
}
aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap);
#if 0 // SJB: Got a compile error. Plus I don't want to test this along with everything else ; save it for later
//enable multi-threaded OpenGL
CGLError cgl_err;
CGLContextObj ctx = CGLGetCurrentContext();
cgl_err = CGLEnable( ctx, kCGLCEMPEngine);
if (cgl_err != kCGLNoError )
if (gSavedSettings.getBOOL("RenderAppleUseMultGL"))
{
llinfos << "Multi-threaded OpenGL not available." << llendl;
}
else
{
llinfos << "Multi-threaded OpenGL enabled." << llendl;
CGLError cgl_err;
CGLContextObj ctx = CGLGetCurrentContext();
cgl_err = CGLEnable( ctx, kCGLCEMPEngine);
if (cgl_err != kCGLNoError )
{
llinfos << "Multi-threaded OpenGL not available." << llendl;
}
else
{
llinfos << "Multi-threaded OpenGL enabled." << llendl;
}
}
#endif
// Don't need to get the current gamma, since there's a call that restores it to the system defaults.
return TRUE;
}

View File

@ -505,6 +505,9 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
#if !LL_SOLARIS
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (bits <= 16) ? 16 : 24);
// We need stencil support for a few (minor) things.
if (!getenv("LL_GL_NO_STENCIL"))
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
#else
// NOTE- use smaller Z-buffer to enable more graphics cards
// - This should not affect better GPUs and has been proven
@ -587,6 +590,11 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
}
mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN);
if (!mWindow && bits > 16)
{
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN);
}
if (mWindow)
{
@ -629,6 +637,11 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
llinfos << "createContext: creating window " << width << "x" << height << "x" << bits << llendl;
mWindow = SDL_SetVideoMode(width, height, bits, sdlflags);
if (!mWindow && bits > 16)
{
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
mWindow = SDL_SetVideoMode(width, height, bits, sdlflags);
}
if (!mWindow)
{

View File

@ -44,6 +44,7 @@
// Require DirectInput version 8
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
@ -428,7 +429,7 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
mhInstance = GetModuleHandle(NULL);
mWndProc = NULL;
mSwapMethod = SWAP_METHOD_UNDEFINED;
mSwapMethod = SWAP_METHOD_EXCHANGE;
// No WPARAM yet.
mLastSizeWParam = 0;
@ -774,7 +775,7 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
attrib_list[cur_attrib++] = GL_TRUE;
attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
attrib_list[cur_attrib++] = 24;
attrib_list[cur_attrib++] = 32;
attrib_list[cur_attrib++] = WGL_RED_BITS_ARB;
attrib_list[cur_attrib++] = 8;
@ -1018,6 +1019,11 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
// based on the system's (or user's) default settings.
allowLanguageTextInput(NULL, FALSE);
initInputDevices();
}
void LLWindowWin32::initInputDevices()
{
// Direct Input
HRESULT hr;
@ -1753,6 +1759,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, LLCoordScreen size, BOOL disa
SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
show();
initInputDevices();
// ok to post quit messages now
mPostQuit = TRUE;
return TRUE;
@ -3199,6 +3207,8 @@ void LLWindowWin32::updateJoystick( )
mJoyAxis[3] = js.lRx/1000.f;
mJoyAxis[4] = js.lRy/1000.f;
mJoyAxis[5] = js.lRz/1000.f;
mJoyAxis[6] = js.rglSlider[0]/1000.f;
mJoyAxis[7] = js.rglSlider[1]/1000.f;
for (U32 i = 0; i < 16; i++)
{

View File

@ -122,6 +122,7 @@ protected:
~LLWindowWin32();
void initCursors();
void initInputDevices();
HCURSOR loadColorCursor(LPCTSTR name);
BOOL isValid();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings version = "101">
<!--NO SHADERS-->
<RenderAvatarCloth value="FALSE"/>
<!--Default for now-->
<RenderAvatarLODFactor value="1.0"/>
<!--NO SHADERS-->
<RenderAvatarVP value="TRUE"/>
<!--Short Range-->
<RenderFarClip value="128"/>
<!--Default for now-->
<RenderFlexTimeFactor value="1"/>
<!--256... but they don't use this-->
<RenderGlowResolutionPow value="9"/>
<!--Sun/Moon only-->
<RenderLightingDetail value="1"/>
<!--Low number-->
<RenderMaxPartCount value="4096"/>
<!--bump okay-->
<RenderObjectBump value="TRUE"/>
<!--NO SHADERS-->
<RenderReflectionDetail value="2"/>
<!--Simple-->
<RenderTerrainDetail value="1"/>
<!--Default for now-->
<RenderTerrainLODFactor value="2"/>
<!--Default for now-->
<RenderTreeLODFactor value="0.5"/>
<!--Try Impostors-->
<RenderUseImpostors value="TRUE"/>
<!--Default for now-->
<RenderVolumeLODFactor value="1.125"/>
<!--NO SHADERS-->
<RenderWaterReflections value="FALSE"/>
<!--NO SHADERS-->
<VertexShaderEnable value="TRUE"/>
<!--NO SHADERS-->
<WindLightUseAtmosShaders value="TRUE"/>
</settings>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings version = "101">
<!--NO SHADERS-->
<RenderAvatarCloth value="FALSE"/>
<!--Default for now-->
<RenderAvatarLODFactor value="0.5"/>
<!--NO SHADERS-->
<RenderAvatarVP value="FALSE"/>
<!--Short Range-->
<RenderFarClip value="64"/>
<!--Default for now-->
<RenderFlexTimeFactor value="0.5"/>
<!--256... but they don't use this-->
<RenderGlowResolutionPow value="8"/>
<!--Sun/Moon only-->
<RenderLightingDetail value="0"/>
<!--Low number-->
<RenderMaxPartCount value="1024"/>
<!--bump okay-->
<RenderObjectBump value="FALSE"/>
<!--NO SHADERS-->
<RenderReflectionDetail value="0"/>
<!--Simple-->
<RenderTerrainDetail value="0"/>
<!--Default for now-->
<RenderTerrainLODFactor value="1.0"/>
<!--Default for now-->
<RenderTreeLODFactor value="0.5"/>
<!--Try Impostors-->
<RenderUseImpostors value="TRUE"/>
<!--Default for now-->
<RenderVolumeLODFactor value="1.125"/>
<!--NO SHADERS-->
<RenderWaterReflections value="FALSE"/>
<!--NO SHADERS-->
<VertexShaderEnable value="FALSE"/>
<!--NO SHADERS-->
<WindLightUseAtmosShaders value="FALSE"/>
</settings>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings version = "101">
<!--NO SHADERS-->
<RenderAvatarCloth value="FALSE"/>
<!--Default for now-->
<RenderAvatarLODFactor value="0.5"/>
<!--NO SHADERS-->
<RenderAvatarVP value="TRUE"/>
<!--Short Range-->
<RenderFarClip value="96"/>
<!--Default for now-->
<RenderFlexTimeFactor value="1"/>
<!--256... but they don't use this-->
<RenderGlowResolutionPow value="8"/>
<!--Sun/Moon only-->
<RenderLightingDetail value="1"/>
<!--Low number-->
<RenderMaxPartCount value="2048"/>
<!--bump okay-->
<RenderObjectBump value="TRUE"/>
<!--NO SHADERS-->
<RenderReflectionDetail value="0"/>
<!--Simple-->
<RenderTerrainDetail value="1"/>
<!--Default for now-->
<RenderTerrainLODFactor value="1.0"/>
<!--Default for now-->
<RenderTreeLODFactor value="0.5"/>
<!--Try Impostors-->
<RenderUseImpostors value="TRUE"/>
<!--Default for now-->
<RenderVolumeLODFactor value="1.125"/>
<!--NO SHADERS-->
<RenderWaterReflections value="FALSE"/>
<!--NO SHADERS-->
<VertexShaderEnable value="TRUE"/>
<!--NO SHADERS-->
<WindLightUseAtmosShaders value="FALSE"/>
</settings>

View File

@ -1,3 +1,10 @@
/**
* @file avatarF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
void default_lighting();
void main()

View File

@ -1,4 +1,9 @@
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
/**
* @file avatarSkinV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
attribute vec4 weight; //1

View File

@ -1,9 +1,13 @@
void default_scatter(vec3 viewVec, vec3 lightDir);
/**
* @file avatarV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getSkinnedTransform();
vec2 getScatterCoord(vec3 viewVec, vec3 lightDir);
attribute vec4 materialColor;
void calcAtmospherics(vec3 inPositionEye);
void main()
{
@ -24,12 +28,16 @@ void main()
norm = normalize(norm);
gl_Position = gl_ProjectionMatrix * pos;
//gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
default_scatter(pos.xyz, gl_LightSource[0].position.xyz);
gl_FogFragCoord = length(pos.xyz);
vec4 color = calcLighting(pos.xyz, norm, materialColor, gl_Color);
calcAtmospherics(pos.xyz);
vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0,0,0,0));
gl_FrontColor = color;
}

View File

@ -1,3 +1,10 @@
/**
* @file eyeballF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
void default_lighting();
void main()

View File

@ -1,7 +1,12 @@
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec3 baseCol);
void default_scatter(vec3 viewVec, vec3 lightDir);
/**
* @file eyeballV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
attribute vec4 materialColor;
vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
void main()
{
@ -12,9 +17,11 @@ void main()
vec3 pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
vec4 color = calcLighting(pos, norm, materialColor, gl_Color.rgb);
default_scatter(pos, gl_LightSource[0].position.xyz);
calcAtmospherics(pos.xyz);
vec4 specular = vec4(1.0);
vec4 color = calcLightingSpecular(pos, norm, gl_Color, specular, vec4(0.0));
gl_FrontColor = color;
}

View File

@ -1,3 +1,10 @@
/**
* @file pickAvatarF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
void main()

View File

@ -1,4 +1,10 @@
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
/**
* @file pickAvatarV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
mat4 getSkinnedTransform();
void main()
@ -14,4 +20,4 @@ void main()
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ProjectionMatrix * pos;
}
}

View File

@ -0,0 +1,28 @@
/**
* @file glowExtractF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#extension GL_ARB_texture_rectangle : enable
uniform sampler2DRect diffuseMap;
uniform float minLuminance;
uniform float maxExtractAlpha;
uniform vec3 lumWeights;
uniform vec3 warmthWeights;
uniform float warmthAmount;
void main()
{
vec4 col = texture2DRect(diffuseMap, gl_TexCoord[0].xy);
/// CALCULATING LUMINANCE (Using NTSC lum weights)
/// http://en.wikipedia.org/wiki/Luma_%28video%29
float lum = smoothstep(minLuminance, 1.0, dot(col.rgb, lumWeights ) );
float warmth = smoothstep(minLuminance, 1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) );
gl_FragColor.rgb = col.rgb;
gl_FragColor.a = max(col.a, mix(lum, warmth, warmthAmount) * maxExtractAlpha);
}

View File

@ -0,0 +1,14 @@
/**
* @file glowExtractV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
}

View File

@ -0,0 +1,31 @@
/**
* @file glowF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
uniform float glowStrength;
void main()
{
vec4 col = vec4(0.0, 0.0, 0.0, 0.0);
// ATI compiler falls down on array initialization.
float kern[8];
kern[0] = 0.25; kern[1] = 0.5; kern[2] = 0.8; kern[3] = 1.0;
kern[4] = 1.0; kern[5] = 0.8; kern[6] = 0.5; kern[7] = 0.25;
col += kern[0] * texture2D(diffuseMap, gl_TexCoord[0].xy);
col += kern[1] * texture2D(diffuseMap, gl_TexCoord[1].xy);
col += kern[2] * texture2D(diffuseMap, gl_TexCoord[2].xy);
col += kern[3] * texture2D(diffuseMap, gl_TexCoord[3].xy);
col += kern[4] * texture2D(diffuseMap, gl_TexCoord[0].zw);
col += kern[5] * texture2D(diffuseMap, gl_TexCoord[1].zw);
col += kern[6] * texture2D(diffuseMap, gl_TexCoord[2].zw);
col += kern[7] * texture2D(diffuseMap, gl_TexCoord[3].zw);
gl_FragColor = vec4(col.rgb * glowStrength, col.a);
}

View File

@ -0,0 +1,22 @@
/**
* @file glowV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform vec2 glowDelta;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + glowDelta*(-3.5);
gl_TexCoord[1].xy = gl_MultiTexCoord0.xy + glowDelta*(-2.5);
gl_TexCoord[2].xy = gl_MultiTexCoord0.xy + glowDelta*(-1.5);
gl_TexCoord[3].xy = gl_MultiTexCoord0.xy + glowDelta*(-0.5);
gl_TexCoord[0].zw = gl_MultiTexCoord0.xy + glowDelta*(0.5);
gl_TexCoord[1].zw = gl_MultiTexCoord0.xy + glowDelta*(1.5);
gl_TexCoord[2].zw = gl_MultiTexCoord0.xy + glowDelta*(2.5);
gl_TexCoord[3].zw = gl_MultiTexCoord0.xy + glowDelta*(3.5);
}

View File

@ -1,9 +1,13 @@
void terrain_lighting(inout vec3 color);
uniform sampler2D detail0; //0
uniform sampler2D detail1; //2
uniform sampler2D alphaRamp; //1
/**
* @file terrainF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D detail0;
uniform sampler2D detail1;
uniform sampler2D alphaRamp;
void main()
{
@ -12,8 +16,6 @@ void main()
texture2D(detail0, gl_TexCoord[0].xy).rgb,
a);
terrain_lighting(color);
gl_FragColor.rgb = color;
gl_FragColor.a = texture2D(alphaRamp, gl_TexCoord[3].xy).a;
}

View File

@ -1,7 +1,11 @@
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void default_scatter(vec3 viewVec, vec3 lightDir);
/**
* @file terrainV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
attribute vec4 materialColor;
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1)
{
@ -25,7 +29,7 @@ void main()
vec4 pos = gl_ModelViewMatrix * gl_Vertex;
vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
vec4 color = calcLighting(pos.xyz, norm, materialColor, gl_Color);
vec4 color = calcLighting(pos.xyz, norm, vec4(1,1,1,1), gl_Color);
gl_FrontColor = color;
@ -33,5 +37,4 @@ void main()
gl_TexCoord[1] = gl_TextureMatrix[1]*gl_MultiTexCoord1;
gl_TexCoord[2] = texgen_object(gl_Vertex,gl_MultiTexCoord2,gl_TextureMatrix[2],gl_ObjectPlaneS[2],gl_ObjectPlaneT[2]);
gl_TexCoord[3] = gl_TextureMatrix[3]*gl_MultiTexCoord3;
default_scatter(pos.xyz, gl_LightSource[0].position.xyz);
}

View File

@ -0,0 +1,23 @@
/**
* @file terrainWaterF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
// this class1 shader is just a copy of terrainF
uniform sampler2D detail0;
uniform sampler2D detail1;
uniform sampler2D alphaRamp;
void main()
{
float a = texture2D(alphaRamp, gl_TexCoord[1].xy).a;
vec3 color = mix(texture2D(detail1, gl_TexCoord[2].xy).rgb,
texture2D(detail0, gl_TexCoord[0].xy).rgb,
a);
gl_FragColor.rgb = color;
gl_FragColor.a = texture2D(alphaRamp, gl_TexCoord[3].xy).a;
}

View File

@ -0,0 +1,45 @@
/**
* @file underWaterF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
uniform sampler2D screenTex;
uniform float refScale;
uniform vec4 waterFogColor;
//bigWave is (refCoord.w, view.w);
varying vec4 refCoord;
varying vec4 littleWave;
varying vec4 view;
void main()
{
vec4 color;
//get bigwave normal
vec3 wavef = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0;
//get detail normals
vec3 dcol = texture2D(bumpMap, littleWave.xy).rgb*0.75;
dcol += texture2D(bumpMap, littleWave.zw).rgb*1.25;
//interpolate between big waves and little waves (big waves in deep water)
wavef = (wavef+dcol)*0.5;
//crunch normal to range [-1,1]
wavef -= vec3(1,1,1);
//figure out distortion vector (ripply)
vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
distort = distort+wavef.xy*refScale;
vec4 fb = texture2D(screenTex, distort);
gl_FragColor.rgb = mix(waterFogColor.rgb, fb.rgb, waterFogColor.a * 0.001 + 0.999);
gl_FragColor.a = fb.a;
}

View File

@ -1,22 +1,94 @@
void water_lighting(inout vec3 diff);
/**
* @file waterF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
vec3 scaleSoftClip(vec3 inColor);
vec3 atmosTransport(vec3 inColor);
uniform samplerCube environmentMap;
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
uniform sampler2D bumpMap;
uniform sampler2D screenTex;
uniform sampler2D refTex;
varying vec4 specular;
uniform float sunAngle;
uniform float sunAngle2;
uniform float scaledAngle;
uniform vec3 lightDir;
uniform vec3 specular;
uniform float lightExp;
uniform float refScale;
uniform float kd;
uniform vec2 screenRes;
uniform vec3 normScale;
uniform float fresnelScale;
uniform float fresnelOffset;
uniform float blurMultiplier;
uniform vec4 fogCol;
//bigWave is (refCoord.w, view.w);
varying vec4 refCoord;
varying vec4 littleWave;
varying vec4 view;
void main()
{
vec4 depth = texture2D(diffuseMap, gl_TexCoord[0].xy);
vec4 diff = texture2D(bumpMap, gl_TexCoord[1].xy);
vec3 ref = textureCube(environmentMap, gl_TexCoord[2].xyz).rgb;
vec3 viewVec = view.xyz;
vec4 color;
diff.rgb *= depth.rgb;
float dist = length(viewVec.xy);
//normalize view vector
viewVec = normalize(viewVec);
//get wave normals
vec3 wavef = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0;
//get detail normals
vec3 dcol = texture2D(bumpMap, littleWave.xy).rgb*0.75;
dcol += texture2D(bumpMap, littleWave.zw).rgb*1.25;
//interpolate between big waves and little waves (big waves in deep water)
wavef = (wavef + dcol) * 0.5;
//crunch normal to range [-1,1]
wavef -= vec3(1,1,1);
wavef = normalize(wavef);
//get base fresnel components
float df = dot(viewVec,wavef) * fresnelScale + fresnelOffset;
vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
float dist2 = dist;
dist = max(dist, 5.0);
//get reflected color
vec2 refdistort = wavef.xy*dot(normScale, vec3(0.333));
vec2 refvec = distort+refdistort/dist;
vec4 refcol = texture2D(refTex, refvec);
//get specular component
float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
//harden specular
spec = pow(spec, lightExp);
//figure out distortion vector (ripply)
vec2 distort2 = distort+wavef.xy*refScale/max(dist*df, 1.0);
vec3 col = mix(diff.rgb, ref, specular.a)+specular.rgb*diff.rgb;
vec4 fb = texture2D(screenTex, distort2);
water_lighting(col.rgb);
gl_FragColor.rgb = col.rgb;
gl_FragColor.a = (gl_Color.a+depth.a)*0.5;
//mix with reflection
color.rgb = mix(mix(fogCol.rgb, fb.rgb, fogCol.a), refcol.rgb, df);
color.rgb += spec * specular;
color.rgb = atmosTransport(color.rgb);
color.rgb = scaleSoftClip(color.rgb);
color.a = spec * sunAngle2;
gl_FragColor = color;
}

View File

@ -0,0 +1,20 @@
/**
* @file waterFogF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
vec4 applyWaterFog(vec4 color)
{
// GL_EXP2 Fog
float fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);
// GL_EXP Fog
// float fog = exp(-gl_Fog.density * gl_FogFragCoord);
// GL_LINEAR Fog
// float fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;
fog = clamp(fog, 0.0, 1.0);
color.rgb = mix(gl_Fog.color.rgb, color.rgb, fog);
return color;
}

View File

@ -1,41 +1,73 @@
void default_scatter(vec3 viewVec, vec3 lightDir);
vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec3 baseCol);
vec2 getScatterCoord(vec3 viewVec, vec3 lightDir);
/**
* @file waterV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
varying vec4 specular;
void calcAtmospherics(vec3 inPositionEye);
vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1)
uniform vec2 d1;
uniform vec2 d2;
uniform float time;
uniform vec3 eyeVec;
uniform float waterHeight;
varying vec4 refCoord;
varying vec4 littleWave;
varying vec4 view;
float wave(vec2 v, float t, float f, vec2 d, float s)
{
vec4 tcoord;
tcoord.x = dot(vpos, tp0);
tcoord.y = dot(vpos, tp1);
tcoord.z = tc.z;
tcoord.w = tc.w;
tcoord = mat * tcoord;
return tcoord;
return (dot(d, v)*f + t*s)*f;
}
void main()
{
//transform vertex
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = texgen_object(gl_Vertex, gl_MultiTexCoord1, gl_TextureMatrix[1], gl_ObjectPlaneS[1],gl_ObjectPlaneT[1]);
vec4 position = gl_Vertex;
mat4 modelViewProj = gl_ModelViewProjectionMatrix;
vec3 pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
vec4 spec = gl_Color;
gl_FrontColor.rgb = calcLightingSpecular(pos, norm, gl_Color, spec, vec3(0.0, 0.0, 0.0)).rgb;
gl_FrontColor.a = gl_Color.a;
specular = spec;
specular.a = gl_Color.a*0.5;
vec3 ref = reflect(pos,norm);
gl_TexCoord[2] = gl_TextureMatrix[2]*vec4(ref,1);
vec4 oPosition;
//get view vector
vec3 oEyeVec;
oEyeVec.xyz = position.xyz-eyeVec;
default_scatter(pos.xyz, gl_LightSource[0].position.xyz);
float d = length(oEyeVec.xy);
float ld = min(d, 2560.0);
position.xy = eyeVec.xy + oEyeVec.xy/d*ld;
view.xyz = oEyeVec;
d = clamp(ld/1536.0-0.5, 0.0, 1.0);
d *= d;
oPosition = position;
oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d);
oPosition = modelViewProj * oPosition;
refCoord.xyz = oPosition.xyz + vec3(0,0,0.2);
//get wave position parameter (create sweeping horizontal waves)
vec3 v = position.xyz;
v.x += (cos(v.x*0.08/*+time*0.01*/)+sin(v.y*0.02))*6.0;
//push position for further horizon effect.
position.xyz = oEyeVec.xyz*(waterHeight/oEyeVec.z);
position.w = 1.0;
position = position*gl_ModelViewMatrix;
calcAtmospherics((gl_ModelViewMatrix * gl_Vertex).xyz);
//pass wave parameters to pixel shader
vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055;
//get two normal map (detail map) texture coordinates
littleWave.xy = (v.xy) * vec2(0.6, 1.2) + d2 * time * 0.05;
// littleWave.zw = (v.xy) * vec2(0.07, 0.15) - d1 * time * 0.043;
littleWave.zw = (v.xy) * vec2(0.3, 0.6) + d1 * time * 0.1;
view.w = bigWave.y;
refCoord.w = bigWave.x;
gl_Position = oPosition;
}

View File

@ -1,3 +1,10 @@
/**
* @file highlightF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
void main()

View File

@ -1,9 +1,14 @@
attribute vec4 materialColor;
/**
* @file highlightV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
void main()
{
//transform vertex
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = ftransform();
vec3 pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
pos = normalize(pos);
float d = dot(pos, normalize(gl_NormalMatrix * gl_Normal));
@ -11,10 +16,10 @@ void main()
d = 1.0 - d;
d *= d;
d = min(d, materialColor.a*2.0);
d = min(d, gl_Color.a*2.0);
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor.rgb = materialColor.rgb;
gl_FrontColor.a = max(d, materialColor.a);
gl_FrontColor.rgb = gl_Color.rgb;
gl_FrontColor.a = max(d, gl_Color.a);
}

View File

@ -1,31 +1,15 @@
void applyScatter(inout vec3 color);
/**
* @file lightF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
void default_lighting()
{
vec4 color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
//applyScatter(color.rgb);
color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
gl_FragColor = color;
}
void alpha_lighting()
{
default_lighting();
}
void water_lighting(inout vec3 diff)
{
applyScatter(diff);
}
void terrain_lighting(inout vec3 color)
{
color.rgb *= gl_Color.rgb;
applyScatter(color);
}
vec4 getLightColor()
{
return gl_Color;
}

View File

@ -0,0 +1,15 @@
/**
* @file lightFullbrightF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
void fullbright_lighting()
{
gl_FragColor = texture2D(diffuseMap, gl_TexCoord[0].xy);
}

View File

@ -0,0 +1,15 @@
/**
* @file lightFullbrightShinyF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
uniform samplerCube environmentMap;
void fullbright_shiny_lighting()
{
gl_FragColor = texture2D(diffuseMap, gl_TexCoord[0].xy);
}

View File

@ -0,0 +1,15 @@
/**
* @file lightFullbrightWaterF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
void fullbright_lighting_water()
{
gl_FragColor = texture2D(diffuseMap, gl_TexCoord[0].xy);
}

View File

@ -0,0 +1,46 @@
/**
* @file lightFuncSpecularV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
float calcDirectionalLight(vec3 n, vec3 l)
{
float a = max(dot(n,l),0.0);
return a;
}
float calcDirectionalSpecular(vec3 view, vec3 n, vec3 l)
{
return pow(max(dot(reflect(view, n),l), 0.0),8.0);
}
float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da)
{
specular.rgb += calcDirectionalSpecular(view,n,l)*lightCol*da;
return max(dot(n,l),0.0);
}
vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol)
{
//get light vector
vec3 lv = l-v;
//get distance
float d = length(lv);
//normalize light vector
lv *= 1.0/d;
//distance attenuation
float da = clamp(1.0/(r * d), 0.0, 1.0);
//angular attenuation
da *= calcDirectionalLightSpecular(specular, view, n, lv, lightCol, da);
return da*lightCol;
}

View File

@ -0,0 +1,34 @@
/**
* @file lightFuncV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
float calcDirectionalLight(vec3 n, vec3 l)
{
float a = max(dot(n,l),0.0);
return a;
}
float calcPointLight(vec3 v, vec3 n, vec4 lp, float la)
{
//get light vector
vec3 lv = lp.xyz-v;
//get distance
float d = length(lv);
//normalize light vector
lv *= 1.0/d;
//distance attenuation
float da = clamp(1.0/(la * d), 0.0, 1.0);
//angular attenuation
da *= calcDirectionalLight(n, lv);
return da;
}

View File

@ -0,0 +1,17 @@
/**
* @file lightShinyF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
uniform samplerCube environmentMap;
void shiny_lighting()
{
color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
gl_FragColor = color;
}

View File

@ -0,0 +1,17 @@
/**
* @file lightShinyWaterF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
uniform samplerCube environmentMap;
void shiny_lighting_water()
{
color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
gl_FragColor = color;
}

View File

@ -0,0 +1,26 @@
/**
* @file lightV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
float calcDirectionalLight(vec3 n, vec3 l);
// Same as non-specular lighting in lightV.glsl
vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol)
{
specularColor.rgb = vec3(0.0, 0.0, 0.0);
vec4 col;
col.a = color.a;
col.rgb = gl_LightModel.ambient.rgb + baseCol.rgb;
col.rgb += gl_LightSource[0].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[0].position.xyz);
col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
col.rgb = min(col.rgb*color.rgb, 1.0);
return col;
}

View File

@ -1,66 +1,11 @@
/**
* @file lightV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
float calcDirectionalLight(vec3 n, vec3 l)
{
float a = max(dot(n,l),0.0);
return a;
}
float calcPointLight(vec3 v, vec3 n, vec3 l, float r, float pw)
{
//get light vector
vec3 lv = l-v;
//get distance
float d = length(lv);
//normalize light vector
lv *= 1.0/d;
//distance attenuation
float da = max((r-d)/r, 0.0);
//da = pow(da, pw);
//angular attenuation
da *= calcDirectionalLight(n, lv);
return da;
}
float calcDirectionalSpecular(vec3 view, vec3 n, vec3 l)
{
float a = max(dot(n,l),0.0);
return a;
}
float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da)
{
specular.rgb += calcDirectionalSpecular(view,n,l)*lightCol*da;
return calcDirectionalLight(n,l);
}
vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol)
{
//get light vector
vec3 lv = l-v;
//get distance
float d = length(lv);
//normalize light vector
lv *= 1.0/d;
//distance attenuation
float da = clamp((r-d)/r, 0.0, 1.0);
//da = pow(da, pw);
//angular attenuation
da *= calcDirectionalLightSpecular(specular, view, n, lv, lightCol, da);
return da*lightCol;
}
float calcDirectionalLight(vec3 n, vec3 l);
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseLight)
{
@ -77,23 +22,3 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseLight)
return col;
}
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec3 baseLight)
{
return calcLighting(pos, norm, color, vec4(baseLight, 1.0));
}
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color)
{
return calcLighting(pos, norm, color, vec3(0.0,0.0,0.0));
}
vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol)
{
specularColor.rgb = vec3(0.0, 0.0, 0.0);
return calcLighting(pos, norm, color, baseCol);
}
vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec3 baseCol)
{
return calcLightingSpecular(pos, norm, color, specularColor, vec4(baseCol, 1.0));
}

View File

@ -0,0 +1,15 @@
/**
* @file lightWaterF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
uniform sampler2D diffuseMap;
void default_lighting_water()
{
vec4 color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
gl_FragColor = color;
}

View File

@ -0,0 +1,35 @@
/**
* @file sumLightsSpecularV.glsl
*
* Copyright (c) 2005-$CurrentYear$, Linden Research, Inc.
* $License$
*/
float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
vec3 atmosAmbient(vec3 light);
vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 atmosGetDiffuseSunlightColor();
vec3 scaleDownLight(vec3 light);
vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol)
{
vec4 col;
col.a = color.a;
vec3 view = normalize(pos);
/// collect all the specular values from each calcXXXLightSpecular() function
vec4 specularSum = vec4(0.0);
col.rgb = gl_LightSource[1].diffuse.rgb * calcDirectionalLightSpecular(specularColor, view, norm, gl_LightSource[1].position.xyz, gl_LightSource[1].diffuse.rgb, 1.0);
col.rgb = scaleDownLight(col.rgb);
col.rgb += atmosAmbient(baseCol.rgb);
col.rgb += atmosAffectDirectionalLight(calcDirectionalLightSpecular(specularSum, view, norm, gl_LightSource[0].position.xyz,atmosGetDiffuseSunlightColor() * baseCol.a, 1.0));
col.rgb = min(col.rgb * color.rgb, 1.0);
specularColor.rgb = min(specularColor.rgb * specularSum.rgb, 1.0);
col.rgb += specularColor.rgb;
return col;
}

View File

@ -0,0 +1,29 @@
/**
* @file sumLightsV.glsl
*
* Copyright (c) 2005-$CurrentYear$, Linden Research, Inc.
* $License$
*/
float calcDirectionalLight(vec3 n, vec3 l);
vec3 atmosAmbient(vec3 light);
vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 scaleDownLight(vec3 light);
vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight)
{
vec4 col;
col.a = color.a;
col.rgb = gl_LightSource[1].diffuse.rgb * calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
col.rgb = scaleDownLight(col.rgb);
col.rgb += atmosAmbient(baseLight.rgb);
col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, gl_LightSource[0].position.xyz));
col.rgb = min(col.rgb*color.rgb, 1.0);
return col;
}

View File

@ -0,0 +1,13 @@
/**
* @file fullbrightF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
void fullbright_lighting();
void main()
{
fullbright_lighting();
}

Some files were not shown because too many files have changed in this diff Show More