pipeline.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "pipeline.h"
00035 
00036 // library includes
00037 #include "audioengine.h" // For MAX_BUFFERS for debugging.
00038 #include "imageids.h"
00039 #include "llerror.h"
00040 #include "llviewercontrol.h"
00041 #include "llfasttimer.h"
00042 #include "llfontgl.h"
00043 #include "llmemory.h"
00044 #include "llmemtype.h"
00045 #include "llnamevalue.h"
00046 #include "llprimitive.h"
00047 #include "llvolume.h"
00048 #include "material_codes.h"
00049 #include "timing.h"
00050 #include "v3color.h"
00051 #include "llui.h" 
00052 #include "llglheaders.h"
00053 
00054 // newview includes
00055 #include "llagent.h"
00056 #include "lldrawable.h"
00057 #include "lldrawpoolalpha.h"
00058 #include "lldrawpoolavatar.h"
00059 #include "lldrawpoolground.h"
00060 #include "lldrawpoolsimple.h"
00061 #include "lldrawpoolbump.h"
00062 #include "lldrawpooltree.h"
00063 #include "lldrawpoolwater.h"
00064 #include "llface.h"
00065 #include "llfeaturemanager.h"
00066 #include "llfloatertelehub.h"
00067 #include "llfloatereventlog.h"
00068 #include "llframestats.h"
00069 #include "llgldbg.h"
00070 #include "llhudmanager.h"
00071 #include "lllightconstants.h"
00072 #include "llresmgr.h"
00073 #include "llselectmgr.h"
00074 #include "llsky.h"
00075 #include "lltracker.h"
00076 #include "lltool.h"
00077 #include "lltoolmgr.h"
00078 #include "llviewercamera.h"
00079 #include "llviewerimagelist.h"
00080 #include "llviewerobject.h"
00081 #include "llviewerobjectlist.h"
00082 #include "llviewerpartsource.h"
00083 #include "llviewerparcelmgr.h"
00084 #include "llviewerregion.h" // for audio debugging.
00085 #include "llviewerwindow.h" // For getSpinAxis
00086 #include "llvoavatar.h"
00087 #include "llvoground.h"
00088 #include "llvosky.h"
00089 #include "llvotree.h"
00090 #include "llvovolume.h"
00091 #include "llvosurfacepatch.h"
00092 #include "llvowater.h"
00093 #include "llvotree.h"
00094 #include "llvopartgroup.h"
00095 #include "llworld.h"
00096 #include "viewer.h"
00097 #include "llcubemap.h"
00098 #include "llfloateravatarlist.h"
00099 #include "lldebugmessagebox.h"
00100 #include "llglslshader.h"
00101 #include "llviewerjoystick.h"
00102 
00103 #ifdef _DEBUG
00104 // Debug indices is disabled for now for debug performance - djs 4/24/02
00105 //#define DEBUG_INDICES
00106 #else
00107 //#define DEBUG_INDICES
00108 #endif
00109 
00110 #define AGGRESSIVE_OCCLUSION 0
00111 
00112 const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
00113 const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
00114 const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
00115 const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
00116 const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40;
00117 const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
00118 
00119 // Guess on the number of visible objects in the scene, used to
00120 // pre-size std::vector and other arrays. JC
00121 const S32 ESTIMATED_VISIBLE_OBJECT_COUNT = 8192;
00122 
00123 // If the sum of the X + Y + Z scale of an object exceeds this number,
00124 // it will be considered a potential occluder.  For instance,
00125 // a box of size 6 x 6 x 1 has sum 13, which might be an occluder. JC
00126 const F32 OCCLUDE_SCALE_SUM_THRESHOLD = 8.f;
00127 
00128 // Max number of occluders to search for. JC
00129 const S32 MAX_OCCLUDER_COUNT = 2;
00130 
00131 extern S32 gBoxFrame;
00132 extern BOOL gRenderLightGlows;
00133 extern BOOL gHideSelectedObjects;
00134 
00135 BOOL    gAvatarBacklight = FALSE;
00136 
00137 S32             gTrivialAccepts = 0;
00138 
00139 BOOL    gRenderForSelect = FALSE;
00140 
00141 //----------------------------------------
00142 
00143 void stamp(F32 x, F32 y, F32 xs, F32 ys)
00144 {
00145         glBegin(GL_QUADS);
00146         glTexCoord2f(0,0);
00147         glVertex3f(x,   y,   0.0f);
00148         glTexCoord2f(1,0);
00149         glVertex3f(x+xs,y,   0.0f);
00150         glTexCoord2f(1,1);
00151         glVertex3f(x+xs,y+ys,0.0f);
00152         glTexCoord2f(0,1);
00153         glVertex3f(x,   y+ys,0.0f);
00154         glEnd();
00155 }
00156 
00157 U32 nhpo2(U32 v) 
00158 {
00159         U32 r = 1;
00160         while (r < v) {
00161                 r *= 2;
00162         }
00163         return r;
00164 }
00165 
00166 
00167 //----------------------------------------
00168 
00169 S32             LLPipeline::sCompiles = 0;
00170 
00171 BOOL    LLPipeline::sShowHUDAttachments = TRUE;
00172 BOOL    LLPipeline::sRenderPhysicalBeacons = TRUE;
00173 BOOL    LLPipeline::sRenderScriptedBeacons = FALSE;
00174 BOOL    LLPipeline::sRenderScriptedTouchBeacons = TRUE;
00175 BOOL    LLPipeline::sRenderParticleBeacons = FALSE;
00176 BOOL    LLPipeline::sRenderSoundBeacons = FALSE;
00177 BOOL    LLPipeline::sRenderBeacons = FALSE;
00178 BOOL    LLPipeline::sRenderHighlight = TRUE;
00179 BOOL    LLPipeline::sRenderProcessBeacons = FALSE;
00180 BOOL    LLPipeline::sUseOcclusion = FALSE;
00181 BOOL    LLPipeline::sSkipUpdate = FALSE;
00182 BOOL    LLPipeline::sDynamicReflections = FALSE;
00183 BOOL    LLPipeline::sRenderGlow = FALSE;
00184 
00185 LLPipeline::LLPipeline() :
00186         mScreenTex(0),
00187         mGlowMap(0),
00188         mGlowBuffer(0),
00189         mVertexShadersEnabled(FALSE),
00190         mVertexShadersLoaded(0),
00191         mLastRebuildPool(NULL),
00192         mAlphaPool(NULL),
00193         mAlphaPoolPostWater(NULL),
00194         mSkyPool(NULL),
00195         mStarsPool(NULL),
00196         mTerrainPool(NULL),
00197         mWaterPool(NULL),
00198         mGroundPool(NULL),
00199         mSimplePool(NULL),
00200         mGlowPool(NULL),
00201         mBumpPool(NULL),
00202         mLightMask(0),
00203         mLightMovingMask(0)
00204 {
00205         mFramebuffer[0] = mFramebuffer[1] = 0;
00206         mCubeFrameBuffer = 0;
00207         mCubeDepth = 0;
00208 }
00209 
00210 void LLPipeline::init()
00211 {
00212         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00213 
00214         mInitialized = TRUE;
00215         
00216         stop_glerror();
00217 
00218         //create object partitions
00219         //MUST MATCH declaration of eObjectPartitions
00220         mObjectPartition.push_back(new LLVolumePartition());    //PARTITION_VOLUME
00221         mObjectPartition.push_back(new LLBridgePartition());    //PARTITION_BRIDGE
00222         mObjectPartition.push_back(new LLHUDPartition());               //PARTITION_HUD
00223         mObjectPartition.push_back(new LLTerrainPartition());   //PARTITION_TERRAIN
00224         mObjectPartition.push_back(new LLWaterPartition());             //PARTITION_WATER
00225         mObjectPartition.push_back(new LLTreePartition());              //PARTITION_TREE
00226         mObjectPartition.push_back(new LLParticlePartition());  //PARTITION_PARTICLE
00227         mObjectPartition.push_back(new LLCloudPartition());             //PARTITION_CLOUD
00228         mObjectPartition.push_back(new LLGrassPartition());             //PARTITION_GRASS
00229         mObjectPartition.push_back(NULL);                                               //PARTITION_NONE
00230         
00231         //create render pass pools
00232         getPool(LLDrawPool::POOL_ALPHA);
00233         getPool(LLDrawPool::POOL_ALPHA_POST_WATER);
00234         getPool(LLDrawPool::POOL_SIMPLE);
00235         getPool(LLDrawPool::POOL_BUMP);
00236         getPool(LLDrawPool::POOL_GLOW);
00237 
00238         mTrianglesDrawnStat.reset();
00239         resetFrameStats();
00240 
00241         mRenderTypeMask = 0xffffffff;   // All render types start on
00242         mRenderDebugFeatureMask = 0xffffffff; // All debugging features on
00243         mRenderFeatureMask = 0; // All features start off
00244         mRenderDebugMask = 0;   // All debug starts off
00245 
00246         mOldRenderDebugMask = mRenderDebugMask;
00247         
00248         mBackfaceCull = TRUE;
00249 
00250         stop_glerror();
00251         
00252         // Enable features
00253         stop_glerror();
00254                 
00255         LLShaderMgr::setShaders();
00256 }
00257 
00258 LLPipeline::~LLPipeline()
00259 {
00260 
00261 }
00262 
00263 void LLPipeline::cleanup()
00264 {
00265         for(pool_set_t::iterator iter = mPools.begin();
00266                 iter != mPools.end(); )
00267         {
00268                 pool_set_t::iterator curiter = iter++;
00269                 LLDrawPool* poolp = *curiter;
00270                 if (poolp->isFacePool())
00271                 {
00272                         LLFacePool* face_pool = (LLFacePool*) poolp;
00273                         if (face_pool->mReferences.empty())
00274                         {
00275                                 mPools.erase(curiter);
00276                                 removeFromQuickLookup( poolp );
00277                                 delete poolp;
00278                         }
00279                 }
00280                 else
00281                 {
00282                         mPools.erase(curiter);
00283                         removeFromQuickLookup( poolp );
00284                         delete poolp;
00285                 }
00286         }
00287         
00288         if (!mTerrainPools.empty())
00289         {
00290                 llwarns << "Terrain Pools not cleaned up" << llendl;
00291         }
00292         if (!mTreePools.empty())
00293         {
00294                 llwarns << "Tree Pools not cleaned up" << llendl;
00295         }
00296                 
00297         delete mAlphaPool;
00298         mAlphaPool = NULL;
00299         delete mAlphaPoolPostWater;
00300         mAlphaPoolPostWater = NULL;
00301         delete mSkyPool;
00302         mSkyPool = NULL;
00303         delete mStarsPool;
00304         mStarsPool = NULL;
00305         delete mTerrainPool;
00306         mTerrainPool = NULL;
00307         delete mWaterPool;
00308         mWaterPool = NULL;
00309         delete mGroundPool;
00310         mGroundPool = NULL;
00311         delete mSimplePool;
00312         mSimplePool = NULL;
00313         delete mGlowPool;
00314         mGlowPool = NULL;
00315         delete mBumpPool;
00316         mBumpPool = NULL;
00317 
00318         releaseGLBuffers();
00319 
00320         mBloomImagep = NULL;
00321         mBloomImage2p = NULL;
00322         mFaceSelectImagep = NULL;
00323         mAlphaSizzleImagep = NULL;
00324 
00325         for (S32 i = 0; i < NUM_PARTITIONS-1; i++)
00326         {
00327                 delete mObjectPartition[i];
00328         }
00329         mObjectPartition.clear();
00330 
00331         mVisibleList.clear();
00332         mVisibleGroups.clear();
00333         mDrawableGroups.clear();
00334         mActiveGroups.clear();
00335         mVisibleBridge.clear();
00336         mMovedBridge.clear();
00337         mOccludedBridge.clear();
00338         mAlphaGroups.clear();
00339         clearRenderMap();
00340 }
00341 
00342 //============================================================================
00343 
00344 void LLPipeline::destroyGL() 
00345 {
00346         stop_glerror();
00347         unloadShaders();
00348         mHighlightFaces.clear();
00349         mVisibleList.clear();
00350         mVisibleGroups.clear();
00351         mDrawableGroups.clear();
00352         mActiveGroups.clear();
00353         mVisibleBridge.clear();
00354         mOccludedBridge.clear();
00355         mAlphaGroups.clear();
00356         clearRenderMap();
00357         resetVertexBuffers();
00358 
00359         releaseGLBuffers();
00360 }
00361 
00362 void LLPipeline::releaseGLBuffers()
00363 {
00364         if (mGlowMap)
00365         {
00366                 glDeleteTextures(1, &mGlowMap);
00367                 mGlowMap = 0;
00368         }
00369 
00370         if (mGlowBuffer)
00371         {
00372                 glDeleteTextures(1, &mGlowBuffer);
00373                 mGlowBuffer = 0;
00374         }
00375 
00376         if (mScreenTex)
00377         {
00378                 glDeleteTextures(1, &mScreenTex);
00379                 mScreenTex = 0;
00380         }
00381 
00382         if (mCubeBuffer)
00383         {
00384                 mCubeBuffer = NULL;
00385         }
00386 
00387         if (mCubeFrameBuffer)
00388         {
00389 #if !defined(__sparc)
00390                 glDeleteFramebuffersEXT(1, &mCubeFrameBuffer);
00391                 glDeleteRenderbuffersEXT(1, &mCubeDepth);
00392 #else
00393 #error Can we generalize this without a CPU architecture test?
00394 #endif
00395                 mCubeDepth = mCubeFrameBuffer = 0;
00396         }
00397 
00398         if (mFramebuffer[0])
00399         {
00400 #if !defined(__sparc)
00401                 glDeleteFramebuffersEXT(2, mFramebuffer);
00402 #else
00403 #error Can we generalize this without a CPU architecture test?
00404 #endif
00405                 mFramebuffer[0] = mFramebuffer[1] = 0;
00406         }
00407 }
00408 
00409 void LLPipeline::restoreGL() 
00410 {
00411         resetVertexBuffers();
00412 
00413         if (mVertexShadersEnabled)
00414         {
00415                 LLShaderMgr::setShaders();
00416         }
00417         
00418         for (U32 i = 0; i < mObjectPartition.size()-1; i++)
00419         {
00420                 if (mObjectPartition[i])
00421                 {
00422                         mObjectPartition[i]->restoreGL();
00423                 }
00424         }
00425 }
00426 
00427 
00428 BOOL LLPipeline::canUseVertexShaders()
00429 {
00430         if (!gGLManager.mHasVertexShader ||
00431                 !gGLManager.mHasFragmentShader ||
00432                 !gFeatureManagerp->isFeatureAvailable("VertexShaderEnable") ||
00433                 mVertexShadersLoaded == -1)
00434         {
00435                 return FALSE;
00436         }
00437         else
00438         {
00439                 return TRUE;
00440         }
00441 }
00442 
00443 void LLPipeline::unloadShaders()
00444 {
00445         LLShaderMgr::unloadShaders();
00446         mVertexShadersLoaded = 0;
00447 }
00448 
00449 //============================================================================
00450 
00451 void LLPipeline::enableShadows(const BOOL enable_shadows)
00452 {
00453         //should probably do something here to wrangle shadows....      
00454 }
00455 
00456 S32 LLPipeline::getMaxLightingDetail() const
00457 {
00458         /*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
00459         {
00460                 return 3;
00461         }
00462         else*/
00463         {
00464                 return 1;
00465         }
00466 }
00467 
00468 S32 LLPipeline::setLightingDetail(S32 level)
00469 {
00470         if (level < 0)
00471         {
00472                 level = gSavedSettings.getS32("RenderLightingDetail");
00473         }
00474         level = llclamp(level, 0, getMaxLightingDetail());
00475         if (level != mLightingDetail)
00476         {
00477                 gSavedSettings.setS32("RenderLightingDetail", level);
00478                 if (level >= 2)
00479                 {
00480                         gObjectList.relightAllObjects();
00481                 }
00482                 mLightingDetail = level;
00483 
00484                 if (mVertexShadersLoaded == 1)
00485                 {
00486                         LLShaderMgr::setShaders();
00487                 }
00488         }
00489         return mLightingDetail;
00490 }
00491 
00492 class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
00493 {
00494 public:
00495         const std::set<LLViewerImage*>& mTextures;
00496 
00497         LLOctreeDirtyTexture(const std::set<LLViewerImage*>& textures) : mTextures(textures) { }
00498 
00499         virtual void visit(const LLOctreeState<LLDrawable>* state)
00500         {
00501                 LLSpatialGroup* group = (LLSpatialGroup*) state->getNode()->getListener(0);
00502 
00503                 if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
00504                 {
00505                         for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
00506                         {
00507                                 for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) 
00508                                 {
00509                                         LLDrawInfo* params = *j;
00510                                         if (mTextures.find(params->mTexture) != mTextures.end())
00511                                         { 
00512                                                 group->setState(LLSpatialGroup::GEOM_DIRTY);
00513                                         }
00514                                 }
00515                         }
00516                 }
00517 
00518                 for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
00519                 {
00520                         LLSpatialBridge* bridge = *i;
00521                         traverse(bridge->mOctree);
00522                 }
00523         }
00524 };
00525 
00526 // Called when a texture changes # of channels (causes faces to move to alpha pool)
00527 void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerImage*>& textures)
00528 {
00529         // *TODO: This is inefficient and causes frame spikes; need a better way to do this
00530         //        Most of the time is spent in dirty.traverse.
00531 
00532         for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
00533         {
00534                 LLDrawPool *poolp = *iter;
00535                 if (poolp->isFacePool())
00536                 {
00537                         ((LLFacePool*) poolp)->dirtyTextures(textures);
00538                 }
00539         }
00540         
00541         LLOctreeDirtyTexture dirty(textures);
00542         for (U32 i = 0; i < mObjectPartition.size(); i++)
00543         {
00544                 if (mObjectPartition[i])
00545                 {
00546                         dirty.traverse(mObjectPartition[i]->mOctree);
00547                 }
00548         }
00549 }
00550 
00551 LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
00552 {
00553         LLDrawPool *poolp = NULL;
00554         switch( type )
00555         {
00556         case LLDrawPool::POOL_SIMPLE:
00557                 poolp = mSimplePool;
00558                 break;
00559 
00560         case LLDrawPool::POOL_GLOW:
00561                 poolp = mGlowPool;
00562                 break;
00563 
00564         case LLDrawPool::POOL_TREE:
00565                 poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
00566                 break;
00567 
00568         case LLDrawPool::POOL_TERRAIN:
00569                 poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
00570                 break;
00571 
00572         case LLDrawPool::POOL_BUMP:
00573                 poolp = mBumpPool;
00574                 break;
00575 
00576         case LLDrawPool::POOL_ALPHA:
00577                 poolp = mAlphaPool;
00578                 break;
00579 
00580         case LLDrawPool::POOL_ALPHA_POST_WATER:
00581                 poolp = mAlphaPoolPostWater;
00582                 break;
00583 
00584         case LLDrawPool::POOL_AVATAR:
00585                 break; // Do nothing
00586 
00587         case LLDrawPool::POOL_SKY:
00588                 poolp = mSkyPool;
00589                 break;
00590 
00591         case LLDrawPool::POOL_STARS:
00592                 poolp = mStarsPool;
00593                 break;
00594 
00595         case LLDrawPool::POOL_WATER:
00596                 poolp = mWaterPool;
00597                 break;
00598 
00599         case LLDrawPool::POOL_GROUND:
00600                 poolp = mGroundPool;
00601                 break;
00602 
00603         default:
00604                 llassert(0);
00605                 llerrs << "Invalid Pool Type in  LLPipeline::findPool() type=" << type << llendl;
00606                 break;
00607         }
00608 
00609         return poolp;
00610 }
00611 
00612 
00613 LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerImage *tex0)
00614 {
00615         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00616         LLDrawPool *poolp = findPool(type, tex0);
00617         if (poolp)
00618         {
00619                 return poolp;
00620         }
00621 
00622         LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0);
00623         addPool( new_poolp );
00624 
00625         return new_poolp;
00626 }
00627 
00628 
00629 // static
00630 LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
00631 {
00632         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00633         U32 type = getPoolTypeFromTE(te, imagep);
00634         return gPipeline.getPool(type, imagep);
00635 }
00636 
00637 //static 
00638 U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
00639 {
00640         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00641         
00642         if (!te || !imagep)
00643         {
00644                 return 0;
00645         }
00646                 
00647         bool alpha = te->getColor().mV[3] < 0.999f;
00648         if (imagep)
00649         {
00650                 alpha = alpha || (imagep->getComponents() == 4) || (imagep->getComponents() == 2);
00651         }
00652 
00653         if (alpha)
00654         {
00655                 return LLDrawPool::POOL_ALPHA;
00656         }
00657         else if ((te->getBumpmap() || te->getShiny()))
00658         {
00659                 return LLDrawPool::POOL_BUMP;
00660         }
00661         else
00662         {
00663                 return LLDrawPool::POOL_SIMPLE;
00664         }
00665 }
00666 
00667 
00668 void LLPipeline::addPool(LLDrawPool *new_poolp)
00669 {
00670         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00671         mPools.insert(new_poolp);
00672         addToQuickLookup( new_poolp );
00673 }
00674 
00675 void LLPipeline::allocDrawable(LLViewerObject *vobj)
00676 {
00677         LLMemType mt(LLMemType::MTYPE_DRAWABLE);
00678         LLDrawable *drawable = new LLDrawable();
00679         vobj->mDrawable = drawable;
00680         
00681         drawable->mVObjp     = vobj;
00682         
00683         //encompass completely sheared objects by taking 
00684         //the most extreme point possible (<1,1,0.5>)
00685         drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).magVec());
00686         if (vobj->isOrphaned())
00687         {
00688                 drawable->setState(LLDrawable::FORCE_INVISIBLE);
00689         }
00690         drawable->updateXform(TRUE);
00691 }
00692 
00693 
00694 void LLPipeline::unlinkDrawable(LLDrawable *drawable)
00695 {
00696         LLFastTimer t(LLFastTimer::FTM_PIPELINE);
00697 
00698         LLPointer<LLDrawable> drawablep = drawable; // make sure this doesn't get deleted before we are done
00699         
00700         // Based on flags, remove the drawable from the queues that it's on.
00701         if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
00702         {
00703                 LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
00704                 if (iter != mMovedList.end())
00705                 {
00706                         mMovedList.erase(iter);
00707                 }
00708         }
00709 
00710         if (drawablep->getSpatialGroup())
00711         {
00712                 if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
00713                 {
00714 #ifdef LL_RELEASE_FOR_DOWNLOAD
00715                         llwarns << "Couldn't remove object from spatial group!" << llendl;
00716 #else
00717                         llerrs << "Couldn't remove object from spatial group!" << llendl;
00718 #endif
00719                 }
00720         }
00721 
00722         mLights.erase(drawablep);
00723 }
00724 
00725 U32 LLPipeline::addObject(LLViewerObject *vobj)
00726 {
00727         LLMemType mt(LLMemType::MTYPE_DRAWABLE);
00728         if (gNoRender)
00729         {
00730                 return 0;
00731         }
00732 
00733         LLDrawable *drawablep = vobj->createDrawable(this);
00734 
00735         llassert(drawablep);
00736 
00737         if (vobj->getParent())
00738         {
00739                 vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1
00740         }
00741         else
00742         {
00743                 vobj->setDrawableParent(NULL); // LLPipeline::addObject 2
00744         }
00745 
00746         markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
00747 
00748         return 1;
00749 }
00750 
00751 
00752 void LLPipeline::resetFrameStats()
00753 {
00754         mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
00755 
00756         mTrianglesDrawn = 0;
00757         sCompiles        = 0;
00758         mVerticesRelit   = 0;
00759         mLightingChanges = 0;
00760         mGeometryChanges = 0;
00761         mNumVisibleFaces = 0;
00762 
00763         if (mOldRenderDebugMask != mRenderDebugMask)
00764         {
00765                 gObjectList.clearDebugText();
00766                 mOldRenderDebugMask = mRenderDebugMask;
00767         }
00768                 
00769 }
00770 
00771 //external functions for asynchronous updating
00772 void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
00773 {
00774         if (gSavedSettings.getBOOL("FreezeTime"))
00775         {
00776                 return;
00777         }
00778         if (!drawablep)
00779         {
00780                 llerrs << "updateMove called with NULL drawablep" << llendl;
00781                 return;
00782         }
00783         if (drawablep->isState(LLDrawable::EARLY_MOVE))
00784         {
00785                 return;
00786         }
00787         // update drawable now
00788         drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED
00789         drawablep->updateMove(); // returns done
00790         drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
00791         // Put on move list so that EARLY_MOVE gets cleared
00792         if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
00793         {
00794                 mMovedList.push_back(drawablep);
00795                 drawablep->setState(LLDrawable::ON_MOVE_LIST);
00796         }
00797 }
00798 
00799 void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
00800 {
00801         if (gSavedSettings.getBOOL("FreezeTime"))
00802         {
00803                 return;
00804         }
00805         if (!drawablep)
00806         {
00807                 llerrs << "updateMove called with NULL drawablep" << llendl;
00808         }
00809         if (drawablep->isState(LLDrawable::EARLY_MOVE))
00810         {
00811                 return;
00812         }
00813         // update drawable now
00814         drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
00815         drawablep->updateMove();
00816         drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
00817         // Put on move list so that EARLY_MOVE gets cleared
00818         if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
00819         {
00820                 mMovedList.push_back(drawablep);
00821                 drawablep->setState(LLDrawable::ON_MOVE_LIST);
00822         }
00823 }
00824 
00825 void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
00826 {
00827         for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
00828                  iter != moved_list.end(); )
00829         {
00830                 LLDrawable::drawable_vector_t::iterator curiter = iter++;
00831                 LLDrawable *drawablep = *curiter;
00832                 BOOL done = TRUE;
00833                 if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
00834                 {
00835                         done = drawablep->updateMove();
00836                 }
00837                 drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
00838                 if (done)
00839                 {
00840                         drawablep->clearState(LLDrawable::ON_MOVE_LIST);
00841                         iter = moved_list.erase(curiter);
00842                 }
00843         }
00844 }
00845 
00846 void LLPipeline::updateMove()
00847 {
00848         //LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE);
00849         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00850 
00851         if (gSavedSettings.getBOOL("FreezeTime"))
00852         {
00853                 return;
00854         }
00855 
00856         for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
00857                  iter != mRetexturedList.end(); ++iter)
00858         {
00859                 LLDrawable* drawablep = *iter;
00860                 if (drawablep && !drawablep->isDead())
00861                 {
00862                         drawablep->updateTexture();
00863                 }
00864         }
00865         mRetexturedList.clear();
00866 
00867         updateMovedList(mMovedList);
00868 
00869         for (LLDrawable::drawable_set_t::iterator iter = mActiveQ.begin();
00870                  iter != mActiveQ.end(); )
00871         {
00872                 LLDrawable::drawable_set_t::iterator curiter = iter++;
00873                 LLDrawable* drawablep = *curiter;
00874                 if (drawablep && !drawablep->isDead()) 
00875                 {
00876                         if (drawablep->isRoot() && 
00877                                 drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && 
00878                                 (!drawablep->getParent() || !drawablep->getParent()->isActive()))
00879                         {
00880                                 drawablep->makeStatic(); // removes drawable and its children from mActiveQ
00881                                 iter = mActiveQ.upper_bound(drawablep); // next valid entry
00882                         }
00883                 }
00884                 else
00885                 {
00886                         mActiveQ.erase(curiter);
00887                 }
00888         }
00889 
00890         //balance octrees
00891         {
00892                 LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE);
00893                 for (U32 i = 0; i < mObjectPartition.size()-1; i++)
00894                 {
00895                         if (mObjectPartition[i])
00896                         {
00897                                 mObjectPartition[i]->mOctree->balance();
00898                         }
00899                 }
00900         }
00901 }
00902 
00904 // Culling and occlusion testing
00906 
00907 //static
00908 F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
00909 {
00910         LLVector3 lookAt = center - camera.getOrigin();
00911         F32 dist = lookAt.magVec();
00912 
00913         //ramp down distance for nearby objects
00914         if (dist < 16.f)
00915         {
00916                 dist /= 16.f;
00917                 dist *= dist;
00918                 dist *= 16.f;
00919         }
00920 
00921         //get area of circle around node
00922         F32 app_angle = atanf(size.magVec()/dist);
00923         F32 radius = app_angle*LLDrawable::sCurPixelAngle;
00924         return radius*radius * 3.14159f;
00925 }
00926 
00927 void LLPipeline::updateCull(LLCamera& camera)
00928 {
00929         LLFastTimer t(LLFastTimer::FTM_CULL);
00930         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00931 
00932         mVisibleList.clear();
00933         mVisibleGroups.clear();
00934         mDrawableGroups.clear();
00935         mActiveGroups.clear();
00936         gTrivialAccepts = 0;
00937         mVisibleBridge.clear();
00938 
00939         processOcclusion(camera);
00940 
00941         for (U32 i = 0; i < mObjectPartition.size(); i++)
00942         {       
00943                 if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
00944                 {
00945                         mObjectPartition[i]->cull(camera);
00946                 }
00947         }
00948 
00949         if (gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull())
00950         {
00951                 // Hack for sky - always visible.
00952                 if (hasRenderType(LLPipeline::RENDER_TYPE_SKY)) 
00953                 {
00954                         gSky.mVOSkyp->mDrawable->setVisible(camera);
00955                         mVisibleList.push_back(gSky.mVOSkyp->mDrawable);
00956                         gSky.updateCull();
00957                         stop_glerror();
00958                 }
00959         }
00960         else
00961         {
00962                 llinfos << "No sky drawable!" << llendl;
00963         }
00964 
00965         if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && gSky.mVOGroundp.notNull() && gSky.mVOGroundp->mDrawable.notNull())
00966         {
00967                 gSky.mVOGroundp->mDrawable->setVisible(camera);
00968                 mVisibleList.push_back(gSky.mVOGroundp->mDrawable);
00969         }
00970 }
00971 
00972 void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera, BOOL active)
00973 {
00974         if (group->getData().empty())
00975         { 
00976                 return;
00977         }
00978         
00979         if (!sSkipUpdate)
00980         {
00981                 group->updateDistance(camera);
00982         }
00983         
00984         const F32 MINIMUM_PIXEL_AREA = 16.f;
00985 
00986         if (group->mPixelArea < MINIMUM_PIXEL_AREA)
00987         {
00988                 return;
00989         }
00990         
00991         group->mLastRenderTime = gFrameTimeSeconds;
00992         if (!group->mSpatialPartition->mRenderByGroup)
00993         { //render by drawable
00994                 mDrawableGroups.push_back(group);
00995                 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
00996                 {
00997                         markVisible(*i, camera);
00998                 }
00999         }
01000         else
01001         { //render by group
01002                 if (active)
01003                 {
01004                         mActiveGroups.push_back(group);
01005                 }
01006                 else
01007                 {
01008                         mVisibleGroups.push_back(group);
01009                         for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
01010                         {
01011                                 LLSpatialBridge* bridge = *i;
01012                                 markVisible(bridge, camera);
01013                         }
01014                 }
01015         }
01016 }
01017 
01018 void LLPipeline::doOcclusion(LLCamera& camera)
01019 {
01020         if (sUseOcclusion)
01021         {
01022                 for (U32 i = 0; i < mObjectPartition.size(); i++)
01023                 {
01024                         if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
01025                         {
01026                                 mObjectPartition[i]->doOcclusion(&camera);
01027                         }
01028                 }
01029                 
01030 #if AGGRESSIVE_OCCLUSION
01031                 for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
01032                 {
01033                         LLSpatialBridge* bridge = *i;
01034                         if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
01035                         {
01036                                 glPushMatrix();
01037                                 glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
01038                                 LLCamera trans = bridge->transformCamera(camera);
01039                                 bridge->doOcclusion(&trans);
01040                                 glPopMatrix();
01041                                 mOccludedBridge.push_back(bridge);
01042                         }
01043                 }
01044 #endif 
01045         }
01046 }
01047         
01048 BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
01049 {
01050         BOOL update_complete = drawablep->updateGeometry(priority);
01051         if (update_complete)
01052         {
01053                 drawablep->setState(LLDrawable::BUILT);
01054                 mGeometryChanges++;
01055         }
01056         return update_complete;
01057 }
01058 
01059 void LLPipeline::updateGeom(F32 max_dtime)
01060 {
01061         LLTimer update_timer;
01062         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01063         LLPointer<LLDrawable> drawablep;
01064 
01065         LLFastTimer t(LLFastTimer::FTM_GEO_UPDATE);
01066 
01067         // notify various object types to reset internal cost metrics, etc.
01068         // for now, only LLVOVolume does this to throttle LOD changes
01069         LLVOVolume::preUpdateGeom();
01070 
01071         // Iterate through all drawables on the priority build queue,
01072         for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
01073                  iter != mBuildQ1.end();)
01074         {
01075                 LLDrawable::drawable_list_t::iterator curiter = iter++;
01076                 LLDrawable* drawablep = *curiter;
01077                 if (drawablep && !drawablep->isDead())
01078                 {
01079                         if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
01080                         {
01081                                 drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
01082                                 LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
01083                                 if (find != mBuildQ2.end())
01084                                 {
01085                                         mBuildQ2.erase(find);
01086                                 }
01087                         }
01088 
01089                         if (updateDrawableGeom(drawablep, TRUE))
01090                         {
01091                                 drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
01092                                 mBuildQ1.erase(curiter);
01093                         }
01094                 }
01095                 else
01096                 {
01097                         mBuildQ1.erase(curiter);
01098                 }
01099         }
01100                 
01101         // Iterate through some drawables on the non-priority build queue
01102         S32 min_count = 16;
01103         if (mBuildQ2.size() > 1000)
01104         {
01105                 min_count = mBuildQ2.size();
01106         }
01107                 
01108         S32 count = 0;
01109         
01110         max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
01111         LLSpatialGroup* last_group = NULL;
01112         LLSpatialBridge* last_bridge = NULL;
01113 
01114         for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
01115                  iter != mBuildQ2.end(); )
01116         {
01117                 LLDrawable::drawable_list_t::iterator curiter = iter++;
01118                 LLDrawable* drawablep = *curiter;
01119 
01120                 LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
01121                                                                         drawablep->getParent()->getSpatialBridge();
01122 
01123                 if (drawablep->getSpatialGroup() != last_group && 
01124                         (!last_bridge || bridge != last_bridge) &&
01125                         (update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
01126                 {
01127                         break;
01128                 }
01129 
01130                 //make sure updates don't stop in the middle of a spatial group
01131                 //to avoid thrashing (objects are enqueued by group)
01132                 last_group = drawablep->getSpatialGroup();
01133                 last_bridge = bridge;
01134 
01135                 BOOL update_complete = TRUE;
01136                 if (!drawablep->isDead())
01137                 {
01138                         update_complete = updateDrawableGeom(drawablep, FALSE);
01139                         count++;
01140                 }
01141                 if (update_complete)
01142                 {
01143                         drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
01144                         mBuildQ2.erase(curiter);
01145                 }
01146         }       
01147 
01148         updateMovedList(mMovedBridge);
01149 }
01150 
01151 void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
01152 {
01153         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01154         if(!drawablep || drawablep->isDead())
01155         {
01156                 llwarns << "LLPipeline::markVisible called with NULL drawablep" << llendl;
01157                 return;
01158         }
01159         
01160         
01161 #if LL_DEBUG
01162         if (drawablep->isSpatialBridge())
01163         {
01164                 if (std::find(mVisibleBridge.begin(), mVisibleBridge.end(), (LLSpatialBridge*) drawablep) !=
01165                         mVisibleBridge.end())
01166                 {
01167                         llerrs << "Spatial bridge marked visible redundantly." << llendl;
01168                 }
01169         }
01170         else
01171         {
01172                 if (std::find(mVisibleList.begin(), mVisibleList.end(), drawablep) !=
01173                         mVisibleList.end())
01174                 {
01175                         llerrs << "Drawable marked visible redundantly." << llendl;
01176                 }
01177         }
01178 #endif
01179 
01180         if (drawablep->isSpatialBridge())
01181         {
01182                 mVisibleBridge.push_back((LLSpatialBridge*) drawablep);
01183         }
01184         else
01185         {
01186                 mVisibleList.push_back(drawablep);
01187         }
01188         drawablep->setVisible(camera);
01189 }
01190 
01191 void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
01192 {
01193         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01194         if (!drawablep)
01195         {
01196                 llerrs << "Sending null drawable to moved list!" << llendl;
01197                 return;
01198         }
01199         
01200         if (drawablep->isDead())
01201         {
01202                 llwarns << "Marking NULL or dead drawable moved!" << llendl;
01203                 return;
01204         }
01205         
01206         if (drawablep->getParent()) 
01207         {
01208                 //ensure that parent drawables are moved first
01209                 markMoved(drawablep->getParent(), damped_motion);
01210         }
01211 
01212 
01213         if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
01214         {
01215                 if (drawablep->isSpatialBridge())
01216                 {
01217                         mMovedBridge.push_back(drawablep);
01218                 }
01219                 else
01220                 {
01221                         mMovedList.push_back(drawablep);
01222                 }
01223                 drawablep->setState(LLDrawable::ON_MOVE_LIST);
01224         }
01225         if (damped_motion == FALSE)
01226         {
01227                 drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED
01228         }
01229         else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
01230         {
01231                 drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
01232         }
01233 }
01234 
01235 void LLPipeline::markShift(LLDrawable *drawablep)
01236 {
01237         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01238         if (!drawablep || drawablep->isDead())
01239         {
01240                 return;
01241         }
01242 
01243         if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST))
01244         {
01245                 drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE);
01246                 if (drawablep->getParent()) 
01247                 {
01248                         markShift(drawablep->getParent());
01249                 }
01250                 mShiftList.push_back(drawablep);
01251                 drawablep->setState(LLDrawable::ON_SHIFT_LIST);
01252         }
01253 }
01254 
01255 void LLPipeline::shiftObjects(const LLVector3 &offset)
01256 {
01257         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01258         for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
01259                  iter != mShiftList.end(); iter++)
01260         {
01261                 LLDrawable *drawablep = *iter;
01262                 if (drawablep->isDead())
01263                 {
01264                         continue;
01265                 }       
01266                 drawablep->shiftPos(offset);    
01267                 drawablep->clearState(LLDrawable::ON_SHIFT_LIST);
01268         }
01269         mShiftList.resize(0);
01270 
01271         for (U32 i = 0; i < mObjectPartition.size()-1; i++)
01272         {
01273                 if (mObjectPartition[i])
01274                 {
01275                         mObjectPartition[i]->shift(offset);
01276                 }
01277         }
01278 }
01279 
01280 void LLPipeline::markTextured(LLDrawable *drawablep)
01281 {
01282         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01283         if (drawablep && !drawablep->isDead())
01284         {
01285                 mRetexturedList.insert(drawablep);
01286         }
01287 }
01288 
01289 void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
01290 {
01291         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01292 
01293         if (drawablep && !drawablep->isDead())
01294         {
01295                 if (!drawablep->isState(LLDrawable::BUILT))
01296                 {
01297                         priority = TRUE;
01298                 }
01299                 if (priority)
01300                 {
01301                         if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
01302                         {
01303                                 mBuildQ1.push_back(drawablep);
01304                                 drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue
01305                         }
01306                 }
01307                 else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
01308                 {
01309                         mBuildQ2.push_back(drawablep);
01310                         drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list
01311                 }
01312                 if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
01313                 {
01314                         drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
01315                 }
01316                 drawablep->setState(flag);
01317                 if ((flag & LLDrawable::REBUILD_LIGHTING) && drawablep->getLit())
01318                 {
01319                         if (drawablep->isLight())
01320                         {
01321                                 drawablep->clearState(LLDrawable::LIGHTING_BUILT);
01322                         }
01323                         else
01324                         {
01325                                 drawablep->clearState(LLDrawable::LIGHTING_BUILT);
01326                         }
01327                 }
01328         }
01329 }
01330 
01331 void LLPipeline::markRelight(LLDrawable *drawablep, const BOOL priority)
01332 {
01333         if (getLightingDetail() >= 2)
01334         {
01335                 markRebuild(drawablep, LLDrawable::REBUILD_LIGHTING, FALSE);
01336         }
01337 }
01338 
01339 void LLPipeline::stateSort(LLCamera& camera)
01340 {
01341         LLFastTimer ftm(LLFastTimer::FTM_STATESORT);
01342         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01343 
01344         for (LLSpatialGroup::sg_vector_t::iterator iter = mVisibleGroups.begin(); iter != mVisibleGroups.end(); ++iter)
01345         {
01346                 stateSort(*iter, camera);
01347         }
01348                 
01349         for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
01350         {
01351                 LLSpatialBridge* bridge = *i;
01352                 if (!bridge->isDead())
01353                 {
01354                         stateSort(bridge, camera);
01355                 }
01356         }
01357 
01358         for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin();
01359                  iter != mVisibleList.end(); iter++)
01360         {
01361                 LLDrawable *drawablep = *iter;
01362                 if (!drawablep->isDead())
01363                 {
01364                         stateSort(drawablep, camera);
01365                 }
01366         }
01367 
01368         for (LLSpatialGroup::sg_vector_t::iterator iter = mActiveGroups.begin(); iter != mActiveGroups.end(); ++iter)
01369         {
01370                 stateSort(*iter, camera);
01371         }
01372 
01373         postSort(camera);
01374 }
01375 
01376 void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
01377 {
01378         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01379         if (!sSkipUpdate && group->changeLOD())
01380         {
01381                 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
01382                 {
01383                         LLDrawable* drawablep = *i;
01384                         stateSort(drawablep, camera);
01385                 }
01386         }
01387         
01388 #if !LL_DARWIN
01389         if (gFrameTimeSeconds - group->mLastUpdateTime > 4.f)
01390         {
01391                 group->makeStatic();
01392         }
01393 #endif
01394 }
01395 
01396 void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
01397 {
01398         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01399         if (!sSkipUpdate)
01400         {
01401                 bridge->updateDistance(camera);
01402         }
01403 }
01404 
01405 void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
01406 {
01407         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01408         LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE);
01409         
01410         if (!drawablep
01411                 || drawablep->isDead() 
01412                 || !hasRenderType(drawablep->getRenderType()))
01413         {
01414                 return;
01415         }
01416         
01417         if (gHideSelectedObjects)
01418         {
01419                 if (drawablep->getVObj().notNull() &&
01420                         drawablep->getVObj()->isSelected())
01421                 {
01422                         return;
01423                 }
01424         }
01425 
01426         if (hasRenderType(drawablep->mRenderType))
01427         {
01428                 if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
01429                 {
01430                         drawablep->setVisible(camera, NULL, FALSE);
01431                 }
01432                 else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
01433                 {
01434                         // clear invisible flag here to avoid single frame glitch
01435                         drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
01436                 }
01437         }
01438 
01439         if (!drawablep->isActive() && drawablep->isVisible())
01440         {
01441                 if (!sSkipUpdate)
01442                 {
01443                         drawablep->updateDistance(camera);
01444                 }
01445         }
01446         else if (drawablep->isAvatar() && drawablep->isVisible())
01447         {
01448                 LLVOAvatar* vobj = (LLVOAvatar*) drawablep->getVObj().get();
01449                 vobj->updateVisibility(FALSE);
01450         }
01451 
01452         for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
01453                         iter != drawablep->mFaces.end(); iter++)
01454         {
01455                 LLFace* facep = *iter;
01456 
01457                 if (facep->hasGeometry())
01458                 {
01459                         if (facep->getPool())
01460                         {
01461                                 facep->getPool()->enqueue(facep);
01462                         }
01463                         else
01464                         {
01465                                 break;
01466                         }
01467                 }
01468         }
01469         
01470         
01471         mNumVisibleFaces += drawablep->getNumFaces();
01472 }
01473 
01474 
01475 void LLPipeline::forAllDrawables(LLSpatialGroup::sg_vector_t& groups, void (*func)(LLDrawable*))
01476 {
01477         for (LLSpatialGroup::sg_vector_t::iterator i = groups.begin(); i != groups.end(); ++i)
01478         {
01479                 for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
01480                 {
01481                         func(*j);       
01482                 }
01483         }
01484 }
01485 
01486 void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
01487 {
01488         forAllDrawables(mDrawableGroups, func);
01489         forAllDrawables(mVisibleGroups, func);
01490         forAllDrawables(mActiveGroups, func);
01491 }
01492 
01493 //function for creating scripted beacons
01494 void renderScriptedBeacons(LLDrawable* drawablep)
01495 {
01496         LLViewerObject *vobj = drawablep->getVObj();
01497         if (vobj 
01498                 && !vobj->isAvatar() 
01499                 && !vobj->getParent()
01500                 && vobj->flagScripted())
01501         {
01502                 if (gPipeline.sRenderBeacons)
01503                 {
01504                         gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01505                 }
01506 
01507                 if (gPipeline.sRenderHighlight)
01508                 {
01509                         S32 face_id;
01510                         for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
01511                         {
01512                                 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01513                         }
01514                 }
01515         }
01516 }
01517 
01518 void renderScriptedTouchBeacons(LLDrawable* drawablep)
01519 {
01520         LLViewerObject *vobj = drawablep->getVObj();
01521         if (vobj 
01522                 && !vobj->isAvatar() 
01523                 && !vobj->getParent()
01524                 && vobj->flagScripted()
01525                 && vobj->flagHandleTouch())
01526         {
01527                 if (gPipeline.sRenderBeacons)
01528                 {
01529                         gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01530                 }
01531 
01532                 if (gPipeline.sRenderHighlight)
01533                 {
01534                         S32 face_id;
01535                         for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
01536                         {
01537                                 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01538                         }
01539                 }
01540         }
01541 }
01542 
01543 void renderPhysicalBeacons(LLDrawable* drawablep)
01544 {
01545         LLViewerObject *vobj = drawablep->getVObj();
01546         if (vobj 
01547                 && !vobj->isAvatar() 
01548                 && !vobj->getParent()
01549                 && vobj->usePhysics())
01550         {
01551                 if (gPipeline.sRenderBeacons)
01552                 {
01553                         gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01554                 }
01555 
01556                 if (gPipeline.sRenderHighlight)
01557                 {
01558                         S32 face_id;
01559                         for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
01560                         {
01561                                 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01562                         }
01563                 }
01564         }
01565 }
01566 
01567 void addSourcesToEventLog(LLDrawable *drawablep)
01568 {
01569         if ( NULL != gFloaterEventLog )
01570         {
01571                 LLViewerObject *vobj = drawablep->getVObj();
01572                 if ( vobj )
01573                 {
01574                         // logObject figures out what to do with it,
01575                         // no particle/sound/etc specific code needed.
01576                         gFloaterEventLog->logObject( vobj );
01577                 }
01578         }
01579 }
01580 
01581 
01582 void renderParticleBeacons(LLDrawable* drawablep)
01583 {
01584         // Look for attachments, objects, etc.
01585         LLViewerObject *vobj = drawablep->getVObj();
01586         if (vobj 
01587                 && vobj->isParticleSource())
01588         {
01589                 if (gPipeline.sRenderBeacons)
01590                 {
01591                         LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
01592                         gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01593                 }
01594 
01595                 if (gPipeline.sRenderHighlight)
01596                 {
01597                         S32 face_id;
01598                         for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
01599                         {
01600                                 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01601                         }
01602                 }
01603         }
01604 }
01605 
01610 void addParticleSourcesToList(LLDrawable *drawablep)
01611 {
01612         if ( NULL != gFloaterAvatarList )
01613         {
01614                 LLViewerObject *vobj = drawablep->getVObj();
01615                 if (vobj && vobj->isParticleSource())
01616                 {
01617                         LLUUID id = vobj->mPartSourcep->getOwnerUUID();
01618                         LLAvatarListEntry *ent = gFloaterAvatarList->getAvatarEntry(id);
01619                         if ( NULL != ent )
01620                         {
01621                                 ent->setActivity(ACTIVITY_PARTICLES);
01622                         }
01623                 }
01624         }
01625 }
01626 
01627 void LLPipeline::postSort(LLCamera& camera)
01628 {
01629         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01630         LLFastTimer ftm(LLFastTimer::FTM_STATESORT_POSTSORT);
01631         //reset render data sets
01632         clearRenderMap();
01633         mAlphaGroups.clear();
01634         mAlphaGroupsPostWater.clear();
01635         
01636         if (!gSavedSettings.getBOOL("RenderRippleWater") && hasRenderType(LLDrawPool::POOL_ALPHA))
01637         {       //turn off clip plane for non-ripple water
01638                 toggleRenderType(LLDrawPool::POOL_ALPHA);
01639         }
01640 
01641         F32 water_height = gAgent.getRegion()->getWaterHeight();
01642         BOOL above_water = gCamera->getOrigin().mV[2] > water_height ? TRUE : FALSE;
01643 
01644         //prepare occlusion geometry
01645         if (sUseOcclusion)
01646         {
01647                 for (U32 i = 0; i < mObjectPartition.size(); i++)
01648                 {
01649                         if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
01650                         {
01651                                 mObjectPartition[i]->buildOcclusion();
01652                         }
01653                 }
01654                 
01655 #if AGGRESSIVE_OCCLUSION
01656                 for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
01657                 {
01658                         LLSpatialBridge* bridge = *i;
01659                         if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
01660                         {       
01661                                 bridge->buildOcclusion();
01662                         }
01663                 }
01664 #endif
01665         }
01666 
01667 
01668         if (!sSkipUpdate)
01669         {
01670                 //rebuild drawable geometry
01671                 for (LLSpatialGroup::sg_vector_t::iterator i = mDrawableGroups.begin(); i != mDrawableGroups.end(); ++i)
01672                 {
01673                         LLSpatialGroup* group = *i;
01674                         group->rebuildGeom();
01675                 }
01676         }
01677 
01678         //build render map
01679         for (LLSpatialGroup::sg_vector_t::iterator i = mVisibleGroups.begin(); i != mVisibleGroups.end(); ++i)
01680         {
01681                 LLSpatialGroup* group = *i;
01682                 if (!sSkipUpdate)
01683                 {
01684                         group->rebuildGeom();
01685                 }
01686                 for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
01687                 {
01688                         LLSpatialGroup::drawmap_elem_t& src_vec = j->second;    
01689                         LLSpatialGroup::drawmap_elem_t& dest_vec = mRenderMap[j->first];  
01690 
01691                         for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) 
01692                         {
01693                                 dest_vec.push_back(*k);
01694                         }
01695                 }
01696                 
01697                 LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
01698                 
01699                 if (alpha != group->mDrawMap.end())
01700                 { //store alpha groups for sorting
01701                         if (!sSkipUpdate)
01702                         {
01703                                 group->updateDistance(camera);
01704                         }
01705                         
01706                         if (hasRenderType(LLDrawPool::POOL_ALPHA))
01707                         {
01708                                 BOOL above = group->mObjectBounds[0].mV[2] + group->mObjectBounds[1].mV[2] > water_height ? TRUE : FALSE;
01709                                 BOOL below = group->mObjectBounds[0].mV[2] - group->mObjectBounds[1].mV[2] < water_height ? TRUE : FALSE;
01710                                 
01711                                 if (below == above_water || above == below)
01712                                 {
01713                                         mAlphaGroups.push_back(group);
01714                                 }
01715 
01716                                 if (above == above_water || below == above)
01717                                 {
01718                                         mAlphaGroupsPostWater.push_back(group);
01719                                 }
01720                         }
01721                         else
01722                         {
01723                                 mAlphaGroupsPostWater.push_back(group);
01724                         }
01725                 }
01726         }
01727         
01728         //store active alpha groups
01729         for (LLSpatialGroup::sg_vector_t::iterator i = mActiveGroups.begin(); i != mActiveGroups.end(); ++i)
01730         {
01731                 LLSpatialGroup* group = *i;
01732                 if (!sSkipUpdate)
01733                 {
01734                         group->rebuildGeom();
01735                 }
01736                 LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
01737                 
01738                 if (alpha != group->mDrawMap.end())
01739                 {
01740                         LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
01741                         LLCamera trans_camera = bridge->transformCamera(camera);
01742                         if (!sSkipUpdate)
01743                         {
01744                                 group->updateDistance(trans_camera);
01745                         }
01746                         
01747                         if (hasRenderType(LLDrawPool::POOL_ALPHA))
01748                         {
01749                                 LLSpatialGroup* bridge_group = bridge->getSpatialGroup();
01750                                 BOOL above = bridge_group->mObjectBounds[0].mV[2] + bridge_group->mObjectBounds[1].mV[2] > water_height ? TRUE : FALSE;
01751                                 BOOL below = bridge_group->mObjectBounds[0].mV[2] - bridge_group->mObjectBounds[1].mV[2] < water_height ? TRUE : FALSE;
01752                                         
01753                                 
01754                                 if (below == above_water || above == below)
01755                                 {
01756                                         mAlphaGroups.push_back(group);
01757                                 }
01758                                 
01759                                 if (above == above_water || below == above)
01760                                 {
01761                                         mAlphaGroupsPostWater.push_back(group);
01762                                 }
01763                         }
01764                         else
01765                         {
01766                                 mAlphaGroupsPostWater.push_back(group);
01767                         }
01768                 }
01769         }
01770 
01771         //sort by texture or bump map
01772         for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i)
01773         {
01774                 if (!mRenderMap[i].empty())
01775                 {
01776                         if (i == LLRenderPass::PASS_BUMP)
01777                         {
01778                                 std::sort(mRenderMap[i].begin(), mRenderMap[i].end(), LLDrawInfo::CompareBump());
01779                         }
01780                         else 
01781                         {
01782                                 std::sort(mRenderMap[i].begin(), mRenderMap[i].end(), LLDrawInfo::CompareTexturePtr());
01783                         }
01784                 }
01785         }
01786 
01787         std::sort(mAlphaGroups.begin(), mAlphaGroups.end(), LLSpatialGroup::CompareDepthGreater());
01788         std::sort(mAlphaGroupsPostWater.begin(), mAlphaGroupsPostWater.end(), LLSpatialGroup::CompareDepthGreater());
01789 
01790         forAllVisibleDrawables(addParticleSourcesToList);
01791         forAllVisibleDrawables(addSourcesToEventLog);
01792 
01793         // only render if the flag is set. The flag is only set if the right key is pressed, we are in edit mode or the toggle is set in the menus
01794         if (sRenderProcessBeacons)
01795         {
01796                 if (sRenderScriptedTouchBeacons)
01797                 {
01798                         // Only show the beacon on the root object.
01799                         forAllVisibleDrawables(renderScriptedTouchBeacons);
01800                 }
01801                 else
01802                 if (sRenderScriptedBeacons)
01803                 {
01804                         // Only show the beacon on the root object.
01805                         forAllVisibleDrawables(renderScriptedBeacons);
01806                 }
01807 
01808                 if (sRenderPhysicalBeacons)
01809                 {
01810                         // Only show the beacon on the root object.
01811                         forAllVisibleDrawables(renderPhysicalBeacons);
01812                 }
01813 
01814                 if (sRenderParticleBeacons)
01815                 {
01816                         forAllVisibleDrawables(renderParticleBeacons);
01817                 }
01818 
01819                 // If god mode, also show audio cues
01820                 if (sRenderSoundBeacons && gAudiop)
01821                 {
01822                         // Update all of our audio sources, clean up dead ones.
01823                         LLAudioEngine::source_map::iterator iter;
01824                         for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
01825                         {
01826                                 LLAudioSource *sourcep = iter->second;
01827 
01828                                 LLVector3d pos_global = sourcep->getPositionGlobal();
01829                                 LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
01830                                 if (gPipeline.sRenderBeacons)
01831                                 {
01832                                         //pos += LLVector3(0.f, 0.f, 0.2f);
01833                                         gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01834                                 }
01835                         }
01836                 }
01837         }
01838 
01839         // Avatar list support
01840         if ( gFloaterAvatarList && gAudiop )
01841         {
01842                 LLAudioEngine::source_map::iterator iter;
01843                 for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
01844                 {
01845                         LLAudioSource *sourcep = iter->second;
01846                         LLUUID uuid = sourcep->getOwnerID();
01847                         LLAvatarListEntry *ent = gFloaterAvatarList->getAvatarEntry(uuid);
01848         
01849                         if ( ent )
01850                         {
01851                                 ent->setActivity(ACTIVITY_SOUND);
01852                         }
01853                 }
01854         }
01855 
01856         // If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
01857         if (LLFloaterTelehub::renderBeacons())
01858         {
01859                 LLFloaterTelehub::addBeacons();
01860         }
01861 
01862         mSelectedFaces.clear();
01863         
01864         // Draw face highlights for selected faces.
01865         if (gSelectMgr->getTEMode())
01866         {
01867                 struct f : public LLSelectedTEFunctor
01868                 {
01869                         virtual bool apply(LLViewerObject* object, S32 te)
01870                         {
01871                                 if (object->mDrawable)
01872                                 {
01873                                         gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
01874                                 }
01875                                 return true;
01876                         }
01877                 } func;
01878                 gSelectMgr->getSelection()->applyToTEs(&func);
01879         }
01880 }
01881 
01882 
01883 static void render_hud_elements()
01884 {
01885         LLFastTimer t(LLFastTimer::FTM_RENDER_UI);
01886         gPipeline.disableLights();              
01887         
01888         gPipeline.renderDebug();
01889 
01890         LLGLDisable fog(GL_FOG);
01891         LLGLSUIDefault gls_ui;
01892         
01893         if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
01894         {
01895                 gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
01896         
01897                 // Draw the tracking overlays
01898                 LLTracker::render3D();
01899                 
01900                 // Show the property lines
01901                 if (gWorldp)
01902                 {
01903                         gWorldp->renderPropertyLines();
01904                 }
01905                 if (gParcelMgr)
01906                 {
01907                         gParcelMgr->render();
01908                         gParcelMgr->renderParcelCollision();
01909                 }
01910         
01911                 // Render debugging beacons.
01912                 gObjectList.renderObjectBeacons();
01913                 LLHUDObject::renderAll();
01914                 gObjectList.resetObjectBeacons();
01915         }
01916         else if (gForceRenderLandFence)
01917         {
01918                 // This is only set when not rendering the UI, for parcel snapshots
01919                 gParcelMgr->render();
01920         }
01921         else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
01922         {
01923                 LLHUDText::renderAllHUD();
01924         }
01925 }
01926 
01927 void LLPipeline::renderHighlights()
01928 {
01929         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01930         // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
01931         // Render highlighted faces.
01932         LLColor4 color(1.f, 1.f, 1.f, 0.5f);
01933         LLGLEnable color_mat(GL_COLOR_MATERIAL);
01934         disableLights();
01935 
01936         if ((LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0))
01937         {
01938                 gHighlightProgram.bind();
01939                 gHighlightProgram.vertexAttrib4f(LLShaderMgr::MATERIAL_COLOR,1,0,0,0.5f);
01940         }
01941         
01942         if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
01943         {
01944                 // Make sure the selection image gets downloaded and decoded
01945                 if (!mFaceSelectImagep)
01946                 {
01947                         mFaceSelectImagep = gImageList.getImage(IMG_FACE_SELECT);
01948                 }
01949                 mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
01950 
01951                 for (U32 i = 0; i < mSelectedFaces.size(); i++)
01952                 {
01953                         LLFace *facep = mSelectedFaces[i];
01954                         if (!facep || facep->getDrawable()->isDead())
01955                         {
01956                                 llerrs << "Bad face on selection" << llendl;
01957                                 return;
01958                         }
01959                         
01960                         facep->renderSelected(mFaceSelectImagep, color);
01961                 }
01962         }
01963 
01964         if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
01965         {
01966                 // Paint 'em red!
01967                 color.setVec(1.f, 0.f, 0.f, 0.5f);
01968                 for (U32 i = 0; i < mHighlightFaces.size(); i++)
01969                 {
01970                         LLFace* facep = mHighlightFaces[i];
01971                         facep->renderSelected(LLViewerImage::sNullImagep, color);
01972                 }
01973         }
01974 
01975         // Contains a list of the faces of objects that are physical or
01976         // have touch-handlers.
01977         mHighlightFaces.clear();
01978 
01979         if (LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0)
01980         {
01981                 gHighlightProgram.unbind();
01982         }
01983 }
01984 
01985 void LLPipeline::renderGeom(LLCamera& camera)
01986 {
01987         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01988         LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY);
01989         
01990         if (!mAlphaSizzleImagep)
01991         {
01992                 mAlphaSizzleImagep = gImageList.getImage(LLUUID(gViewerArt.getString("alpha_sizzle.tga")), MIPMAP_TRUE, TRUE);
01993         }
01994 
01996         //
01997         // Sync and verify GL state
01998         //
01999         //
02000 
02001         glEnableClientState(GL_VERTEX_ARRAY);
02002 
02003         stop_glerror();
02004         gFrameStats.start(LLFrameStats::RENDER_SYNC);
02005 
02006         // Do verification of GL state
02007 #ifndef LL_RELEASE_FOR_DOWNLOAD
02008         LLGLState::checkStates();
02009         LLGLState::checkTextureChannels();
02010         LLGLState::checkClientArrays();
02011 #endif
02012         if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
02013         {
02014                 if (!verify())
02015                 {
02016                         llerrs << "Pipeline verification failed!" << llendl;
02017                 }
02018         }
02019 
02020         {
02021                 //LLFastTimer ftm(LLFastTimer::FTM_TEMP6);
02022                 LLVertexBuffer::startRender();
02023         }
02024 
02025         for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
02026         {
02027                 LLDrawPool *poolp = *iter;
02028                 if (hasRenderType(poolp->getType()))
02029                 {
02030                         poolp->prerender();
02031                 }
02032         }
02033 
02034         gFrameStats.start(LLFrameStats::RENDER_GEOM);
02035 
02036         // Initialize lots of GL state to "safe" values
02037         glMatrixMode(GL_TEXTURE);
02038         glLoadIdentity();
02039         glMatrixMode(GL_MODELVIEW);
02040 
02041         LLGLSPipeline gls_pipeline;
02042         
02043         LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
02044         // LLGLState normalize(GL_NORMALIZE, TRUE);
02045                         
02046         // Toggle backface culling for debugging
02047         LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
02048         // Set fog
02049         LLGLEnable fog_enable(hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG) ? GL_FOG : 0);
02050         gSky.updateFog(camera.getFar());
02051 
02052         LLViewerImage::sDefaultImagep->bind(0);
02053         LLViewerImage::sDefaultImagep->setClamp(FALSE, FALSE);
02054         
02056         //
02057         // Actually render all of the geometry
02058         //
02059         //      
02060         stop_glerror();
02061         BOOL did_hud_elements = LLDrawPoolWater::sSkipScreenCopy;
02062         BOOL occlude = sUseOcclusion;
02063 
02064         U32 cur_type = 0;
02065 
02066         //********UMICH 3D LAB********
02067         // protect the color mask change for correct anaglyph render
02068         GLboolean mask[4];
02069         glGetBooleanv(GL_COLOR_WRITEMASK, mask);
02070         glColorMask(mask[0], mask[1], mask[2], GL_FALSE);
02071         //********UMICH 3D LAB********
02072 
02073         if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING))
02074         {
02075                 gObjectList.renderObjectsForSelect(camera);
02076         }
02077         else
02078         {
02079                 LLFastTimer t(LLFastTimer::FTM_POOLS);
02080                 calcNearbyLights(camera);
02081                 pool_set_t::iterator iter1 = mPools.begin();
02082                 while ( iter1 != mPools.end() )
02083                 {
02084                         LLDrawPool *poolp = *iter1;
02085                         
02086                         cur_type = poolp->getType();
02087 
02088                         if (occlude && cur_type > LLDrawPool::POOL_AVATAR)
02089                         {
02090                                 occlude = FALSE;
02091                                 doOcclusion(camera);
02092                         }
02093 
02094                         if (cur_type > LLDrawPool::POOL_ALPHA_POST_WATER && !did_hud_elements)
02095                         {
02096                                 renderHighlights();
02097                                 // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
02098                                 render_hud_elements();
02099                                 did_hud_elements = TRUE;
02100                         }
02101 
02102                         pool_set_t::iterator iter2 = iter1;
02103                         if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
02104                         {
02105                                 LLFastTimer t(LLFastTimer::FTM_POOLRENDER);
02106 
02107                                 setupHWLights(poolp);
02108                         
02109                                 for( S32 i = 0; i < poolp->getNumPasses(); i++ )
02110                                 {
02111                                         poolp->beginRenderPass(i);
02112                                         for (iter2 = iter1; iter2 != mPools.end(); iter2++)
02113                                         {
02114                                                 LLDrawPool *p = *iter2;
02115                                                 if (p->getType() != cur_type)
02116                                                 {
02117                                                         break;
02118                                                 }
02119                                                 
02120                                                 p->resetTrianglesDrawn();
02121                                                 p->render(i);
02122                                                 mTrianglesDrawn += p->getTrianglesDrawn();
02123                                         }
02124                                         poolp->endRenderPass(i);
02125 #ifndef LL_RELEASE_FOR_DOWNLOAD
02126 #if LL_DEBUG_GL
02127                                         GLint depth;
02128                                         glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
02129                                         if (depth > 3)
02130                                         {
02131                                                 llerrs << "GL matrix stack corrupted!" << llendl;
02132                                         }
02133                                         LLGLState::checkStates();
02134                                         LLGLState::checkTextureChannels();
02135                                         LLGLState::checkClientArrays();
02136 #endif
02137 #endif
02138                                 }
02139                         }
02140                         else
02141                         {
02142                                 // Skip all pools of this type
02143                                 for (iter2 = iter1; iter2 != mPools.end(); iter2++)
02144                                 {
02145                                         LLDrawPool *p = *iter2;
02146                                         if (p->getType() != cur_type)
02147                                         {
02148                                                 break;
02149                                         }
02150                                 }
02151                         }
02152                         iter1 = iter2;
02153                         stop_glerror();
02154                 }
02155         }
02156 
02157 #ifndef LL_RELEASE_FOR_DOWNLOAD
02158         LLGLState::checkStates();
02159         LLGLState::checkTextureChannels();
02160         LLGLState::checkClientArrays();
02161 #endif
02162 
02163         if (occlude)
02164         {
02165                 doOcclusion(camera);
02166                 occlude = FALSE;
02167         }
02168 
02169         if (!did_hud_elements)
02170         {
02171                 renderHighlights();
02172                 render_hud_elements();
02173         }
02174 
02175         stop_glerror();
02176         
02177         {
02178                 LLVertexBuffer::stopRender();
02179         }
02180         
02181 #ifndef LL_RELEASE_FOR_DOWNLOAD
02182                 LLGLState::checkStates();
02183                 LLGLState::checkTextureChannels();
02184                 LLGLState::checkClientArrays();
02185 #endif
02186         
02187         // Contains a list of the faces of objects that are physical or
02188         // have touch-handlers.
02189         mHighlightFaces.clear();
02190 
02191         //********UMICH 3D LAB********
02192         // protect the color mask change for correct anaglyph render
02193         glGetBooleanv(GL_COLOR_WRITEMASK, mask);
02194         glColorMask(mask[0], mask[1], mask[2], GL_FALSE);
02195         //********UMICH 3D LAB********
02196 
02197         if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && 
02198                 !LLDrawPoolWater::sSkipScreenCopy &&
02199                 sRenderGlow &&
02200                 gGLManager.mHasFramebufferObject)
02201         {
02202                 const U32 glow_res = nhpo2(gSavedSettings.getS32("RenderGlowResolution"));
02203                 if (mGlowMap == 0)
02204                 {
02205                         glGenTextures(1, &mGlowMap);
02206                         glBindTexture(GL_TEXTURE_2D, mGlowMap);
02207                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
02208                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
02209                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
02210                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
02211                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glow_res, glow_res, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
02212                 }
02213 
02214                 if (mGlowBuffer == 0)
02215                 {
02216                         glGenTextures(1, &mGlowBuffer);
02217                         glBindTexture(GL_TEXTURE_2D, mGlowBuffer);
02218                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
02219                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
02220                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
02221                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
02222                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glow_res, glow_res, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
02223                 }
02224 
02225                 bindScreenToTexture();
02226                 renderBloom(mScreenTex, mGlowMap, mGlowBuffer, glow_res, LLVector2(0,0), mScreenScale);
02227         }
02228 }
02229 
02230 void LLPipeline::processOcclusion(LLCamera& camera)
02231 {
02232         //process occlusion (readback)
02233         if (sUseOcclusion)
02234         {
02235                 for (U32 i = 0; i < mObjectPartition.size(); i++)
02236                 {
02237                         if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
02238                         {
02239                                 mObjectPartition[i]->processOcclusion(&camera);
02240                         }
02241                 }
02242                 
02243 #if AGGRESSIVE_OCCLUSION
02244                 for (LLSpatialBridge::bridge_vector_t::iterator i = mOccludedBridge.begin(); i != mOccludedBridge.end(); ++i)
02245                 {
02246                         LLSpatialBridge* bridge = *i;
02247                         if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
02248                         {
02249                                 LLCamera trans = bridge->transformCamera(camera);
02250                                 bridge->processOcclusion(&trans);
02251                         }
02252                 }
02253 #endif
02254                 mOccludedBridge.clear();
02255         }
02256 }
02257 
02258 void LLPipeline::renderDebug()
02259 {
02260         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02261 
02262         // Disable all client state
02263     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
02264     glDisableClientState(GL_NORMAL_ARRAY);
02265         glDisableClientState(GL_COLOR_ARRAY);
02266 
02267         // Debug stuff.
02268         for (U32 i = 0; i < mObjectPartition.size(); i++)
02269         {
02270                 if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
02271                 {
02272                         mObjectPartition[i]->renderDebug();
02273                 }
02274         }
02275 
02276         for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
02277         {
02278                 LLSpatialBridge* bridge = *i;
02279                 if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
02280                 {
02281                         glPushMatrix();
02282                         glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
02283                         bridge->renderDebug();
02284                         glPopMatrix();
02285                 }
02286         }
02287 
02288         if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_LIGHT_TRACE)
02289         {
02290                 LLGLSNoTexture no_texture;
02291 
02292                 LLVector3 pos, pos1;
02293 
02294                 for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin();
02295                          iter != mVisibleList.end(); iter++)
02296                 {
02297                         LLDrawable *drawablep = *iter;
02298                         if (drawablep->isDead())
02299                         {
02300                                 continue;
02301                         }
02302                         for (LLDrawable::drawable_set_t::iterator iter = drawablep->mLightSet.begin();
02303                                  iter != drawablep->mLightSet.end(); iter++)
02304                         {
02305                                 LLDrawable *targetp = *iter;
02306                                 if (targetp->isDead() || !targetp->getVObj()->getNumTEs())
02307                                 {
02308                                         continue;
02309                                 }
02310                                 else
02311                                 {
02312                                         if (targetp->getTextureEntry(0))
02313                                         {
02314                                                 if (drawablep->getVObj()->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
02315                                                 {
02316                                                         glColor4f(0.f, 1.f, 0.f, 1.f);
02317                                                         gObjectList.addDebugBeacon(drawablep->getPositionAgent(), "TC");
02318                                                 }
02319                                                 else
02320                                                 {
02321                                                         glColor4fv (targetp->getTextureEntry(0)->getColor().mV);
02322                                                 }
02323                                                 glBegin(GL_LINES);
02324                                                 glVertex3fv(targetp->getPositionAgent().mV);
02325                                                 glVertex3fv(drawablep->getPositionAgent().mV);
02326                                                 glEnd();
02327                                         }
02328                                 }
02329                         }
02330                 }
02331         }
02332 
02333         if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
02334         {
02335                 // Debug composition layers
02336                 F32 x, y;
02337 
02338                 LLGLSNoTexture gls_no_texture;
02339 
02340                 glBegin(GL_POINTS);
02341                 if (gAgent.getRegion())
02342                 {
02343                         // Draw the composition layer for the region that I'm in.
02344                         for (x = 0; x <= 260; x++)
02345                         {
02346                                 for (y = 0; y <= 260; y++)
02347                                 {
02348                                         if ((x > 255) || (y > 255))
02349                                         {
02350                                                 glColor4f(1.f, 0.f, 0.f, 1.f);
02351                                         }
02352                                         else
02353                                         {
02354                                                 glColor4f(0.f, 0.f, 1.f, 1.f);
02355                                         }
02356                                         F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y);
02357                                         z *= 5.f;
02358                                         z += 50.f;
02359                                         glVertex3f(x, y, z);
02360                                 }
02361                         }
02362                 }
02363                 glEnd();
02364         }
02365 }
02366 
02367 void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects)
02368 {
02369         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02370         
02371         LLVertexBuffer::startRender();
02372         
02373         glMatrixMode(GL_MODELVIEW);
02374 
02375         LLGLSDefault gls_default;
02376         LLGLSObjectSelect gls_object_select;
02377         LLGLDepthTest gls_depth(GL_TRUE,GL_TRUE);
02378         disableLights();
02379         
02380     glEnableClientState ( GL_VERTEX_ARRAY );
02381 
02382         //for each drawpool
02383 #ifndef LL_RELEASE_FOR_DOWNLOAD
02384         LLGLState::checkStates();
02385         LLGLState::checkTextureChannels();
02386         LLGLState::checkClientArrays();
02387         U32 last_type = 0;
02388 #endif
02389         for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
02390         {
02391                 LLDrawPool *poolp = *iter;
02392                 if (poolp->isFacePool() && hasRenderType(poolp->getType()))
02393                 {
02394                         LLFacePool* face_pool = (LLFacePool*) poolp;
02395                         face_pool->renderForSelect();
02396                 
02397 #ifndef LL_RELEASE_FOR_DOWNLOAD
02398                         if (poolp->getType() != last_type)
02399                         {
02400                                 last_type = poolp->getType();
02401                                 LLGLState::checkStates();
02402                                 LLGLState::checkTextureChannels();
02403                                 LLGLState::checkClientArrays();
02404                         }
02405 #endif
02406                 }
02407         }
02408 
02409         LLGLEnable tex(GL_TEXTURE_2D);
02410         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
02411         LLGLEnable alpha_test(GL_ALPHA_TEST);
02412         if (gPickTransparent)
02413         {
02414                 glAlphaFunc(GL_GEQUAL, 0.0f);
02415         }
02416         else
02417         {
02418                 glAlphaFunc(GL_GREATER, 0.2f);
02419         }
02420 
02421         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
02422         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_REPLACE);
02423         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB,         GL_MODULATE);
02424 
02425         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_PRIMARY_COLOR);
02426         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
02427 
02428         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,         GL_TEXTURE);
02429         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
02430 
02431         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB,         GL_PRIMARY_COLOR_ARB);
02432         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB,        GL_SRC_ALPHA);
02433 
02434         U32 prim_mask = LLVertexBuffer::MAP_VERTEX | 
02435                                         LLVertexBuffer::MAP_TEXCOORD;
02436 
02437         for (std::set<LLViewerObject*>::iterator i = objects.begin(); i != objects.end(); ++i)
02438         {
02439                 LLViewerObject* vobj = *i;
02440                 LLDrawable* drawable = vobj->mDrawable;
02441                 if (vobj->isDead() || 
02442                         vobj->isHUDAttachment() ||
02443                         (gHideSelectedObjects && vobj->isSelected()) ||
02444                         drawable->isDead() || 
02445                         !hasRenderType(drawable->getRenderType()))
02446                 {
02447                         continue;
02448                 }
02449 
02450                 for (S32 j = 0; j < drawable->getNumFaces(); ++j)
02451                 {
02452                         LLFace* facep = drawable->getFace(j);
02453                         if (!facep->getPool())
02454                         {
02455                                 facep->renderForSelect(prim_mask);
02456                         }
02457                 }
02458         }
02459 
02460         // pick HUD objects
02461         LLVOAvatar* avatarp = gAgent.getAvatarObject();
02462         if (avatarp && sShowHUDAttachments)
02463         {
02464                 glMatrixMode(GL_PROJECTION);
02465                 glPushMatrix();
02466                 glMatrixMode(GL_MODELVIEW);
02467                 glPushMatrix();
02468 
02469                 setup_hud_matrices(TRUE);
02470                 LLViewerJointAttachment* attachmentp;
02471                 for (attachmentp = avatarp->mAttachmentPoints.getFirstData();
02472                         attachmentp;
02473                         attachmentp = avatarp->mAttachmentPoints.getNextData())
02474                 {
02475                         if (attachmentp->getIsHUDAttachment())
02476                         {
02477                                 LLViewerObject* objectp = attachmentp->getObject();
02478                                 if (objectp)
02479                                 {
02480                                         LLDrawable* drawable = objectp->mDrawable;
02481                                         if (drawable->isDead())
02482                                         {
02483                                                 continue;
02484                                         }
02485 
02486                                         for (S32 j = 0; j < drawable->getNumFaces(); ++j)
02487                                         {
02488                                                 LLFace* facep = drawable->getFace(j);
02489                                                 if (!facep->getPool())
02490                                                 {
02491                                                         facep->renderForSelect(prim_mask);
02492                                                 }
02493                                         }
02494 
02495                                         //render child faces
02496                                         for (U32 k = 0; k < drawable->getChildCount(); ++k)
02497                                         {
02498                                                 LLDrawable* child = drawable->getChild(k);
02499                                                 for (S32 l = 0; l < child->getNumFaces(); ++l)
02500                                                 {
02501                                                         LLFace* facep = child->getFace(l);
02502                                                         if (!facep->getPool())
02503                                                         {
02504                                                                 facep->renderForSelect(prim_mask);
02505                                                         }
02506                                                 }
02507                                         }
02508                                 }       
02509                         }
02510                 }
02511 
02512                 glMatrixMode(GL_PROJECTION);
02513                 glPopMatrix();
02514                 glMatrixMode(GL_MODELVIEW);
02515                 glPopMatrix();
02516         }
02517 
02518         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
02519         glDisableClientState( GL_TEXTURE_COORD_ARRAY );
02520         
02521         LLVertexBuffer::stopRender();
02522 }
02523 
02524 void LLPipeline::renderFaceForUVSelect(LLFace* facep)
02525 {
02526         if (facep) facep->renderSelectedUV();
02527 }
02528 
02529 void LLPipeline::rebuildPools()
02530 {
02531         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02532         S32 max_count = mPools.size();
02533         pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
02534         while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS)
02535         {
02536                 if (iter1 == mPools.end())
02537                 {
02538                         iter1 = mPools.begin();
02539                 }
02540                 LLDrawPool* poolp = *iter1;
02541 
02542                 if (poolp->isDead())
02543                 {
02544                         mPools.erase(iter1++);
02545                         removeFromQuickLookup( poolp );
02546                         if (poolp == mLastRebuildPool)
02547                         {
02548                                 mLastRebuildPool = NULL;
02549                         }
02550                         delete poolp;
02551                 }
02552                 else
02553                 {
02554                         mLastRebuildPool = poolp;
02555                         iter1++;
02556                 }
02557                 max_count--;
02558         }
02559 
02560         if (gAgent.getAvatarObject())
02561         {
02562                 gAgent.getAvatarObject()->rebuildHUD();
02563         }
02564 }
02565 
02566 void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
02567 {
02568         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02569         switch( new_poolp->getType() )
02570         {
02571         case LLDrawPool::POOL_SIMPLE:
02572                 if (mSimplePool)
02573                 {
02574                         llassert(0);
02575                         llwarns << "Ignoring duplicate simple pool." << llendl;
02576                 }
02577                 else
02578                 {
02579                         mSimplePool = (LLRenderPass*) new_poolp;
02580                 }
02581                 break;
02582 
02583         case LLDrawPool::POOL_GLOW:
02584                 if (mGlowPool)
02585                 {
02586                         llassert(0);
02587                         llwarns << "Ignoring duplicate glow pool." << llendl;
02588                 }
02589                 else
02590                 {
02591                         mGlowPool = (LLRenderPass*) new_poolp;
02592                 }
02593                 break;
02594 
02595         case LLDrawPool::POOL_TREE:
02596                 mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
02597                 break;
02598  
02599         case LLDrawPool::POOL_TERRAIN:
02600                 mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
02601                 break;
02602 
02603         case LLDrawPool::POOL_BUMP:
02604                 if (mBumpPool)
02605                 {
02606                         llassert(0);
02607                         llwarns << "Ignoring duplicate bump pool." << llendl;
02608                 }
02609                 else
02610                 {
02611                         mBumpPool = new_poolp;
02612                 }
02613                 break;
02614 
02615         case LLDrawPool::POOL_ALPHA:
02616                 if( mAlphaPool )
02617                 {
02618                         llassert(0);
02619                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
02620                 }
02621                 else
02622                 {
02623                         mAlphaPool = new_poolp;
02624                 }
02625                 break;
02626 
02627         case LLDrawPool::POOL_ALPHA_POST_WATER:
02628                 if( mAlphaPoolPostWater )
02629                 {
02630                         llassert(0);
02631                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
02632                 }
02633                 else
02634                 {
02635                         mAlphaPoolPostWater = new_poolp;
02636                 }
02637                 break;
02638 
02639         case LLDrawPool::POOL_AVATAR:
02640                 break; // Do nothing
02641 
02642         case LLDrawPool::POOL_SKY:
02643                 if( mSkyPool )
02644                 {
02645                         llassert(0);
02646                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl;
02647                 }
02648                 else
02649                 {
02650                         mSkyPool = new_poolp;
02651                 }
02652                 break;
02653 
02654         case LLDrawPool::POOL_STARS:
02655                 if( mStarsPool )
02656                 {
02657                         llassert(0);
02658                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Stars pool" << llendl;
02659                 }
02660                 else
02661                 {
02662                         mStarsPool = new_poolp;
02663                 }
02664                 break;
02665         
02666         case LLDrawPool::POOL_WATER:
02667                 if( mWaterPool )
02668                 {
02669                         llassert(0);
02670                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl;
02671                 }
02672                 else
02673                 {
02674                         mWaterPool = new_poolp;
02675                 }
02676                 break;
02677 
02678         case LLDrawPool::POOL_GROUND:
02679                 if( mGroundPool )
02680                 {
02681                         llassert(0);
02682                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl;
02683                 }
02684                 else
02685                 { 
02686                         mGroundPool = new_poolp;
02687                 }
02688                 break;
02689 
02690         default:
02691                 llassert(0);
02692                 llwarns << "Invalid Pool Type in  LLPipeline::addPool()" << llendl;
02693                 break;
02694         }
02695 }
02696 
02697 void LLPipeline::removePool( LLDrawPool* poolp )
02698 {
02699         removeFromQuickLookup(poolp);
02700         mPools.erase(poolp);
02701         delete poolp;
02702 }
02703 
02704 void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
02705 {
02706         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02707         switch( poolp->getType() )
02708         {
02709         case LLDrawPool::POOL_SIMPLE:
02710                 llassert(mSimplePool == poolp);
02711                 mSimplePool = NULL;
02712                 break;
02713 
02714         case LLDrawPool::POOL_GLOW:
02715                 llassert(mGlowPool == poolp);
02716                 mGlowPool = NULL;
02717                 break;
02718 
02719         case LLDrawPool::POOL_TREE:
02720                 #ifdef _DEBUG
02721                         {
02722                                 BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() );
02723                                 llassert( found );
02724                         }
02725                 #else
02726                         mTreePools.erase( (uintptr_t)poolp->getTexture() );
02727                 #endif
02728                 break;
02729 
02730         case LLDrawPool::POOL_TERRAIN:
02731                 #ifdef _DEBUG
02732                         {
02733                                 BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
02734                                 llassert( found );
02735                         }
02736                 #else
02737                         mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
02738                 #endif
02739                 break;
02740 
02741         case LLDrawPool::POOL_BUMP:
02742                 llassert( poolp == mBumpPool );
02743                 mBumpPool = NULL;
02744                 break;
02745         
02746         case LLDrawPool::POOL_ALPHA:
02747                 llassert( poolp == mAlphaPool );
02748                 mAlphaPool = NULL;
02749                 break;
02750 
02751         case LLDrawPool::POOL_ALPHA_POST_WATER:
02752                 llassert( poolp == mAlphaPoolPostWater );
02753                 mAlphaPoolPostWater = NULL;
02754                 break;
02755 
02756         case LLDrawPool::POOL_AVATAR:
02757                 break; // Do nothing
02758 
02759         case LLDrawPool::POOL_SKY:
02760                 llassert( poolp == mSkyPool );
02761                 mSkyPool = NULL;
02762                 break;
02763 
02764         case LLDrawPool::POOL_STARS:
02765                 llassert( poolp == mStarsPool );
02766                 mStarsPool = NULL;
02767                 break;
02768 
02769         case LLDrawPool::POOL_WATER:
02770                 llassert( poolp == mWaterPool );
02771                 mWaterPool = NULL;
02772                 break;
02773 
02774         case LLDrawPool::POOL_GROUND:
02775                 llassert( poolp == mGroundPool );
02776                 mGroundPool = NULL;
02777                 break;
02778 
02779         default:
02780                 llassert(0);
02781                 llwarns << "Invalid Pool Type in  LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
02782                 break;
02783         }
02784 }
02785 
02786 void LLPipeline::resetDrawOrders()
02787 {
02788         // Iterate through all of the draw pools and rebuild them.
02789         for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
02790         {
02791                 LLDrawPool *poolp = *iter;
02792                 poolp->resetDrawOrders();
02793         }
02794 }
02795 
02796 //============================================================================
02797 // Once-per-frame setup of hardware lights,
02798 // including sun/moon, avatar backlight, and up to 6 local lights
02799 
02800 void LLPipeline::setupAvatarLights(BOOL for_edit)
02801 {
02802         const LLColor4 black(0,0,0,1);
02803 
02804         if (for_edit)
02805         {
02806                 LLColor4 diffuse(0.8f, 0.8f, 0.8f, 0.f);
02807                 LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f);  // w==0 => directional light
02808                 LLMatrix4 camera_mat = gCamera->getModelview();
02809                 LLMatrix4 camera_rot(camera_mat.getMat3());
02810                 camera_rot.invert();
02811                 LLVector4 light_pos = light_pos_cam * camera_rot;
02812                 
02813                 light_pos.normVec();
02814 
02815                 mHWLightColors[1] = diffuse;
02816                 glLightfv(GL_LIGHT1, GL_DIFFUSE,  diffuse.mV);
02817                 glLightfv(GL_LIGHT1, GL_AMBIENT,  black.mV);
02818                 glLightfv(GL_LIGHT1, GL_SPECULAR, black.mV);
02819                 glLightfv(GL_LIGHT1, GL_POSITION, light_pos.mV); 
02820                 glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION,  1.0f);
02821                 glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION,      0.0f);
02822                 glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
02823                 glLightf (GL_LIGHT1, GL_SPOT_EXPONENT,           0.0f);
02824                 glLightf (GL_LIGHT1, GL_SPOT_CUTOFF,                     180.0f);
02825         }
02826         else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini)
02827         {
02828                 LLVector3 opposite_pos = -1.f * mSunDir;
02829                 LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
02830                 LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
02831                 backlight_pos.normVec();
02832                         
02833                 LLColor4 light_diffuse = mSunDiffuse * mSunShadowFactor;
02834                 LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
02835                 F32 max_component = 0.001f;
02836                 for (S32 i = 0; i < 3; i++)
02837                 {
02838                         if (backlight_diffuse.mV[i] > max_component)
02839                         {
02840                                 max_component = backlight_diffuse.mV[i];
02841                         }
02842                 }
02843                 F32 backlight_mag;
02844                 if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS)
02845                 {
02846                         backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
02847                 }
02848                 else
02849                 {
02850                         backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT;
02851                 }
02852                 backlight_diffuse *= backlight_mag / max_component;
02853 
02854                 mHWLightColors[1] = backlight_diffuse;
02855                 glLightfv(GL_LIGHT1, GL_POSITION, backlight_pos.mV); // this is just sun/moon direction
02856                 glLightfv(GL_LIGHT1, GL_DIFFUSE,  backlight_diffuse.mV);
02857                 glLightfv(GL_LIGHT1, GL_AMBIENT,  black.mV);
02858                 glLightfv(GL_LIGHT1, GL_SPECULAR, black.mV);
02859                 glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION,  1.0f);
02860                 glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION,    0.0f);
02861                 glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
02862                 glLightf (GL_LIGHT1, GL_SPOT_EXPONENT,         0.0f);
02863                 glLightf (GL_LIGHT1, GL_SPOT_CUTOFF,           180.0f);
02864         }
02865         else
02866         {
02867                 mHWLightColors[1] = black;
02868                 glLightfv(GL_LIGHT1, GL_DIFFUSE,  black.mV);
02869                 glLightfv(GL_LIGHT1, GL_AMBIENT,  black.mV);
02870                 glLightfv(GL_LIGHT1, GL_SPECULAR, black.mV);
02871         }
02872 }
02873 
02874 static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
02875 {
02876         F32 inten = light->getLightIntensity();
02877         if (inten < .001f)
02878         {
02879                 return max_dist;
02880         }
02881         F32 radius = light->getLightRadius();
02882         BOOL selected = light->isSelected();
02883         LLVector3 dpos = light->getRenderPosition() - cam_pos;
02884         F32 dist2 = dpos.magVecSquared();
02885         if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
02886         {
02887                 return max_dist;
02888         }
02889         F32 dist = fsqrtf(dist2);
02890         dist *= 1.f / inten;
02891         dist -= radius;
02892         if (selected)
02893         {
02894                 dist -= 10000.f; // selected lights get highest priority
02895         }
02896         if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
02897         {
02898                 // moving lights get a little higher priority (too much causes artifacts)
02899                 dist -= light->getLightRadius()*0.25f;
02900         }
02901         return dist;
02902 }
02903 
02904 void LLPipeline::calcNearbyLights(LLCamera& camera)
02905 {
02906         if (mLightingDetail >= 1)
02907         {
02908                 // mNearbyLight (and all light_set_t's) are sorted such that
02909                 // begin() == the closest light and rbegin() == the farthest light
02910                 const S32 MAX_LOCAL_LIGHTS = 6;
02911 //              LLVector3 cam_pos = gAgent.getCameraPositionAgent();
02912                 LLVector3 cam_pos = LLPipeline::sSkipUpdate || LLViewerJoystick::sOverrideCamera ?
02913                                                 camera.getOrigin() : 
02914                                                 gAgent.getPositionAgent();
02915 
02916                 F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
02917                 
02918                 // UPDATE THE EXISTING NEARBY LIGHTS
02919                 if (!LLPipeline::sSkipUpdate)
02920                 {
02921                         light_set_t cur_nearby_lights;
02922                         for (light_set_t::iterator iter = mNearbyLights.begin();
02923                                 iter != mNearbyLights.end(); iter++)
02924                         {
02925                                 const Light* light = &(*iter);
02926                                 LLDrawable* drawable = light->drawable;
02927                                 LLVOVolume* volight = drawable->getVOVolume();
02928                                 if (!volight || !drawable->isState(LLDrawable::LIGHT))
02929                                 {
02930                                         drawable->clearState(LLDrawable::NEARBY_LIGHT);
02931                                         continue;
02932                                 }
02933                                 if (light->fade <= -LIGHT_FADE_TIME)
02934                                 {
02935                                         drawable->clearState(LLDrawable::NEARBY_LIGHT);
02936                                 }
02937                                 else
02938                                 {
02939                                         F32 dist = calc_light_dist(volight, cam_pos, max_dist);
02940                                         cur_nearby_lights.insert(Light(drawable, dist, light->fade));
02941                                 }
02942                         }
02943                         mNearbyLights = cur_nearby_lights;
02944                 }
02945                 
02946                 // FIND NEW LIGHTS THAT ARE IN RANGE
02947                 light_set_t new_nearby_lights;
02948                 for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
02949                          iter != mLights.end(); ++iter)
02950                 {
02951                         LLDrawable* drawable = *iter;
02952                         LLVOVolume* light = drawable->getVOVolume();
02953                         if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT))
02954                         {
02955                                 continue;
02956                         }
02957                         if (light->isHUDAttachment())
02958                         {
02959                                 continue; // no lighting from HUD objects
02960                         }
02961                         F32 dist = calc_light_dist(light, cam_pos, max_dist);
02962                         if (dist >= max_dist)
02963                         {
02964                                 continue;
02965                         }
02966                         new_nearby_lights.insert(Light(drawable, dist, 0.f));
02967                         if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
02968                         {
02969                                 new_nearby_lights.erase(--new_nearby_lights.end());
02970                                 const Light& last = *new_nearby_lights.rbegin();
02971                                 max_dist = last.dist;
02972                         }
02973                 }
02974 
02975                 // INSERT ANY NEW LIGHTS
02976                 for (light_set_t::iterator iter = new_nearby_lights.begin();
02977                          iter != new_nearby_lights.end(); iter++)
02978                 {
02979                         const Light* light = &(*iter);
02980                         if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
02981                         {
02982                                 mNearbyLights.insert(*light);
02983                                 ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
02984                         }
02985                         else
02986                         {
02987                                 // crazy cast so that we can overwrite the fade value
02988                                 // even though gcc enforces sets as const
02989                                 // (fade value doesn't affect sort so this is safe)
02990                                 Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
02991                                 if (light->dist < farthest_light->dist)
02992                                 {
02993                                         if (farthest_light->fade >= 0.f)
02994                                         {
02995                                                 farthest_light->fade = -gFrameIntervalSeconds;
02996                                         }
02997                                 }
02998                                 else
02999                                 {
03000                                         break; // none of the other lights are closer
03001                                 }
03002                         }
03003                 }
03004                 
03005         }
03006 }
03007 
03008 void LLPipeline::setupHWLights(LLDrawPool* pool)
03009 {
03010         const LLColor4 black(0,0,0,1);
03011 
03012         // Ambient
03013         LLColor4 ambient = gSky.getTotalAmbientColor();
03014         glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
03015 
03016         // Light 0 = Sun or Moon (All objects)
03017         {
03018                 mSunShadowFactor = 1.f; // no shadowing by defailt
03019                 if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS)
03020                 {
03021                         mSunDir.setVec(gSky.getSunDirection());
03022                         mSunDiffuse.setVec(gSky.getSunDiffuseColor());
03023                 }
03024                 else
03025                 {
03026                         mSunDir.setVec(gSky.getMoonDirection());
03027                         mSunDiffuse.setVec(gSky.getMoonDiffuseColor() * 1.5f);
03028                 }
03029 
03030                 F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
03031                 if (max_color > 1.f)
03032                 {
03033                         mSunDiffuse *= 1.f/max_color;
03034                 }
03035                 mSunDiffuse.clamp();
03036 
03037                 LLVector4 light_pos(mSunDir, 0.0f);
03038                 LLColor4 light_diffuse = mSunDiffuse * mSunShadowFactor;
03039                 mHWLightColors[0] = light_diffuse;
03040                 glLightfv(GL_LIGHT0, GL_POSITION, light_pos.mV); // this is just sun/moon direction
03041                 glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse.mV);
03042                 glLightfv(GL_LIGHT0, GL_AMBIENT,  black.mV);
03043                 glLightfv(GL_LIGHT0, GL_SPECULAR, black.mV);
03044                 glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION,  1.0f);
03045                 glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION,    0.0f);
03046                 glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f);
03047                 glLightf (GL_LIGHT0, GL_SPOT_EXPONENT,         0.0f);
03048                 glLightf (GL_LIGHT0, GL_SPOT_CUTOFF,           180.0f);
03049         }
03050         
03051         // Light 1 = Backlight (for avatars)
03052         // (set by enableLightsAvatar)
03053         
03054         S32 cur_light = 2;
03055         
03056         // Nearby lights = LIGHT 2-7
03057 
03058         mLightMovingMask = 0;
03059         
03060         if (mLightingDetail >= 1)
03061         {
03062                 for (light_set_t::iterator iter = mNearbyLights.begin();
03063                          iter != mNearbyLights.end(); ++iter)
03064                 {
03065                         LLDrawable* drawable = iter->drawable;
03066                         LLVOVolume* light = drawable->getVOVolume();
03067                         if (!light)
03068                         {
03069                                 continue;
03070                         }
03071                         if (drawable->isState(LLDrawable::ACTIVE))
03072                         {
03073                                 mLightMovingMask |= (1<<cur_light);
03074                         }
03075                         
03076                         LLColor4  light_color = light->getLightColor();
03077                         light_color.mV[3] = 0.0f;
03078 
03079                         F32 fade = LLPipeline::sSkipUpdate ? 1.f : iter->fade;
03080                         if (fade < LIGHT_FADE_TIME)
03081                         {
03082                                 // fade in/out light
03083                                 if (fade >= 0.f)
03084                                 {
03085                                         fade = fade / LIGHT_FADE_TIME;
03086                                         ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds;
03087                                 }
03088                                 else
03089                                 {
03090                                         fade = 1.f + fade / LIGHT_FADE_TIME;
03091                                         ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds;
03092                                 }
03093                                 fade = llclamp(fade,0.f,1.f);
03094                                 light_color *= fade;
03095                         }
03096 
03097                         LLVector3 light_pos(light->getRenderPosition());
03098                         LLVector4 light_pos_gl(light_pos, 1.0f);
03099         
03100                         F32 light_radius = llmax(light->getLightRadius(), 0.001f);
03101                         F32 atten, quad;
03102 
03103 #if 0 //1.9.1
03104                         if (pool->getVertexShaderLevel() > 0)
03105                         {
03106                                 atten = light_radius;
03107                                 quad = llmax(light->getLightFalloff(), 0.0001f);
03108                         }
03109                         else
03110 #endif
03111                         {
03112                                 F32 x = (3.f * (1.f + light->getLightFalloff()));
03113                                 atten = x / (light_radius); // % of brightness at radius
03114                                 quad = 0.0f;
03115                         }
03116                         mHWLightColors[cur_light] = light_color;
03117                         S32 gllight = GL_LIGHT0+cur_light;
03118                         glLightfv(gllight, GL_POSITION, light_pos_gl.mV);
03119                         glLightfv(gllight, GL_DIFFUSE,  light_color.mV);
03120                         glLightfv(gllight, GL_AMBIENT,  black.mV);
03121                         glLightfv(gllight, GL_SPECULAR, black.mV);
03122                         glLightf (gllight, GL_CONSTANT_ATTENUATION,   0.0f);
03123                         glLightf (gllight, GL_LINEAR_ATTENUATION,     atten);
03124                         glLightf (gllight, GL_QUADRATIC_ATTENUATION,  quad);
03125                         glLightf (gllight, GL_SPOT_EXPONENT,          0.0f);
03126                         glLightf (gllight, GL_SPOT_CUTOFF,            180.0f);
03127                         cur_light++;
03128                         if (cur_light >= 8)
03129                         {
03130                                 break; // safety
03131                         }
03132                 }
03133         }
03134         for ( ; cur_light < 8 ; cur_light++)
03135         {
03136                 mHWLightColors[cur_light] = black;
03137                 S32 gllight = GL_LIGHT0+cur_light;
03138                 glLightfv(gllight, GL_DIFFUSE,  black.mV);
03139                 glLightfv(gllight, GL_AMBIENT,  black.mV);
03140                 glLightfv(gllight, GL_SPECULAR, black.mV);
03141         }
03142 
03143         // Init GL state
03144         glDisable(GL_LIGHTING);
03145         for (S32 gllight=GL_LIGHT0; gllight<=GL_LIGHT7; gllight++)
03146         {
03147                 glDisable(gllight);
03148         }
03149         mLightMask = 0;
03150 }
03151 
03152 void LLPipeline::enableLights(U32 mask, F32 shadow_factor)
03153 {
03154         if (mLightingDetail == 0)
03155         {
03156                 mask &= 0xf003; // sun and backlight only (and fullbright bit)
03157         }
03158         if (mLightMask != mask)
03159         {
03160                 if (!mLightMask)
03161                 {
03162                         glEnable(GL_LIGHTING);
03163                 }
03164                 if (mask)
03165                 {
03166                         for (S32 i=0; i<8; i++)
03167                         {
03168                                 if (mask & (1<<i))
03169                                 {
03170                                         glEnable(GL_LIGHT0 + i);
03171                                         glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  mHWLightColors[i].mV);
03172                                 }
03173                                 else
03174                                 {
03175                                         glDisable(GL_LIGHT0 + i);
03176                                         glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  LLColor4::black.mV);
03177                                 }
03178                         }
03179                 }
03180                 else
03181                 {
03182                         glDisable(GL_LIGHTING);
03183                 }
03184                 mLightMask = mask;
03185                 LLColor4 ambient = gSky.getTotalAmbientColor();
03186                 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
03187         }
03188 }
03189 
03190 void LLPipeline::enableLightsStatic(F32 shadow_factor)
03191 {
03192         U32 mask = 0x01; // Sun
03193         if (mLightingDetail >= 2)
03194         {
03195                 mask |= mLightMovingMask; // Hardware moving lights
03196                 glColor4f(0.f, 0.f, 0.f, 1.0f); // no local lighting by default
03197         }
03198         else
03199         {
03200                 mask |= 0xff & (~2); // Hardware local lights
03201         }
03202         enableLights(mask, shadow_factor);
03203 }
03204 
03205 void LLPipeline::enableLightsDynamic(F32 shadow_factor)
03206 {
03207         U32 mask = 0xff & (~2); // Local lights
03208         enableLights(mask, shadow_factor);
03209         if (mLightingDetail >= 2)
03210         {
03211                 glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default
03212         }
03213 }
03214 
03215 void LLPipeline::enableLightsAvatar(F32 shadow_factor)
03216 {
03217         U32 mask = 0xff; // All lights
03218         setupAvatarLights(FALSE);
03219         enableLights(mask, shadow_factor);
03220 }
03221 
03222 void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
03223 {
03224         U32 mask = 0x2002; // Avatar backlight only, set ambient
03225         setupAvatarLights(TRUE);
03226         enableLights(mask, 1.0f);
03227 
03228         glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
03229 }
03230 
03231 void LLPipeline::enableLightsFullbright(const LLColor4& color)
03232 {
03233         U32 mask = 0x1000; // Non-0 mask, set ambient
03234         enableLights(mask, 1.f);
03235 
03236         glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
03237         if (mLightingDetail >= 2)
03238         {
03239                 glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default
03240         }
03241 }
03242 
03243 void LLPipeline::disableLights()
03244 {
03245         enableLights(0, 0.f); // no lighting (full bright)
03246         glColor4f(1.f, 1.f, 1.f, 1.f); // lighting color = white by default
03247 }
03248 
03249 // Call *after*s etting up lights
03250 void LLPipeline::setAmbient(const LLColor4& ambient)
03251 {
03252         mLightMask |= 0x4000; // tweak mask so that ambient will get reset
03253         LLColor4 amb = ambient + gSky.getTotalAmbientColor();
03254         amb.clamp();
03255         glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb.mV);
03256 }
03257 
03258 //============================================================================
03259 
03260 class LLMenuItemGL;
03261 class LLInvFVBridge;
03262 struct cat_folder_pair;
03263 class LLVOBranch;
03264 class LLVOLeaf;
03265 class Foo;
03266 
03267 void scale_stamp(const F32 x, const F32 y, const F32 xs, const F32 ys)
03268 {
03269         stamp(0.25f + 0.5f*x,
03270                   0.5f + 0.45f*y,
03271                   0.5f*xs,
03272                   0.45f*ys);
03273 }
03274 
03275 void drawBars(const F32 begin, const F32 end, const F32 height = 1.f)
03276 {
03277         if (begin >= 0 && end <=1)
03278         {
03279                 F32 lines  = 40.0f;
03280                 S32 ibegin = (S32)(begin * lines);
03281                 S32 iend   = (S32)(end   * lines);
03282                 F32 fbegin = begin * lines - ibegin;
03283                 F32 fend   = end   * lines - iend;
03284 
03285                 F32 line_height = height/lines;
03286 
03287                 if (iend == ibegin)
03288                 {
03289                         scale_stamp(fbegin, (F32)ibegin/lines,fend-fbegin, line_height);
03290                 }
03291                 else
03292                 {
03293                         // Beginning row
03294                         scale_stamp(fbegin, (F32)ibegin/lines,  1.0f-fbegin, line_height);
03295 
03296                         // End row
03297                         scale_stamp(0.0,    (F32)iend/lines,  fend, line_height);
03298 
03299                         // Middle rows
03300                         for (S32 l = (ibegin+1); l < iend; l++)
03301                         {
03302                                 scale_stamp(0.0f, (F32)l/lines, 1.0f, line_height);
03303                         }
03304                 }
03305         }
03306 }
03307 
03308 void LLPipeline::findReferences(LLDrawable *drawablep)
03309 {
03310         if (std::find(mVisibleList.begin(), mVisibleList.end(), drawablep) != mVisibleList.end())
03311         {
03312                 llinfos << "In mVisibleList" << llendl;
03313         }
03314         if (mLights.find(drawablep) != mLights.end())
03315         {
03316                 llinfos << "In mLights" << llendl;
03317         }
03318         if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
03319         {
03320                 llinfos << "In mMovedList" << llendl;
03321         }
03322         if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end())
03323         {
03324                 llinfos << "In mShiftList" << llendl;
03325         }
03326         if (mRetexturedList.find(drawablep) != mRetexturedList.end())
03327         {
03328                 llinfos << "In mRetexturedList" << llendl;
03329         }
03330         
03331         if (mActiveQ.find(drawablep) != mActiveQ.end())
03332         {
03333                 llinfos << "In mActiveQ" << llendl;
03334         }
03335         if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
03336         {
03337                 llinfos << "In mBuildQ1" << llendl;
03338         }
03339         if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
03340         {
03341                 llinfos << "In mBuildQ2" << llendl;
03342         }
03343 
03344         S32 count;
03345         
03346         count = gObjectList.findReferences(drawablep);
03347         if (count)
03348         {
03349                 llinfos << "In other drawables: " << count << " references" << llendl;
03350         }
03351 }
03352 
03353 BOOL LLPipeline::verify()
03354 {
03355         BOOL ok = TRUE;
03356         for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
03357         {
03358                 LLDrawPool *poolp = *iter;
03359                 if (!poolp->verify())
03360                 {
03361                         ok = FALSE;
03362                 }
03363         }
03364 
03365         if (!ok)
03366         {
03367                 llwarns << "Pipeline verify failed!" << llendl;
03368         }
03369         return ok;
03370 }
03371 
03373 //
03374 // Collision detection
03375 //
03376 //
03377 
03379 
03399 
03400 //#define RAYAABB_EPSILON 0.00001f
03401 #define IR(x)   ((U32&)x)
03402 
03403 bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon)
03404 {
03405         BOOL Inside = TRUE;
03406         LLVector3 MinB = center - size;
03407         LLVector3 MaxB = center + size;
03408         LLVector3 MaxT;
03409         MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f;
03410 
03411         // Find candidate planes.
03412         for(U32 i=0;i<3;i++)
03413         {
03414                 if(origin.mV[i] < MinB.mV[i])
03415                 {
03416                         coord.mV[i]     = MinB.mV[i];
03417                         Inside          = FALSE;
03418 
03419                         // Calculate T distances to candidate planes
03420                         if(IR(dir.mV[i]))       MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i];
03421                 }
03422                 else if(origin.mV[i] > MaxB.mV[i])
03423                 {
03424                         coord.mV[i]     = MaxB.mV[i];
03425                         Inside          = FALSE;
03426 
03427                         // Calculate T distances to candidate planes
03428                         if(IR(dir.mV[i]))       MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i];
03429                 }
03430         }
03431 
03432         // Ray origin inside bounding box
03433         if(Inside)
03434         {
03435                 coord = origin;
03436                 return true;
03437         }
03438 
03439         // Get largest of the maxT's for final choice of intersection
03440         U32 WhichPlane = 0;
03441         if(MaxT.mV[1] > MaxT.mV[WhichPlane])    WhichPlane = 1;
03442         if(MaxT.mV[2] > MaxT.mV[WhichPlane])    WhichPlane = 2;
03443 
03444         // Check final candidate actually inside box
03445         if(IR(MaxT.mV[WhichPlane])&0x80000000) return false;
03446 
03447         for(U32 i=0;i<3;i++)
03448         {
03449                 if(i!=WhichPlane)
03450                 {
03451                         coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i];
03452                         if (epsilon > 0)
03453                         {
03454                                 if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon)    return false;
03455                         }
03456                         else
03457                         {
03458                                 if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i])        return false;
03459                         }
03460                 }
03461         }
03462         return true;    // ray hits box
03463 }
03464 
03466 //
03467 // Macros, functions, and inline methods from other classes
03468 //
03469 //
03470 
03471 void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
03472 {
03473         if (drawablep)
03474         {
03475                 if (is_light)
03476                 {
03477                         mLights.insert(drawablep);
03478                         drawablep->setState(LLDrawable::LIGHT);
03479                 }
03480                 else
03481                 {
03482                         drawablep->clearState(LLDrawable::LIGHT);
03483                         mLights.erase(drawablep);
03484                 }
03485                 markRelight(drawablep);
03486         }
03487 }
03488 
03489 void LLPipeline::setActive(LLDrawable *drawablep, BOOL active)
03490 {
03491         if (active)
03492         {
03493                 mActiveQ.insert(drawablep);
03494         }
03495         else
03496         {
03497                 mActiveQ.erase(drawablep);
03498         }
03499 }
03500 
03501 //static
03502 void LLPipeline::toggleRenderType(U32 type)
03503 {
03504         U32 bit = (1<<type);
03505         gPipeline.mRenderTypeMask ^= bit;
03506 }
03507 
03508 //static
03509 void LLPipeline::toggleRenderTypeControl(void* data)
03510 {
03511         U32 type = (U32)(intptr_t)data;
03512         U32 bit = (1<<type);
03513         if (gPipeline.hasRenderType(type))
03514         {
03515                 llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl;
03516         }
03517         else
03518         {
03519                 llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
03520         }
03521         gPipeline.toggleRenderType(type);
03522 }
03523 
03524 //static
03525 BOOL LLPipeline::hasRenderTypeControl(void* data)
03526 {
03527         U32 type = (U32)(intptr_t)data;
03528         return gPipeline.hasRenderType(type);
03529 }
03530 
03531 // Allows UI items labeled "Hide foo" instead of "Show foo"
03532 //static
03533 BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
03534 {
03535         S32 type = (S32)(intptr_t)data;
03536         return !gPipeline.hasRenderType(type);
03537 }
03538 
03539 //static
03540 void LLPipeline::toggleRenderDebug(void* data)
03541 {
03542         U32 bit = (U32)(intptr_t)data;
03543         if (gPipeline.hasRenderDebugMask(bit))
03544         {
03545                 llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl;
03546         }
03547         else
03548         {
03549                 llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl;
03550         }
03551         gPipeline.mRenderDebugMask ^= bit;
03552 }
03553 
03554 
03555 //static
03556 BOOL LLPipeline::toggleRenderDebugControl(void* data)
03557 {
03558         U32 bit = (U32)(intptr_t)data;
03559         return gPipeline.hasRenderDebugMask(bit);
03560 }
03561 
03562 //static
03563 void LLPipeline::toggleRenderDebugFeature(void* data)
03564 {
03565         U32 bit = (U32)(intptr_t)data;
03566         gPipeline.mRenderDebugFeatureMask ^= bit;
03567 }
03568 
03569 
03570 //static
03571 BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
03572 {
03573         U32 bit = (U32)(intptr_t)data;
03574         return gPipeline.hasRenderDebugFeatureMask(bit);
03575 }
03576 
03577 // static
03578 void LLPipeline::setRenderScriptedBeacons(BOOL val)
03579 {
03580         sRenderScriptedBeacons = val;
03581 }
03582 
03583 // static
03584 void LLPipeline::toggleRenderScriptedBeacons(void*)
03585 {
03586         sRenderScriptedBeacons = !sRenderScriptedBeacons;
03587 }
03588 
03589 // static
03590 BOOL LLPipeline::getRenderScriptedBeacons(void*)
03591 {
03592         return sRenderScriptedBeacons;
03593 }
03594 
03595 // static
03596 void LLPipeline::setRenderScriptedTouchBeacons(BOOL val)
03597 {
03598         sRenderScriptedTouchBeacons = val;
03599 }
03600 
03601 // static
03602 void LLPipeline::toggleRenderScriptedTouchBeacons(void*)
03603 {
03604         sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons;
03605 }
03606 
03607 // static
03608 BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
03609 {
03610         return sRenderScriptedTouchBeacons;
03611 }
03612 
03613 // static
03614 void LLPipeline::setRenderPhysicalBeacons(BOOL val)
03615 {
03616         sRenderPhysicalBeacons = val;
03617 }
03618 
03619 // static
03620 void LLPipeline::toggleRenderPhysicalBeacons(void*)
03621 {
03622         sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
03623 }
03624 
03625 // static
03626 BOOL LLPipeline::getRenderPhysicalBeacons(void*)
03627 {
03628         return sRenderPhysicalBeacons;
03629 }
03630 
03631 // static
03632 void LLPipeline::setRenderParticleBeacons(BOOL val)
03633 {
03634         sRenderParticleBeacons = val;
03635 }
03636 
03637 // static
03638 void LLPipeline::toggleRenderParticleBeacons(void*)
03639 {
03640         sRenderParticleBeacons = !sRenderParticleBeacons;
03641 }
03642 
03643 // static
03644 BOOL LLPipeline::getRenderParticleBeacons(void*)
03645 {
03646         return sRenderParticleBeacons;
03647 }
03648 
03649 // static
03650 void LLPipeline::setRenderSoundBeacons(BOOL val)
03651 {
03652         sRenderSoundBeacons = val;
03653 }
03654 
03655 // static
03656 void LLPipeline::toggleRenderSoundBeacons(void*)
03657 {
03658         sRenderSoundBeacons = !sRenderSoundBeacons;
03659 }
03660 
03661 // static
03662 BOOL LLPipeline::getRenderSoundBeacons(void*)
03663 {
03664         return sRenderSoundBeacons;
03665 }
03666 
03667 // static
03668 void LLPipeline::setRenderBeacons(BOOL val)
03669 {
03670         sRenderBeacons = val;
03671 }
03672 
03673 // static
03674 void LLPipeline::toggleRenderBeacons(void*)
03675 {
03676         sRenderBeacons = !sRenderBeacons;
03677 }
03678 
03679 // static
03680 BOOL LLPipeline::getRenderBeacons(void*)
03681 {
03682         return sRenderBeacons;
03683 }
03684 
03685 // static
03686 void LLPipeline::setRenderHighlights(BOOL val)
03687 {
03688         sRenderHighlight = val;
03689 }
03690 
03691 // static
03692 void LLPipeline::toggleRenderHighlights(void*)
03693 {
03694         sRenderHighlight = !sRenderHighlight;
03695 }
03696 
03697 // static
03698 BOOL LLPipeline::getRenderHighlights(void*)
03699 {
03700         return sRenderHighlight;
03701 }
03702 
03703 // static
03704 BOOL LLPipeline::getProcessBeacons(void* data)
03705 {
03706         return sRenderProcessBeacons;
03707 }
03708 
03709 LLViewerObject* LLPipeline::pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision)
03710 {
03711         LLDrawable* drawable = mObjectPartition[PARTITION_VOLUME]->pickDrawable(start, end, collision);
03712         return drawable ? drawable->getVObj().get() : NULL;
03713 }
03714 
03715 LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
03716 {
03717         if (vobj)
03718         {
03719                 return getSpatialPartition(vobj->getPartitionType());
03720         }
03721         return NULL;
03722 }
03723 
03724 LLSpatialPartition* LLPipeline::getSpatialPartition(U32 type)
03725 {
03726         if (type < mObjectPartition.size())
03727         {
03728                 return mObjectPartition[type];
03729         }
03730         return NULL;
03731 }
03732 
03733 void LLPipeline::clearRenderMap()
03734 {
03735         for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++)
03736         {
03737                 mRenderMap[i].clear();
03738         }
03739 }
03740 
03741 
03742 void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
03743 {
03744         for (S32 i = 0; i < drawable->getNumFaces(); i++)
03745         {
03746                 LLFace* facep = drawable->getFace(i);
03747                 facep->mVertexBuffer = NULL;
03748                 facep->mLastVertexBuffer = NULL;
03749         }
03750 }
03751 
03752 void LLPipeline::resetVertexBuffers()
03753 {
03754         for (U32 i = 0; i < mObjectPartition.size(); ++i)
03755         {
03756                 if (mObjectPartition[i])
03757                 {
03758                         mObjectPartition[i]->resetVertexBuffers();
03759                 }
03760         }
03761 
03762         resetDrawOrders();
03763 
03764         if (gSky.mVOSkyp.notNull())
03765         {
03766                 resetVertexBuffers(gSky.mVOSkyp->mDrawable);
03767                 resetVertexBuffers(gSky.mVOGroundp->mDrawable);
03768                 resetVertexBuffers(gSky.mVOStarsp->mDrawable);
03769                 markRebuild(gSky.mVOSkyp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
03770                 markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
03771                 markRebuild(gSky.mVOStarsp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
03772         }
03773 
03774         if (LLVertexBuffer::sGLCount > 0)
03775         {
03776                 LLVertexBuffer::cleanupClass();
03777         }
03778 }
03779 
03780 void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture)
03781 {
03782         mSimplePool->renderStatic(type, mask, texture);
03783         mSimplePool->renderActive(type, mask, texture);
03784 }
03785 
03786 void LLPipeline::setUseVBO(BOOL use_vbo)
03787 {
03788         if (use_vbo != LLVertexBuffer::sEnableVBOs)
03789         {
03790                 if (use_vbo)
03791                 {
03792                         llinfos << "Enabling VBO." << llendl;
03793                 }
03794                 else
03795                 { 
03796                         llinfos << "Disabling VBO." << llendl;
03797                 }
03798                 
03799                 resetVertexBuffers();
03800                 LLVertexBuffer::initClass(use_vbo);
03801         }
03802 }
03803 
03804 void apply_cube_face_rotation(U32 face)
03805 {
03806         switch (face)
03807         {
03808                 case 0: 
03809                         glRotatef(90.f, 0, 1, 0);
03810                         glRotatef(180.f, 1, 0, 0);
03811                 break;
03812                 case 2: 
03813                         glRotatef(-90.f, 1, 0, 0);
03814                 break;
03815                 case 4:
03816                         glRotatef(180.f, 0, 1, 0);
03817                         glRotatef(180.f, 0, 0, 1);
03818                 break;
03819                 case 1: 
03820                         glRotatef(-90.f, 0, 1, 0);
03821                         glRotatef(180.f, 1, 0, 0);
03822                 break;
03823                 case 3:
03824                         glRotatef(90, 1, 0, 0);
03825                 break;
03826                 case 5: 
03827                         glRotatef(180, 0, 0, 1);
03828                 break;
03829         }
03830 }
03831 void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam, GLsizei res)
03832 {
03833         //render dynamic cube map
03834         U32 type_mask = gPipeline.getRenderTypeMask();
03835         BOOL use_occlusion = LLPipeline::sUseOcclusion;
03836         LLPipeline::sUseOcclusion = FALSE;
03837         LLPipeline::sSkipUpdate = TRUE;
03838         static GLuint blur_tex = 0;
03839         if (!blur_tex)
03840         {
03841                 glGenTextures(1, &blur_tex);
03842         }
03843 
03844         BOOL reattach = FALSE;
03845         if (mCubeFrameBuffer == 0)
03846         {
03847 #if !defined(__sparc)
03848                 glGenFramebuffersEXT(1, &mCubeFrameBuffer);
03849                 glGenRenderbuffersEXT(1, &mCubeDepth);
03850 #else
03851 #error Can we generalize this without a CPU architecture test?
03852 #endif
03853                 reattach = TRUE;
03854         }
03855 
03856         BOOL toggle_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
03857         if (toggle_ui)
03858         {
03859                 gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
03860         }
03861         
03862         U32 cube_mask = (1 << LLPipeline::RENDER_TYPE_SIMPLE) |
03863                                         (1 << LLPipeline::RENDER_TYPE_WATER) |
03864                                         (1 << LLPipeline::RENDER_TYPE_BUMP) |
03865                                         (1 << LLPipeline::RENDER_TYPE_ALPHA) |
03866                                         (1 << LLPipeline::RENDER_TYPE_TREE) |
03867                                         (1 << LLDrawPool::POOL_ALPHA_POST_WATER) |
03868                                         //(1 << LLPipeline::RENDER_TYPE_PARTICLES) |
03869                                         (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
03870                                         //(1 << LLPipeline::RENDER_TYPE_STARS) |
03871                                         //(1 << LLPipeline::RENDER_TYPE_AVATAR) |
03872                                         (1 << LLPipeline::RENDER_TYPE_GLOW) |
03873                                         (1 << LLPipeline::RENDER_TYPE_GRASS) |
03874                                         (1 << LLPipeline::RENDER_TYPE_VOLUME) |
03875                                         (1 << LLPipeline::RENDER_TYPE_TERRAIN) |
03876                                         (1 << LLPipeline::RENDER_TYPE_SKY) |
03877                                         (1 << LLPipeline::RENDER_TYPE_GROUND);
03878         
03879         LLDrawPoolWater::sSkipScreenCopy = TRUE;
03880         cube_mask = cube_mask & type_mask;
03881         gPipeline.setRenderTypeMask(cube_mask);
03882 
03883         glMatrixMode(GL_PROJECTION);
03884         glPushMatrix();
03885         glMatrixMode(GL_MODELVIEW);
03886         glPushMatrix();
03887 
03888         glViewport(0,0,res,res);
03889         
03890         glClearColor(0,0,0,0);                  
03891         
03892         U32 cube_face[] = 
03893         {
03894                 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
03895                 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
03896                 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
03897                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
03898                 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
03899                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
03900         };
03901         
03902         LLVector3 origin = cube_cam.getOrigin();
03903 
03904         gPipeline.calcNearbyLights(cube_cam);
03905 
03906         cube_map->bind();
03907         for (S32 i = 0; i < 6; i++)
03908         {
03909                 GLint res_x, res_y;
03910                 glGetTexLevelParameteriv(cube_face[i], 0, GL_TEXTURE_WIDTH, &res_x);
03911                 glGetTexLevelParameteriv(cube_face[i], 0, GL_TEXTURE_HEIGHT, &res_y);
03912 
03913                 if (res_x != res || res_y != res)
03914                 {
03915                         glTexImage2D(cube_face[i],0,GL_RGBA,res,res,0,GL_RGBA,GL_FLOAT,NULL);
03916                         reattach = TRUE;
03917                 }
03918         }
03919         cube_map->disable();
03920 
03921         if (reattach)
03922         {
03923 #if !defined(__sparc)
03924                 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mCubeDepth);
03925                 GLint res_x, res_y;
03926                 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_WIDTH_EXT, &res_x);
03927                 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &res_y);
03928 
03929                 if (res_x != res || res_y != res)
03930                 {
03931                         glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,res,res);
03932                 }
03933                 
03934                 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
03935 #else
03936 #error Can we generalize this without a CPU architecture test?
03937 #endif
03938         }
03939 
03940         for (S32 i = 0; i < 6; i++)
03941         {
03942 #if !defined(__sparc)
03943                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer);
03944                 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
03945                                                                         cube_face[i], cube_map->getGLName(), 0);
03946                 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
03947                                                                                 GL_RENDERBUFFER_EXT, mCubeDepth);               
03948 #else
03949 #error Can we generalize this without a CPU architecture test?
03950 #endif
03951                 glMatrixMode(GL_PROJECTION);
03952                 glLoadIdentity();
03953                 gluPerspective(90.f, 1.f, 0.1f, 1024.f);
03954                 glMatrixMode(GL_MODELVIEW);
03955                 glLoadIdentity();
03956                 
03957                 apply_cube_face_rotation(i);
03958 
03959                 glTranslatef(-origin.mV[0], -origin.mV[1], -origin.mV[2]);
03960                 cube_cam.setOrigin(origin);
03961                 LLViewerCamera::updateFrustumPlanes(cube_cam);
03962                 cube_cam.setOrigin(gCamera->getOrigin());
03963                 gPipeline.updateCull(cube_cam);
03964                 gPipeline.stateSort(cube_cam);
03965                 
03966                 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
03967                 gPipeline.renderGeom(cube_cam);
03968         }
03969 
03970 #if !defined(__sparc)
03971         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
03972 #else
03973 #error Can we generalize this without a CPU architecture test?
03974 #endif
03975 
03976         cube_cam.setOrigin(origin);
03977         gPipeline.resetDrawOrders();
03978         gShinyOrigin.setVec(cube_cam.getOrigin(), cube_cam.getFar()*2.f);
03979         glMatrixMode(GL_PROJECTION);
03980         glPopMatrix();
03981         glMatrixMode(GL_MODELVIEW);
03982         glPopMatrix();
03983 
03984         gPipeline.setRenderTypeMask(type_mask);
03985         LLPipeline::sUseOcclusion = use_occlusion;
03986         LLPipeline::sSkipUpdate = FALSE;
03987 
03988         if (toggle_ui)
03989         {
03990                 gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
03991         }
03992         LLDrawPoolWater::sSkipScreenCopy = FALSE;
03993 }
03994 
03995 //send cube map vertices and texture coordinates
03996 void render_cube_map()
03997 {
03998         U32 idx[36];
03999 
04000         idx[0] = 1; idx[1] = 0; idx[2] = 2; //front
04001         idx[3] = 3; idx[4] = 2; idx[5] = 0;
04002 
04003         idx[6] = 4; idx[7] = 5; idx[8] = 1; //top
04004         idx[9] = 0; idx[10] = 1; idx[11] = 5; 
04005 
04006         idx[12] = 5; idx[13] = 4; idx[14] = 6; //back
04007         idx[15] = 7; idx[16] = 6; idx[17] = 4;
04008 
04009         idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom
04010         idx[21] = 2; idx[22] = 3; idx[23] = 7;
04011 
04012         idx[24] = 0; idx[25] = 5; idx[26] = 3; //left
04013         idx[27] = 6; idx[28] = 3; idx[29] = 5;
04014 
04015         idx[30] = 4; idx[31] = 1; idx[32] = 7; //right
04016         idx[33] = 2; idx[34] = 7; idx[35] = 1;
04017 
04018         LLVector3 vert[8];
04019         LLVector3 r = LLVector3(1,1,1);
04020 
04021         vert[0] = r.scaledVec(LLVector3(-1,1,1)); //   0 - left top front
04022         vert[1] = r.scaledVec(LLVector3(1,1,1));  //   1 - right top front
04023         vert[2] = r.scaledVec(LLVector3(1,-1,1)); //   2 - right bottom front
04024         vert[3] = r.scaledVec(LLVector3(-1,-1,1)); //  3 - left bottom front
04025 
04026         vert[4] = r.scaledVec(LLVector3(1,1,-1)); //  4 - left top back
04027         vert[5] = r.scaledVec(LLVector3(-1,1,-1)); //   5 - right top back
04028         vert[6] = r.scaledVec(LLVector3(-1,-1,-1)); //  6 - right bottom back
04029         vert[7] = r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back
04030 
04031         glBegin(GL_TRIANGLES);
04032         for (U32 i = 0; i < 36; i++)
04033         {
04034                 glTexCoord3fv(vert[idx[i]].mV);
04035                 glVertex3fv(vert[idx[i]].mV);
04036         }
04037         glEnd();
04038 }
04039 
04040 void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32 res)
04041 {
04042         LLGLEnable cube(GL_TEXTURE_CUBE_MAP_ARB);
04043         LLGLDepthTest depth(GL_FALSE);
04044         //********UMICH 3D LAB********
04045         // protect the color mask change for correct anaglyph render
04046         GLboolean mask[4];
04047         glGetBooleanv(GL_COLOR_WRITEMASK, mask);
04048         glColorMask(mask[0], mask[1], mask[2], GL_FALSE);
04049         //********UMICH 3D LAB********
04050         glMatrixMode(GL_PROJECTION);
04051         glPushMatrix();
04052         glLoadIdentity();
04053         gluPerspective(90.f+45.f/res, 1.f, 0.1f, 1024.f);
04054         glMatrixMode(GL_MODELVIEW);
04055         glPushMatrix();
04056 
04057         glViewport(0, 0, res, res);
04058         LLGLEnable blend(GL_BLEND);
04059         
04060         S32 kernel = 2;
04061         F32 step = 90.f/res;
04062         F32 alpha = 1.f/((kernel*2)+1);
04063 
04064         glColor4f(alpha,alpha,alpha,alpha*1.25f);
04065 
04066         S32 x = 0;
04067 
04068         U32 cube_face[] = 
04069         {
04070                 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
04071                 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
04072                 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
04073                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
04074                 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
04075                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
04076         };
04077 
04078         LLVector3 axis[] = 
04079         {
04080                 LLVector3(1,0,0),
04081                 LLVector3(0,1,0),
04082                 LLVector3(0,0,1)
04083         };
04084 
04085         
04086         glBlendFunc(GL_ONE, GL_ONE);
04087         //3-axis blur
04088         for (U32 j = 0; j < 3; j++)
04089         {
04090                 glViewport(0,0,res, res*6);
04091                 glClear(GL_COLOR_BUFFER_BIT);
04092                 if (j == 0)
04093                 {
04094                         cube_in->bind();
04095                 }
04096 
04097                 for (U32 i = 0; i < 6; i++)
04098                 {
04099                         glViewport(0,i*res, res, res);
04100                         glLoadIdentity();
04101                         apply_cube_face_rotation(i);
04102                         for (x = -kernel; x <= kernel; ++x)
04103                         {
04104                                 glPushMatrix();
04105                                 glRotatef(x*step, axis[j].mV[0], axis[j].mV[1], axis[j].mV[2]);
04106                                 render_cube_map();
04107                                 glPopMatrix();
04108                         }
04109                 }       
04110 
04111                 //readback
04112                 if (j == 0)
04113                 {
04114                         cube_out->bind();
04115                 }
04116                 for (U32 i = 0; i < 6; i++)
04117                 {
04118                         glCopyTexImage2D(cube_face[i], 0, GL_RGBA, 0, i*res, res, res, 0);
04119                 }
04120         }
04121         
04122         glMatrixMode(GL_PROJECTION);
04123         glPopMatrix();
04124         glMatrixMode(GL_MODELVIEW);
04125         glPopMatrix();
04126 
04127         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
04128         glClear(GL_COLOR_BUFFER_BIT);
04129 }
04130 
04131 void LLPipeline::bindScreenToTexture() 
04132 {
04133         LLGLEnable gl_texture_2d(GL_TEXTURE_2D);
04134 
04135         GLint* viewport = (GLint*) gGLViewport;
04136         GLuint resX = nhpo2(viewport[2]);
04137         GLuint resY = nhpo2(viewport[3]);
04138 
04139         if (mScreenTex == 0)
04140         {
04141                 glGenTextures(1, &mScreenTex);
04142                 glBindTexture(GL_TEXTURE_2D, mScreenTex);
04143                 
04144                 gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
04145                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, resX, resY, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
04146 
04147                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
04148                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
04149                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
04150                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
04151         }
04152 
04153         glBindTexture(GL_TEXTURE_2D, mScreenTex);
04154         GLint cResX;
04155         GLint cResY;
04156         glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX);
04157         glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY);
04158 
04159         if (cResX != (GLint)resX || cResY != (GLint)resY)
04160         {
04161                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL);
04162                 gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
04163         }
04164 
04165         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]); 
04166 
04167         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
04168         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
04169         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
04170         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
04171 
04172         
04173         mScreenScale.mV[0] = (float) viewport[2]/resX;
04174         mScreenScale.mV[1] = (float) viewport[3]/resY;
04175         
04176         LLImageGL::sBoundTextureMemory += resX * resY * 3;
04177 }
04178 
04179 void LLPipeline::renderBloom(GLuint source, GLuint dest, GLuint buffer, U32 res, LLVector2 tc1, LLVector2 tc2)
04180 {
04181         gGlowProgram.bind();
04182 
04183         LLGLEnable tex(GL_TEXTURE_2D);
04184         LLGLDepthTest depth(GL_FALSE);
04185         LLGLDisable blend(GL_BLEND);
04186         LLGLDisable cull(GL_CULL_FACE);
04187 
04188 #if !defined(__sparc)
04189         if (mFramebuffer[0] == 0)
04190         {
04191                 glGenFramebuffersEXT(2, mFramebuffer);
04192         }
04193 #else
04194 #error Can we generalize this without a CPU architecture test?
04195 #endif
04196 
04197         GLint viewport[4];
04198         glGetIntegerv(GL_VIEWPORT, viewport);
04199         glViewport(0,0,res,res);
04200 
04201         glMatrixMode(GL_PROJECTION);
04202         glPushMatrix();
04203         glLoadIdentity();
04204         glMatrixMode(GL_MODELVIEW);
04205         glPushMatrix();
04206         glLoadIdentity();
04207 
04208         glBindTexture(GL_TEXTURE_2D, source);
04209         
04210         S32 kernel = gSavedSettings.getS32("RenderGlowSize")*2;
04211         
04212         LLGLDisable test(GL_ALPHA_TEST);
04213 
04214         F32 delta = 1.f/(res*gSavedSettings.getF32("RenderGlowStrength"));
04215 
04216         for (S32 i = 0; i < kernel; i++)
04217         {
04218 #if !defined(__sparc)
04219                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebuffer[i%2]);
04220                 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 
04221                                                                 GL_COLOR_ATTACHMENT0_EXT,
04222                                                                 GL_TEXTURE_2D, 
04223                                                                 i%2 == 0 ? buffer : dest, 0);
04224 #else
04225 #error Can we generalize this without a CPU architecture test?
04226 #endif
04227                 
04228                 glBindTexture(GL_TEXTURE_2D, i == 0 ? source : 
04229                                                                         i%2==0 ? dest :
04230                                                                         buffer);
04231                 
04232                 glUniform1fARB(gGlowProgram.mUniform[LLShaderMgr::GLOW_DELTA],delta);                                   
04233 
04234                 glBegin(GL_TRIANGLE_STRIP);
04235                 glTexCoord2f(tc1.mV[0], tc1.mV[1]);
04236                 glVertex2f(-1,-1);
04237                 
04238                 glTexCoord2f(tc1.mV[0], tc2.mV[1]);
04239                 glVertex2f(-1,1);
04240                 
04241                 glTexCoord2f(tc2.mV[0], tc1.mV[1]);
04242                 glVertex2f(1,-1);
04243                 
04244                 glTexCoord2f(tc2.mV[0], tc2.mV[1]);
04245                 glVertex2f(1,1);
04246                 glEnd();
04247         
04248                 tc1.setVec(0,0);
04249                 tc2.setVec(1,1);
04250                 
04251         }
04252 
04253 #if !defined(__sparc)
04254         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
04255 #else
04256 #error Can we generalize this without a CPU architecture test?
04257 #endif
04258         gGlowProgram.unbind();
04259 
04260         glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
04261 
04262         if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_GLOW))
04263         {
04264                 glClear(GL_COLOR_BUFFER_BIT);
04265         }
04266 
04267         glBindTexture(GL_TEXTURE_2D, dest);
04268         {
04269                 LLGLEnable blend(GL_BLEND);
04270                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
04271 
04272                 glBegin(GL_TRIANGLE_STRIP);
04273                 glColor4f(1,1,1,1);
04274                 glTexCoord2f(tc1.mV[0], tc1.mV[1]);
04275                 glVertex2f(-1,-1);
04276                 
04277                 glTexCoord2f(tc1.mV[0], tc2.mV[1]);
04278                 glVertex2f(-1,1);
04279                 
04280                 glTexCoord2f(tc2.mV[0], tc1.mV[1]);
04281                 glVertex2f(1,-1);
04282                 
04283                 glTexCoord2f(tc2.mV[0], tc2.mV[1]);
04284                 glVertex2f(1,1);
04285                 glEnd();
04286 
04287                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
04288         }
04289 
04290         glMatrixMode(GL_PROJECTION);
04291         glPopMatrix();
04292         glMatrixMode(GL_MODELVIEW);
04293         glPopMatrix();
04294 }

Generated on Thu Jul 1 06:09:59 2010 for Second Life Viewer by  doxygen 1.4.7