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_r80620master
parent
6027ad2630
commit
6d52efe452
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ public:
|
|||
// deactivates terminated motions`
|
||||
void updateMotion();
|
||||
|
||||
void clearBlenders() { mPoseBlender.clearBlenders(); }
|
||||
|
||||
// flush motions
|
||||
// releases all motion instances
|
||||
void flushAllMotions();
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ llofstream::llofstream(const char *_Filename,
|
|||
|
||||
llofstream::~llofstream()
|
||||
{ // destroy the object
|
||||
close();
|
||||
delete _Filebuffer;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ LLCamera::LLCamera() :
|
|||
mViewHeightInPixels( -1 ), // invalid height
|
||||
mNearPlane(DEFAULT_NEAR_PLANE),
|
||||
mFarPlane(DEFAULT_FAR_PLANE),
|
||||
mFixedDistance(-1.f)
|
||||
mFixedDistance(-1.f),
|
||||
mPlaneCount(6)
|
||||
{
|
||||
calculateFrustumPlanes();
|
||||
}
|
||||
|
|
@ -56,7 +57,8 @@ LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pix
|
|||
mViewHeightInPixels(view_height_in_pixels),
|
||||
mNearPlane(near_plane),
|
||||
mFarPlane(far_plane),
|
||||
mFixedDistance(-1.f)
|
||||
mFixedDistance(-1.f),
|
||||
mPlaneCount(6)
|
||||
{
|
||||
if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; }
|
||||
else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; }
|
||||
|
|
@ -78,6 +80,18 @@ LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pix
|
|||
|
||||
// ---------------- LLCamera::setFoo() member functions ----------------
|
||||
|
||||
void LLCamera::setUserClipPlane(LLPlane plane)
|
||||
{
|
||||
mPlaneCount = 7;
|
||||
mAgentPlanes[6].p = plane;
|
||||
mAgentPlanes[6].mask = calcPlaneMask(plane);
|
||||
}
|
||||
|
||||
void LLCamera::disableUserClipPlane()
|
||||
{
|
||||
mPlaneCount = 6;
|
||||
}
|
||||
|
||||
void LLCamera::setView(F32 field_of_view)
|
||||
{
|
||||
mView = field_of_view;
|
||||
|
|
@ -150,7 +164,7 @@ size_t LLCamera::readFrustumFromBuffer(const char *buffer)
|
|||
|
||||
// ---------------- test methods ----------------
|
||||
|
||||
int LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius)
|
||||
S32 LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius)
|
||||
{
|
||||
static const LLVector3 scaler[] = {
|
||||
LLVector3(-1,-1,-1),
|
||||
|
|
@ -166,10 +180,56 @@ int LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius)
|
|||
U8 mask = 0;
|
||||
S32 result = 2;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
for (U32 i = 0; i < mPlaneCount; i++)
|
||||
{
|
||||
mask = 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 ¢er, const LLVector3& radius)
|
||||
{
|
||||
static const LLVector3 scaler[] = {
|
||||
LLVector3(-1,-1,-1),
|
||||
LLVector3( 1,-1,-1),
|
||||
LLVector3(-1, 1,-1),
|
||||
LLVector3( 1, 1,-1),
|
||||
LLVector3(-1,-1, 1),
|
||||
LLVector3( 1,-1, 1),
|
||||
LLVector3(-1, 1, 1),
|
||||
LLVector3( 1, 1, 1)
|
||||
};
|
||||
|
||||
U8 mask = 0;
|
||||
S32 result = 2;
|
||||
|
||||
for (U32 i = 0; i < mPlaneCount; i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ const F32 MAX_FIELD_OF_VIEW = F_PI;
|
|||
const F32 MAX_ASPECT_RATIO = 50.0f;
|
||||
const F32 MAX_NEAR_PLANE = 10.f;
|
||||
const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though.
|
||||
const F32 MAX_FAR_CLIP = 1024.0f;
|
||||
const F32 MAX_FAR_CLIP = 512.0f;
|
||||
|
||||
const F32 MIN_FIELD_OF_VIEW = 0.1f;
|
||||
const F32 MIN_ASPECT_RATIO = 0.02f;
|
||||
|
|
@ -114,16 +114,28 @@ protected:
|
|||
|
||||
LLPlane mWorldPlanes[PLANE_NUM];
|
||||
LLPlane mHorizPlanes[HORIZ_PLANE_NUM];
|
||||
LLPlane mAgentPlanes[6]; //frustum in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
|
||||
U8 mAgentPlaneMask[6];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LLPlane p;
|
||||
U8 mask;
|
||||
} frustum_plane;
|
||||
frustum_plane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
|
||||
|
||||
U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in
|
||||
|
||||
LLVector3 mWorldPlanePos; // Position of World Planes (may be offset from camera)
|
||||
public:
|
||||
LLVector3 mAgentFrustum[8];
|
||||
LLVector3 mAgentFrustum[8]; //8 corners of 6-plane frustum
|
||||
F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane
|
||||
|
||||
public:
|
||||
LLCamera();
|
||||
LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
|
||||
|
||||
void setUserClipPlane(LLPlane plane);
|
||||
void disableUserClipPlane();
|
||||
U8 calcPlaneMask(const LLPlane& plane);
|
||||
void setView(F32 new_view);
|
||||
void setViewHeightInPixels(S32 height);
|
||||
void setAspect(F32 new_aspect);
|
||||
|
|
@ -164,6 +176,8 @@ public:
|
|||
S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); }
|
||||
S32 sphereInFrustumFull(const LLVector3 ¢er, const F32 radius) const { return sphereInFrustum(center, radius); }
|
||||
S32 AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius);
|
||||
S32 AABBInFrustumNoFarClip(const LLVector3 ¢er, const LLVector3& radius);
|
||||
|
||||
//does a quick 'n dirty sphere-sphere check
|
||||
S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ¢er, LLVector3d &size, T* data)
|
||||
static void pushCenter(LLVector3d ¢er, const LLVector3d &size, const T* data)
|
||||
{
|
||||
LLVector3d pos(data->getPositionGroup());
|
||||
const LLVector3d& pos = data->getPositionGroup();
|
||||
for (U32 i = 0; i < 3; i++)
|
||||
{
|
||||
if (pos.mdV[i] > center.mdV[i])
|
||||
|
|
@ -221,76 +227,25 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
oct_node* mParent;
|
||||
LLVector3d mCenter;
|
||||
LLVector3d mSize;
|
||||
LLVector3d mMax;
|
||||
LLVector3d mMin;
|
||||
U8 mOctant;
|
||||
};
|
||||
|
||||
template <class 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1639,12 +1639,27 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge
|
|||
}
|
||||
}
|
||||
|
||||
void LLVolume::resizePath(S32 length)
|
||||
{
|
||||
mPathp->resizePath(length);
|
||||
if (mVolumeFaces != NULL)
|
||||
{
|
||||
delete[] mVolumeFaces;
|
||||
mVolumeFaces = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLVolume::regen()
|
||||
{
|
||||
generate();
|
||||
createVolumeFaces();
|
||||
}
|
||||
|
||||
void LLVolume::genBinormals(S32 face)
|
||||
{
|
||||
mVolumeFaces[face].createBinormals();
|
||||
}
|
||||
|
||||
LLVolume::~LLVolume()
|
||||
{
|
||||
sNumMeshPoints -= mMesh.size();
|
||||
|
|
@ -1746,12 +1761,6 @@ void LLVolume::createVolumeFaces()
|
|||
{
|
||||
S32 i;
|
||||
|
||||
if (mVolumeFaces != NULL)
|
||||
{
|
||||
delete[] mVolumeFaces;
|
||||
mVolumeFaces = NULL;
|
||||
}
|
||||
|
||||
if (mGenerateSingleFace)
|
||||
{
|
||||
mNumVolumeFaces = 0;
|
||||
|
|
@ -1760,7 +1769,12 @@ void LLVolume::createVolumeFaces()
|
|||
{
|
||||
S32 num_faces = getNumFaces();
|
||||
mNumVolumeFaces = num_faces;
|
||||
mVolumeFaces = new LLVolumeFace[num_faces];
|
||||
BOOL partial_build = TRUE;
|
||||
if (!mVolumeFaces)
|
||||
{
|
||||
partial_build = FALSE;
|
||||
mVolumeFaces = new LLVolumeFace[num_faces];
|
||||
}
|
||||
// Initialize volume faces with parameter data
|
||||
for (i = 0; i < num_faces; i++)
|
||||
{
|
||||
|
|
@ -1823,7 +1837,7 @@ void LLVolume::createVolumeFaces()
|
|||
|
||||
for (i = 0; i < mNumVolumeFaces; i++)
|
||||
{
|
||||
mVolumeFaces[i].create();
|
||||
mVolumeFaces[i].create(partial_build);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -389,4 +389,3 @@ S32 LLTextureEntry::setGlow(F32 glow)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
1034
indra/llui/llui.cpp
1034
indra/llui/llui.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
|
||||
#define INITGUID
|
||||
#include <dxdiag.h>
|
||||
#undef INITGUID
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ protected:
|
|||
ESwapMethod mSwapMethod;
|
||||
BOOL mHideCursorPermanent;
|
||||
U32 mFlags;
|
||||
F32 mJoyAxis[6];
|
||||
F32 mJoyAxis[8];
|
||||
U8 mJoyButtonState[16];
|
||||
U16 mHighSurrogate;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ protected:
|
|||
~LLWindowWin32();
|
||||
|
||||
void initCursors();
|
||||
void initInputDevices();
|
||||
HCURSOR loadColorCursor(LPCTSTR name);
|
||||
BOOL isValid();
|
||||
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -1,3 +1,10 @@
|
|||
/**
|
||||
* @file avatarF.glsl
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
void default_lighting();
|
||||
|
||||
void main()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
/**
|
||||
* @file eyeballF.glsl
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
void default_lighting();
|
||||
|
||||
void main()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
/**
|
||||
* @file pickAvatarF.glsl
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
void main()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
/**
|
||||
* @file highlightF.glsl
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
void main()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
Loading…
Reference in New Issue